From c37ea1129e35a88c700c67aeb267d9b9beb6b527 Mon Sep 17 00:00:00 2001 From: Alexander V Date: Tue, 29 Jan 2019 02:36:28 +0300 Subject: [PATCH] Line endings (#2915) * Fix line endings to lf * Configs for lf eol --- .editorconfig | 5 +- .gitattributes | 3 + code/__DEFINES/misc.dm | 414 +- code/__HELPERS/files.dm | 120 +- code/__HELPERS/game.dm | 1232 +-- code/__HELPERS/global_lists.dm | 192 +- code/__HELPERS/icons.dm | 1776 ++-- code/__HELPERS/lists.dm | 1466 +-- code/__HELPERS/logging.dm | 310 +- code/__HELPERS/maths.dm | 290 +- code/__HELPERS/matrices.dm | 508 +- code/__HELPERS/mobs.dm | 466 +- code/__HELPERS/names.dm | 672 +- code/__HELPERS/sanitize_values.dm | 92 +- code/__HELPERS/text.dm | 790 +- code/__HELPERS/time.dm | 150 +- code/__HELPERS/type2type.dm | 530 +- code/__HELPERS/unsorted.dm | 3230 +++--- code/_onclick/overmind.dm | 30 +- code/datums/ai_laws.dm | 328 +- code/datums/computerfiles.dm | 14 +- code/datums/datacore.dm | 358 +- code/datums/datumvars.dm | 2124 ++-- code/datums/disease.dm | 402 +- code/datums/diseases/advance/advance.dm | 846 +- code/datums/diseases/advance/presets.dm | 86 +- .../diseases/advance/symptoms/confusion.dm | 78 +- .../datums/diseases/advance/symptoms/cough.dm | 78 +- .../advance/symptoms/damage_converter.dm | 86 +- .../datums/diseases/advance/symptoms/dizzy.dm | 74 +- .../datums/diseases/advance/symptoms/fever.dm | 70 +- .../diseases/advance/symptoms/hallucigen.dm | 74 +- .../diseases/advance/symptoms/headache.dm | 66 +- code/datums/diseases/advance/symptoms/heal.dm | 80 +- .../diseases/advance/symptoms/itching.dm | 66 +- .../diseases/advance/symptoms/shivering.dm | 70 +- .../diseases/advance/symptoms/sneeze.dm | 76 +- .../diseases/advance/symptoms/symptoms.dm | 76 +- .../diseases/advance/symptoms/voice_change.dm | 108 +- .../datums/diseases/advance/symptoms/vomit.dm | 188 +- .../diseases/advance/symptoms/weight.dm | 238 +- code/datums/diseases/appendicitis.dm | 114 +- code/datums/diseases/brainrot.dm | 134 +- code/datums/diseases/cold.dm | 132 +- code/datums/diseases/cold9.dm | 78 +- code/datums/diseases/dna_spread.dm | 138 +- code/datums/diseases/fake_gbs.dm | 64 +- code/datums/diseases/flu.dm | 132 +- code/datums/diseases/fluspanish.dm | 72 +- code/datums/diseases/gbs.dm | 80 +- code/datums/diseases/jungle_fever.dm | 24 +- code/datums/diseases/magnitis.dm | 186 +- code/datums/diseases/pierrot_throat.dm | 58 +- code/datums/diseases/plasmatoid.dm | 10 +- code/datums/diseases/retrovirus.dm | 216 +- .../datums/diseases/robotic_transformation.dm | 130 +- code/datums/diseases/wizarditis.dm | 250 +- code/datums/diseases/xeno_transformation.dm | 122 +- .../helper_datums/construction_datum.dm | 242 +- code/datums/helper_datums/events.dm | 134 +- code/datums/helper_datums/global_iterator.dm | 308 +- code/datums/helper_datums/teleport.dm | 424 +- code/datums/helper_datums/topic_input.dm | 120 +- code/datums/mind.dm | 3396 +++---- code/datums/modules.dm | 124 +- code/datums/recipe.dm | 250 +- code/datums/spell.dm | 660 +- code/datums/spells/area_teleport.dm | 134 +- code/datums/spells/conjure.dm | 284 +- code/datums/spells/dumbfire.dm | 172 +- code/datums/spells/emplosion.dm | 26 +- code/datums/spells/ethereal_jaunt.dm | 230 +- code/datums/spells/explosion.dm | 30 +- code/datums/spells/genetic.dm | 64 +- code/datums/spells/inflict_handler.dm | 118 +- code/datums/spells/knock.dm | 48 +- code/datums/spells/lighting_shock.dm | 114 +- code/datums/spells/mind_transfer.dm | 256 +- code/datums/spells/projectile.dm | 166 +- code/datums/spells/trigger.dm | 54 +- code/datums/spells/turf_teleport.dm | 68 +- code/datums/spells/wizard.dm | 776 +- code/defines/obj.dm | 614 +- code/defines/obj/hydro.dm | 2850 +++--- code/defines/obj/weapon.dm | 1706 ++-- code/defines/procs/AStar.dm | 380 +- code/defines/procs/captain_announce.dm | 12 +- code/defines/procs/command_alert.dm | 22 +- code/defines/procs/dbcore.dm | 416 +- code/defines/procs/statistics.dm | 324 +- code/game/area/ai_monitored.dm | 50 +- code/game/area/areas.dm | 892 +- code/game/asteroid.dm | 308 +- code/game/atoms.dm | 1050 +- code/game/atoms_movable.dm | 664 +- code/game/communications.dm | 600 +- code/game/gamemodes/blob/blob.dm | 334 +- code/game/gamemodes/blob/blob_finish.dm | 102 +- code/game/gamemodes/blob/blob_report.dm | 242 +- code/game/gamemodes/blob/blobs/core.dm | 180 +- code/game/gamemodes/blob/blobs/factory.dm | 292 +- code/game/gamemodes/blob/blobs/node.dm | 62 +- code/game/gamemodes/blob/blobs/resource.dm | 66 +- code/game/gamemodes/blob/blobs/shield.dm | 42 +- code/game/gamemodes/blob/overmind.dm | 182 +- code/game/gamemodes/blob/powers.dm | 472 +- code/game/gamemodes/blob/theblob.dm | 428 +- code/game/gamemodes/changeling/changeling.dm | 674 +- .../gamemodes/changeling/changeling_power.dm | 140 +- .../gamemodes/changeling/evolution_menu.dm | 860 +- .../gamemodes/changeling/powers/absorb.dm | 288 +- .../changeling/powers/changespecies.dm | 58 +- .../gamemodes/changeling/powers/chemsynth.dm | 24 +- .../changeling/powers/digitalcamo.dm | 58 +- .../gamemodes/changeling/powers/fakedeath.dm | 176 +- .../gamemodes/changeling/powers/fleshmend.dm | 40 +- .../gamemodes/changeling/powers/glands.dm | 24 +- .../gamemodes/changeling/powers/hivemind.dm | 142 +- .../gamemodes/changeling/powers/humanform.dm | 164 +- .../gamemodes/changeling/powers/lesserform.dm | 150 +- .../changeling/powers/mimic_voice.dm | 56 +- .../gamemodes/changeling/powers/mutations.dm | 612 +- .../gamemodes/changeling/powers/panacea.dm | 46 +- .../gamemodes/changeling/powers/revive.dm | 70 +- .../gamemodes/changeling/powers/shriek.dm | 58 +- .../gamemodes/changeling/powers/stings.dm | 566 +- .../changeling/powers/stings_range.dm | 24 +- .../gamemodes/changeling/powers/transform.dm | 76 +- code/game/gamemodes/cult/cult.dm | 686 +- code/game/gamemodes/cult/cult_items.dm | 202 +- code/game/gamemodes/cult/ritual.dm | 862 +- code/game/gamemodes/cult/talisman.dm | 180 +- code/game/gamemodes/events/biomass.dm | 346 +- .../gamemodes/events/holidays/Christmas.dm | 120 +- .../gamemodes/events/holidays/Holidays.dm | 338 +- code/game/gamemodes/events/holidays/Other.dm | 20 +- code/game/gamemodes/events/spacevines.dm | 452 +- code/game/gamemodes/events/wormholes.dm | 128 +- code/game/gamemodes/extended/extended.dm | 38 +- code/game/gamemodes/game_mode.dm | 1004 +- code/game/gamemodes/intercept_report.dm | 492 +- .../gamemodes/malfunction/Malf_Modules.dm | 780 +- .../game/gamemodes/malfunction/malfunction.dm | 570 +- code/game/gamemodes/meme/meme.dm | 500 +- code/game/gamemodes/meteor/meteor.dm | 126 +- code/game/gamemodes/meteor/meteors.dm | 308 +- code/game/gamemodes/nuclear/nuclear.dm | 820 +- code/game/gamemodes/nuclear/nuclearbomb.dm | 1104 +-- code/game/gamemodes/nuclear/pinpointer.dm | 304 +- code/game/gamemodes/objective.dm | 1984 ++-- code/game/gamemodes/revolution/revolution.dm | 1006 +- .../gamemodes/revolution/rp_revolution.dm | 530 +- code/game/gamemodes/sandbox/h_sandbox.dm | 308 +- code/game/gamemodes/sandbox/sandbox.dm | 42 +- code/game/gamemodes/setupgame.dm | 216 +- code/game/gamemodes/traitor/traitor.dm | 716 +- code/game/gamemodes/wizard/soulstone.dm | 428 +- code/game/gamemodes/wizard/spellbook.dm | 1054 +- code/game/gamemodes/wizard/wizard.dm | 604 +- code/game/jobs/access.dm | 1142 +-- code/game/jobs/job/assistant.dm | 164 +- code/game/jobs/job/civilian.dm | 896 +- code/game/jobs/job/civilian_chaplain.dm | 310 +- code/game/jobs/job/engineering.dm | 274 +- code/game/jobs/job/job.dm | 316 +- code/game/jobs/job/medical.dm | 564 +- code/game/jobs/job/science.dm | 358 +- code/game/jobs/job/security.dm | 440 +- code/game/jobs/job/silicon.dm | 94 +- code/game/jobs/jobprocs.dm | 110 +- code/game/jobs/jobs.dm | 302 +- code/game/jobs/whitelist.dm | 100 +- code/game/machinery/OpTable.dm | 296 +- code/game/machinery/PDApainter.dm | 210 +- code/game/machinery/Sleeper.dm | 658 +- code/game/machinery/airlock_control.dm | 528 +- code/game/machinery/alarm.dm | 2484 ++--- code/game/machinery/autolathe.dm | 682 +- code/game/machinery/bees_items.dm | 180 +- code/game/machinery/biogenerator.dm | 630 +- code/game/machinery/bots/bots.dm | 378 +- code/game/machinery/bots/cleanbot.dm | 726 +- code/game/machinery/bots/ed209bot.dm | 1032 +- code/game/machinery/bots/floorbot.dm | 862 +- code/game/machinery/bots/medbot.dm | 1186 +-- code/game/machinery/bots/mulebot.dm | 1720 ++-- code/game/machinery/bots/secbot.dm | 1404 +-- code/game/machinery/buttons.dm | 94 +- code/game/machinery/camera/camera.dm | 802 +- code/game/machinery/camera/camera_assembly.dm | 330 +- code/game/machinery/camera/motion.dm | 122 +- code/game/machinery/camera/presets.dm | 164 +- code/game/machinery/camera/tracking.dm | 568 +- code/game/machinery/cell_charger.dm | 212 +- code/game/machinery/cloning.dm | 1018 +- code/game/machinery/computer/Operating.dm | 118 +- code/game/machinery/computer/aifixer.dm | 230 +- code/game/machinery/computer/arcade.dm | 674 +- .../game/machinery/computer/buildandrepair.dm | 952 +- code/game/machinery/computer/camera.dm | 522 +- .../game/machinery/computer/communications.dm | 1102 +-- code/game/machinery/computer/crew.dm | 36 +- code/game/machinery/computer/medical.dm | 1070 +- code/game/machinery/computer/power.dm | 192 +- code/game/machinery/computer/robot.dm | 420 +- code/game/machinery/computer/security.dm | 1248 +-- code/game/machinery/computer/shuttle.dm | 138 +- .../machinery/computer/specops_shuttle.dm | 522 +- code/game/machinery/computer/station_alert.dm | 198 +- .../computer/syndicate_specops_shuttle.dm | 306 +- code/game/machinery/constructable_frame.dm | 1606 +-- code/game/machinery/deployable.dm | 554 +- code/game/machinery/door_control.dm | 268 +- code/game/machinery/doors/airlock.dm | 2332 ++--- .../machinery/doors/airlock_electronics.dm | 220 +- code/game/machinery/doors/alarmlock.dm | 86 +- code/game/machinery/doors/brigdoors.dm | 738 +- .../machinery/doors/checkForMultipleDoors.dm | 32 +- code/game/machinery/doors/door.dm | 764 +- code/game/machinery/doors/firedoor.dm | 692 +- code/game/machinery/doors/poddoor.dm | 164 +- code/game/machinery/doors/shutters.dm | 50 +- code/game/machinery/doors/windowdoor.dm | 942 +- code/game/machinery/doppler_array.dm | 110 +- .../embedded_controller_base.dm | 200 +- code/game/machinery/flasher.dm | 300 +- code/game/machinery/hologram.dm | 528 +- code/game/machinery/hydroponics.dm | 2024 ++-- code/game/machinery/igniter.dm | 280 +- code/game/machinery/iv_drip.dm | 352 +- code/game/machinery/kitchen/deep_fryer.dm | 210 +- code/game/machinery/kitchen/gibber.dm | 476 +- code/game/machinery/kitchen/juicer.dm | 326 +- code/game/machinery/kitchen/processor.dm | 404 +- code/game/machinery/kitchen/smartfridge.dm | 738 +- code/game/machinery/lightswitch.dm | 162 +- code/game/machinery/machinery.dm | 970 +- code/game/machinery/magnet.dm | 768 +- code/game/machinery/mass_driver.dm | 96 +- code/game/machinery/navbeacon.dm | 452 +- code/game/machinery/overview.dm | 724 +- code/game/machinery/pipe/construction.dm | 1528 +-- code/game/machinery/pipe/pipe_dispenser.dm | 460 +- code/game/machinery/portable_turret.dm | 1884 ++-- code/game/machinery/rechargestation.dm | 424 +- code/game/machinery/requests_console.dm | 832 +- code/game/machinery/robot_fabricator.dm | 268 +- code/game/machinery/seed_extractor.dm | 194 +- code/game/machinery/shieldgen.dm | 1258 +-- code/game/machinery/status_display.dm | 604 +- code/game/machinery/suit_storage_unit.dm | 1128 +-- code/game/machinery/syndicatebeacon.dm | 472 +- code/game/machinery/telecomms/presets.dm | 454 +- .../machinery/telecomms/telecomunications.dm | 1238 +-- code/game/machinery/transformer.dm | 110 +- code/game/machinery/vending.dm | 2414 ++--- code/game/machinery/washing_machine.dm | 686 +- code/game/mecha/combat/combat.dm | 546 +- code/game/mecha/combat/durand.dm | 192 +- code/game/mecha/combat/gygax.dm | 254 +- code/game/mecha/combat/honker.dm | 324 +- code/game/mecha/combat/marauder.dm | 396 +- code/game/mecha/combat/phazon.dm | 178 +- code/game/mecha/equipment/mecha_equipment.dm | 280 +- .../mecha/equipment/tools/medical_tools.dm | 1352 +-- code/game/mecha/equipment/tools/tools.dm | 2406 ++--- .../mecha/equipment/tools/unused_tools.dm | 314 +- code/game/mecha/equipment/weapons/weapons.dm | 646 +- code/game/mecha/mech_bay.dm | 324 +- code/game/mecha/mech_fabricator.dm | 1134 +-- code/game/mecha/mecha.dm | 3694 +++---- code/game/mecha/mecha_construction_paths.dm | 3618 +++---- code/game/mecha/mecha_control_console.dm | 252 +- code/game/mecha/mecha_parts.dm | 1042 +- code/game/mecha/mecha_wreckage.dm | 636 +- code/game/mecha/medical/medical.dm | 46 +- code/game/mecha/medical/odysseus.dm | 172 +- code/game/mecha/working/ripley.dm | 304 +- code/game/mecha/working/working.dm | 66 +- code/game/objects/effects/anomalies.dm | 374 +- code/game/objects/effects/biomass_rift.dm | 254 +- code/game/objects/effects/bump_teleporter.dm | 68 +- .../effects/decals/Cleanable/aliens.dm | 66 +- .../effects/decals/Cleanable/humans.dm | 520 +- .../objects/effects/decals/Cleanable/misc.dm | 332 +- .../effects/decals/Cleanable/robots.dm | 102 +- code/game/objects/effects/decals/cleanable.dm | 28 +- code/game/objects/effects/decals/crayon.dm | 164 +- code/game/objects/effects/decals/misc.dm | 38 +- code/game/objects/effects/decals/remains.dm | 46 +- code/game/objects/effects/effect_system.dm | 1510 +-- code/game/objects/effects/gibs.dm | 160 +- code/game/objects/effects/glowshroom.dm | 332 +- code/game/objects/effects/landmarks.dm | 552 +- code/game/objects/effects/manifest.dm | 34 +- code/game/objects/effects/mines.dm | 200 +- code/game/objects/effects/misc.dm | 16 +- code/game/objects/effects/overlays.dm | 130 +- code/game/objects/effects/portals.dm | 228 +- .../objects/effects/spawners/bombspawner.dm | 134 +- .../objects/effects/spawners/gibspawner.dm | 182 +- .../objects/effects/spawners/vaultspawner.dm | 56 +- code/game/objects/effects/spiders.dm | 462 +- code/game/objects/empulse.dm | 76 +- code/game/objects/explosion.dm | 48 +- code/game/objects/explosion_recursive.dm | 246 +- code/game/objects/items.dm | 1758 ++-- code/game/objects/items/apc_frame.dm | 84 +- code/game/objects/items/bodybag.dm | 218 +- code/game/objects/items/candle.dm | 402 +- code/game/objects/items/crayons.dm | 504 +- code/game/objects/items/devices/PDA/PDA.dm | 2590 ++--- code/game/objects/items/devices/PDA/cart.dm | 1212 +-- code/game/objects/items/devices/PDA/radio.dm | 518 +- code/game/objects/items/devices/aicard.dm | 270 +- .../objects/items/devices/chameleonproj.dm | 356 +- code/game/objects/items/devices/debugger.dm | 186 +- code/game/objects/items/devices/flash.dm | 436 +- code/game/objects/items/devices/flashlight.dm | 568 +- .../objects/items/devices/lightreplacer.dm | 406 +- code/game/objects/items/devices/multitool.dm | 42 +- code/game/objects/items/devices/paicard.dm | 612 +- code/game/objects/items/devices/powersink.dm | 240 +- .../objects/items/devices/radio/beacon.dm | 306 +- .../items/devices/radio/electropack.dm | 254 +- .../objects/items/devices/radio/headset.dm | 602 +- .../objects/items/devices/radio/intercom.dm | 148 +- .../game/objects/items/devices/radio/radio.dm | 1692 ++-- code/game/objects/items/devices/scanners.dm | 876 +- .../objects/items/devices/taperecorder.dm | 514 +- .../objects/items/devices/transfer_valve.dm | 430 +- code/game/objects/items/latexballoon.dm | 96 +- code/game/objects/items/robot/robot_items.dm | 192 +- code/game/objects/items/shooting_range.dm | 364 +- code/game/objects/items/stacks/medical.dm | 690 +- code/game/objects/items/stacks/rods.dm | 148 +- .../game/objects/items/stacks/sheets/glass.dm | 788 +- .../objects/items/stacks/sheets/leather.dm | 248 +- .../game/objects/items/stacks/sheets/light.dm | 58 +- .../objects/items/stacks/sheets/mineral.dm | 580 +- .../objects/items/stacks/sheets/sheets.dm | 50 +- code/game/objects/items/stacks/tiles/light.dm | 72 +- .../objects/items/stacks/tiles/plasteel.dm | 90 +- .../objects/items/stacks/tiles/tile_types.dm | 250 +- code/game/objects/items/toys.dm | 3190 +++--- code/game/objects/items/trash.dm | 152 +- code/game/objects/items/weapons/AI_modules.dm | 988 +- code/game/objects/items/weapons/RCD.dm | 430 +- code/game/objects/items/weapons/RSF.dm | 468 +- code/game/objects/items/weapons/bell.dm | 40 +- code/game/objects/items/weapons/cards_ids.dm | 900 +- .../objects/items/weapons/cigs_lighters.dm | 982 +- .../game/objects/items/weapons/clown_items.dm | 476 +- code/game/objects/items/weapons/cosmetics.dm | 892 +- code/game/objects/items/weapons/dice.dm | 574 +- .../objects/items/weapons/dna_injector.dm | 1300 +-- code/game/objects/items/weapons/explosives.dm | 114 +- .../objects/items/weapons/extinguisher.dm | 292 +- .../objects/items/weapons/flamethrower.dm | 404 +- .../items/weapons/grenades/chem_grenade.dm | 618 +- .../items/weapons/grenades/emgrenade.dm | 24 +- .../items/weapons/grenades/flashbang.dm | 358 +- .../objects/items/weapons/grenades/grenade.dm | 256 +- .../items/weapons/grenades/smokebomb.dm | 66 +- .../items/weapons/grenades/spawnergrenade.dm | 86 +- code/game/objects/items/weapons/handcuffs.dm | 258 +- .../game/objects/items/weapons/hydroponics.dm | 426 +- .../objects/items/weapons/implants/implant.dm | 1054 +- .../items/weapons/implants/implantcase.dm | 274 +- .../items/weapons/implants/implantchair.dm | 304 +- .../items/weapons/implants/implanter.dm | 248 +- .../items/weapons/implants/implantfreedom.dm | 100 +- .../items/weapons/implants/implantpad.dm | 196 +- .../items/weapons/implants/implantuplink.dm | 44 +- code/game/objects/items/weapons/kitchen.dm | 1102 +-- code/game/objects/items/weapons/manuals.dm | 810 +- .../objects/items/weapons/melee/energy.dm | 184 +- code/game/objects/items/weapons/melee/misc.dm | 52 +- code/game/objects/items/weapons/mop.dm | 130 +- code/game/objects/items/weapons/paint.dm | 352 +- code/game/objects/items/weapons/paiwire.dm | 22 +- .../game/objects/items/weapons/power_cells.dm | 274 +- code/game/objects/items/weapons/scrolls.dm | 182 +- code/game/objects/items/weapons/shields.dm | 294 +- .../objects/items/weapons/storage/backpack.dm | 678 +- .../objects/items/weapons/storage/bags.dm | 568 +- .../objects/items/weapons/storage/belt.dm | 422 +- .../objects/items/weapons/storage/bible.dm | 88 +- .../objects/items/weapons/storage/boxes.dm | 1378 +-- .../items/weapons/storage/briefcase.dm | 100 +- .../objects/items/weapons/storage/fancy.dm | 780 +- .../objects/items/weapons/storage/firstaid.dm | 512 +- .../objects/items/weapons/storage/lockbox.dm | 192 +- .../objects/items/weapons/storage/secure.dm | 472 +- .../objects/items/weapons/storage/storage.dm | 1016 +- .../objects/items/weapons/storage/toolbox.dm | 172 +- .../objects/items/weapons/swords_axes_etc.dm | 584 +- .../objects/items/weapons/table_rack_parts.dm | 294 +- .../objects/items/weapons/tanks/jetpack.dm | 220 +- .../objects/items/weapons/tanks/tank_types.dm | 258 +- .../game/objects/items/weapons/tanks/tanks.dm | 502 +- .../objects/items/weapons/teleportation.dm | 360 +- code/game/objects/items/weapons/tools.dm | 1140 +-- code/game/objects/items/weapons/twohanded.dm | 544 +- code/game/objects/items/weapons/weaponry.dm | 410 +- code/game/objects/objs.dm | 486 +- code/game/objects/structures.dm | 340 +- code/game/objects/structures/bedsheet_bin.dm | 488 +- code/game/objects/structures/bobross.dm | 50 +- .../structures/crates_lockers/closets.dm | 672 +- .../crates_lockers/closets/coffin.dm | 24 +- .../crates_lockers/closets/crittercrate.dm | 208 +- .../crates_lockers/closets/fitness.dm | 132 +- .../crates_lockers/closets/gimmick.dm | 184 +- .../crates_lockers/closets/job_closets.dm | 328 +- .../crates_lockers/closets/l3closet.dm | 114 +- .../crates_lockers/closets/malfunction.dm | 30 +- .../closets/secure/engineering.dm | 266 +- .../crates_lockers/closets/secure/freezer.dm | 150 +- .../crates_lockers/closets/secure/medical.dm | 352 +- .../crates_lockers/closets/secure/personal.dm | 212 +- .../closets/secure/scientist.dm | 94 +- .../closets/secure/secure_closets.dm | 270 +- .../crates_lockers/closets/secure/security.dm | 738 +- .../crates_lockers/closets/syndicate.dm | 212 +- .../crates_lockers/closets/utility_closets.dm | 432 +- .../crates_lockers/closets/wardrobe.dm | 832 +- .../structures/crates_lockers/crates.dm | 1040 +- .../structures/crates_lockers/largecrate.dm | 52 +- code/game/objects/structures/displaycase.dm | 196 +- code/game/objects/structures/door_assembly.dm | 554 +- code/game/objects/structures/false_walls.dm | 704 +- code/game/objects/structures/flora.dm | 1010 +- code/game/objects/structures/girders.dm | 578 +- code/game/objects/structures/grille.dm | 476 +- code/game/objects/structures/janicart.dm | 592 +- code/game/objects/structures/kitchen_spike.dm | 250 +- code/game/objects/structures/ladders.dm | 162 +- code/game/objects/structures/lamarr_cage.dm | 202 +- code/game/objects/structures/lattice.dm | 164 +- code/game/objects/structures/mineral_doors.dm | 668 +- code/game/objects/structures/mirror.dm | 532 +- code/game/objects/structures/mop_bucket.dm | 90 +- code/game/objects/structures/morgue.dm | 902 +- code/game/objects/structures/noticeboard.dm | 166 +- code/game/objects/structures/safe.dm | 384 +- .../stool_bed_chair_nest/alien_nests.dm | 132 +- .../structures/stool_bed_chair_nest/bed.dm | 336 +- .../structures/stool_bed_chair_nest/chairs.dm | 628 +- .../structures/stool_bed_chair_nest/stools.dm | 210 +- code/game/objects/structures/tables_racks.dm | 1672 ++-- .../game/objects/structures/tank_dispenser.dm | 226 +- code/game/objects/structures/target_stake.dm | 104 +- code/game/objects/structures/window.dm | 1046 +- code/game/shuttle_engines.dm | 96 +- code/game/skincmd.dm | 26 +- code/game/smoothwall.dm | 308 +- code/game/sound.dm | 260 +- code/game/turfs/simulated.dm | 444 +- code/game/turfs/simulated/floor.dm | 1264 +-- code/game/turfs/simulated/floor_types.dm | 726 +- code/game/turfs/simulated/walls.dm | 972 +- code/game/turfs/simulated/walls_mineral.dm | 292 +- code/game/turfs/simulated/walls_misc.dm | 10 +- code/game/turfs/simulated/walls_reinforced.dm | 706 +- code/game/turfs/space/space.dm | 552 +- code/game/turfs/space/transit.dm | 226 +- code/game/turfs/unsimulated.dm | 10 +- code/game/turfs/unsimulated/beach.dm | 40 +- code/game/turfs/unsimulated/floor.dm | 30 +- code/game/turfs/unsimulated/walls.dm | 66 +- code/game/verbs/ooc.dm | 356 +- code/game/verbs/suicide.dm | 468 +- code/game/verbs/who.dm | 248 +- code/hub.dm | 26 +- code/js/byjax.dm | 100 +- code/js/menus.dm | 74 +- code/modules/admin/NewBan.dm | 452 +- code/modules/admin/admin.dm | 2606 ++--- code/modules/admin/admin_ranks.dm | 326 +- code/modules/admin/admin_verbs.dm | 2248 ++--- code/modules/admin/banjob.dm | 74 +- code/modules/admin/create_mob.dm | 18 +- code/modules/admin/create_object.dm | 54 +- code/modules/admin/create_turf.dm | 18 +- code/modules/admin/holder2.dm | 208 +- .../admin/permissionverbs/permissionedit.dm | 650 +- code/modules/admin/topic.dm | 5752 +++++------ code/modules/admin/verbs/BrokenInhands.dm | 68 +- code/modules/admin/verbs/adminhelp.dm | 38 +- code/modules/admin/verbs/adminjump.dm | 322 +- code/modules/admin/verbs/adminsay.dm | 44 +- code/modules/admin/verbs/atmosdebug.dm | 82 +- code/modules/admin/verbs/deadsay.dm | 88 +- code/modules/admin/verbs/debug.dm | 3938 ++++---- code/modules/admin/verbs/diagnostics.dm | 176 +- code/modules/admin/verbs/mapping.dm | 708 +- code/modules/admin/verbs/massmodvar.dm | 984 +- code/modules/admin/verbs/modifyvariables.dm | 1110 +-- code/modules/admin/verbs/one_click_antag.dm | 1266 +-- code/modules/admin/verbs/onlyone.dm | 100 +- code/modules/admin/verbs/playsound.dm | 142 +- code/modules/admin/verbs/pray.dm | 114 +- code/modules/admin/verbs/randomverbs.dm | 2218 ++--- code/modules/admin/verbs/striketeam.dm | 350 +- .../admin/verbs/striketeam_syndicate.dm | 356 +- code/modules/admin/verbs/tripAI.dm | 44 +- code/modules/assembly/assembly.dm | 292 +- code/modules/assembly/bomb.dm | 318 +- code/modules/assembly/helpers.dm | 28 +- code/modules/assembly/holder.dm | 508 +- code/modules/assembly/igniter.dm | 76 +- code/modules/assembly/infrared.dm | 488 +- code/modules/assembly/mousetrap.dm | 228 +- code/modules/assembly/proximity.dm | 350 +- code/modules/assembly/shock_kit.dm | 90 +- code/modules/assembly/signaler.dm | 420 +- code/modules/assembly/timer.dm | 248 +- .../awaymissions/bluespaceartillery.dm | 146 +- code/modules/awaymissions/corpse.dm | 468 +- code/modules/awaymissions/exile.dm | 86 +- code/modules/awaymissions/gateway.dm | 490 +- code/modules/awaymissions/loot.dm | 50 +- code/modules/awaymissions/pamphlet.dm | 76 +- code/modules/awaymissions/trigger.dm | 88 +- code/modules/cargo/packs.dm | 2962 +++--- code/modules/client/preferences.dm | 770 +- code/modules/client/preferences_savefile.dm | 896 +- code/modules/client/preferences_toggles.dm | 618 +- code/modules/clothing/clothing.dm | 1186 +-- code/modules/clothing/glasses/glasses.dm | 710 +- code/modules/clothing/glasses/hud.dm | 146 +- code/modules/clothing/gloves/boxing.dm | 54 +- code/modules/clothing/gloves/color.dm | 250 +- code/modules/clothing/gloves/miscellaneous.dm | 270 +- code/modules/clothing/gloves/stungloves.dm | 186 +- code/modules/clothing/head/collectable.dm | 262 +- code/modules/clothing/head/helmet.dm | 338 +- code/modules/clothing/head/jobs.dm | 192 +- code/modules/clothing/head/misc.dm | 780 +- code/modules/clothing/head/misc_special.dm | 334 +- code/modules/clothing/head/soft_caps.dm | 212 +- code/modules/clothing/masks/boxing.dm | 82 +- code/modules/clothing/masks/breath.dm | 106 +- code/modules/clothing/masks/gasmask.dm | 564 +- code/modules/clothing/masks/miscellaneous.dm | 554 +- code/modules/clothing/shoes/colour.dm | 314 +- code/modules/clothing/shoes/magboots.dm | 76 +- code/modules/clothing/shoes/miscellaneous.dm | 404 +- code/modules/clothing/spacesuits/captain.dm | 62 +- .../clothing/spacesuits/miscellaneous.dm | 204 +- code/modules/clothing/spacesuits/ninja.dm | 136 +- code/modules/clothing/spacesuits/rig.dm | 1100 +-- code/modules/clothing/spacesuits/syndi.dm | 282 +- code/modules/clothing/spacesuits/void.dm | 28 +- code/modules/clothing/suits/armor.dm | 620 +- code/modules/clothing/suits/bio.dm | 172 +- code/modules/clothing/suits/jobs.dm | 466 +- code/modules/clothing/suits/labcoat.dm | 206 +- code/modules/clothing/suits/miscellaneous.dm | 1240 +-- code/modules/clothing/suits/utility.dm | 216 +- code/modules/clothing/suits/wiz_robe.dm | 272 +- code/modules/clothing/under/chameleon.dm | 1024 +- code/modules/clothing/under/color.dm | 312 +- code/modules/clothing/under/jobs/civilian.dm | 420 +- .../clothing/under/jobs/engineering.dm | 68 +- code/modules/clothing/under/jobs/medsci.dm | 456 +- code/modules/clothing/under/jobs/security.dm | 336 +- code/modules/clothing/under/miscellaneous.dm | 1502 +-- code/modules/clothing/under/shorts.dm | 52 +- code/modules/clothing/under/syndicate.dm | 54 +- code/modules/clothing/under/ties.dm | 948 +- code/modules/destilery/main.dm | 612 +- code/modules/events/alien_infestation.dm | 100 +- code/modules/events/blob.dm | 56 +- code/modules/events/brand_intelligence.dm | 112 +- code/modules/events/carp_migration.dm | 56 +- .../modules/events/communications_blackout.dm | 40 +- code/modules/events/disease_outbreak.dm | 92 +- code/modules/events/electrical_storm.dm | 56 +- code/modules/events/event.dm | 222 +- code/modules/events/prison_break.dm | 106 +- code/modules/events/radiation_storm.dm | 24 +- code/modules/events/spacevine.dm | 24 +- code/modules/events/spider_infestation.dm | 76 +- .../events/spontaneous_appendicitis.dm | 26 +- code/modules/genetics/side_effects.dm | 222 +- .../holidays/new_year/new_year_mate.dm | 40 +- code/modules/library/lib_items.dm | 612 +- code/modules/library/lib_machines.dm | 1080 +- code/modules/library/lib_readme.dm | 122 +- code/modules/liquid/splash_simulation.dm | 412 +- .../mining/machine_input_output_plates.dm | 66 +- code/modules/mining/mine_areas.dm | 104 +- code/modules/mining/money_bag.dm | 222 +- code/modules/mob/camera/camera.dm | 14 +- .../mob/dead/new_player/sprite_accessories.dm | 2930 +++--- code/modules/mob/dead/observer/login.dm | 34 +- code/modules/mob/dead/observer/logout.dm | 10 +- code/modules/mob/dead/observer/observer.dm | 1360 +-- code/modules/mob/dead/observer/say.dm | 130 +- code/modules/mob/emote.dm | 170 +- code/modules/mob/inventory.dm | 842 +- code/modules/mob/living/blob/blob.dm | 518 +- code/modules/mob/living/carbon/alien/alien.dm | 724 +- .../carbon/alien/humanoid/alien_powers.dm | 648 +- .../carbon/alien/humanoid/caste/drone.dm | 152 +- .../carbon/alien/humanoid/caste/hunter.dm | 312 +- .../carbon/alien/humanoid/caste/sentinel.dm | 88 +- .../mob/living/carbon/alien/humanoid/emote.dm | 270 +- .../living/carbon/alien/humanoid/humanoid.dm | 88 +- .../living/carbon/alien/humanoid/inventory.dm | 108 +- .../mob/living/carbon/alien/humanoid/queen.dm | 216 +- .../carbon/alien/humanoid/update_icons.dm | 346 +- .../mob/living/carbon/alien/larva/emote.dm | 254 +- .../living/carbon/alien/larva/inventory.dm | 14 +- .../mob/living/carbon/alien/larva/larva.dm | 116 +- .../mob/living/carbon/alien/larva/life.dm | 76 +- .../mob/living/carbon/alien/larva/powers.dm | 128 +- .../living/carbon/alien/larva/update_icons.dm | 70 +- code/modules/mob/living/carbon/alien/login.dm | 16 +- .../modules/mob/living/carbon/alien/logout.dm | 8 +- .../modules/mob/living/carbon/alien/powers.dm | 38 +- code/modules/mob/living/carbon/alien/say.dm | 212 +- code/modules/mob/living/carbon/brain/MMI.dm | 400 +- code/modules/mob/living/carbon/brain/brain.dm | 116 +- .../mob/living/carbon/brain/brain_item.dm | 194 +- code/modules/mob/living/carbon/brain/death.dm | 84 +- code/modules/mob/living/carbon/brain/emote.dm | 164 +- code/modules/mob/living/carbon/brain/life.dm | 524 +- code/modules/mob/living/carbon/brain/login.dm | 6 +- code/modules/mob/living/carbon/brain/say.dm | 54 +- code/modules/mob/living/carbon/carbon.dm | 1372 +-- .../mob/living/carbon/carbon_defines.dm | 78 +- code/modules/mob/living/carbon/human/death.dm | 296 +- code/modules/mob/living/carbon/human/emote.dm | 1238 +-- .../mob/living/carbon/human/examine.dm | 1028 +- code/modules/mob/living/carbon/human/human.dm | 3544 +++---- .../living/carbon/human/human_attackhand.dm | 594 +- .../living/carbon/human/human_attackpaw.dm | 46 +- .../mob/living/carbon/human/human_damage.dm | 718 +- .../mob/living/carbon/human/human_defense.dm | 914 +- .../mob/living/carbon/human/human_defines.dm | 202 +- .../mob/living/carbon/human/human_movement.dm | 230 +- .../mob/living/carbon/human/inventory.dm | 1746 ++-- code/modules/mob/living/carbon/human/life.dm | 3834 ++++---- code/modules/mob/living/carbon/human/login.dm | 14 +- code/modules/mob/living/carbon/human/say.dm | 600 +- .../mob/living/carbon/human/update_icons.dm | 1890 ++-- .../mob/living/carbon/human/whisper.dm | 266 +- .../mob/living/carbon/metroid/death.dm | 58 +- .../mob/living/carbon/metroid/emote.dm | 210 +- .../mob/living/carbon/metroid/examine.dm | 50 +- code/modules/mob/living/carbon/metroid/hud.dm | 4 +- .../modules/mob/living/carbon/metroid/life.dm | 1538 +-- .../mob/living/carbon/metroid/login.dm | 8 +- .../mob/living/carbon/metroid/metroid.dm | 2262 ++--- .../mob/living/carbon/metroid/powers.dm | 518 +- .../mob/living/carbon/metroid/subtypes.dm | 964 +- .../mob/living/carbon/metroid/update_icons.dm | 4 +- .../modules/mob/living/carbon/monkey/death.dm | 110 +- .../modules/mob/living/carbon/monkey/emote.dm | 294 +- .../mob/living/carbon/monkey/examine.dm | 90 +- .../mob/living/carbon/monkey/inventory.dm | 434 +- code/modules/mob/living/carbon/monkey/life.dm | 1318 +-- .../modules/mob/living/carbon/monkey/login.dm | 8 +- .../mob/living/carbon/monkey/monkey.dm | 1046 +- .../mob/living/carbon/monkey/powers.dm | 12 +- .../mob/living/carbon/monkey/update_icons.dm | 272 +- code/modules/mob/living/damage_procs.dm | 166 +- code/modules/mob/living/living_defense.dm | 598 +- code/modules/mob/living/living_defines.dm | 108 +- code/modules/mob/living/logout.dm | 14 +- code/modules/mob/living/parasite/meme.dm | 1302 +-- code/modules/mob/living/say.dm | 426 +- code/modules/mob/living/silicon/ai/ai.dm | 1804 ++-- code/modules/mob/living/silicon/ai/death.dm | 132 +- code/modules/mob/living/silicon/ai/examine.dm | 46 +- .../living/silicon/ai/freelook/cameranet.dm | 346 +- .../mob/living/silicon/ai/freelook/chunk.dm | 368 +- .../mob/living/silicon/ai/freelook/eye.dm | 348 +- .../mob/living/silicon/ai/freelook/read_me.dm | 102 +- .../silicon/ai/freelook/update_triggers.dm | 148 +- code/modules/mob/living/silicon/ai/laws.dm | 330 +- code/modules/mob/living/silicon/ai/life.dm | 390 +- code/modules/mob/living/silicon/ai/login.dm | 30 +- code/modules/mob/living/silicon/ai/logout.dm | 28 +- code/modules/mob/living/silicon/ai/say.dm | 256 +- .../modules/mob/living/silicon/decoy/death.dm | 20 +- .../modules/mob/living/silicon/decoy/decoy.dm | 12 +- code/modules/mob/living/silicon/decoy/life.dm | 30 +- code/modules/mob/living/silicon/login.dm | 16 +- code/modules/mob/living/silicon/pai/death.dm | 34 +- code/modules/mob/living/silicon/pai/hud.dm | 226 +- code/modules/mob/living/silicon/pai/life.dm | 56 +- code/modules/mob/living/silicon/pai/pai.dm | 550 +- .../mob/living/silicon/pai/personality.dm | 120 +- .../modules/mob/living/silicon/pai/recruit.dm | 742 +- code/modules/mob/living/silicon/pai/say.dm | 10 +- .../mob/living/silicon/pai/software.dm | 1410 +-- .../mob/living/silicon/robot/component.dm | 448 +- .../modules/mob/living/silicon/robot/death.dm | 130 +- .../modules/mob/living/silicon/robot/emote.dm | 440 +- .../mob/living/silicon/robot/examine.dm | 76 +- .../mob/living/silicon/robot/inventory.dm | 490 +- code/modules/mob/living/silicon/robot/laws.dm | 378 +- code/modules/mob/living/silicon/robot/life.dm | 628 +- .../modules/mob/living/silicon/robot/login.dm | 8 +- .../modules/mob/living/silicon/robot/robot.dm | 2652 ++--- .../mob/living/silicon/robot/robot_damage.dm | 296 +- .../mob/living/silicon/robot/robot_modules.dm | 898 +- .../living/silicon/robot/robot_movement.dm | 64 +- code/modules/mob/living/silicon/say.dm | 512 +- code/modules/mob/living/silicon/silicon.dm | 392 +- .../mob/living/simple_animal/constructs.dm | 476 +- .../mob/living/simple_animal/corpse.dm | 316 +- .../mob/living/simple_animal/friendly/cat.dm | 308 +- .../living/simple_animal/friendly/corgi.dm | 356 +- .../mob/living/simple_animal/friendly/crab.dm | 556 +- .../simple_animal/friendly/farm_animals.dm | 698 +- .../mob/living/simple_animal/friendly/fox.dm | 52 +- .../living/simple_animal/friendly/lizard.dm | 38 +- .../living/simple_animal/friendly/mouse.dm | 380 +- .../living/simple_animal/friendly/mushroom.dm | 34 +- .../living/simple_animal/friendly/shiba.dm | 180 +- .../living/simple_animal/friendly/slime.dm | 98 +- .../living/simple_animal/friendly/tomato.dm | 34 +- .../living/simple_animal/friendly/walle.dm | 34 +- .../mob/living/simple_animal/hostile/alien.dm | 194 +- .../mob/living/simple_animal/hostile/bear.dm | 344 +- .../mob/living/simple_animal/hostile/carp.dm | 210 +- .../living/simple_animal/hostile/creature.dm | 32 +- .../living/simple_animal/hostile/faithless.dm | 100 +- .../simple_animal/hostile/giant_spider.dm | 414 +- .../living/simple_animal/hostile/hivebot.dm | 212 +- .../living/simple_animal/hostile/hostile.dm | 608 +- .../mob/living/simple_animal/hostile/mimic.dm | 406 +- .../living/simple_animal/hostile/pirate.dm | 118 +- .../simple_animal/hostile/retaliate/clown.dm | 156 +- .../hostile/retaliate/retaliate.dm | 98 +- .../living/simple_animal/hostile/russian.dm | 110 +- .../living/simple_animal/hostile/syndicate.dm | 334 +- .../mob/living/simple_animal/hostile/tree.dm | 112 +- .../mob/living/simple_animal/parrot.dm | 1678 ++-- .../modules/mob/living/simple_animal/shade.dm | 122 +- .../mob/living/simple_animal/simple_animal.dm | 904 +- code/modules/mob/living/simple_animal/worm.dm | 402 +- code/modules/mob/login.dm | 154 +- code/modules/mob/logout.dm | 22 +- code/modules/mob/mob.dm | 2266 ++--- code/modules/mob/mob_grab.dm | 990 +- code/modules/mob/mob_helpers.dm | 970 +- code/modules/mob/mob_movement.dm | 882 +- code/modules/mob/say.dm | 336 +- code/modules/mob/transform_procs.dm | 772 +- code/modules/mob/update_icons.dm | 142 +- code/modules/paperwork/photography.dm | 824 +- code/modules/power/antimatter/computer.dm | 174 +- .../power/antimatter/containment_jar.dm | 82 +- code/modules/power/antimatter/control.dm | 658 +- code/modules/power/antimatter/engine.dm | 410 +- code/modules/power/antimatter/fuel.dm | 198 +- code/modules/power/antimatter/shielding.dm | 444 +- code/modules/power/apc.dm | 2484 ++--- code/modules/power/cable.dm | 1324 +-- code/modules/power/cell.dm | 366 +- code/modules/power/engine.dm | 46 +- code/modules/power/generator.dm | 414 +- code/modules/power/lighting.dm | 1566 +-- code/modules/power/port_gen.dm | 560 +- code/modules/power/power.dm | 738 +- code/modules/power/singularity/collector.dm | 302 +- .../power/singularity/containment_field.dm | 210 +- code/modules/power/singularity/emitter.dm | 578 +- .../power/singularity/field_generator.dm | 702 +- code/modules/power/singularity/generator.dm | 64 +- .../particle_accelerator/particle.dm | 208 +- .../particle_accelerator.dm | 830 +- .../particle_accelerator/particle_chamber.dm | 20 +- .../particle_accelerator/particle_control.dm | 462 +- .../particle_accelerator/particle_emitter.dm | 98 +- .../particle_accelerator/particle_power.dm | 20 +- code/modules/power/singularity/singularity.dm | 718 +- code/modules/power/smes.dm | 956 +- code/modules/power/solar.dm | 1038 +- code/modules/power/terminal.dm | 162 +- code/modules/power/tracker.dm | 186 +- code/modules/projectiles/ammunition.dm | 292 +- code/modules/projectiles/ammunition/boxes.dm | 414 +- .../modules/projectiles/ammunition/bullets.dm | 404 +- code/modules/projectiles/ammunition/energy.dm | 282 +- .../projectiles/ammunition/magazines.dm | 984 +- .../modules/projectiles/ammunition/special.dm | 86 +- code/modules/projectiles/firing.dm | 126 +- code/modules/projectiles/gun.dm | 446 +- code/modules/projectiles/guns/energy.dm | 180 +- code/modules/projectiles/guns/energy/laser.dm | 456 +- .../projectiles/guns/energy/nuclear.dm | 258 +- code/modules/projectiles/guns/energy/pulse.dm | 112 +- .../projectiles/guns/energy/special.dm | 728 +- code/modules/projectiles/guns/energy/stun.dm | 198 +- .../projectiles/guns/energy/temperature.dm | 24 +- code/modules/projectiles/guns/magic.dm | 140 +- code/modules/projectiles/guns/magic/staff.dm | 74 +- code/modules/projectiles/guns/projectile.dm | 210 +- .../projectiles/guns/projectile/automatic.dm | 992 +- .../projectiles/guns/projectile/pistol.dm | 564 +- .../projectiles/guns/projectile/revolver.dm | 510 +- .../projectiles/guns/projectile/shotgun.dm | 478 +- .../projectiles/guns/projectile/silencer.dm | 90 +- code/modules/projectiles/projectile.dm | 906 +- .../modules/projectiles/projectile/animate.dm | 32 +- code/modules/projectiles/projectile/beams.dm | 350 +- .../modules/projectiles/projectile/bullets.dm | 424 +- code/modules/projectiles/projectile/change.dm | 186 +- code/modules/projectiles/projectile/energy.dm | 172 +- code/modules/projectiles/projectile/magic.dm | 466 +- .../modules/projectiles/projectile/special.dm | 514 +- code/modules/reagents/Chemistry-Colours.dm | 130 +- code/modules/reagents/Chemistry-Holder.dm | 1226 +-- code/modules/reagents/Chemistry-Machinery.dm | 2822 +++--- code/modules/reagents/Chemistry-Readme.dm | 498 +- code/modules/reagents/Chemistry-Reagents.dm | 326 +- code/modules/reagents/Chemistry-Recipes.dm | 4870 ++++----- code/modules/reagents/grenade_launcher.dm | 114 +- code/modules/reagents/reagent_containers.dm | 200 +- .../reagents/reagent_containers/blood_pack.dm | 106 +- .../reagents/reagent_containers/borghydro.dm | 214 +- .../reagents/reagent_containers/dropper.dm | 238 +- .../reagents/reagent_containers/food.dm | 26 +- .../reagent_containers/food/condiment.dm | 386 +- .../reagent_containers/food/drinks.dm | 654 +- .../reagent_containers/food/drinks/bottle.dm | 766 +- .../food/drinks/drinkingglass.dm | 1130 +-- .../reagent_containers/food/drinks/jar.dm | 60 +- .../reagent_containers/food/snacks.dm | 8696 ++++++++--------- .../reagent_containers/food/snacks/grown.dm | 2164 ++-- .../reagent_containers/food/snacks/meat.dm | 122 +- .../reagent_containers/glass/bottle.dm | 1026 +- .../reagent_containers/glass/bottle/robot.dm | 62 +- .../reagents/reagent_containers/hypospray.dm | 168 +- .../reagents/reagent_containers/pill.dm | 588 +- .../reagent_containers/robodropper.dm | 196 +- .../reagents/reagent_containers/spray.dm | 776 +- .../reagents/reagent_containers/syringes.dm | 932 +- code/modules/reagents/reagent_dispenser.dm | 572 +- code/modules/reagents/syringe_gun.dm | 282 +- code/modules/recycling/conveyor2.dm | 722 +- .../recycling/disposal-construction.dm | 568 +- code/modules/recycling/disposal.dm | 2880 +++--- code/modules/recycling/sortingmachinery.dm | 630 +- code/modules/research/circuitprinter.dm | 272 +- code/modules/research/designs.dm | 5166 +++++----- code/modules/research/destructive_analyzer.dm | 196 +- code/modules/research/message_server.dm | 694 +- code/modules/research/protolathe.dm | 392 +- code/modules/research/rd-readme.dm | 478 +- code/modules/research/rdconsole.dm | 1934 ++-- code/modules/research/rdmachines.dm | 80 +- code/modules/research/research.dm | 602 +- code/modules/research/server.dm | 672 +- .../modules/research/xenoarchaeology/areas.dm | 152 +- .../xenoarchaeology/finds/finds_pipboy.dm | 562 +- .../research/xenoarchaeology/manuals.dm | 788 +- .../research/xenoarchaeology/readme.dm | 10 +- code/modules/virus2/analyser.dm | 132 +- code/modules/virus2/antibodies.dm | 102 +- code/modules/virus2/curer.dm | 208 +- code/modules/virus2/diseasesplicer.dm | 354 +- code/modules/virus2/dishincubator.dm | 476 +- code/modules/virus2/isolator.dm | 456 +- code/world.dm | 924 +- 872 files changed, 213798 insertions(+), 213792 deletions(-) diff --git a/.editorconfig b/.editorconfig index fda3f29c5d2f..2091f778773b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,7 @@ [*] insert_final_newline = false indent_style = tab -indent_size = 4 \ No newline at end of file +indent_size = 4 + +[*.dm] +end_of_line = lf diff --git a/.gitattributes b/.gitattributes index cba7def31aeb..1eb9dda13fbf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,3 +5,6 @@ # dmi icon merger hook # needs additional setup, see tools/dmitool/README.md *.dmi merge=merge-dmi + +# line endings +*.dm text eol=lf diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 80cbf5723bda..00bfbb7579e9 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -1,207 +1,207 @@ -//gets all subtypes of type -#define subtypesof(typepath) ( typesof(typepath) - typepath ) - -//number of deciseconds in a day -#define MIDNIGHT_ROLLOVER 864000 - -//singularity defines -#define STAGE_ONE 1 -#define STAGE_TWO 3 -#define STAGE_THREE 5 -#define STAGE_FOUR 7 -#define STAGE_FIVE 9 -#define STAGE_SIX 11 //From supermatter shard - -//Ghost orbit types: -#define GHOST_ORBIT_CIRCLE "circle" -#define GHOST_ORBIT_TRIANGLE "triangle" -#define GHOST_ORBIT_HEXAGON "hexagon" -#define GHOST_ORBIT_SQUARE "square" -#define GHOST_ORBIT_PENTAGON "pentagon" - -//zlevel defines, can be overriden for different maps in the appropriate _maps file. -#define ZLEVEL_STATION 1 -#define ZLEVEL_CENTCOMM 2 //EI NATH!! -#define ZLEVEL_CENTCOM 2 -#define ZLEVEL_TELECOMMS 3 -#define ZLEVEL_DERELICT 4 -#define ZLEVEL_ASTEROID 5 -#define ZLEVEL_EMPTY 6 - -#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level - -#define ENGINE_EJECT_Z 3 //Unused now - -//HUD styles. Please ensure HUD_VERSIONS is the same as the maximum index. Index order defines how they are cycled in F12. -#define HUD_STYLE_STANDARD 1 -#define HUD_STYLE_REDUCED 2 -#define HUD_STYLE_NOHUD 3 - -#define HUD_VERSIONS 3 //used in show_hud() -//1 = standard hud -//2 = reduced hud (just hands and intent switcher) -//3 = no hud (for screenshots) - -//ticker.current_state values -#define GAME_STATE_STARTUP 0 -#define GAME_STATE_PREGAME 1 -#define GAME_STATE_SETTING_UP 2 -#define GAME_STATE_PLAYING 3 -#define GAME_STATE_FINISHED 4 - -//Security levels -#define SEC_LEVEL_GREEN 0 -#define SEC_LEVEL_BLUE 1 -#define SEC_LEVEL_RED 2 -#define SEC_LEVEL_DELTA 3 - -#define ROUNDSTART_LOGOUT_REPORT_TIME 6000 //Amount of time (in deciseconds) after the rounds starts, that the player disconnect report is issued. - -// Doors! -#define DOOR_CRUSH_DAMAGE 10 - -#define FIREDOOR_MAX_PRESSURE_DIFF 25 // kPa - -#define FIREDOOR_MAX_TEMP 50 // °C -#define FIREDOOR_MIN_TEMP 0 - -#define FIREDOOR_ALERT_HOT 1 -#define FIREDOOR_ALERT_COLD 2 - - -//Germs and infection -#define GERM_LEVEL_AMBIENT 110 //maximum germ level you can reach by standing still -#define GERM_LEVEL_MOVE_CAP 200 //maximum germ level you can reach by running around - -#define INFECTION_LEVEL_ONE 100 -#define INFECTION_LEVEL_TWO 500 -#define INFECTION_LEVEL_THREE 1000 - -#define INFECTION_LEVEL_ONE_PLUS INFECTION_LEVEL_ONE + ( (INFECTION_LEVEL_TWO - INFECTION_LEVEL_ONE) * 1/3 ) -#define INFECTION_LEVEL_ONE_PLUS_PLUS INFECTION_LEVEL_ONE + ( (INFECTION_LEVEL_TWO - INFECTION_LEVEL_ONE) * 2/3 ) -#define INFECTION_LEVEL_TWO_PLUS INFECTION_LEVEL_TWO + ( (INFECTION_LEVEL_THREE - INFECTION_LEVEL_TWO) * 1/3 ) -#define INFECTION_LEVEL_TWO_PLUS_PLUS INFECTION_LEVEL_TWO + ( (INFECTION_LEVEL_THREE - INFECTION_LEVEL_TWO) * 2/3 ) - -//metal, glass, rod stacks -#define MAX_STACK_AMOUNT_METAL 50 -#define MAX_STACK_AMOUNT_GLASS 50 -#define MAX_STACK_AMOUNT_RODS 60 - -//some arbitrary defines to be used by self-pruning global lists. (see master_controller) -#define PROCESS_KILL 26 //Used to trigger removal from a processing list - -#define shuttle_time_in_station 1800 // 3 minutes in the station -#define shuttle_time_to_arrive 6000 // 10 minutes to arrive - -#define FOR_DVIEW(type, range, center, invis_flags) \ - dview_mob.loc = center; \ - dview_mob.see_invisible = invis_flags; \ - for(type in view(range, dview_mob)) -#define END_FOR_DVIEW dview_mob.loc = null - -//defines -#define RESIZE_DEFAULT_SIZE 1 - -//Just space -#define SPACE_ICON_STATE "[((x + y) ^ ~(x * y) + z) % 25]" - -//Material defines -#define MAT_METAL "$metal" -#define MAT_GLASS "$glass" -#define MAT_SILVER "$silver" -#define MAT_GOLD "$gold" -#define MAT_DIAMOND "$diamond" -#define MAT_URANIUM "$uranium" -#define MAT_PHORON "$phoron" -#define MAT_PLASTIC "$plastic" -#define MAT_BANANIUM "$bananium" - -#define COIN_STANDARD "Coin" -#define COIN_GOLD "Gold coin" -#define COIN_SILVER "Silver coin" -#define COIN_DIAMOND "Diamond coin" -#define COIN_IRON "Iron coin" -#define COIN_PHORON "Solid phoron coin" -#define COIN_URANIUM "Uranium coin" -#define COIN_BANANIUM "Bananium coin" -#define COIN_PLATINUM "Platunum coin" - -#define MINERAL_MATERIAL_AMOUNT 2000 -//The amount of materials you get from a sheet of mineral like iron/diamond/glass etc - -#define APC_MIN_TO_MALF_DECLARE 5 -//if malf apcs < than this, malf can't begin the takeover attempt - -#define APC_BONUS_WITH_INTERCEPT 4 -//If AI intercepts message, he can hack additional APC_BONUS_WITH_INTERCEPT APCs without attracting attention - -#define MALF_SMALL_MODULE_PRICE 10 -#define MALF_LARGE_MODULE_PRICE 50 -//Malf modules prices - -// Maploader bounds indices -#define MAP_MINX 1 -#define MAP_MINY 2 -#define MAP_MINZ 3 -#define MAP_MAXX 4 -#define MAP_MAXY 5 -#define MAP_MAXZ 6 - -// Bluespace shelter deploy checks -#define SHELTER_DEPLOY_ALLOWED "allowed" -#define SHELTER_DEPLOY_BAD_TURFS "bad turfs" -#define SHELTER_DEPLOY_BAD_AREA "bad area" -#define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects" - -// Cargo-related stuff. -#define MANIFEST_ERROR_CHANCE 5 -#define MANIFEST_ERROR_NAME 1 -#define MANIFEST_ERROR_CONTENTS 2 -#define MANIFEST_ERROR_ITEM 4 - - -//teleport checks -#define TELE_CHECK_NONE 0 -#define TELE_CHECK_TURFS 1 -#define TELE_CHECK_ALL 2 - -//get_turf(): Returns the turf that contains the atom. -//Example: A fork inside a box inside a locker will return the turf the locker is standing on. -#define get_turf(A) (get_step(A, 0)) - -// Door assembly states -#define ASSEMBLY_SECURED 0 -#define ASSEMBLY_WIRED 1 -#define ASSEMBLY_NEAR_FINISHED 2 - -//Wet floor states/severity -#define WATER_FLOOR 1 -#define LUBE_FLOOR 2 - -#define WORLD_ICON_SIZE 32 -#define PIXEL_MULTIPLIER WORLD_ICON_SIZE/32 - -// (Bay12 = -2), but we don't have that projectile code, so... -#define PROJECTILE_FORCE_MISS -1 - -#define COORD(A) "([A.x],[A.y],[A.z])" - -//Error handler defines -#define ERROR_USEFUL_LEN 2 - -//Filters -#define AMBIENT_OCCLUSION filter(type = "drop_shadow", x = 0, y = -2, size = 4, border = 4, color = "#04080FAA") - -#define CLIENT_FROM_VAR(I) (ismob(I) ? I:client : (istype(I, /client) ? I : (istype(I, /datum/mind) ? I:current?:client : null))) - -#define ENTITY_TAB "    " - -//world/proc/shelleo -#define SHELLEO_ERRORLEVEL 1 -#define SHELLEO_STDOUT 2 -#define SHELLEO_STDERR 3 - -//https://secure.byond.com/docs/ref/info.html#/atom/var/mouse_opacity -#define MOUSE_OPACITY_TRANSPARENT 0 -#define MOUSE_OPACITY_ICON 1 -#define MOUSE_OPACITY_OPAQUE 2 +//gets all subtypes of type +#define subtypesof(typepath) ( typesof(typepath) - typepath ) + +//number of deciseconds in a day +#define MIDNIGHT_ROLLOVER 864000 + +//singularity defines +#define STAGE_ONE 1 +#define STAGE_TWO 3 +#define STAGE_THREE 5 +#define STAGE_FOUR 7 +#define STAGE_FIVE 9 +#define STAGE_SIX 11 //From supermatter shard + +//Ghost orbit types: +#define GHOST_ORBIT_CIRCLE "circle" +#define GHOST_ORBIT_TRIANGLE "triangle" +#define GHOST_ORBIT_HEXAGON "hexagon" +#define GHOST_ORBIT_SQUARE "square" +#define GHOST_ORBIT_PENTAGON "pentagon" + +//zlevel defines, can be overriden for different maps in the appropriate _maps file. +#define ZLEVEL_STATION 1 +#define ZLEVEL_CENTCOMM 2 //EI NATH!! +#define ZLEVEL_CENTCOM 2 +#define ZLEVEL_TELECOMMS 3 +#define ZLEVEL_DERELICT 4 +#define ZLEVEL_ASTEROID 5 +#define ZLEVEL_EMPTY 6 + +#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level + +#define ENGINE_EJECT_Z 3 //Unused now + +//HUD styles. Please ensure HUD_VERSIONS is the same as the maximum index. Index order defines how they are cycled in F12. +#define HUD_STYLE_STANDARD 1 +#define HUD_STYLE_REDUCED 2 +#define HUD_STYLE_NOHUD 3 + +#define HUD_VERSIONS 3 //used in show_hud() +//1 = standard hud +//2 = reduced hud (just hands and intent switcher) +//3 = no hud (for screenshots) + +//ticker.current_state values +#define GAME_STATE_STARTUP 0 +#define GAME_STATE_PREGAME 1 +#define GAME_STATE_SETTING_UP 2 +#define GAME_STATE_PLAYING 3 +#define GAME_STATE_FINISHED 4 + +//Security levels +#define SEC_LEVEL_GREEN 0 +#define SEC_LEVEL_BLUE 1 +#define SEC_LEVEL_RED 2 +#define SEC_LEVEL_DELTA 3 + +#define ROUNDSTART_LOGOUT_REPORT_TIME 6000 //Amount of time (in deciseconds) after the rounds starts, that the player disconnect report is issued. + +// Doors! +#define DOOR_CRUSH_DAMAGE 10 + +#define FIREDOOR_MAX_PRESSURE_DIFF 25 // kPa + +#define FIREDOOR_MAX_TEMP 50 // °C +#define FIREDOOR_MIN_TEMP 0 + +#define FIREDOOR_ALERT_HOT 1 +#define FIREDOOR_ALERT_COLD 2 + + +//Germs and infection +#define GERM_LEVEL_AMBIENT 110 //maximum germ level you can reach by standing still +#define GERM_LEVEL_MOVE_CAP 200 //maximum germ level you can reach by running around + +#define INFECTION_LEVEL_ONE 100 +#define INFECTION_LEVEL_TWO 500 +#define INFECTION_LEVEL_THREE 1000 + +#define INFECTION_LEVEL_ONE_PLUS INFECTION_LEVEL_ONE + ( (INFECTION_LEVEL_TWO - INFECTION_LEVEL_ONE) * 1/3 ) +#define INFECTION_LEVEL_ONE_PLUS_PLUS INFECTION_LEVEL_ONE + ( (INFECTION_LEVEL_TWO - INFECTION_LEVEL_ONE) * 2/3 ) +#define INFECTION_LEVEL_TWO_PLUS INFECTION_LEVEL_TWO + ( (INFECTION_LEVEL_THREE - INFECTION_LEVEL_TWO) * 1/3 ) +#define INFECTION_LEVEL_TWO_PLUS_PLUS INFECTION_LEVEL_TWO + ( (INFECTION_LEVEL_THREE - INFECTION_LEVEL_TWO) * 2/3 ) + +//metal, glass, rod stacks +#define MAX_STACK_AMOUNT_METAL 50 +#define MAX_STACK_AMOUNT_GLASS 50 +#define MAX_STACK_AMOUNT_RODS 60 + +//some arbitrary defines to be used by self-pruning global lists. (see master_controller) +#define PROCESS_KILL 26 //Used to trigger removal from a processing list + +#define shuttle_time_in_station 1800 // 3 minutes in the station +#define shuttle_time_to_arrive 6000 // 10 minutes to arrive + +#define FOR_DVIEW(type, range, center, invis_flags) \ + dview_mob.loc = center; \ + dview_mob.see_invisible = invis_flags; \ + for(type in view(range, dview_mob)) +#define END_FOR_DVIEW dview_mob.loc = null + +//defines +#define RESIZE_DEFAULT_SIZE 1 + +//Just space +#define SPACE_ICON_STATE "[((x + y) ^ ~(x * y) + z) % 25]" + +//Material defines +#define MAT_METAL "$metal" +#define MAT_GLASS "$glass" +#define MAT_SILVER "$silver" +#define MAT_GOLD "$gold" +#define MAT_DIAMOND "$diamond" +#define MAT_URANIUM "$uranium" +#define MAT_PHORON "$phoron" +#define MAT_PLASTIC "$plastic" +#define MAT_BANANIUM "$bananium" + +#define COIN_STANDARD "Coin" +#define COIN_GOLD "Gold coin" +#define COIN_SILVER "Silver coin" +#define COIN_DIAMOND "Diamond coin" +#define COIN_IRON "Iron coin" +#define COIN_PHORON "Solid phoron coin" +#define COIN_URANIUM "Uranium coin" +#define COIN_BANANIUM "Bananium coin" +#define COIN_PLATINUM "Platunum coin" + +#define MINERAL_MATERIAL_AMOUNT 2000 +//The amount of materials you get from a sheet of mineral like iron/diamond/glass etc + +#define APC_MIN_TO_MALF_DECLARE 5 +//if malf apcs < than this, malf can't begin the takeover attempt + +#define APC_BONUS_WITH_INTERCEPT 4 +//If AI intercepts message, he can hack additional APC_BONUS_WITH_INTERCEPT APCs without attracting attention + +#define MALF_SMALL_MODULE_PRICE 10 +#define MALF_LARGE_MODULE_PRICE 50 +//Malf modules prices + +// Maploader bounds indices +#define MAP_MINX 1 +#define MAP_MINY 2 +#define MAP_MINZ 3 +#define MAP_MAXX 4 +#define MAP_MAXY 5 +#define MAP_MAXZ 6 + +// Bluespace shelter deploy checks +#define SHELTER_DEPLOY_ALLOWED "allowed" +#define SHELTER_DEPLOY_BAD_TURFS "bad turfs" +#define SHELTER_DEPLOY_BAD_AREA "bad area" +#define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects" + +// Cargo-related stuff. +#define MANIFEST_ERROR_CHANCE 5 +#define MANIFEST_ERROR_NAME 1 +#define MANIFEST_ERROR_CONTENTS 2 +#define MANIFEST_ERROR_ITEM 4 + + +//teleport checks +#define TELE_CHECK_NONE 0 +#define TELE_CHECK_TURFS 1 +#define TELE_CHECK_ALL 2 + +//get_turf(): Returns the turf that contains the atom. +//Example: A fork inside a box inside a locker will return the turf the locker is standing on. +#define get_turf(A) (get_step(A, 0)) + +// Door assembly states +#define ASSEMBLY_SECURED 0 +#define ASSEMBLY_WIRED 1 +#define ASSEMBLY_NEAR_FINISHED 2 + +//Wet floor states/severity +#define WATER_FLOOR 1 +#define LUBE_FLOOR 2 + +#define WORLD_ICON_SIZE 32 +#define PIXEL_MULTIPLIER WORLD_ICON_SIZE/32 + +// (Bay12 = -2), but we don't have that projectile code, so... +#define PROJECTILE_FORCE_MISS -1 + +#define COORD(A) "([A.x],[A.y],[A.z])" + +//Error handler defines +#define ERROR_USEFUL_LEN 2 + +//Filters +#define AMBIENT_OCCLUSION filter(type = "drop_shadow", x = 0, y = -2, size = 4, border = 4, color = "#04080FAA") + +#define CLIENT_FROM_VAR(I) (ismob(I) ? I:client : (istype(I, /client) ? I : (istype(I, /datum/mind) ? I:current?:client : null))) + +#define ENTITY_TAB "    " + +//world/proc/shelleo +#define SHELLEO_ERRORLEVEL 1 +#define SHELLEO_STDOUT 2 +#define SHELLEO_STDERR 3 + +//https://secure.byond.com/docs/ref/info.html#/atom/var/mouse_opacity +#define MOUSE_OPACITY_TRANSPARENT 0 +#define MOUSE_OPACITY_ICON 1 +#define MOUSE_OPACITY_OPAQUE 2 diff --git a/code/__HELPERS/files.dm b/code/__HELPERS/files.dm index c6d5dfbb1e26..5e0a3268dba1 100644 --- a/code/__HELPERS/files.dm +++ b/code/__HELPERS/files.dm @@ -1,60 +1,60 @@ -//checks if a file exists and contains text -//returns text as a string if these conditions are met -/proc/return_file_text(filename) - if(fexists(filename) == 0) - error("File not found ([filename])") - return - - var/text = file2text(filename) - if(!text) - error("File empty ([filename])") - return - - return text - -//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")) - 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) - 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 -#undef FTPDELAY +//checks if a file exists and contains text +//returns text as a string if these conditions are met +/proc/return_file_text(filename) + if(fexists(filename) == 0) + error("File not found ([filename])") + return + + var/text = file2text(filename) + if(!text) + error("File empty ([filename])") + return + + return text + +//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")) + 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) + 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 +#undef FTPDELAY diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index ae94fa3adbfa..3e134a32bf3e 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -1,616 +1,616 @@ -//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a -#define RANGE_TURFS(RADIUS, CENTER) \ - block( \ - locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \ - locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \ - ) - -/proc/dopage(src,target) - var/href_list - var/href - href_list = params2list("src=\ref[src]&[target]=1") - href = "src=\ref[src];[target]=1" - src:temphtml = null - src:Topic(href, href_list) - return null - -/proc/is_on_same_plane_or_station(z1, z2) - if(z1 == z2) - return 1 - if((z1 in config.station_levels) && (z2 in config.station_levels)) - return 1 - return 0 - -/proc/get_area_master(const/O) - var/area/A = get_area(O) - - if (isarea(A)) - return A - -/proc/get_area(O) - if(isarea(O)) - return O - var/turf/loc = get_turf(O) - if(loc) - var/area/res = loc.loc - . = res - -/proc/get_area_name(N) //get area by its name - for(var/area/A in all_areas) - if(A.name == N) - return A - return 0 - -/proc/in_range(source, user) - if(get_dist(source, user) <= 1) - return 1 - - return 0 //not in range and not telekinetic - -// Like view but bypasses luminosity check - -/proc/hear(range, atom/source) - - var/lum = source.luminosity - source.luminosity = 6 - - var/list/heard = view(range, source) - source.luminosity = lum - - return heard - -/proc/isStationLevel(level) - return level in config.station_levels - -/proc/isNotStationLevel(level) - return !isStationLevel(level) - -/proc/isPlayerLevel(level) - return level in config.player_levels - -/proc/isAdminLevel(level) - return level in config.admin_levels - -/proc/isNotAdminLevel(level) - return !isAdminLevel(level) - -/proc/circlerange(center=usr,radius=3) - - var/turf/centerturf = get_turf(center) - var/list/turfs = new/list() - var/rsq = radius * (radius+0.5) - - for(var/atom/T in range(radius, centerturf)) - var/dx = T.x - centerturf.x - var/dy = T.y - centerturf.y - if(dx*dx + dy*dy <= rsq) - turfs += T - - //turfs += centerturf - return turfs - -/proc/circleview(center=usr,radius=3) - - var/turf/centerturf = get_turf(center) - var/list/atoms = new/list() - var/rsq = radius * (radius+0.5) - - for(var/atom/A in view(radius, centerturf)) - var/dx = A.x - centerturf.x - var/dy = A.y - centerturf.y - if(dx*dx + dy*dy <= rsq) - atoms += A - - //turfs += centerturf - return atoms - -/proc/get_dist_euclidian(atom/Loc1,atom/Loc2) - var/dx = Loc1.x - Loc2.x - var/dy = Loc1.y - Loc2.y - - var/dist = sqrt(dx**2 + dy**2) - - return dist - -/proc/circlerangeturfs(center=usr,radius=3) - - var/turf/centerturf = get_turf(center) - var/list/turfs = new/list() - var/rsq = radius * (radius+0.5) - - for(var/turf/T in range(radius, centerturf)) - var/dx = T.x - centerturf.x - var/dy = T.y - centerturf.y - if(dx*dx + dy*dy <= rsq) - turfs += T - return turfs - -/proc/circleviewturfs(center=usr,radius=3) //Is there even a diffrence between this proc and circlerangeturfs()? - - var/turf/centerturf = get_turf(center) - var/list/turfs = new/list() - var/rsq = radius * (radius+0.5) - - for(var/turf/T in view(radius, centerturf)) - var/dx = T.x - centerturf.x - var/dy = T.y - centerturf.y - if(dx*dx + dy*dy <= rsq) - turfs += T - return turfs - - - -//var/debug_mob = 0 - -// Will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents. -// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects, -// being unable to hear people due to being in a box within a bag. - -/proc/recursive_mob_check(atom/O, list/L = list(), recursion_limit = 3, client_check = 1, sight_check = 1, include_radio = 1) - - //debug_mob += O.contents.len - if(!recursion_limit) - return L - for(var/atom/A in O.contents) - - if(ismob(A)) - var/mob/M = A - if(client_check && !M.client) - L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) - continue - if(sight_check && !isInSight(A, O)) - continue - L |= M - //world.log << "[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])" - - else if(include_radio && istype(A, /obj/item/device/radio)) - if(sight_check && !isInSight(A, O)) - continue - L |= A - - if(isobj(A) || ismob(A)) - L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) - return L - -// The old system would loop through lists for a total of 5000 per function call, in an empty server. -// This new system will loop at around 1000 in an empty server. - -/proc/get_mobs_in_view(R, atom/source) - // Returns a list of mobs in range of R from source. Used in radio and say code. - - var/turf/T = get_turf(source) - var/list/hear = list() - - if(!T) - return hear - - var/list/range = hear(R, T) - - for(var/atom/A in range) - if(ismob(A)) - var/mob/M = A - if(M.client) - hear += M - //world.log << "Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])" - else if(istype(A, /obj/item/device/radio)) - hear += A - - if(isobj(A) || ismob(A)) - hear |= recursive_mob_check(A, hear, 3, 1, 0, 1) - - return hear - - -/proc/get_hearers_in_view(R, atom/source) - // Returns a list of hearers in view(R) from source (ignoring luminosity). Used in saycode. - var/turf/T = get_turf(source) - var/list/hear = list() - - if(!T) - return hear - - var/lum = T.luminosity - T.luminosity = 6 - hear = get_mobs_in_view(R, T) - T.luminosity = lum - return hear - - -/proc/get_mobs_in_radio_ranges(list/obj/item/device/radio/radios) - - //set background = 1 - - . = list() - // Returns a list of mobs who can hear any of the radios given in @radios - var/list/speaker_coverage = list() - for(var/obj/item/device/radio/R in radios) - if(R) - //Cyborg checks. Receiving message uses a bit of cyborg's charge. - var/obj/item/device/radio/borg/BR = R - if(istype(BR) && BR.myborg) - var/mob/living/silicon/robot/borg = BR.myborg - var/datum/robot_component/CO = borg.get_component("radio") - if(!CO) - continue //No radio component (Shouldn't happen) - if(!borg.is_component_functioning("radio") || !borg.cell_use_power(CO.active_usage)) - continue //No power. - - var/turf/speaker = get_turf(R) - if(speaker) - for(var/turf/T in hear(R.canhear_range,speaker)) - speaker_coverage[T] = T - - - // Try to find all the players who can hear the message - for(var/i = 1; i <= player_list.len; i++) - var/mob/M = player_list[i] - if(M) - var/turf/ear = get_turf(M) - if(ear) - // Ghostship is magic: Ghosts can hear radio chatter from anywhere - if(speaker_coverage[ear] || (istype(M, /mob/dead/observer) && (M.client) && (M.client.prefs.chat_toggles & CHAT_GHOSTRADIO))) - . |= M // Since we're already looping through mobs, why bother using |= ? This only slows things down. - return . - -/atom/movable/proc/get_mob() - return - -/obj/machinery/bot/mulebot/get_mob() - if(load && istype(load, /mob/living)) - return load - -/obj/mecha/get_mob() - return occupant - -/mob/get_mob() - return src - -/proc/mobs_in_view(range, source) - var/list/mobs = list() - for(var/atom/movable/AM in view(range, source)) - var/M = AM.get_mob() - if(M) - mobs += M - - return mobs - -#define SIGN(X) ((X<0)?-1:1) - -proc - inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5) - var/turf/T - if(X1==X2) - if(Y1==Y2) - return 1 //Light cannot be blocked on same tile - else - var/s = SIGN(Y2-Y1) - Y1+=s - while(Y1!=Y2) - T=locate(X1,Y1,Z) - if(T.opacity) - return 0 - Y1+=s - else - var/m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1)) - var/b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles - var/signX = SIGN(X2-X1) - var/signY = SIGN(Y2-Y1) - if(X1 abs (dx)) //slope is above 1:1 (move horizontally in a tie) - if(dy > 0) - return get_step(start, SOUTH) - else - return get_step(start, NORTH) - else - if(dx > 0) - return get_step(start, WEST) - else - return get_step(start, EAST) - -/proc/try_move_adjacent(atom/movable/AM) - var/turf/T = get_turf(AM) - for(var/direction in cardinal) - if(AM.Move(get_step(T, direction))) - break - -/proc/get_mob_by_key(key) - for(var/mob/M in mob_list) - if(M.ckey == lowertext(key)) - return M - return null - - -// Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer. -/proc/get_active_candidates(buffer = 1) - - var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn - var/i = 0 - while(candidates.len <= 0 && i < 5) - for(var/mob/dead/observer/G in player_list) - if(((G.client.inactivity/10)/60) <= buffer + i) // the most active players are more likely to become an alien - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - candidates += G.key - i++ - return candidates - -// Same as above but for alien candidates. - -/proc/get_alien_candidates() - - var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn - var/i = 0 - while(candidates.len <= 0 && i < 5) - for(var/mob/dead/observer/G in player_list) - if(ROLE_ALIEN in G.client.prefs.be_role) - if(((G.client.inactivity/10)/60) <= ALIEN_SELECT_AFK_BUFFER + i) // the most active players are more likely to become an alien - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - candidates += G.key - i++ - return candidates - -/proc/get_candidates(be_role_type, afk_bracket=3000) //Get candidates for Blob - var/list/candidates = list() - // Keep looping until we find a non-afk candidate within the time bracket (we limit the bracket to 10 minutes (6000)) - while(!candidates.len && afk_bracket < 6000) - for(var/mob/dead/observer/G in player_list) - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - if(!G.client.is_afk(afk_bracket) && (be_role_type in G.client.prefs.be_role)) - candidates += G.client - afk_bracket += 600 // Add a minute to the bracket, for every attempt - return candidates - -/proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480) - if(!isobj(O)) O = new /obj/screen/text() - O.maptext = maptext - O.maptext_height = maptext_height - O.maptext_width = maptext_width - O.screen_loc = screen_loc - return O - -/proc/Show2Group4Delay(obj/O, list/group, delay=0) - if(!isobj(O)) return - if(!group) group = clients - for(var/client/C in group) - C.screen += O - if(delay) - spawn(delay) - for(var/client/C in group) - C.screen -= O - -/datum/projectile_data - var/src_x - var/src_y - var/time - var/distance - var/power_x - var/power_y - var/dest_x - var/dest_y - -/datum/projectile_data/New(var/src_x, var/src_y, var/time, var/distance, \ - var/power_x, var/power_y, var/dest_x, var/dest_y) - src.src_x = src_x - src.src_y = src_y - src.time = time - src.distance = distance - src.power_x = power_x - src.power_y = power_y - src.dest_x = dest_x - src.dest_y = dest_y - -/proc/projectile_trajectory(src_x, src_y, rotation, angle, power) - - // returns the destination (Vx,y) that a projectile shot at [src_x], [src_y], with an angle of [angle], - // rotated at [rotation] and with the power of [power] - // Thanks to VistaPOWA for this function - - var/power_x = power * cos(angle) - var/power_y = power * sin(angle) - var/time = 2* power_y / 10 //10 = g - - var/distance = time * power_x - - var/dest_x = src_x + distance*sin(rotation); - var/dest_y = src_y + distance*cos(rotation); - - return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y) - -/proc/GetRedPart(const/hexa) - return hex2num(copytext(hexa,2,4)) - -/proc/GetGreenPart(const/hexa) - return hex2num(copytext(hexa,4,6)) - -/proc/GetBluePart(const/hexa) - return hex2num(copytext(hexa,6,8)) - -/proc/GetHexColors(const/hexa) - return list( - GetRedPart(hexa), - GetGreenPart(hexa), - GetBluePart(hexa) - ) - -/proc/MixColors(const/list/colors) - var/list/reds = list() - var/list/blues = list() - var/list/greens = list() - var/list/weights = list() - - for (var/i = 0, ++i <= colors.len) - reds.Add(GetRedPart(colors[i])) - blues.Add(GetBluePart(colors[i])) - greens.Add(GetGreenPart(colors[i])) - weights.Add(1) - - var/r = mixOneColor(weights, reds) - var/g = mixOneColor(weights, greens) - var/b = mixOneColor(weights, blues) - return rgb(r,g,b) - -/proc/random_color() - var/list/rand = list("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f") - return "#" + pick(rand) + pick(rand) + pick(rand) + pick(rand) + pick(rand) + pick(rand) - -/proc/noob_notify(mob/M) - //todo: check db before - if(!M.client) - return - if(M.client.holder) - return - if(M.client.player_age == 0) - var/player_assigned_role = (M.mind.assigned_role ? " ([M.mind.assigned_role])" : "") - var/player_byond_profile = "http://www.byond.com/members/[M.ckey]" - - var/msg = {"New player notify - Player '[M.ckey]' joined to the game as [M.mind.name][player_assigned_role] [ADMIN_FLW(M)] [ADMIN_PP(M)] [ADMIN_VV(M)] - Byond profile: open"} - - message_admins(msg) - -// Better get_dir proc -/proc/get_general_dir(atom/Loc1, atom/Loc2) - var/dir = get_dir(Loc1, Loc2) - switch(dir) - if(NORTH, EAST, SOUTH, WEST) - return dir - - if(NORTHEAST, SOUTHWEST) - var/abs_x = abs(Loc2.x - Loc1.x) - var/abs_y = abs(Loc2.y - Loc1.y) - - if(abs_y > (2*abs_x)) - return turn(dir,45) - else if(abs_x > (2*abs_y)) - return turn(dir,-45) - else - return dir - - if(NORTHWEST, SOUTHEAST) - var/abs_x = abs(Loc2.x - Loc1.x) - var/abs_y = abs(Loc2.y - Loc1.y) - - if(abs_y > (2*abs_x)) - return turn(dir,-45) - else if(abs_x > (2*abs_y)) - return turn(dir,45) - else - return dir - -//============VG PORTS============ -/proc/recursive_type_check(atom/O, type = /atom) - var/list/processing_list = list(O) - var/list/processed_list = new/list() - var/found_atoms = new/list() - - while (processing_list.len) - var/atom/A = processing_list[1] - - if (istype(A, type)) - found_atoms |= A - - for (var/atom/B in A) - if (!processed_list[B]) - processing_list |= B - - processing_list.Cut(1, 2) - processed_list[A] = A - - return found_atoms - -/proc/get_contents_in_object(atom/O, type_path = /atom/movable) - if (O) - return recursive_type_check(O, type_path) - O - else - return new/list() - -//============TG PORTS============ -/proc/flick_overlay(image/I, list/show_to, duration) - for(var/client/C in show_to) - C.images += I - spawn(duration) - for(var/client/C in show_to) - C.images -= I - - -//============Bay12 atmos============= -/proc/convert_k2c(temp) - return ((temp - T0C)) - -/proc/convert_c2k(temp) - return ((temp + T0C)) - -/proc/getCardinalAirInfo(turf/loc, 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)) - var/list/rstats = new /list(stats.len) - if(T && istype(T) && T.zone) - var/datum/gas_mixture/environment = T.return_air() - for(var/i in 1 to stats.len) - if(stats[i] == "pressure") - rstats[i] = environment.return_pressure() - else - 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 in 1 to stats.len) - if(stats[i] == "pressure") - rstats[i] = environment.return_pressure() - else - rstats[i] = environment.vars[stats[i]] - temps[direction] = rstats - return temps +//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a +#define RANGE_TURFS(RADIUS, CENTER) \ + block( \ + locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \ + locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \ + ) + +/proc/dopage(src,target) + var/href_list + var/href + href_list = params2list("src=\ref[src]&[target]=1") + href = "src=\ref[src];[target]=1" + src:temphtml = null + src:Topic(href, href_list) + return null + +/proc/is_on_same_plane_or_station(z1, z2) + if(z1 == z2) + return 1 + if((z1 in config.station_levels) && (z2 in config.station_levels)) + return 1 + return 0 + +/proc/get_area_master(const/O) + var/area/A = get_area(O) + + if (isarea(A)) + return A + +/proc/get_area(O) + if(isarea(O)) + return O + var/turf/loc = get_turf(O) + if(loc) + var/area/res = loc.loc + . = res + +/proc/get_area_name(N) //get area by its name + for(var/area/A in all_areas) + if(A.name == N) + return A + return 0 + +/proc/in_range(source, user) + if(get_dist(source, user) <= 1) + return 1 + + return 0 //not in range and not telekinetic + +// Like view but bypasses luminosity check + +/proc/hear(range, atom/source) + + var/lum = source.luminosity + source.luminosity = 6 + + var/list/heard = view(range, source) + source.luminosity = lum + + return heard + +/proc/isStationLevel(level) + return level in config.station_levels + +/proc/isNotStationLevel(level) + return !isStationLevel(level) + +/proc/isPlayerLevel(level) + return level in config.player_levels + +/proc/isAdminLevel(level) + return level in config.admin_levels + +/proc/isNotAdminLevel(level) + return !isAdminLevel(level) + +/proc/circlerange(center=usr,radius=3) + + var/turf/centerturf = get_turf(center) + var/list/turfs = new/list() + var/rsq = radius * (radius+0.5) + + for(var/atom/T in range(radius, centerturf)) + var/dx = T.x - centerturf.x + var/dy = T.y - centerturf.y + if(dx*dx + dy*dy <= rsq) + turfs += T + + //turfs += centerturf + return turfs + +/proc/circleview(center=usr,radius=3) + + var/turf/centerturf = get_turf(center) + var/list/atoms = new/list() + var/rsq = radius * (radius+0.5) + + for(var/atom/A in view(radius, centerturf)) + var/dx = A.x - centerturf.x + var/dy = A.y - centerturf.y + if(dx*dx + dy*dy <= rsq) + atoms += A + + //turfs += centerturf + return atoms + +/proc/get_dist_euclidian(atom/Loc1,atom/Loc2) + var/dx = Loc1.x - Loc2.x + var/dy = Loc1.y - Loc2.y + + var/dist = sqrt(dx**2 + dy**2) + + return dist + +/proc/circlerangeturfs(center=usr,radius=3) + + var/turf/centerturf = get_turf(center) + var/list/turfs = new/list() + var/rsq = radius * (radius+0.5) + + for(var/turf/T in range(radius, centerturf)) + var/dx = T.x - centerturf.x + var/dy = T.y - centerturf.y + if(dx*dx + dy*dy <= rsq) + turfs += T + return turfs + +/proc/circleviewturfs(center=usr,radius=3) //Is there even a diffrence between this proc and circlerangeturfs()? + + var/turf/centerturf = get_turf(center) + var/list/turfs = new/list() + var/rsq = radius * (radius+0.5) + + for(var/turf/T in view(radius, centerturf)) + var/dx = T.x - centerturf.x + var/dy = T.y - centerturf.y + if(dx*dx + dy*dy <= rsq) + turfs += T + return turfs + + + +//var/debug_mob = 0 + +// Will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents. +// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects, +// being unable to hear people due to being in a box within a bag. + +/proc/recursive_mob_check(atom/O, list/L = list(), recursion_limit = 3, client_check = 1, sight_check = 1, include_radio = 1) + + //debug_mob += O.contents.len + if(!recursion_limit) + return L + for(var/atom/A in O.contents) + + if(ismob(A)) + var/mob/M = A + if(client_check && !M.client) + L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) + continue + if(sight_check && !isInSight(A, O)) + continue + L |= M + //world.log << "[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])" + + else if(include_radio && istype(A, /obj/item/device/radio)) + if(sight_check && !isInSight(A, O)) + continue + L |= A + + if(isobj(A) || ismob(A)) + L |= recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio) + return L + +// The old system would loop through lists for a total of 5000 per function call, in an empty server. +// This new system will loop at around 1000 in an empty server. + +/proc/get_mobs_in_view(R, atom/source) + // Returns a list of mobs in range of R from source. Used in radio and say code. + + var/turf/T = get_turf(source) + var/list/hear = list() + + if(!T) + return hear + + var/list/range = hear(R, T) + + for(var/atom/A in range) + if(ismob(A)) + var/mob/M = A + if(M.client) + hear += M + //world.log << "Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])" + else if(istype(A, /obj/item/device/radio)) + hear += A + + if(isobj(A) || ismob(A)) + hear |= recursive_mob_check(A, hear, 3, 1, 0, 1) + + return hear + + +/proc/get_hearers_in_view(R, atom/source) + // Returns a list of hearers in view(R) from source (ignoring luminosity). Used in saycode. + var/turf/T = get_turf(source) + var/list/hear = list() + + if(!T) + return hear + + var/lum = T.luminosity + T.luminosity = 6 + hear = get_mobs_in_view(R, T) + T.luminosity = lum + return hear + + +/proc/get_mobs_in_radio_ranges(list/obj/item/device/radio/radios) + + //set background = 1 + + . = list() + // Returns a list of mobs who can hear any of the radios given in @radios + var/list/speaker_coverage = list() + for(var/obj/item/device/radio/R in radios) + if(R) + //Cyborg checks. Receiving message uses a bit of cyborg's charge. + var/obj/item/device/radio/borg/BR = R + if(istype(BR) && BR.myborg) + var/mob/living/silicon/robot/borg = BR.myborg + var/datum/robot_component/CO = borg.get_component("radio") + if(!CO) + continue //No radio component (Shouldn't happen) + if(!borg.is_component_functioning("radio") || !borg.cell_use_power(CO.active_usage)) + continue //No power. + + var/turf/speaker = get_turf(R) + if(speaker) + for(var/turf/T in hear(R.canhear_range,speaker)) + speaker_coverage[T] = T + + + // Try to find all the players who can hear the message + for(var/i = 1; i <= player_list.len; i++) + var/mob/M = player_list[i] + if(M) + var/turf/ear = get_turf(M) + if(ear) + // Ghostship is magic: Ghosts can hear radio chatter from anywhere + if(speaker_coverage[ear] || (istype(M, /mob/dead/observer) && (M.client) && (M.client.prefs.chat_toggles & CHAT_GHOSTRADIO))) + . |= M // Since we're already looping through mobs, why bother using |= ? This only slows things down. + return . + +/atom/movable/proc/get_mob() + return + +/obj/machinery/bot/mulebot/get_mob() + if(load && istype(load, /mob/living)) + return load + +/obj/mecha/get_mob() + return occupant + +/mob/get_mob() + return src + +/proc/mobs_in_view(range, source) + var/list/mobs = list() + for(var/atom/movable/AM in view(range, source)) + var/M = AM.get_mob() + if(M) + mobs += M + + return mobs + +#define SIGN(X) ((X<0)?-1:1) + +proc + inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5) + var/turf/T + if(X1==X2) + if(Y1==Y2) + return 1 //Light cannot be blocked on same tile + else + var/s = SIGN(Y2-Y1) + Y1+=s + while(Y1!=Y2) + T=locate(X1,Y1,Z) + if(T.opacity) + return 0 + Y1+=s + else + var/m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1)) + var/b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles + var/signX = SIGN(X2-X1) + var/signY = SIGN(Y2-Y1) + if(X1 abs (dx)) //slope is above 1:1 (move horizontally in a tie) + if(dy > 0) + return get_step(start, SOUTH) + else + return get_step(start, NORTH) + else + if(dx > 0) + return get_step(start, WEST) + else + return get_step(start, EAST) + +/proc/try_move_adjacent(atom/movable/AM) + var/turf/T = get_turf(AM) + for(var/direction in cardinal) + if(AM.Move(get_step(T, direction))) + break + +/proc/get_mob_by_key(key) + for(var/mob/M in mob_list) + if(M.ckey == lowertext(key)) + return M + return null + + +// Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer. +/proc/get_active_candidates(buffer = 1) + + var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn + var/i = 0 + while(candidates.len <= 0 && i < 5) + for(var/mob/dead/observer/G in player_list) + if(((G.client.inactivity/10)/60) <= buffer + i) // the most active players are more likely to become an alien + if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) + candidates += G.key + i++ + return candidates + +// Same as above but for alien candidates. + +/proc/get_alien_candidates() + + var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn + var/i = 0 + while(candidates.len <= 0 && i < 5) + for(var/mob/dead/observer/G in player_list) + if(ROLE_ALIEN in G.client.prefs.be_role) + if(((G.client.inactivity/10)/60) <= ALIEN_SELECT_AFK_BUFFER + i) // the most active players are more likely to become an alien + if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) + candidates += G.key + i++ + return candidates + +/proc/get_candidates(be_role_type, afk_bracket=3000) //Get candidates for Blob + var/list/candidates = list() + // Keep looping until we find a non-afk candidate within the time bracket (we limit the bracket to 10 minutes (6000)) + while(!candidates.len && afk_bracket < 6000) + for(var/mob/dead/observer/G in player_list) + if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) + if(!G.client.is_afk(afk_bracket) && (be_role_type in G.client.prefs.be_role)) + candidates += G.client + afk_bracket += 600 // Add a minute to the bracket, for every attempt + return candidates + +/proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480) + if(!isobj(O)) O = new /obj/screen/text() + O.maptext = maptext + O.maptext_height = maptext_height + O.maptext_width = maptext_width + O.screen_loc = screen_loc + return O + +/proc/Show2Group4Delay(obj/O, list/group, delay=0) + if(!isobj(O)) return + if(!group) group = clients + for(var/client/C in group) + C.screen += O + if(delay) + spawn(delay) + for(var/client/C in group) + C.screen -= O + +/datum/projectile_data + var/src_x + var/src_y + var/time + var/distance + var/power_x + var/power_y + var/dest_x + var/dest_y + +/datum/projectile_data/New(var/src_x, var/src_y, var/time, var/distance, \ + var/power_x, var/power_y, var/dest_x, var/dest_y) + src.src_x = src_x + src.src_y = src_y + src.time = time + src.distance = distance + src.power_x = power_x + src.power_y = power_y + src.dest_x = dest_x + src.dest_y = dest_y + +/proc/projectile_trajectory(src_x, src_y, rotation, angle, power) + + // returns the destination (Vx,y) that a projectile shot at [src_x], [src_y], with an angle of [angle], + // rotated at [rotation] and with the power of [power] + // Thanks to VistaPOWA for this function + + var/power_x = power * cos(angle) + var/power_y = power * sin(angle) + var/time = 2* power_y / 10 //10 = g + + var/distance = time * power_x + + var/dest_x = src_x + distance*sin(rotation); + var/dest_y = src_y + distance*cos(rotation); + + return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y) + +/proc/GetRedPart(const/hexa) + return hex2num(copytext(hexa,2,4)) + +/proc/GetGreenPart(const/hexa) + return hex2num(copytext(hexa,4,6)) + +/proc/GetBluePart(const/hexa) + return hex2num(copytext(hexa,6,8)) + +/proc/GetHexColors(const/hexa) + return list( + GetRedPart(hexa), + GetGreenPart(hexa), + GetBluePart(hexa) + ) + +/proc/MixColors(const/list/colors) + var/list/reds = list() + var/list/blues = list() + var/list/greens = list() + var/list/weights = list() + + for (var/i = 0, ++i <= colors.len) + reds.Add(GetRedPart(colors[i])) + blues.Add(GetBluePart(colors[i])) + greens.Add(GetGreenPart(colors[i])) + weights.Add(1) + + var/r = mixOneColor(weights, reds) + var/g = mixOneColor(weights, greens) + var/b = mixOneColor(weights, blues) + return rgb(r,g,b) + +/proc/random_color() + var/list/rand = list("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f") + return "#" + pick(rand) + pick(rand) + pick(rand) + pick(rand) + pick(rand) + pick(rand) + +/proc/noob_notify(mob/M) + //todo: check db before + if(!M.client) + return + if(M.client.holder) + return + if(M.client.player_age == 0) + var/player_assigned_role = (M.mind.assigned_role ? " ([M.mind.assigned_role])" : "") + var/player_byond_profile = "http://www.byond.com/members/[M.ckey]" + + var/msg = {"New player notify + Player '[M.ckey]' joined to the game as [M.mind.name][player_assigned_role] [ADMIN_FLW(M)] [ADMIN_PP(M)] [ADMIN_VV(M)] + Byond profile: open"} + + message_admins(msg) + +// Better get_dir proc +/proc/get_general_dir(atom/Loc1, atom/Loc2) + var/dir = get_dir(Loc1, Loc2) + switch(dir) + if(NORTH, EAST, SOUTH, WEST) + return dir + + if(NORTHEAST, SOUTHWEST) + var/abs_x = abs(Loc2.x - Loc1.x) + var/abs_y = abs(Loc2.y - Loc1.y) + + if(abs_y > (2*abs_x)) + return turn(dir,45) + else if(abs_x > (2*abs_y)) + return turn(dir,-45) + else + return dir + + if(NORTHWEST, SOUTHEAST) + var/abs_x = abs(Loc2.x - Loc1.x) + var/abs_y = abs(Loc2.y - Loc1.y) + + if(abs_y > (2*abs_x)) + return turn(dir,-45) + else if(abs_x > (2*abs_y)) + return turn(dir,45) + else + return dir + +//============VG PORTS============ +/proc/recursive_type_check(atom/O, type = /atom) + var/list/processing_list = list(O) + var/list/processed_list = new/list() + var/found_atoms = new/list() + + while (processing_list.len) + var/atom/A = processing_list[1] + + if (istype(A, type)) + found_atoms |= A + + for (var/atom/B in A) + if (!processed_list[B]) + processing_list |= B + + processing_list.Cut(1, 2) + processed_list[A] = A + + return found_atoms + +/proc/get_contents_in_object(atom/O, type_path = /atom/movable) + if (O) + return recursive_type_check(O, type_path) - O + else + return new/list() + +//============TG PORTS============ +/proc/flick_overlay(image/I, list/show_to, duration) + for(var/client/C in show_to) + C.images += I + spawn(duration) + for(var/client/C in show_to) + C.images -= I + + +//============Bay12 atmos============= +/proc/convert_k2c(temp) + return ((temp - T0C)) + +/proc/convert_c2k(temp) + return ((temp + T0C)) + +/proc/getCardinalAirInfo(turf/loc, 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)) + var/list/rstats = new /list(stats.len) + if(T && istype(T) && T.zone) + var/datum/gas_mixture/environment = T.return_air() + for(var/i in 1 to stats.len) + if(stats[i] == "pressure") + rstats[i] = environment.return_pressure() + else + 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 in 1 to stats.len) + if(stats[i] == "pressure") + rstats[i] = environment.return_pressure() + else + rstats[i] = environment.vars[stats[i]] + temps[direction] = rstats + return temps diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 646fdcfbc83a..d6ec87bdeb32 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -1,96 +1,96 @@ -////////////////////////// -/////Initial Building///// -////////////////////////// - -/proc/make_datum_references_lists() - //Hair - Initialise all /datum/sprite_accessory/hair into an list indexed by hair-style name - for(var/path in subtypesof(/datum/sprite_accessory/hair)) - var/datum/sprite_accessory/hair/H = new path() - hair_styles_list[H.name] = H - switch(H.gender) - if(MALE) hair_styles_male_list += H.name - if(FEMALE) hair_styles_female_list += H.name - else - hair_styles_male_list += H.name - hair_styles_female_list += H.name - - //Facial Hair - Initialise all /datum/sprite_accessory/facial_hair into an list indexed by facialhair-style name - for(var/path in subtypesof(/datum/sprite_accessory/facial_hair)) - var/datum/sprite_accessory/facial_hair/H = new path() - facial_hair_styles_list[H.name] = H - switch(H.gender) - if(MALE) facial_hair_styles_male_list += H.name - if(FEMALE) facial_hair_styles_female_list += H.name - else - facial_hair_styles_male_list += H.name - facial_hair_styles_female_list += H.name - - //Surgery Steps - Initialize all /datum/surgery_step into a list - for(var/T in subtypesof(/datum/surgery_step)) - var/datum/surgery_step/S = new T - surgery_steps += S - sort_surgeries() - - init_subtypes(/datum/crafting_recipe, crafting_recipes) - - //Medical side effects. List all effects by their names - for(var/T in subtypesof(/datum/medical_effect)) - var/datum/medical_effect/M = new T - side_effects[M.name] = T - - //List of job. I can't believe this was calculated multiple times per tick! - for(var/T in (subtypesof(/datum/job) - list(/datum/job/ai,/datum/job/cyborg))) - var/datum/job/J = new T - joblist[J.title] = J - - //Languages and species. - for(var/T in subtypesof(/datum/language)) - var/datum/language/L = new T - all_languages[L.name] = L - - for(var/language_name in all_languages) - var/datum/language/L = all_languages[language_name] - for(var/key in L.key) - language_keys[":[lowertext_(key)]"] = L - - var/rkey = 0 - for(var/T in subtypesof(/datum/species)) - rkey++ - var/datum/species/S = new T - S.race_key = rkey //Used in mob icon caching. - all_species[S.name] = S - - if(S.flags[IS_WHITELISTED]) - whitelisted_species += S.name - -/* // 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, .) -*/ - -//creates every subtype of prototype (excluding prototype) and adds it to list L. -//if no list/L is provided, one is created. -/proc/init_subtypes(prototype, list/L) - if(!istype(L)) - L = list() - for(var/path in subtypesof(prototype)) - L += new path() - return L - -//returns a list of paths to every subtype of prototype (excluding prototype) -//if no list/L is provided, one is created. -/proc/init_paths(prototype, list/L) - if(!istype(L)) - L = list() - for(var/path in typesof(prototype)) - if(path == prototype) - continue - L+= path - return L +////////////////////////// +/////Initial Building///// +////////////////////////// + +/proc/make_datum_references_lists() + //Hair - Initialise all /datum/sprite_accessory/hair into an list indexed by hair-style name + for(var/path in subtypesof(/datum/sprite_accessory/hair)) + var/datum/sprite_accessory/hair/H = new path() + hair_styles_list[H.name] = H + switch(H.gender) + if(MALE) hair_styles_male_list += H.name + if(FEMALE) hair_styles_female_list += H.name + else + hair_styles_male_list += H.name + hair_styles_female_list += H.name + + //Facial Hair - Initialise all /datum/sprite_accessory/facial_hair into an list indexed by facialhair-style name + for(var/path in subtypesof(/datum/sprite_accessory/facial_hair)) + var/datum/sprite_accessory/facial_hair/H = new path() + facial_hair_styles_list[H.name] = H + switch(H.gender) + if(MALE) facial_hair_styles_male_list += H.name + if(FEMALE) facial_hair_styles_female_list += H.name + else + facial_hair_styles_male_list += H.name + facial_hair_styles_female_list += H.name + + //Surgery Steps - Initialize all /datum/surgery_step into a list + for(var/T in subtypesof(/datum/surgery_step)) + var/datum/surgery_step/S = new T + surgery_steps += S + sort_surgeries() + + init_subtypes(/datum/crafting_recipe, crafting_recipes) + + //Medical side effects. List all effects by their names + for(var/T in subtypesof(/datum/medical_effect)) + var/datum/medical_effect/M = new T + side_effects[M.name] = T + + //List of job. I can't believe this was calculated multiple times per tick! + for(var/T in (subtypesof(/datum/job) - list(/datum/job/ai,/datum/job/cyborg))) + var/datum/job/J = new T + joblist[J.title] = J + + //Languages and species. + for(var/T in subtypesof(/datum/language)) + var/datum/language/L = new T + all_languages[L.name] = L + + for(var/language_name in all_languages) + var/datum/language/L = all_languages[language_name] + for(var/key in L.key) + language_keys[":[lowertext_(key)]"] = L + + var/rkey = 0 + for(var/T in subtypesof(/datum/species)) + rkey++ + var/datum/species/S = new T + S.race_key = rkey //Used in mob icon caching. + all_species[S.name] = S + + if(S.flags[IS_WHITELISTED]) + whitelisted_species += S.name + +/* // 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, .) +*/ + +//creates every subtype of prototype (excluding prototype) and adds it to list L. +//if no list/L is provided, one is created. +/proc/init_subtypes(prototype, list/L) + if(!istype(L)) + L = list() + for(var/path in subtypesof(prototype)) + L += new path() + return L + +//returns a list of paths to every subtype of prototype (excluding prototype) +//if no list/L is provided, one is created. +/proc/init_paths(prototype, list/L) + if(!istype(L)) + L = list() + for(var/path in typesof(prototype)) + if(path == prototype) + continue + L+= path + return L diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 7103ca37858c..2e0783873385 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1,888 +1,888 @@ -/* -IconProcs README - -A BYOND library for manipulating icons and colors - -by Lummox JR - -version 1.0 - -The IconProcs library was made to make a lot of common icon operations much easier. BYOND's icon manipulation -routines are very capable but some of the advanced capabilities like using alpha transparency can be unintuitive to beginners. - -CHANGING ICONS - -Several new procs have been added to the /icon datum to simplify working with icons. To use them, -remember you first need to setup an /icon var like so: - -var/icon/my_icon = new('iconfile.dmi') - -icon/ChangeOpacity(amount = 1) - A very common operation in DM is to try to make an icon more or less transparent. Making an icon more - transparent is usually much easier than making it less so, however. This proc basically is a frontend - for MapColors() which can change opacity any way you like, in much the same way that SetIntensity() - can make an icon lighter or darker. If amount is 0.5, the opacity of the icon will be cut in half. - If amount is 2, opacity is doubled and anything more than half-opaque will become fully opaque. -icon/GrayScale() - Converts the icon to grayscale instead of a fully colored icon. Alpha values are left intact. -icon/ColorTone(tone) - Similar to GrayScale(), this proc converts the icon to a range of black -> tone -> white, where tone is an - RGB color (its alpha is ignored). This can be used to create a sepia tone or similar effect. - See also the global ColorTone() proc. -icon/MinColors(icon) - The icon is blended with a second icon where the minimum of each RGB pixel is the result. - Transparency may increase, as if the icons were blended with ICON_ADD. You may supply a color in place of an icon. -icon/MaxColors(icon) - The icon is blended with a second icon where the maximum of each RGB pixel is the result. - Opacity may increase, as if the icons were blended with ICON_OR. You may supply a color in place of an icon. -icon/Opaque(background = "#000000") - All alpha values are set to 255 throughout the icon. Transparent pixels become black, or whatever background color you specify. -icon/BecomeAlphaMask() - You can convert a simple grayscale icon into an alpha mask to use with other icons very easily with this proc. - The black parts become transparent, the white parts stay white, and anything in between becomes a translucent shade of white. -icon/AddAlphaMask(mask) - The alpha values of the mask icon will be blended with the current icon. Anywhere the mask is opaque, - the current icon is untouched. Anywhere the mask is transparent, the current icon becomes transparent. - Where the mask is translucent, the current icon becomes more transparent. -icon/UseAlphaMask(mask, mode) - Sometimes you may want to take the alpha values from one icon and use them on a different icon. - This proc will do that. Just supply the icon whose alpha mask you want to use, and src will change - so it has the same colors as before but uses the mask for opacity. - -COLOR MANAGEMENT AND HSV - -RGB isn't the only way to represent color. Sometimes it's more useful to work with a model called HSV, which stands for hue, saturation, and value. - - * The hue of a color describes where it is along the color wheel. It goes from red to yellow to green to - cyan to blue to magenta and back to red. - * The saturation of a color is how much color is in it. A color with low saturation will be more gray, - and with no saturation at all it is a shade of gray. - * The value of a color determines how bright it is. A high-value color is vivid, moderate value is dark, - and no value at all is black. - -Just as BYOND uses "#rrggbb" to represent RGB values, a similar format is used for HSV: "#hhhssvv". The hue is three -hex digits because it ranges from 0 to 0x5FF. - - * 0 to 0xFF - red to yellow - * 0x100 to 0x1FF - yellow to green - * 0x200 to 0x2FF - green to cyan - * 0x300 to 0x3FF - cyan to blue - * 0x400 to 0x4FF - blue to magenta - * 0x500 to 0x5FF - magenta to red - -Knowing this, you can figure out that red is "#000ffff" in HSV format, which is hue 0 (red), saturation 255 (as colorful as possible), -value 255 (as bright as possible). Green is "#200ffff" and blue is "#400ffff". - -More than one HSV color can match the same RGB color. - -Here are some procs you can use for color management: - -ReadRGB(rgb) - Takes an RGB string like "#ffaa55" and converts it to a list such as list(255,170,85). If an RGBA format is used - that includes alpha, the list will have a fourth item for the alpha value. -hsv(hue, sat, val, apha) - Counterpart to rgb(), this takes the values you input and converts them to a string in "#hhhssvv" or "#hhhssvvaa" - format. Alpha is not included in the result if null. -ReadHSV(rgb) - Takes an HSV string like "#100FF80" and converts it to a list such as list(256,255,128). If an HSVA format is used that - includes alpha, the list will have a fourth item for the alpha value. -RGBtoHSV(rgb) - Takes an RGB or RGBA string like "#ffaa55" and converts it into an HSV or HSVA color such as "#080aaff". -HSVtoRGB(hsv) - Takes an HSV or HSVA string like "#080aaff" and converts it into an RGB or RGBA color such as "#ff55aa". -BlendRGB(rgb1, rgb2, amount) - Blends between two RGB or RGBA colors using regular RGB blending. If amount is 0, the first color is the result; - if 1, the second color is the result. 0.5 produces an average of the two. Values outside the 0 to 1 range are allowed as well. - The returned value is an RGB or RGBA color. -BlendHSV(hsv1, hsv2, amount) - Blends between two HSV or HSVA colors using HSV blending, which tends to produce nicer results than regular RGB - blending because the brightness of the color is left intact. If amount is 0, the first color is the result; if 1, - the second color is the result. 0.5 produces an average of the two. Values outside the 0 to 1 range are allowed as well. - The returned value is an HSV or HSVA color. -BlendRGBasHSV(rgb1, rgb2, amount) - Like BlendHSV(), but the colors used and the return value are RGB or RGBA colors. The blending is done in HSV form. -HueToAngle(hue) - Converts a hue to an angle range of 0 to 360. Angle 0 is red, 120 is green, and 240 is blue. -AngleToHue(hue) - Converts an angle to a hue in the valid range. -RotateHue(hsv, angle) - Takes an HSV or HSVA value and rotates the hue forward through red, green, and blue by an angle from 0 to 360. - (Rotating red by 60� produces yellow.) The result is another HSV or HSVA color with the same saturation and value - as the original, but a different hue. -GrayScale(rgb) - Takes an RGB or RGBA color and converts it to grayscale. Returns an RGB or RGBA string. -ColorTone(rgb, tone) - Similar to GrayScale(), this proc converts an RGB or RGBA color to a range of black -> tone -> white instead of - using strict shades of gray. The tone value is an RGB color; any alpha value is ignored. -*/ - -/* -Get Flat Icon DEMO by DarkCampainger - -This is a test for the get flat icon proc, modified approprietly for icons and their states. -Probably not a good idea to run this unless you want to see how the proc works in detail. -mob - icon = 'old_or_unused.dmi' - icon_state = "green" - - Login() - // Testing image underlays - underlays += image(icon='old_or_unused.dmi',icon_state="red") - underlays += image(icon='old_or_unused.dmi',icon_state="red", pixel_x = 32) - underlays += image(icon='old_or_unused.dmi',icon_state="red", pixel_x = -32) - - // Testing image overlays - overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = 32, pixel_y = -32) - overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = 32, pixel_y = 32) - overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = -32, pixel_y = -32) - - // Testing icon file overlays (defaults to mob's state) - overlays += '_flat_demoIcons2.dmi' - - // Testing icon_state overlays (defaults to mob's icon) - overlays += "white" - - // Testing dynamic icon overlays - var/icon/I = icon('old_or_unused.dmi', icon_state="aqua") - I.Shift(NORTH,16,1) - overlays+=I - - // Testing dynamic image overlays - I=image(icon=I,pixel_x = -32, pixel_y = 32) - overlays+=I - - // Testing object types (and layers) - overlays+=/obj/effect/overlayTest - - loc = locate (10,10,1) - verb - Browse_Icon() - set name = "1. Browse Icon" - // Give it a name for the cache - var/iconName = "[ckey(src.name)]_flattened.dmi" - // Send the icon to src's local cache - src<

") - - Output_Icon() - set name = "2. Output Icon" - to_chat(src, "Icon is: [bicon(getFlatIcon(src))]") - - Label_Icon() - set name = "3. Label Icon" - // Give it a name for the cache - var/iconName = "[ckey(src.name)]_flattened.dmi" - // Copy the file to the rsc manually - var/icon/I = fcopy_rsc(getFlatIcon(src)) - // Send the icon to src's local cache - src< transparent, gray -> translucent white, white -> solid white - proc/BecomeAlphaMask() - SwapColor(null, "#000000ff") // don't let transparent become gray - MapColors(0,0,0,0.3, 0,0,0,0.59, 0,0,0,0.11, 0,0,0,0, 1,1,1,0) - - proc/UseAlphaMask(mask) - Opaque() - AddAlphaMask(mask) - - proc/AddAlphaMask(mask) - var/icon/M = new(mask) - M.Blend("#ffffff", ICON_SUBTRACT) - // apply mask - Blend(M, ICON_ADD) - -/* - HSV format is represented as "#hhhssvv" or "#hhhssvvaa" - - Hue ranges from 0 to 0x5ff (1535) - - 0x000 = red - 0x100 = yellow - 0x200 = green - 0x300 = cyan - 0x400 = blue - 0x500 = magenta - - Saturation is from 0 to 0xff (255) - - More saturation = more color - Less saturation = more gray - - Value ranges from 0 to 0xff (255) - - Higher value means brighter color - */ - -proc/ReadRGB(rgb) - if(!rgb) return - - // interpret the HSV or HSVA value - var/i=1,start=1 - if(text2ascii(rgb) == 35) ++start // skip opening # - var/ch,which=0,r=0,g=0,b=0,alpha=0,usealpha - var/digits=0 - for(i=start, i<=length(rgb), ++i) - ch = text2ascii(rgb, i) - if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102) break - ++digits - if(digits == 8) break - - var/single = digits < 6 - if(digits != 3 && digits != 4 && digits != 6 && digits != 8) return - if(digits == 4 || digits == 8) usealpha = 1 - for(i=start, digits>0, ++i) - ch = text2ascii(rgb, i) - if(ch >= 48 && ch <= 57) ch -= 48 - else if(ch >= 65 && ch <= 70) ch -= 55 - else if(ch >= 97 && ch <= 102) ch -= 87 - else break - --digits - switch(which) - if(0) - r = (r << 4) | ch - if(single) - r |= r << 4 - ++which - else if(!(digits & 1)) ++which - if(1) - g = (g << 4) | ch - if(single) - g |= g << 4 - ++which - else if(!(digits & 1)) ++which - if(2) - b = (b << 4) | ch - if(single) - b |= b << 4 - ++which - else if(!(digits & 1)) ++which - if(3) - alpha = (alpha << 4) | ch - if(single) alpha |= alpha << 4 - - . = list(r, g, b) - if(usealpha) . += alpha - -proc/ReadHSV(hsv) - if(!hsv) return - - // interpret the HSV or HSVA value - var/i=1,start=1 - if(text2ascii(hsv) == 35) ++start // skip opening # - var/ch,which=0,hue=0,sat=0,val=0,alpha=0,usealpha - var/digits=0 - for(i=start, i<=length(hsv), ++i) - ch = text2ascii(hsv, i) - if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102) break - ++digits - if(digits == 9) break - if(digits > 7) usealpha = 1 - if(digits <= 4) ++which - if(digits <= 2) ++which - for(i=start, digits>0, ++i) - ch = text2ascii(hsv, i) - if(ch >= 48 && ch <= 57) ch -= 48 - else if(ch >= 65 && ch <= 70) ch -= 55 - else if(ch >= 97 && ch <= 102) ch -= 87 - else break - --digits - switch(which) - if(0) - hue = (hue << 4) | ch - if(digits == (usealpha ? 6 : 4)) ++which - if(1) - sat = (sat << 4) | ch - if(digits == (usealpha ? 4 : 2)) ++which - if(2) - val = (val << 4) | ch - if(digits == (usealpha ? 2 : 0)) ++which - if(3) - alpha = (alpha << 4) | ch - - . = list(hue, sat, val) - if(usealpha) . += alpha - -proc/HSVtoRGB(hsv) - if(!hsv) return "#000000" - var/list/HSV = ReadHSV(hsv) - if(!HSV) return "#000000" - - var/hue = HSV[1] - var/sat = HSV[2] - var/val = HSV[3] - - // Compress hue into easier-to-manage range - hue -= hue >> 8 - if(hue >= 0x5fa) hue -= 0x5fa - - var/hi,mid,lo,r,g,b - hi = val - lo = round((255 - sat) * val / 255, 1) - mid = lo + round(abs(round(hue, 510) - hue) * (hi - lo) / 255, 1) - if(hue >= 765) - if(hue >= 1275) {r=hi; g=lo; b=mid} - else if(hue >= 1020) {r=mid; g=lo; b=hi } - else {r=lo; g=mid; b=hi } - else - if(hue >= 510) {r=lo; g=hi; b=mid} - else if(hue >= 255) {r=mid; g=hi; b=lo } - else {r=hi; g=mid; b=lo } - - return (HSV.len > 3) ? rgb(r,g,b,HSV[4]) : rgb(r,g,b) - -proc/RGBtoHSV(rgb) - if(!rgb) return "#0000000" - var/list/RGB = ReadRGB(rgb) - if(!RGB) return "#0000000" - - var/r = RGB[1] - var/g = RGB[2] - var/b = RGB[3] - var/hi = max(r,g,b) - var/lo = min(r,g,b) - - var/val = hi - var/sat = hi ? round((hi-lo) * 255 / hi, 1) : 0 - var/hue = 0 - - if(sat) - var/dir - var/mid - if(hi == r) - if(lo == b) {hue=0; dir=1; mid=g} - else {hue=1535; dir=-1; mid=b} - else if(hi == g) - if(lo == r) {hue=512; dir=1; mid=b} - else {hue=511; dir=-1; mid=r} - else if(hi == b) - if(lo == g) {hue=1024; dir=1; mid=r} - else {hue=1023; dir=-1; mid=g} - hue += dir * round((mid-lo) * 255 / (hi-lo), 1) - - return hsv(hue, sat, val, (RGB.len>3 ? RGB[4] : null)) - -proc/hsv(hue, sat, val, alpha) - if(hue < 0 || hue >= 1536) hue %= 1536 - if(hue < 0) hue += 1536 - if((hue & 0xFF) == 0xFF) - ++hue - if(hue >= 1536) hue = 0 - if(sat < 0) sat = 0 - if(sat > 255) sat = 255 - if(val < 0) val = 0 - if(val > 255) val = 255 - . = "#" - . += TO_HEX_DIGIT(hue >> 8) - . += TO_HEX_DIGIT(hue >> 4) - . += TO_HEX_DIGIT(hue) - . += TO_HEX_DIGIT(sat >> 4) - . += TO_HEX_DIGIT(sat) - . += TO_HEX_DIGIT(val >> 4) - . += TO_HEX_DIGIT(val) - if(!isnull(alpha)) - if(alpha < 0) alpha = 0 - if(alpha > 255) alpha = 255 - . += TO_HEX_DIGIT(alpha >> 4) - . += TO_HEX_DIGIT(alpha) - -/* - Smooth blend between HSV colors - - amount=0 is the first color - amount=1 is the second color - amount=0.5 is directly between the two colors - - amount<0 or amount>1 are allowed - */ -proc/BlendHSV(hsv1, hsv2, amount) - var/list/HSV1 = ReadHSV(hsv1) - var/list/HSV2 = ReadHSV(hsv2) - - // add missing alpha if needed - if(HSV1.len < HSV2.len) HSV1 += 255 - else if(HSV2.len < HSV1.len) HSV2 += 255 - var/usealpha = HSV1.len > 3 - - // normalize hsv values in case anything is screwy - if(HSV1[1] > 1536) HSV1[1] %= 1536 - if(HSV2[1] > 1536) HSV2[1] %= 1536 - if(HSV1[1] < 0) HSV1[1] += 1536 - if(HSV2[1] < 0) HSV2[1] += 1536 - if(!HSV1[3]) {HSV1[1] = 0; HSV1[2] = 0} - if(!HSV2[3]) {HSV2[1] = 0; HSV2[2] = 0} - - // no value for one color means don't change saturation - if(!HSV1[3]) HSV1[2] = HSV2[2] - if(!HSV2[3]) HSV2[2] = HSV1[2] - // no saturation for one color means don't change hues - if(!HSV1[2]) HSV1[1] = HSV2[1] - if(!HSV2[2]) HSV2[1] = HSV1[1] - - // Compress hues into easier-to-manage range - HSV1[1] -= HSV1[1] >> 8 - HSV2[1] -= HSV2[1] >> 8 - - var/hue_diff = HSV2[1] - HSV1[1] - if(hue_diff > 765) hue_diff -= 1530 - else if(hue_diff <= -765) hue_diff += 1530 - - var/hue = round(HSV1[1] + hue_diff * amount, 1) - var/sat = round(HSV1[2] + (HSV2[2] - HSV1[2]) * amount, 1) - var/val = round(HSV1[3] + (HSV2[3] - HSV1[3]) * amount, 1) - var/alpha = usealpha ? round(HSV1[4] + (HSV2[4] - HSV1[4]) * amount, 1) : null - - // normalize hue - if(hue < 0 || hue >= 1530) hue %= 1530 - if(hue < 0) hue += 1530 - // decompress hue - hue += round(hue / 255) - - return hsv(hue, sat, val, alpha) - -/* - Smooth blend between RGB colors - - amount=0 is the first color - amount=1 is the second color - amount=0.5 is directly between the two colors - - amount<0 or amount>1 are allowed - */ -proc/BlendRGB(rgb1, rgb2, amount) - var/list/RGB1 = ReadRGB(rgb1) - var/list/RGB2 = ReadRGB(rgb2) - - // add missing alpha if needed - if(RGB1.len < RGB2.len) RGB1 += 255 - else if(RGB2.len < RGB1.len) RGB2 += 255 - var/usealpha = RGB1.len > 3 - - var/r = round(RGB1[1] + (RGB2[1] - RGB1[1]) * amount, 1) - var/g = round(RGB1[2] + (RGB2[2] - RGB1[2]) * amount, 1) - var/b = round(RGB1[3] + (RGB2[3] - RGB1[3]) * amount, 1) - var/alpha = usealpha ? round(RGB1[4] + (RGB2[4] - RGB1[4]) * amount, 1) : null - - return isnull(alpha) ? rgb(r, g, b) : rgb(r, g, b, alpha) - -proc/BlendRGBasHSV(rgb1, rgb2, amount) - return HSVtoRGB(RGBtoHSV(rgb1), RGBtoHSV(rgb2), amount) - -proc/HueToAngle(hue) - // normalize hsv in case anything is screwy - if(hue < 0 || hue >= 1536) hue %= 1536 - if(hue < 0) hue += 1536 - // Compress hue into easier-to-manage range - hue -= hue >> 8 - return hue / (1530/360) - -proc/AngleToHue(angle) - // normalize hsv in case anything is screwy - if(angle < 0 || angle >= 360) angle -= 360 * round(angle / 360) - var/hue = angle * (1530/360) - // Decompress hue - hue += round(hue / 255) - return hue - - -// positive angle rotates forward through red->green->blue -proc/RotateHue(hsv, angle) - var/list/HSV = ReadHSV(hsv) - - // normalize hsv in case anything is screwy - if(HSV[1] >= 1536) HSV[1] %= 1536 - if(HSV[1] < 0) HSV[1] += 1536 - - // Compress hue into easier-to-manage range - HSV[1] -= HSV[1] >> 8 - - if(angle < 0 || angle >= 360) angle -= 360 * round(angle / 360) - HSV[1] = round(HSV[1] + angle * (1530/360), 1) - - // normalize hue - if(HSV[1] < 0 || HSV[1] >= 1530) HSV[1] %= 1530 - if(HSV[1] < 0) HSV[1] += 1530 - // decompress hue - HSV[1] += round(HSV[1] / 255) - - return hsv(HSV[1], HSV[2], HSV[3], (HSV.len > 3 ? HSV[4] : null)) - -// Convert an rgb color to grayscale -proc/GrayScale(rgb) - var/list/RGB = ReadRGB(rgb) - var/gray = RGB[1]*0.3 + RGB[2]*0.59 + RGB[3]*0.11 - return (RGB.len > 3) ? rgb(gray, gray, gray, RGB[4]) : rgb(gray, gray, gray) - -// Change grayscale color to black->tone->white range -proc/ColorTone(rgb, tone) - var/list/RGB = ReadRGB(rgb) - var/list/TONE = ReadRGB(tone) - - var/gray = RGB[1]*0.3 + RGB[2]*0.59 + RGB[3]*0.11 - var/tone_gray = TONE[1]*0.3 + TONE[2]*0.59 + TONE[3]*0.11 - - if(gray <= tone_gray) return BlendRGB("#000000", tone, gray/(tone_gray || 1)) - else return BlendRGB(tone, "#ffffff", (gray-tone_gray)/((255-tone_gray) || 1)) - - -/* -Get flat icon by DarkCampainger. As it says on the tin, will return an icon with all the overlays -as a single icon. Useful for when you want to manipulate an icon via the above as overlays are not normally included. -The _flatIcons list is a cache for generated icon files. -*/ - -// Creates a single icon from a given /atom or /image. Only the first argument is required. -/proc/getFlatIcon(image/A, defdir=A.dir, deficon=A.icon, defstate=A.icon_state, defblend=A.blend_mode, exact=0) - // We start with a blank canvas, otherwise some icon procs crash silently - var/icon/flat = icon('icons/effects/effects.dmi', "nothing") // Final flattened icon - if(!A) - return flat - if(A.alpha <= 0) - return flat - var/noIcon = FALSE - - var/curicon - if(A.icon) - curicon = A.icon - else - curicon = deficon - - if(!curicon) - noIcon = TRUE // Do not render this object. - - var/curstate - if(A.icon_state) - curstate = A.icon_state - else - curstate = defstate - - if(!noIcon && !(curstate in icon_states(curicon))) - if("" in icon_states(curicon)) - curstate = "" - else - noIcon = TRUE // Do not render this object. - - var/curdir - if(!exact && (A.dir != 2)) - curdir = A.dir - else if(exact) - curdir = 2 - else - curdir = defdir - - var/curblend - if(A.blend_mode == BLEND_DEFAULT) - curblend = defblend - else - curblend = A.blend_mode - - // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed - var/list/layers = list() - var/image/copy - // Add the atom's icon itself, without pixel_x/y offsets. - if(!noIcon) - copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir) - copy.color = A.color - copy.alpha = A.alpha - copy.blend_mode = curblend - layers[copy] = A.layer - - // Loop through the underlays, then overlays, sorting them into the layers list - var/list/process = A.underlays // Current list being processed - var/pSet=0 // Which list is being processed: 0 = underlays, 1 = overlays - var/curIndex=1 // index of 'current' in list being processed - var/current // Current overlay being sorted - var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER) - var/compare // The overlay 'add' is being compared against - var/cmpIndex // The index in the layers list of 'compare' - while(TRUE) - if(curIndex<=process.len) - current = process[curIndex] - if(!current) - curIndex++ //Try the next layer - continue - currentLayer = current:layer - if(currentLayer<0) // Special case for FLY_LAYER - if(currentLayer <= -1000) return flat - if(pSet == 0) // Underlay - currentLayer = A.layer+currentLayer/1000 - else // Overlay - currentLayer = A.layer+(1000+currentLayer)/1000 - - // Sort add into layers list - for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++) - compare = layers[cmpIndex] - if(currentLayer < layers[compare]) // Associated value is the calculated layer - layers.Insert(cmpIndex,current) - layers[current] = currentLayer - break - if(cmpIndex>layers.len) // Reached end of list without inserting - layers[current]=currentLayer // Place at end - - curIndex++ - - if(curIndex>process.len) - if(pSet == 0) // Switch to overlays - curIndex = 1 - pSet = 1 - process = A.overlays - else // All done - break - - var/icon/add // Icon of overlay being added - - // Current dimensions of flattened icon - var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()} - // Dimensions of overlay being added - var/{addX1;addX2;addY1;addY2} - - for(var/I in layers) - - if(I:alpha == 0) - continue - - if(I == copy) // 'I' is an /image based on the object being flattened. - curblend = BLEND_OVERLAY - add = icon(I:icon, I:icon_state, I:dir) - else // 'I' is an appearance object. - add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend) - - // Find the new dimensions of the flat icon to fit the added overlay - addX1 = min(flatX1, I:pixel_x+1) - addX2 = max(flatX2, I:pixel_x+add.Width()) - addY1 = min(flatY1, I:pixel_y+1) - addY2 = max(flatY2, I:pixel_y+add.Height()) - - if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2) - // Resize the flattened icon so the new icon fits - flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1) - flatX1=addX1;flatX2=addX2 - flatY1=addY1;flatY2=addY2 - - // Blend the overlay into the flattened icon - flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1) - - if(A.color) - if(islist(A.color)) // Matrix color support. - flat.MapColors( - A.color[1] , A.color[2] , A.color[3] - , A.color[5] , A.color[6] , A.color[7] - , A.color[9] , A.color[10] , A.color[11] - , A.color[17] , A.color[18] , A.color[19] - ) - else - flat.Blend(A.color, ICON_MULTIPLY) - if(A.alpha < 255) - flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) - - return icon(flat, "", SOUTH) - -/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 - -//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 - composite.Blend(icon(I.icon, I.icon_state, I.dir, 1), ICON_OVERLAY) - return composite - -proc/adjust_brightness(color, 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/sort_atoms_by_layer(list/atoms) - // Comb sort icons based on levels - var/list/result = atoms.Copy() - var/gap = result.len - var/swapped = 1 - while (gap > 1 || swapped) - swapped = 0 - if(gap > 1) - gap = round(gap / 1.3) // 1.3 is the emperic comb sort coefficient - if(gap < 1) - gap = 1 - for(var/i = 1; gap + i <= result.len; i++) - var/atom/l = result[i] //Fucking hate - var/atom/r = result[gap+i] //how lists work here - if(l.layer > r.layer) //no "result[i].layer" for me - result.Swap(i, gap + i) - swapped = 1 - return result - -var/global/list/humanoid_icon_cache = list() -//For creating consistent icons for human looking simple animals -/proc/get_flat_human_icon(icon_id,datum/job/J,datum/preferences/prefs) - if(!icon_id || !humanoid_icon_cache[icon_id]) - var/mob/living/carbon/human/dummy/body = new(null, prefs.species) - - if(prefs) - prefs.copy_to(body) - if(J) - J.equip(body, TRUE) - - var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing") - - body.dir = NORTH - var/icon/partial = getFlatIcon(body) - out_icon.Insert(partial,dir=NORTH) - - body.dir = SOUTH - partial = getFlatIcon(body) - out_icon.Insert(partial,dir=SOUTH) - - body.dir = WEST - partial = getFlatIcon(body) - out_icon.Insert(partial,dir=WEST) - - body.dir = EAST - partial = getFlatIcon(body) - out_icon.Insert(partial,dir=EAST) - - qdel(body) - - humanoid_icon_cache[icon_id] = out_icon - return out_icon - else - return humanoid_icon_cache[icon_id] +/* +IconProcs README + +A BYOND library for manipulating icons and colors + +by Lummox JR + +version 1.0 + +The IconProcs library was made to make a lot of common icon operations much easier. BYOND's icon manipulation +routines are very capable but some of the advanced capabilities like using alpha transparency can be unintuitive to beginners. + +CHANGING ICONS + +Several new procs have been added to the /icon datum to simplify working with icons. To use them, +remember you first need to setup an /icon var like so: + +var/icon/my_icon = new('iconfile.dmi') + +icon/ChangeOpacity(amount = 1) + A very common operation in DM is to try to make an icon more or less transparent. Making an icon more + transparent is usually much easier than making it less so, however. This proc basically is a frontend + for MapColors() which can change opacity any way you like, in much the same way that SetIntensity() + can make an icon lighter or darker. If amount is 0.5, the opacity of the icon will be cut in half. + If amount is 2, opacity is doubled and anything more than half-opaque will become fully opaque. +icon/GrayScale() + Converts the icon to grayscale instead of a fully colored icon. Alpha values are left intact. +icon/ColorTone(tone) + Similar to GrayScale(), this proc converts the icon to a range of black -> tone -> white, where tone is an + RGB color (its alpha is ignored). This can be used to create a sepia tone or similar effect. + See also the global ColorTone() proc. +icon/MinColors(icon) + The icon is blended with a second icon where the minimum of each RGB pixel is the result. + Transparency may increase, as if the icons were blended with ICON_ADD. You may supply a color in place of an icon. +icon/MaxColors(icon) + The icon is blended with a second icon where the maximum of each RGB pixel is the result. + Opacity may increase, as if the icons were blended with ICON_OR. You may supply a color in place of an icon. +icon/Opaque(background = "#000000") + All alpha values are set to 255 throughout the icon. Transparent pixels become black, or whatever background color you specify. +icon/BecomeAlphaMask() + You can convert a simple grayscale icon into an alpha mask to use with other icons very easily with this proc. + The black parts become transparent, the white parts stay white, and anything in between becomes a translucent shade of white. +icon/AddAlphaMask(mask) + The alpha values of the mask icon will be blended with the current icon. Anywhere the mask is opaque, + the current icon is untouched. Anywhere the mask is transparent, the current icon becomes transparent. + Where the mask is translucent, the current icon becomes more transparent. +icon/UseAlphaMask(mask, mode) + Sometimes you may want to take the alpha values from one icon and use them on a different icon. + This proc will do that. Just supply the icon whose alpha mask you want to use, and src will change + so it has the same colors as before but uses the mask for opacity. + +COLOR MANAGEMENT AND HSV + +RGB isn't the only way to represent color. Sometimes it's more useful to work with a model called HSV, which stands for hue, saturation, and value. + + * The hue of a color describes where it is along the color wheel. It goes from red to yellow to green to + cyan to blue to magenta and back to red. + * The saturation of a color is how much color is in it. A color with low saturation will be more gray, + and with no saturation at all it is a shade of gray. + * The value of a color determines how bright it is. A high-value color is vivid, moderate value is dark, + and no value at all is black. + +Just as BYOND uses "#rrggbb" to represent RGB values, a similar format is used for HSV: "#hhhssvv". The hue is three +hex digits because it ranges from 0 to 0x5FF. + + * 0 to 0xFF - red to yellow + * 0x100 to 0x1FF - yellow to green + * 0x200 to 0x2FF - green to cyan + * 0x300 to 0x3FF - cyan to blue + * 0x400 to 0x4FF - blue to magenta + * 0x500 to 0x5FF - magenta to red + +Knowing this, you can figure out that red is "#000ffff" in HSV format, which is hue 0 (red), saturation 255 (as colorful as possible), +value 255 (as bright as possible). Green is "#200ffff" and blue is "#400ffff". + +More than one HSV color can match the same RGB color. + +Here are some procs you can use for color management: + +ReadRGB(rgb) + Takes an RGB string like "#ffaa55" and converts it to a list such as list(255,170,85). If an RGBA format is used + that includes alpha, the list will have a fourth item for the alpha value. +hsv(hue, sat, val, apha) + Counterpart to rgb(), this takes the values you input and converts them to a string in "#hhhssvv" or "#hhhssvvaa" + format. Alpha is not included in the result if null. +ReadHSV(rgb) + Takes an HSV string like "#100FF80" and converts it to a list such as list(256,255,128). If an HSVA format is used that + includes alpha, the list will have a fourth item for the alpha value. +RGBtoHSV(rgb) + Takes an RGB or RGBA string like "#ffaa55" and converts it into an HSV or HSVA color such as "#080aaff". +HSVtoRGB(hsv) + Takes an HSV or HSVA string like "#080aaff" and converts it into an RGB or RGBA color such as "#ff55aa". +BlendRGB(rgb1, rgb2, amount) + Blends between two RGB or RGBA colors using regular RGB blending. If amount is 0, the first color is the result; + if 1, the second color is the result. 0.5 produces an average of the two. Values outside the 0 to 1 range are allowed as well. + The returned value is an RGB or RGBA color. +BlendHSV(hsv1, hsv2, amount) + Blends between two HSV or HSVA colors using HSV blending, which tends to produce nicer results than regular RGB + blending because the brightness of the color is left intact. If amount is 0, the first color is the result; if 1, + the second color is the result. 0.5 produces an average of the two. Values outside the 0 to 1 range are allowed as well. + The returned value is an HSV or HSVA color. +BlendRGBasHSV(rgb1, rgb2, amount) + Like BlendHSV(), but the colors used and the return value are RGB or RGBA colors. The blending is done in HSV form. +HueToAngle(hue) + Converts a hue to an angle range of 0 to 360. Angle 0 is red, 120 is green, and 240 is blue. +AngleToHue(hue) + Converts an angle to a hue in the valid range. +RotateHue(hsv, angle) + Takes an HSV or HSVA value and rotates the hue forward through red, green, and blue by an angle from 0 to 360. + (Rotating red by 60� produces yellow.) The result is another HSV or HSVA color with the same saturation and value + as the original, but a different hue. +GrayScale(rgb) + Takes an RGB or RGBA color and converts it to grayscale. Returns an RGB or RGBA string. +ColorTone(rgb, tone) + Similar to GrayScale(), this proc converts an RGB or RGBA color to a range of black -> tone -> white instead of + using strict shades of gray. The tone value is an RGB color; any alpha value is ignored. +*/ + +/* +Get Flat Icon DEMO by DarkCampainger + +This is a test for the get flat icon proc, modified approprietly for icons and their states. +Probably not a good idea to run this unless you want to see how the proc works in detail. +mob + icon = 'old_or_unused.dmi' + icon_state = "green" + + Login() + // Testing image underlays + underlays += image(icon='old_or_unused.dmi',icon_state="red") + underlays += image(icon='old_or_unused.dmi',icon_state="red", pixel_x = 32) + underlays += image(icon='old_or_unused.dmi',icon_state="red", pixel_x = -32) + + // Testing image overlays + overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = 32, pixel_y = -32) + overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = 32, pixel_y = 32) + overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = -32, pixel_y = -32) + + // Testing icon file overlays (defaults to mob's state) + overlays += '_flat_demoIcons2.dmi' + + // Testing icon_state overlays (defaults to mob's icon) + overlays += "white" + + // Testing dynamic icon overlays + var/icon/I = icon('old_or_unused.dmi', icon_state="aqua") + I.Shift(NORTH,16,1) + overlays+=I + + // Testing dynamic image overlays + I=image(icon=I,pixel_x = -32, pixel_y = 32) + overlays+=I + + // Testing object types (and layers) + overlays+=/obj/effect/overlayTest + + loc = locate (10,10,1) + verb + Browse_Icon() + set name = "1. Browse Icon" + // Give it a name for the cache + var/iconName = "[ckey(src.name)]_flattened.dmi" + // Send the icon to src's local cache + src<

") + + Output_Icon() + set name = "2. Output Icon" + to_chat(src, "Icon is: [bicon(getFlatIcon(src))]") + + Label_Icon() + set name = "3. Label Icon" + // Give it a name for the cache + var/iconName = "[ckey(src.name)]_flattened.dmi" + // Copy the file to the rsc manually + var/icon/I = fcopy_rsc(getFlatIcon(src)) + // Send the icon to src's local cache + src< transparent, gray -> translucent white, white -> solid white + proc/BecomeAlphaMask() + SwapColor(null, "#000000ff") // don't let transparent become gray + MapColors(0,0,0,0.3, 0,0,0,0.59, 0,0,0,0.11, 0,0,0,0, 1,1,1,0) + + proc/UseAlphaMask(mask) + Opaque() + AddAlphaMask(mask) + + proc/AddAlphaMask(mask) + var/icon/M = new(mask) + M.Blend("#ffffff", ICON_SUBTRACT) + // apply mask + Blend(M, ICON_ADD) + +/* + HSV format is represented as "#hhhssvv" or "#hhhssvvaa" + + Hue ranges from 0 to 0x5ff (1535) + + 0x000 = red + 0x100 = yellow + 0x200 = green + 0x300 = cyan + 0x400 = blue + 0x500 = magenta + + Saturation is from 0 to 0xff (255) + + More saturation = more color + Less saturation = more gray + + Value ranges from 0 to 0xff (255) + + Higher value means brighter color + */ + +proc/ReadRGB(rgb) + if(!rgb) return + + // interpret the HSV or HSVA value + var/i=1,start=1 + if(text2ascii(rgb) == 35) ++start // skip opening # + var/ch,which=0,r=0,g=0,b=0,alpha=0,usealpha + var/digits=0 + for(i=start, i<=length(rgb), ++i) + ch = text2ascii(rgb, i) + if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102) break + ++digits + if(digits == 8) break + + var/single = digits < 6 + if(digits != 3 && digits != 4 && digits != 6 && digits != 8) return + if(digits == 4 || digits == 8) usealpha = 1 + for(i=start, digits>0, ++i) + ch = text2ascii(rgb, i) + if(ch >= 48 && ch <= 57) ch -= 48 + else if(ch >= 65 && ch <= 70) ch -= 55 + else if(ch >= 97 && ch <= 102) ch -= 87 + else break + --digits + switch(which) + if(0) + r = (r << 4) | ch + if(single) + r |= r << 4 + ++which + else if(!(digits & 1)) ++which + if(1) + g = (g << 4) | ch + if(single) + g |= g << 4 + ++which + else if(!(digits & 1)) ++which + if(2) + b = (b << 4) | ch + if(single) + b |= b << 4 + ++which + else if(!(digits & 1)) ++which + if(3) + alpha = (alpha << 4) | ch + if(single) alpha |= alpha << 4 + + . = list(r, g, b) + if(usealpha) . += alpha + +proc/ReadHSV(hsv) + if(!hsv) return + + // interpret the HSV or HSVA value + var/i=1,start=1 + if(text2ascii(hsv) == 35) ++start // skip opening # + var/ch,which=0,hue=0,sat=0,val=0,alpha=0,usealpha + var/digits=0 + for(i=start, i<=length(hsv), ++i) + ch = text2ascii(hsv, i) + if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102) break + ++digits + if(digits == 9) break + if(digits > 7) usealpha = 1 + if(digits <= 4) ++which + if(digits <= 2) ++which + for(i=start, digits>0, ++i) + ch = text2ascii(hsv, i) + if(ch >= 48 && ch <= 57) ch -= 48 + else if(ch >= 65 && ch <= 70) ch -= 55 + else if(ch >= 97 && ch <= 102) ch -= 87 + else break + --digits + switch(which) + if(0) + hue = (hue << 4) | ch + if(digits == (usealpha ? 6 : 4)) ++which + if(1) + sat = (sat << 4) | ch + if(digits == (usealpha ? 4 : 2)) ++which + if(2) + val = (val << 4) | ch + if(digits == (usealpha ? 2 : 0)) ++which + if(3) + alpha = (alpha << 4) | ch + + . = list(hue, sat, val) + if(usealpha) . += alpha + +proc/HSVtoRGB(hsv) + if(!hsv) return "#000000" + var/list/HSV = ReadHSV(hsv) + if(!HSV) return "#000000" + + var/hue = HSV[1] + var/sat = HSV[2] + var/val = HSV[3] + + // Compress hue into easier-to-manage range + hue -= hue >> 8 + if(hue >= 0x5fa) hue -= 0x5fa + + var/hi,mid,lo,r,g,b + hi = val + lo = round((255 - sat) * val / 255, 1) + mid = lo + round(abs(round(hue, 510) - hue) * (hi - lo) / 255, 1) + if(hue >= 765) + if(hue >= 1275) {r=hi; g=lo; b=mid} + else if(hue >= 1020) {r=mid; g=lo; b=hi } + else {r=lo; g=mid; b=hi } + else + if(hue >= 510) {r=lo; g=hi; b=mid} + else if(hue >= 255) {r=mid; g=hi; b=lo } + else {r=hi; g=mid; b=lo } + + return (HSV.len > 3) ? rgb(r,g,b,HSV[4]) : rgb(r,g,b) + +proc/RGBtoHSV(rgb) + if(!rgb) return "#0000000" + var/list/RGB = ReadRGB(rgb) + if(!RGB) return "#0000000" + + var/r = RGB[1] + var/g = RGB[2] + var/b = RGB[3] + var/hi = max(r,g,b) + var/lo = min(r,g,b) + + var/val = hi + var/sat = hi ? round((hi-lo) * 255 / hi, 1) : 0 + var/hue = 0 + + if(sat) + var/dir + var/mid + if(hi == r) + if(lo == b) {hue=0; dir=1; mid=g} + else {hue=1535; dir=-1; mid=b} + else if(hi == g) + if(lo == r) {hue=512; dir=1; mid=b} + else {hue=511; dir=-1; mid=r} + else if(hi == b) + if(lo == g) {hue=1024; dir=1; mid=r} + else {hue=1023; dir=-1; mid=g} + hue += dir * round((mid-lo) * 255 / (hi-lo), 1) + + return hsv(hue, sat, val, (RGB.len>3 ? RGB[4] : null)) + +proc/hsv(hue, sat, val, alpha) + if(hue < 0 || hue >= 1536) hue %= 1536 + if(hue < 0) hue += 1536 + if((hue & 0xFF) == 0xFF) + ++hue + if(hue >= 1536) hue = 0 + if(sat < 0) sat = 0 + if(sat > 255) sat = 255 + if(val < 0) val = 0 + if(val > 255) val = 255 + . = "#" + . += TO_HEX_DIGIT(hue >> 8) + . += TO_HEX_DIGIT(hue >> 4) + . += TO_HEX_DIGIT(hue) + . += TO_HEX_DIGIT(sat >> 4) + . += TO_HEX_DIGIT(sat) + . += TO_HEX_DIGIT(val >> 4) + . += TO_HEX_DIGIT(val) + if(!isnull(alpha)) + if(alpha < 0) alpha = 0 + if(alpha > 255) alpha = 255 + . += TO_HEX_DIGIT(alpha >> 4) + . += TO_HEX_DIGIT(alpha) + +/* + Smooth blend between HSV colors + + amount=0 is the first color + amount=1 is the second color + amount=0.5 is directly between the two colors + + amount<0 or amount>1 are allowed + */ +proc/BlendHSV(hsv1, hsv2, amount) + var/list/HSV1 = ReadHSV(hsv1) + var/list/HSV2 = ReadHSV(hsv2) + + // add missing alpha if needed + if(HSV1.len < HSV2.len) HSV1 += 255 + else if(HSV2.len < HSV1.len) HSV2 += 255 + var/usealpha = HSV1.len > 3 + + // normalize hsv values in case anything is screwy + if(HSV1[1] > 1536) HSV1[1] %= 1536 + if(HSV2[1] > 1536) HSV2[1] %= 1536 + if(HSV1[1] < 0) HSV1[1] += 1536 + if(HSV2[1] < 0) HSV2[1] += 1536 + if(!HSV1[3]) {HSV1[1] = 0; HSV1[2] = 0} + if(!HSV2[3]) {HSV2[1] = 0; HSV2[2] = 0} + + // no value for one color means don't change saturation + if(!HSV1[3]) HSV1[2] = HSV2[2] + if(!HSV2[3]) HSV2[2] = HSV1[2] + // no saturation for one color means don't change hues + if(!HSV1[2]) HSV1[1] = HSV2[1] + if(!HSV2[2]) HSV2[1] = HSV1[1] + + // Compress hues into easier-to-manage range + HSV1[1] -= HSV1[1] >> 8 + HSV2[1] -= HSV2[1] >> 8 + + var/hue_diff = HSV2[1] - HSV1[1] + if(hue_diff > 765) hue_diff -= 1530 + else if(hue_diff <= -765) hue_diff += 1530 + + var/hue = round(HSV1[1] + hue_diff * amount, 1) + var/sat = round(HSV1[2] + (HSV2[2] - HSV1[2]) * amount, 1) + var/val = round(HSV1[3] + (HSV2[3] - HSV1[3]) * amount, 1) + var/alpha = usealpha ? round(HSV1[4] + (HSV2[4] - HSV1[4]) * amount, 1) : null + + // normalize hue + if(hue < 0 || hue >= 1530) hue %= 1530 + if(hue < 0) hue += 1530 + // decompress hue + hue += round(hue / 255) + + return hsv(hue, sat, val, alpha) + +/* + Smooth blend between RGB colors + + amount=0 is the first color + amount=1 is the second color + amount=0.5 is directly between the two colors + + amount<0 or amount>1 are allowed + */ +proc/BlendRGB(rgb1, rgb2, amount) + var/list/RGB1 = ReadRGB(rgb1) + var/list/RGB2 = ReadRGB(rgb2) + + // add missing alpha if needed + if(RGB1.len < RGB2.len) RGB1 += 255 + else if(RGB2.len < RGB1.len) RGB2 += 255 + var/usealpha = RGB1.len > 3 + + var/r = round(RGB1[1] + (RGB2[1] - RGB1[1]) * amount, 1) + var/g = round(RGB1[2] + (RGB2[2] - RGB1[2]) * amount, 1) + var/b = round(RGB1[3] + (RGB2[3] - RGB1[3]) * amount, 1) + var/alpha = usealpha ? round(RGB1[4] + (RGB2[4] - RGB1[4]) * amount, 1) : null + + return isnull(alpha) ? rgb(r, g, b) : rgb(r, g, b, alpha) + +proc/BlendRGBasHSV(rgb1, rgb2, amount) + return HSVtoRGB(RGBtoHSV(rgb1), RGBtoHSV(rgb2), amount) + +proc/HueToAngle(hue) + // normalize hsv in case anything is screwy + if(hue < 0 || hue >= 1536) hue %= 1536 + if(hue < 0) hue += 1536 + // Compress hue into easier-to-manage range + hue -= hue >> 8 + return hue / (1530/360) + +proc/AngleToHue(angle) + // normalize hsv in case anything is screwy + if(angle < 0 || angle >= 360) angle -= 360 * round(angle / 360) + var/hue = angle * (1530/360) + // Decompress hue + hue += round(hue / 255) + return hue + + +// positive angle rotates forward through red->green->blue +proc/RotateHue(hsv, angle) + var/list/HSV = ReadHSV(hsv) + + // normalize hsv in case anything is screwy + if(HSV[1] >= 1536) HSV[1] %= 1536 + if(HSV[1] < 0) HSV[1] += 1536 + + // Compress hue into easier-to-manage range + HSV[1] -= HSV[1] >> 8 + + if(angle < 0 || angle >= 360) angle -= 360 * round(angle / 360) + HSV[1] = round(HSV[1] + angle * (1530/360), 1) + + // normalize hue + if(HSV[1] < 0 || HSV[1] >= 1530) HSV[1] %= 1530 + if(HSV[1] < 0) HSV[1] += 1530 + // decompress hue + HSV[1] += round(HSV[1] / 255) + + return hsv(HSV[1], HSV[2], HSV[3], (HSV.len > 3 ? HSV[4] : null)) + +// Convert an rgb color to grayscale +proc/GrayScale(rgb) + var/list/RGB = ReadRGB(rgb) + var/gray = RGB[1]*0.3 + RGB[2]*0.59 + RGB[3]*0.11 + return (RGB.len > 3) ? rgb(gray, gray, gray, RGB[4]) : rgb(gray, gray, gray) + +// Change grayscale color to black->tone->white range +proc/ColorTone(rgb, tone) + var/list/RGB = ReadRGB(rgb) + var/list/TONE = ReadRGB(tone) + + var/gray = RGB[1]*0.3 + RGB[2]*0.59 + RGB[3]*0.11 + var/tone_gray = TONE[1]*0.3 + TONE[2]*0.59 + TONE[3]*0.11 + + if(gray <= tone_gray) return BlendRGB("#000000", tone, gray/(tone_gray || 1)) + else return BlendRGB(tone, "#ffffff", (gray-tone_gray)/((255-tone_gray) || 1)) + + +/* +Get flat icon by DarkCampainger. As it says on the tin, will return an icon with all the overlays +as a single icon. Useful for when you want to manipulate an icon via the above as overlays are not normally included. +The _flatIcons list is a cache for generated icon files. +*/ + +// Creates a single icon from a given /atom or /image. Only the first argument is required. +/proc/getFlatIcon(image/A, defdir=A.dir, deficon=A.icon, defstate=A.icon_state, defblend=A.blend_mode, exact=0) + // We start with a blank canvas, otherwise some icon procs crash silently + var/icon/flat = icon('icons/effects/effects.dmi', "nothing") // Final flattened icon + if(!A) + return flat + if(A.alpha <= 0) + return flat + var/noIcon = FALSE + + var/curicon + if(A.icon) + curicon = A.icon + else + curicon = deficon + + if(!curicon) + noIcon = TRUE // Do not render this object. + + var/curstate + if(A.icon_state) + curstate = A.icon_state + else + curstate = defstate + + if(!noIcon && !(curstate in icon_states(curicon))) + if("" in icon_states(curicon)) + curstate = "" + else + noIcon = TRUE // Do not render this object. + + var/curdir + if(!exact && (A.dir != 2)) + curdir = A.dir + else if(exact) + curdir = 2 + else + curdir = defdir + + var/curblend + if(A.blend_mode == BLEND_DEFAULT) + curblend = defblend + else + curblend = A.blend_mode + + // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed + var/list/layers = list() + var/image/copy + // Add the atom's icon itself, without pixel_x/y offsets. + if(!noIcon) + copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=curdir) + copy.color = A.color + copy.alpha = A.alpha + copy.blend_mode = curblend + layers[copy] = A.layer + + // Loop through the underlays, then overlays, sorting them into the layers list + var/list/process = A.underlays // Current list being processed + var/pSet=0 // Which list is being processed: 0 = underlays, 1 = overlays + var/curIndex=1 // index of 'current' in list being processed + var/current // Current overlay being sorted + var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER) + var/compare // The overlay 'add' is being compared against + var/cmpIndex // The index in the layers list of 'compare' + while(TRUE) + if(curIndex<=process.len) + current = process[curIndex] + if(!current) + curIndex++ //Try the next layer + continue + currentLayer = current:layer + if(currentLayer<0) // Special case for FLY_LAYER + if(currentLayer <= -1000) return flat + if(pSet == 0) // Underlay + currentLayer = A.layer+currentLayer/1000 + else // Overlay + currentLayer = A.layer+(1000+currentLayer)/1000 + + // Sort add into layers list + for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++) + compare = layers[cmpIndex] + if(currentLayer < layers[compare]) // Associated value is the calculated layer + layers.Insert(cmpIndex,current) + layers[current] = currentLayer + break + if(cmpIndex>layers.len) // Reached end of list without inserting + layers[current]=currentLayer // Place at end + + curIndex++ + + if(curIndex>process.len) + if(pSet == 0) // Switch to overlays + curIndex = 1 + pSet = 1 + process = A.overlays + else // All done + break + + var/icon/add // Icon of overlay being added + + // Current dimensions of flattened icon + var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()} + // Dimensions of overlay being added + var/{addX1;addX2;addY1;addY2} + + for(var/I in layers) + + if(I:alpha == 0) + continue + + if(I == copy) // 'I' is an /image based on the object being flattened. + curblend = BLEND_OVERLAY + add = icon(I:icon, I:icon_state, I:dir) + else // 'I' is an appearance object. + add = getFlatIcon(new/image(I), curdir, curicon, curstate, curblend) + + // Find the new dimensions of the flat icon to fit the added overlay + addX1 = min(flatX1, I:pixel_x+1) + addX2 = max(flatX2, I:pixel_x+add.Width()) + addY1 = min(flatY1, I:pixel_y+1) + addY2 = max(flatY2, I:pixel_y+add.Height()) + + if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2) + // Resize the flattened icon so the new icon fits + flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1) + flatX1=addX1;flatX2=addX2 + flatY1=addY1;flatY2=addY2 + + // Blend the overlay into the flattened icon + flat.Blend(add, blendMode2iconMode(curblend), I:pixel_x + 2 - flatX1, I:pixel_y + 2 - flatY1) + + if(A.color) + if(islist(A.color)) // Matrix color support. + flat.MapColors( + A.color[1] , A.color[2] , A.color[3] + , A.color[5] , A.color[6] , A.color[7] + , A.color[9] , A.color[10] , A.color[11] + , A.color[17] , A.color[18] , A.color[19] + ) + else + flat.Blend(A.color, ICON_MULTIPLY) + if(A.alpha < 255) + flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY) + + return icon(flat, "", SOUTH) + +/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 + +//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 + composite.Blend(icon(I.icon, I.icon_state, I.dir, 1), ICON_OVERLAY) + return composite + +proc/adjust_brightness(color, 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/sort_atoms_by_layer(list/atoms) + // Comb sort icons based on levels + var/list/result = atoms.Copy() + var/gap = result.len + var/swapped = 1 + while (gap > 1 || swapped) + swapped = 0 + if(gap > 1) + gap = round(gap / 1.3) // 1.3 is the emperic comb sort coefficient + if(gap < 1) + gap = 1 + for(var/i = 1; gap + i <= result.len; i++) + var/atom/l = result[i] //Fucking hate + var/atom/r = result[gap+i] //how lists work here + if(l.layer > r.layer) //no "result[i].layer" for me + result.Swap(i, gap + i) + swapped = 1 + return result + +var/global/list/humanoid_icon_cache = list() +//For creating consistent icons for human looking simple animals +/proc/get_flat_human_icon(icon_id,datum/job/J,datum/preferences/prefs) + if(!icon_id || !humanoid_icon_cache[icon_id]) + var/mob/living/carbon/human/dummy/body = new(null, prefs.species) + + if(prefs) + prefs.copy_to(body) + if(J) + J.equip(body, TRUE) + + var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing") + + body.dir = NORTH + var/icon/partial = getFlatIcon(body) + out_icon.Insert(partial,dir=NORTH) + + body.dir = SOUTH + partial = getFlatIcon(body) + out_icon.Insert(partial,dir=SOUTH) + + body.dir = WEST + partial = getFlatIcon(body) + out_icon.Insert(partial,dir=WEST) + + body.dir = EAST + partial = getFlatIcon(body) + out_icon.Insert(partial,dir=EAST) + + qdel(body) + + humanoid_icon_cache[icon_id] = out_icon + return out_icon + else + return humanoid_icon_cache[icon_id] diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 8a211f52846d..f0c81f8d6176 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -1,733 +1,733 @@ -/* - * Holds procs to help with list operations - * Contains groups: - * Misc - * Sorting - */ - -/* - * Misc - */ - -//Returns a list in plain english as a string -/proc/english_list(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/list,index) - if(istype(list) && list.len) - if(isnum(index)) - if(InRange(index,1,list.len)) - return list[index] - else if(index in list) - return list[index] - return - -//Return either pick(list) or null if list is not of type /list or is empty -proc/safepick(list/list) - if(!islist(list) || !list.len) - return - return pick(list) - -//Checks if the list is empty -proc/isemptylist(list/list) - if(!list.len) - return 1 - return 0 - -//Checks for specific types in a list -/proc/is_type_in_list(atom/A, list/L) - if(!L || !L.len || !A) - return 0 - 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/list) - if(istype(list)) - while(null in list) - list -= null - return - -// same as above, except it returns list back. -/proc/removeNullsFromList(list/L) - while(L.Remove(null)) - continue - return L - -/* - * 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(list/first, list/second, 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(list/first, list/second, 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/listfrom) - if (listfrom.len > 0) - var/picked = pick(listfrom) - listfrom -= picked - return picked - return null - -//Returns the top(last) element from the list and removes it from the list (typical stack function) -/proc/pop(list/listfrom) - if (listfrom.len > 0) - var/picked = listfrom[listfrom.len] - listfrom.len-- - return picked - return null - -//Returns the next element in parameter list after first appearance of parameter element. If it is the last element of the list or not present in list, returns first element. -/proc/next_in_list(element, list/L) - for(var/i=1, i= 1; i--) - output += L[i] - return output - -//Randomize: Return the list in a random order -/proc/shuffle(list/shufflelist) - if(!shufflelist) - return - var/list/new_list = list() - var/list/old_list = shufflelist.Copy() - while(old_list.len) - var/item = pick(old_list) - new_list += item - old_list -= item - return new_list - -//Return a list with no duplicate entries -/proc/uniquelist(list/L) - var/list/K = list() - for(var/item in L) - if(!(item in K)) - K += item - return K - -//Mergesort: divides up the list into halves to begin the sort -/proc/sortKey(list/client/L, order = 1) - if(isnull(L) || L.len < 2) - return L - var/middle = L.len / 2 + 1 - return mergeKey(sortKey(L.Copy(0,middle)), sortKey(L.Copy(middle)), order) - -//Mergsort: does the actual sorting and returns the results back to sortAtom -/proc/mergeKey(list/client/L, list/client/R, order = 1) - var/Li=1 - var/Ri=1 - var/list/result = new() - while(Li <= L.len && Ri <= R.len) - var/client/rL = L[Li] - var/client/rR = R[Ri] - if(sorttext(rL.ckey, rR.ckey) == order) - result += L[Li++] - else - result += R[Ri++] - - if(Li <= L.len) - return (result + L.Copy(Li, 0)) - return (result + R.Copy(Ri, 0)) - -//Mergesort: divides up the list into halves to begin the sort -/proc/sortAtom(list/atom/L, order = 1) - if(isnull(L) || L.len < 2) - return L - var/middle = L.len / 2 + 1 - return mergeAtoms(sortAtom(L.Copy(0,middle)), sortAtom(L.Copy(middle)), order) - -//Mergsort: does the actual sorting and returns the results back to sortAtom -/proc/mergeAtoms(list/atom/L, list/atom/R, order = 1) - var/Li=1 - var/Ri=1 - var/list/result = new() - while(Li <= L.len && Ri <= R.len) - var/atom/rL = L[Li] - var/atom/rR = R[Ri] - if(sorttext(rL.name, rR.name) == order) - result += L[Li++] - else - result += R[Ri++] - - if(Li <= L.len) - return (result + L.Copy(Li, 0)) - return (result + R.Copy(Ri, 0)) - - - - -//Mergesort: Specifically for record datums in a list. -/proc/sortRecord(list/datum/data/record/L, field = "name", order = 1) - if(isnull(L)) - return list() - if(L.len < 2) - return L - var/middle = L.len / 2 + 1 - return mergeRecordLists(sortRecord(L.Copy(0, middle), field, order), sortRecord(L.Copy(middle), field, order), field, order) - -//Mergsort: does the actual sorting and returns the results back to sortRecord -/proc/mergeRecordLists(list/datum/data/record/L, list/datum/data/record/R, field = "name", order = 1) - var/Li=1 - var/Ri=1 - var/list/result = new() - if(!isnull(L) && !isnull(R)) - while(Li <= L.len && Ri <= R.len) - var/datum/data/record/rL = L[Li] - if(isnull(rL)) - L -= rL - continue - var/datum/data/record/rR = R[Ri] - if(isnull(rR)) - R -= rR - continue - if(sorttext(rL.fields[field], rR.fields[field]) == order) - result += L[Li++] - else - result += R[Ri++] - - if(Li <= L.len) - return (result + L.Copy(Li, 0)) - return (result + R.Copy(Ri, 0)) - - - - -//any value in a list -/proc/sortList(list/L, cmp=/proc/cmp_text_asc) - return sortTim(L.Copy(), cmp) - -//Mergsorge: uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead -/proc/sortNames(list/L) - var/list/Q = new() - for(var/atom/x in L) - Q[x.name] = x - return sortList(Q) - -/proc/mergeLists(list/L, list/R) - var/Li=1 - var/Ri=1 - var/list/result = new() - while(Li <= L.len && Ri <= R.len) - if(sorttext(L[Li], R[Ri]) < 1) - result += R[Ri++] - else - result += L[Li++] - - if(Li <= L.len) - return (result + L.Copy(Li, 0)) - return (result + R.Copy(Ri, 0)) - - -// List of lists, sorts by element[key] - for things like crew monitoring computer sorting records by name. -/proc/sortByKey(list/L, key) - if(L.len < 2) - return L - var/middle = L.len / 2 + 1 - return mergeKeyedLists(sortByKey(L.Copy(0, middle), key), sortByKey(L.Copy(middle), key), key) - -/proc/mergeKeyedLists(list/L, list/R, key) - var/Li=1 - var/Ri=1 - var/list/result = new() - while(Li <= L.len && Ri <= R.len) - if(sorttext(L[Li][key], R[Ri][key]) < 1) - // Works around list += list2 merging lists; it's not pretty but it works - result += "temp item" - result[result.len] = R[Ri++] - else - result += "temp item" - result[result.len] = L[Li++] - - if(Li <= L.len) - return (result + L.Copy(Li, 0)) - return (result + R.Copy(Ri, 0)) - - -//Mergesort: any value in a list, preserves key=value structure -/proc/sortAssoc(list/L) - if(L.len < 2) - return L - var/middle = L.len / 2 + 1 // Copy is first,second-1 - return mergeAssoc(sortAssoc(L.Copy(0,middle)), sortAssoc(L.Copy(middle))) //second parameter null = to end of list - -/proc/mergeAssoc(list/L, list/R) - var/Li=1 - var/Ri=1 - var/list/result = new() - while(Li <= L.len && Ri <= R.len) - if(sorttext(L[Li], R[Ri]) < 1) - result += R&R[Ri++] - else - result += L&L[Li++] - - if(Li <= L.len) - return (result + L.Copy(Li, 0)) - return (result + R.Copy(Ri, 0)) - -//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(list/L, index) - var/i = 1 - for(var/key in L) - if(index == i) - return key - i++ - return null - -/proc/count_by_type(list/L, type) - var/i = 0 - for(var/T in L) - if(istype(T, type)) - i++ - return i - -//Don't use this on lists larger than half a dozen or so -/proc/insertion_sort_numeric_list_ascending(list/L) - //world.log << "ascending len input: [L.len]" - var/list/out = list(pop(L)) - for(var/entry in L) - if(isnum(entry)) - var/success = 0 - for(var/i=1, i<=out.len, i++) - if(entry <= out[i]) - success = 1 - out.Insert(i, entry) - break - if(!success) - out.Add(entry) - - //world.log << " output: [out.len]" - return out - -/proc/insertion_sort_numeric_list_descending(list/L) - //world.log << "descending len input: [L.len]" - var/list/out = insertion_sort_numeric_list_ascending(L) - //world.log << " output: [out.len]" - return reverselist(out) - -/proc/dd_sortedObjectList(list/L, cache=list()) - if(L.len < 2) - return L - var/middle = L.len / 2 + 1 // Copy is first,second-1 - return dd_mergeObjectList(dd_sortedObjectList(L.Copy(0,middle), cache), dd_sortedObjectList(L.Copy(middle), cache), cache) //second parameter null = to end of list - -/proc/dd_mergeObjectList(list/L, list/R, list/cache) - var/Li=1 - var/Ri=1 - var/list/result = new() - while(Li <= L.len && Ri <= R.len) - var/LLi = L[Li] - var/RRi = R[Ri] - var/LLiV = cache[LLi] - var/RRiV = cache[RRi] - if(!LLiV) - LLiV = LLi:dd_SortValue() - cache[LLi] = LLiV - if(!RRiV) - RRiV = RRi:dd_SortValue() - cache[RRi] = RRiV - if(LLiV < RRiV) - result += L[Li++] - else - result += R[Ri++] - - if(Li <= L.len) - return (result + L.Copy(Li, 0)) - return (result + R.Copy(Ri, 0)) - -// Insert an object into a sorted list, preserving sortedness -/proc/dd_insertObjectList(list/L, O) - var/min = 1 - var/max = L.len - var/Oval = O:dd_SortValue() - - while(1) - var/mid = min+round((max-min)/2) - - if(mid == max) - L.Insert(mid, O) - return - - var/Lmid = L[mid] - var/midval = Lmid:dd_SortValue() - if(Oval == midval) - L.Insert(mid, O) - return - else if(Oval < midval) - max = mid - else - min = mid+1 - -/* -proc/dd_sortedObjectList(list/incoming) - /* - Use binary search to order by dd_SortValue(). - This works by going to the half-point of the list, seeing if the node in - question is higher or lower cost, then going halfway up or down the list - and checking again. This is a very fast way to sort an item into a list. - */ - var/list/sorted_list = new() - var/low_index - var/high_index - var/insert_index - var/midway_calc - var/current_index - var/current_item - var/current_item_value - var/current_sort_object_value - var/list/list_bottom - - var/current_sort_object - for (current_sort_object in incoming) - low_index = 1 - high_index = sorted_list.len - while (low_index <= high_index) - // Figure out the midpoint, rounding up for fractions. (BYOND rounds down, so add 1 if necessary.) - midway_calc = (low_index + high_index) / 2 - current_index = round(midway_calc) - if (midway_calc > current_index) - current_index++ - current_item = sorted_list[current_index] - - current_item_value = current_item:dd_SortValue() - current_sort_object_value = current_sort_object:dd_SortValue() - if (current_sort_object_value < current_item_value) - high_index = current_index - 1 - else if (current_sort_object_value > current_item_value) - low_index = current_index + 1 - else - // current_sort_object == current_item - low_index = current_index - break - - // Insert before low_index. - insert_index = low_index - - // Special case adding to end of list. - if (insert_index > sorted_list.len) - sorted_list += current_sort_object - continue - - // Because BYOND lists don't support insert, have to do it by: - // 1) taking out bottom of list, 2) adding item, 3) putting back bottom of list. - list_bottom = sorted_list.Copy(insert_index) - sorted_list.Cut(insert_index) - sorted_list += current_sort_object - sorted_list += list_bottom - return sorted_list -*/ - -proc/dd_sortedtextlist(list/incoming, case_sensitive = 0) - // Returns a new list with the text values sorted. - // Use binary search to order by sortValue. - // This works by going to the half-point of the list, seeing if the node in question is higher or lower cost, - // then going halfway up or down the list and checking again. - // This is a very fast way to sort an item into a list. - var/list/sorted_text = new() - var/low_index - var/high_index - var/insert_index - var/midway_calc - var/current_index - var/current_item - var/list/list_bottom - var/sort_result - - var/current_sort_text - for (current_sort_text in incoming) - low_index = 1 - high_index = sorted_text.len - while (low_index <= high_index) - // Figure out the midpoint, rounding up for fractions. (BYOND rounds down, so add 1 if necessary.) - midway_calc = (low_index + high_index) / 2 - current_index = round(midway_calc) - if (midway_calc > current_index) - current_index++ - current_item = sorted_text[current_index] - - if (case_sensitive) - sort_result = sorttextEx(current_sort_text, current_item) - else - sort_result = sorttext(current_sort_text, current_item) - - switch(sort_result) - if (1) - high_index = current_index - 1 // current_sort_text < current_item - if (-1) - low_index = current_index + 1 // current_sort_text > current_item - if (0) - low_index = current_index // current_sort_text == current_item - break - - // Insert before low_index. - insert_index = low_index - - // Special case adding to end of list. - if (insert_index > sorted_text.len) - sorted_text += current_sort_text - continue - - // Because BYOND lists don't support insert, have to do it by: - // 1) taking out bottom of list, 2) adding item, 3) putting back bottom of list. - list_bottom = sorted_text.Copy(insert_index) - sorted_text.Cut(insert_index) - sorted_text += current_sort_text - sorted_text += list_bottom - return sorted_text - - -proc/dd_sortedTextList(list/incoming) - var/case_sensitive = 1 - return dd_sortedtextlist(incoming, case_sensitive) - -datum/proc/dd_SortValue() - return "[src]" - -/obj/machinery/dd_SortValue() - return "[sanitize(name)]" - -/obj/machinery/camera/dd_SortValue() - return "[c_tag]" - -/proc/filter_list(var/list/L, var/type) - . = list() - for(var/entry in L) - if(istype(entry, type)) - . += entry - -///datum/alarm/dd_SortValue() -// return "[sanitize(last_name)]" - -//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 && I <= length(L) ? L[I] : null) : L[I]) : null) -#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V; -#define LAZYLEN(L) length(L) -#define LAZYCLEARLIST(L) if(L) L.Cut() -#define LAZYCOPY(L) L && L.len ? L.Copy() : null -#define SANITIZE_LIST(L) ( islist(L) ? L : list() ) +/* + * Holds procs to help with list operations + * Contains groups: + * Misc + * Sorting + */ + +/* + * Misc + */ + +//Returns a list in plain english as a string +/proc/english_list(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/list,index) + if(istype(list) && list.len) + if(isnum(index)) + if(InRange(index,1,list.len)) + return list[index] + else if(index in list) + return list[index] + return + +//Return either pick(list) or null if list is not of type /list or is empty +proc/safepick(list/list) + if(!islist(list) || !list.len) + return + return pick(list) + +//Checks if the list is empty +proc/isemptylist(list/list) + if(!list.len) + return 1 + return 0 + +//Checks for specific types in a list +/proc/is_type_in_list(atom/A, list/L) + if(!L || !L.len || !A) + return 0 + 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/list) + if(istype(list)) + while(null in list) + list -= null + return + +// same as above, except it returns list back. +/proc/removeNullsFromList(list/L) + while(L.Remove(null)) + continue + return L + +/* + * 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(list/first, list/second, 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(list/first, list/second, 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/listfrom) + if (listfrom.len > 0) + var/picked = pick(listfrom) + listfrom -= picked + return picked + return null + +//Returns the top(last) element from the list and removes it from the list (typical stack function) +/proc/pop(list/listfrom) + if (listfrom.len > 0) + var/picked = listfrom[listfrom.len] + listfrom.len-- + return picked + return null + +//Returns the next element in parameter list after first appearance of parameter element. If it is the last element of the list or not present in list, returns first element. +/proc/next_in_list(element, list/L) + for(var/i=1, i= 1; i--) + output += L[i] + return output + +//Randomize: Return the list in a random order +/proc/shuffle(list/shufflelist) + if(!shufflelist) + return + var/list/new_list = list() + var/list/old_list = shufflelist.Copy() + while(old_list.len) + var/item = pick(old_list) + new_list += item + old_list -= item + return new_list + +//Return a list with no duplicate entries +/proc/uniquelist(list/L) + var/list/K = list() + for(var/item in L) + if(!(item in K)) + K += item + return K + +//Mergesort: divides up the list into halves to begin the sort +/proc/sortKey(list/client/L, order = 1) + if(isnull(L) || L.len < 2) + return L + var/middle = L.len / 2 + 1 + return mergeKey(sortKey(L.Copy(0,middle)), sortKey(L.Copy(middle)), order) + +//Mergsort: does the actual sorting and returns the results back to sortAtom +/proc/mergeKey(list/client/L, list/client/R, order = 1) + var/Li=1 + var/Ri=1 + var/list/result = new() + while(Li <= L.len && Ri <= R.len) + var/client/rL = L[Li] + var/client/rR = R[Ri] + if(sorttext(rL.ckey, rR.ckey) == order) + result += L[Li++] + else + result += R[Ri++] + + if(Li <= L.len) + return (result + L.Copy(Li, 0)) + return (result + R.Copy(Ri, 0)) + +//Mergesort: divides up the list into halves to begin the sort +/proc/sortAtom(list/atom/L, order = 1) + if(isnull(L) || L.len < 2) + return L + var/middle = L.len / 2 + 1 + return mergeAtoms(sortAtom(L.Copy(0,middle)), sortAtom(L.Copy(middle)), order) + +//Mergsort: does the actual sorting and returns the results back to sortAtom +/proc/mergeAtoms(list/atom/L, list/atom/R, order = 1) + var/Li=1 + var/Ri=1 + var/list/result = new() + while(Li <= L.len && Ri <= R.len) + var/atom/rL = L[Li] + var/atom/rR = R[Ri] + if(sorttext(rL.name, rR.name) == order) + result += L[Li++] + else + result += R[Ri++] + + if(Li <= L.len) + return (result + L.Copy(Li, 0)) + return (result + R.Copy(Ri, 0)) + + + + +//Mergesort: Specifically for record datums in a list. +/proc/sortRecord(list/datum/data/record/L, field = "name", order = 1) + if(isnull(L)) + return list() + if(L.len < 2) + return L + var/middle = L.len / 2 + 1 + return mergeRecordLists(sortRecord(L.Copy(0, middle), field, order), sortRecord(L.Copy(middle), field, order), field, order) + +//Mergsort: does the actual sorting and returns the results back to sortRecord +/proc/mergeRecordLists(list/datum/data/record/L, list/datum/data/record/R, field = "name", order = 1) + var/Li=1 + var/Ri=1 + var/list/result = new() + if(!isnull(L) && !isnull(R)) + while(Li <= L.len && Ri <= R.len) + var/datum/data/record/rL = L[Li] + if(isnull(rL)) + L -= rL + continue + var/datum/data/record/rR = R[Ri] + if(isnull(rR)) + R -= rR + continue + if(sorttext(rL.fields[field], rR.fields[field]) == order) + result += L[Li++] + else + result += R[Ri++] + + if(Li <= L.len) + return (result + L.Copy(Li, 0)) + return (result + R.Copy(Ri, 0)) + + + + +//any value in a list +/proc/sortList(list/L, cmp=/proc/cmp_text_asc) + return sortTim(L.Copy(), cmp) + +//Mergsorge: uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead +/proc/sortNames(list/L) + var/list/Q = new() + for(var/atom/x in L) + Q[x.name] = x + return sortList(Q) + +/proc/mergeLists(list/L, list/R) + var/Li=1 + var/Ri=1 + var/list/result = new() + while(Li <= L.len && Ri <= R.len) + if(sorttext(L[Li], R[Ri]) < 1) + result += R[Ri++] + else + result += L[Li++] + + if(Li <= L.len) + return (result + L.Copy(Li, 0)) + return (result + R.Copy(Ri, 0)) + + +// List of lists, sorts by element[key] - for things like crew monitoring computer sorting records by name. +/proc/sortByKey(list/L, key) + if(L.len < 2) + return L + var/middle = L.len / 2 + 1 + return mergeKeyedLists(sortByKey(L.Copy(0, middle), key), sortByKey(L.Copy(middle), key), key) + +/proc/mergeKeyedLists(list/L, list/R, key) + var/Li=1 + var/Ri=1 + var/list/result = new() + while(Li <= L.len && Ri <= R.len) + if(sorttext(L[Li][key], R[Ri][key]) < 1) + // Works around list += list2 merging lists; it's not pretty but it works + result += "temp item" + result[result.len] = R[Ri++] + else + result += "temp item" + result[result.len] = L[Li++] + + if(Li <= L.len) + return (result + L.Copy(Li, 0)) + return (result + R.Copy(Ri, 0)) + + +//Mergesort: any value in a list, preserves key=value structure +/proc/sortAssoc(list/L) + if(L.len < 2) + return L + var/middle = L.len / 2 + 1 // Copy is first,second-1 + return mergeAssoc(sortAssoc(L.Copy(0,middle)), sortAssoc(L.Copy(middle))) //second parameter null = to end of list + +/proc/mergeAssoc(list/L, list/R) + var/Li=1 + var/Ri=1 + var/list/result = new() + while(Li <= L.len && Ri <= R.len) + if(sorttext(L[Li], R[Ri]) < 1) + result += R&R[Ri++] + else + result += L&L[Li++] + + if(Li <= L.len) + return (result + L.Copy(Li, 0)) + return (result + R.Copy(Ri, 0)) + +//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(list/L, index) + var/i = 1 + for(var/key in L) + if(index == i) + return key + i++ + return null + +/proc/count_by_type(list/L, type) + var/i = 0 + for(var/T in L) + if(istype(T, type)) + i++ + return i + +//Don't use this on lists larger than half a dozen or so +/proc/insertion_sort_numeric_list_ascending(list/L) + //world.log << "ascending len input: [L.len]" + var/list/out = list(pop(L)) + for(var/entry in L) + if(isnum(entry)) + var/success = 0 + for(var/i=1, i<=out.len, i++) + if(entry <= out[i]) + success = 1 + out.Insert(i, entry) + break + if(!success) + out.Add(entry) + + //world.log << " output: [out.len]" + return out + +/proc/insertion_sort_numeric_list_descending(list/L) + //world.log << "descending len input: [L.len]" + var/list/out = insertion_sort_numeric_list_ascending(L) + //world.log << " output: [out.len]" + return reverselist(out) + +/proc/dd_sortedObjectList(list/L, cache=list()) + if(L.len < 2) + return L + var/middle = L.len / 2 + 1 // Copy is first,second-1 + return dd_mergeObjectList(dd_sortedObjectList(L.Copy(0,middle), cache), dd_sortedObjectList(L.Copy(middle), cache), cache) //second parameter null = to end of list + +/proc/dd_mergeObjectList(list/L, list/R, list/cache) + var/Li=1 + var/Ri=1 + var/list/result = new() + while(Li <= L.len && Ri <= R.len) + var/LLi = L[Li] + var/RRi = R[Ri] + var/LLiV = cache[LLi] + var/RRiV = cache[RRi] + if(!LLiV) + LLiV = LLi:dd_SortValue() + cache[LLi] = LLiV + if(!RRiV) + RRiV = RRi:dd_SortValue() + cache[RRi] = RRiV + if(LLiV < RRiV) + result += L[Li++] + else + result += R[Ri++] + + if(Li <= L.len) + return (result + L.Copy(Li, 0)) + return (result + R.Copy(Ri, 0)) + +// Insert an object into a sorted list, preserving sortedness +/proc/dd_insertObjectList(list/L, O) + var/min = 1 + var/max = L.len + var/Oval = O:dd_SortValue() + + while(1) + var/mid = min+round((max-min)/2) + + if(mid == max) + L.Insert(mid, O) + return + + var/Lmid = L[mid] + var/midval = Lmid:dd_SortValue() + if(Oval == midval) + L.Insert(mid, O) + return + else if(Oval < midval) + max = mid + else + min = mid+1 + +/* +proc/dd_sortedObjectList(list/incoming) + /* + Use binary search to order by dd_SortValue(). + This works by going to the half-point of the list, seeing if the node in + question is higher or lower cost, then going halfway up or down the list + and checking again. This is a very fast way to sort an item into a list. + */ + var/list/sorted_list = new() + var/low_index + var/high_index + var/insert_index + var/midway_calc + var/current_index + var/current_item + var/current_item_value + var/current_sort_object_value + var/list/list_bottom + + var/current_sort_object + for (current_sort_object in incoming) + low_index = 1 + high_index = sorted_list.len + while (low_index <= high_index) + // Figure out the midpoint, rounding up for fractions. (BYOND rounds down, so add 1 if necessary.) + midway_calc = (low_index + high_index) / 2 + current_index = round(midway_calc) + if (midway_calc > current_index) + current_index++ + current_item = sorted_list[current_index] + + current_item_value = current_item:dd_SortValue() + current_sort_object_value = current_sort_object:dd_SortValue() + if (current_sort_object_value < current_item_value) + high_index = current_index - 1 + else if (current_sort_object_value > current_item_value) + low_index = current_index + 1 + else + // current_sort_object == current_item + low_index = current_index + break + + // Insert before low_index. + insert_index = low_index + + // Special case adding to end of list. + if (insert_index > sorted_list.len) + sorted_list += current_sort_object + continue + + // Because BYOND lists don't support insert, have to do it by: + // 1) taking out bottom of list, 2) adding item, 3) putting back bottom of list. + list_bottom = sorted_list.Copy(insert_index) + sorted_list.Cut(insert_index) + sorted_list += current_sort_object + sorted_list += list_bottom + return sorted_list +*/ + +proc/dd_sortedtextlist(list/incoming, case_sensitive = 0) + // Returns a new list with the text values sorted. + // Use binary search to order by sortValue. + // This works by going to the half-point of the list, seeing if the node in question is higher or lower cost, + // then going halfway up or down the list and checking again. + // This is a very fast way to sort an item into a list. + var/list/sorted_text = new() + var/low_index + var/high_index + var/insert_index + var/midway_calc + var/current_index + var/current_item + var/list/list_bottom + var/sort_result + + var/current_sort_text + for (current_sort_text in incoming) + low_index = 1 + high_index = sorted_text.len + while (low_index <= high_index) + // Figure out the midpoint, rounding up for fractions. (BYOND rounds down, so add 1 if necessary.) + midway_calc = (low_index + high_index) / 2 + current_index = round(midway_calc) + if (midway_calc > current_index) + current_index++ + current_item = sorted_text[current_index] + + if (case_sensitive) + sort_result = sorttextEx(current_sort_text, current_item) + else + sort_result = sorttext(current_sort_text, current_item) + + switch(sort_result) + if (1) + high_index = current_index - 1 // current_sort_text < current_item + if (-1) + low_index = current_index + 1 // current_sort_text > current_item + if (0) + low_index = current_index // current_sort_text == current_item + break + + // Insert before low_index. + insert_index = low_index + + // Special case adding to end of list. + if (insert_index > sorted_text.len) + sorted_text += current_sort_text + continue + + // Because BYOND lists don't support insert, have to do it by: + // 1) taking out bottom of list, 2) adding item, 3) putting back bottom of list. + list_bottom = sorted_text.Copy(insert_index) + sorted_text.Cut(insert_index) + sorted_text += current_sort_text + sorted_text += list_bottom + return sorted_text + + +proc/dd_sortedTextList(list/incoming) + var/case_sensitive = 1 + return dd_sortedtextlist(incoming, case_sensitive) + +datum/proc/dd_SortValue() + return "[src]" + +/obj/machinery/dd_SortValue() + return "[sanitize(name)]" + +/obj/machinery/camera/dd_SortValue() + return "[c_tag]" + +/proc/filter_list(var/list/L, var/type) + . = list() + for(var/entry in L) + if(istype(entry, type)) + . += entry + +///datum/alarm/dd_SortValue() +// return "[sanitize(last_name)]" + +//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 && I <= length(L) ? L[I] : null) : L[I]) : null) +#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V; +#define LAZYLEN(L) length(L) +#define LAZYCLEARLIST(L) if(L) L.Cut() +#define LAZYCOPY(L) L && L.len ? L.Copy() : null +#define SANITIZE_LIST(L) ( islist(L) ? L : list() ) diff --git a/code/__HELPERS/logging.dm b/code/__HELPERS/logging.dm index 0b32a7934b90..24b7555e1221 100644 --- a/code/__HELPERS/logging.dm +++ b/code/__HELPERS/logging.dm @@ -1,156 +1,156 @@ -#define LOG_CLEANING(text) \ - replace_characters(text, list("\proper"="","\improper"="", JA_CODE=JA_PLACEHOLDER, JA_CODE_ASCII=JA_PLACEHOLDER, JA_CHARACTER=JA_PLACEHOLDER)) - -//print an error message to world.log - - -// On Linux/Unix systems the line endings are LF, on windows it's CRLF, admins that don't use notepad++ -// will get logs that are one big line if the system is Linux and they are using notepad. This solves it by adding CR to every line ending -// in the logs. ascii character 13 = CR - -/var/global/log_end= world.system_type == UNIX ? ascii2text(13) : "" - -//print an error message to world.log -#define ERROR(MSG) error("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].") -/proc/error(msg) - world.log << "## ERROR: [msg][log_end]" - -//print a warning message to world.log -#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].") -/proc/warning(msg) - world.log << "## WARNING: [msg][log_end]" - -//print a testing-mode debug message to world.log -/proc/testing(msg) - world.log << "## TESTING: [msg][log_end]" - -/proc/log_admin(text) - admin_log.Add(text) - if (config.log_admin) - diary << "\[[time_stamp()]]ADMIN: [LOG_CLEANING(text)][log_end]" - - -/proc/log_debug(text) - if (config.log_debug) - diary << "\[[time_stamp()]]DEBUG: [text][log_end]" - - for(var/client/C in admins) - if(C.prefs.chat_toggles & CHAT_DEBUGLOGS) - to_chat(C, "DEBUG: [text]") - - -/proc/log_game(text) - if (config.log_game) - diary << "\[[time_stamp()]]GAME: [text][log_end]" - -/proc/log_vote(text) - if (config.log_vote) - diary << "\[[time_stamp()]]VOTE: [LOG_CLEANING(text)][log_end]" - -/proc/log_access(text) - if (config.log_access) - diary << "\[[time_stamp()]]ACCESS: [text][log_end]" - -/proc/log_say(text) - if (config.log_say) - diary << "\[[time_stamp()]]SAY: [LOG_CLEANING(text)][log_end]" - -/proc/log_ooc(text) - if (config.log_ooc) - diary << "\[[time_stamp()]]OOC: [LOG_CLEANING(text)][log_end]" - -/proc/log_whisper(text) - if (config.log_whisper) - diary << "\[[time_stamp()]]WHISPER: [LOG_CLEANING(text)][log_end]" - -/proc/log_emote(text) - if (config.log_emote) - diary << "\[[time_stamp()]]EMOTE: [LOG_CLEANING(text)][log_end]" - -/proc/log_attack(text) - if (config.log_attack) - diary << "\[[time_stamp()]]ATTACK: [text][log_end]" //Seperate attack logs? Why? FOR THE GLORY OF SATAN! - -/proc/log_adminsay(text, say_type) - admin_log.Add(text) - if (config.log_adminchat) - diary << "\[[time_stamp()]][say_type]: [LOG_CLEANING(text)][log_end]" - -/proc/log_adminwarn(text) - if (config.log_adminwarn) - diary << "\[[time_stamp()]]ADMINWARN: [LOG_CLEANING(text)][log_end]" - -/proc/log_pda(text) - if (config.log_pda) - diary << "\[[time_stamp()]]PDA: [LOG_CLEANING(text)][log_end]" - -/proc/log_misc(text) - diary << "\[[time_stamp()]]MISC: [text][log_end]" - -//pretty print a direction bitflag, can be useful for debugging. -/proc/print_dir(dir) - var/list/comps = list() - if(dir & NORTH) comps += "NORTH" - if(dir & SOUTH) comps += "SOUTH" - if(dir & EAST) comps += "EAST" - if(dir & WEST) comps += "WEST" - if(dir & UP) comps += "UP" - if(dir & DOWN) comps += "DOWN" - - return english_list(comps, nothing_text="0", and_text="|", comma_text="|") - -/proc/log_fax(text) - if (config.log_fax) - diary << "\[[time_stamp()]]FAX: [LOG_CLEANING(text)][log_end]" - -/proc/datum_info_line(datum/D) - if(!istype(D)) - return - if(!istype(D, /mob)) - return "[D] ([D.type])" - var/mob/M = D - return "[M] ([M.ckey]) ([M.type])" - -/proc/atom_loc_line(atom/A) - if(!istype(A)) - return - var/turf/T = get_turf(A) - if(istype(T)) - return "[A.loc] [COORD(T)] ([A.loc.type])" - else if(A.loc) - return "[A.loc] (0, 0, 0) ([A.loc.type])" - -//Print a list of antagonists to the server log -/proc/antagonist_announce() - var/text = "ANTAG LIST:\n" - var/objectives - var/temprole - var/list/total_antagonists = list() - //Look into all mobs in world, dead or alive - for(var/datum/mind/Mind in ticker.minds) - temprole = Mind.special_role - objectives = "" - if(temprole) //if they are an antagonist of some sort. - if(Mind.objectives.len) - for(var/datum/objective/O in Mind.objectives) - if(length(objectives)) - objectives += " | " - objectives += "[O.explanation_text]" - objectives = " \[[objectives]\]" - - if(temprole in total_antagonists) //If the role exists already, add the name to it - total_antagonists[temprole] += "\n, [Mind.name]([Mind.key])[objectives]" - else - total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob - total_antagonists[temprole] += ": [Mind.name]([Mind.key])[objectives]" - - //Now print them all into the log! - if(total_antagonists.len) - for(var/i in total_antagonists) - text += "[i]s[total_antagonists[i]]." - else - text += "no antagonists this moment" - - log_game(text) - +#define LOG_CLEANING(text) \ + replace_characters(text, list("\proper"="","\improper"="", JA_CODE=JA_PLACEHOLDER, JA_CODE_ASCII=JA_PLACEHOLDER, JA_CHARACTER=JA_PLACEHOLDER)) + +//print an error message to world.log + + +// On Linux/Unix systems the line endings are LF, on windows it's CRLF, admins that don't use notepad++ +// will get logs that are one big line if the system is Linux and they are using notepad. This solves it by adding CR to every line ending +// in the logs. ascii character 13 = CR + +/var/global/log_end= world.system_type == UNIX ? ascii2text(13) : "" + +//print an error message to world.log +#define ERROR(MSG) error("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].") +/proc/error(msg) + world.log << "## ERROR: [msg][log_end]" + +//print a warning message to world.log +#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].") +/proc/warning(msg) + world.log << "## WARNING: [msg][log_end]" + +//print a testing-mode debug message to world.log +/proc/testing(msg) + world.log << "## TESTING: [msg][log_end]" + +/proc/log_admin(text) + admin_log.Add(text) + if (config.log_admin) + diary << "\[[time_stamp()]]ADMIN: [LOG_CLEANING(text)][log_end]" + + +/proc/log_debug(text) + if (config.log_debug) + diary << "\[[time_stamp()]]DEBUG: [text][log_end]" + + for(var/client/C in admins) + if(C.prefs.chat_toggles & CHAT_DEBUGLOGS) + to_chat(C, "DEBUG: [text]") + + +/proc/log_game(text) + if (config.log_game) + diary << "\[[time_stamp()]]GAME: [text][log_end]" + +/proc/log_vote(text) + if (config.log_vote) + diary << "\[[time_stamp()]]VOTE: [LOG_CLEANING(text)][log_end]" + +/proc/log_access(text) + if (config.log_access) + diary << "\[[time_stamp()]]ACCESS: [text][log_end]" + +/proc/log_say(text) + if (config.log_say) + diary << "\[[time_stamp()]]SAY: [LOG_CLEANING(text)][log_end]" + +/proc/log_ooc(text) + if (config.log_ooc) + diary << "\[[time_stamp()]]OOC: [LOG_CLEANING(text)][log_end]" + +/proc/log_whisper(text) + if (config.log_whisper) + diary << "\[[time_stamp()]]WHISPER: [LOG_CLEANING(text)][log_end]" + +/proc/log_emote(text) + if (config.log_emote) + diary << "\[[time_stamp()]]EMOTE: [LOG_CLEANING(text)][log_end]" + +/proc/log_attack(text) + if (config.log_attack) + diary << "\[[time_stamp()]]ATTACK: [text][log_end]" //Seperate attack logs? Why? FOR THE GLORY OF SATAN! + +/proc/log_adminsay(text, say_type) + admin_log.Add(text) + if (config.log_adminchat) + diary << "\[[time_stamp()]][say_type]: [LOG_CLEANING(text)][log_end]" + +/proc/log_adminwarn(text) + if (config.log_adminwarn) + diary << "\[[time_stamp()]]ADMINWARN: [LOG_CLEANING(text)][log_end]" + +/proc/log_pda(text) + if (config.log_pda) + diary << "\[[time_stamp()]]PDA: [LOG_CLEANING(text)][log_end]" + +/proc/log_misc(text) + diary << "\[[time_stamp()]]MISC: [text][log_end]" + +//pretty print a direction bitflag, can be useful for debugging. +/proc/print_dir(dir) + var/list/comps = list() + if(dir & NORTH) comps += "NORTH" + if(dir & SOUTH) comps += "SOUTH" + if(dir & EAST) comps += "EAST" + if(dir & WEST) comps += "WEST" + if(dir & UP) comps += "UP" + if(dir & DOWN) comps += "DOWN" + + return english_list(comps, nothing_text="0", and_text="|", comma_text="|") + +/proc/log_fax(text) + if (config.log_fax) + diary << "\[[time_stamp()]]FAX: [LOG_CLEANING(text)][log_end]" + +/proc/datum_info_line(datum/D) + if(!istype(D)) + return + if(!istype(D, /mob)) + return "[D] ([D.type])" + var/mob/M = D + return "[M] ([M.ckey]) ([M.type])" + +/proc/atom_loc_line(atom/A) + if(!istype(A)) + return + var/turf/T = get_turf(A) + if(istype(T)) + return "[A.loc] [COORD(T)] ([A.loc.type])" + else if(A.loc) + return "[A.loc] (0, 0, 0) ([A.loc.type])" + +//Print a list of antagonists to the server log +/proc/antagonist_announce() + var/text = "ANTAG LIST:\n" + var/objectives + var/temprole + var/list/total_antagonists = list() + //Look into all mobs in world, dead or alive + for(var/datum/mind/Mind in ticker.minds) + temprole = Mind.special_role + objectives = "" + if(temprole) //if they are an antagonist of some sort. + if(Mind.objectives.len) + for(var/datum/objective/O in Mind.objectives) + if(length(objectives)) + objectives += " | " + objectives += "[O.explanation_text]" + objectives = " \[[objectives]\]" + + if(temprole in total_antagonists) //If the role exists already, add the name to it + total_antagonists[temprole] += "\n, [Mind.name]([Mind.key])[objectives]" + else + total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob + total_antagonists[temprole] += ": [Mind.name]([Mind.key])[objectives]" + + //Now print them all into the log! + if(total_antagonists.len) + for(var/i in total_antagonists) + text += "[i]s[total_antagonists[i]]." + else + text += "no antagonists this moment" + + log_game(text) + #undef LOG_CLEANING \ No newline at end of file diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index c20fccf6d8cd..f7a36b1154d3 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -1,145 +1,145 @@ -// Credits to Nickr5 for the useful procs I've taken from his library resource. -#define ACCURACY 10000 //accuracy for normal distribution - -var/const/E = 2.71828183 -var/const/Sqrt2 = 1.41421356 - -/proc/Atan2(x, y) - if(!x && !y) return 0 - var/a = arccos(x / sqrt(x*x + y*y)) - return y >= 0 ? a : -a - -// 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) - return round(x) - -// 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) - -// Performs a linear interpolation between a and b. -// Note that amount=0 returns a, amount=1 returns b, and -// amount=0.5 returns the mean of a and b. -/proc/Lerp(a, b, amount = 0.5) - return a + (b - a) * amount - -/proc/Mean(...) - var/values = 0 - var/sum = 0 - for(var/val in args) - values++ - sum += val - return sum / values - -var/normal_next -/proc/NormalDistr(mean = 0, stddev = 1) //because gaussian() looks... strange. This is Box-Muller transform - if(normal_next != null) - . = mean + normal_next * stddev - normal_next = null - else - var/R1 = sqrt(-2.0 * log(rand(1, ACCURACY) / ACCURACY)) - var/R2 = 360 * (rand(0, ACCURACY) / ACCURACY) //because BYOND's cos() and sin() accepts degrees - . = mean + (R1 * cos(R2)) * stddev - normal_next = R1 * sin(R2) - return . - -// Returns the nth root of x. -/proc/Root(n, x) - return x ** (1 / n) - -// secant -/proc/Sec(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(x) - return sin(x) / cos(x) - -/proc/ToDegrees(radians) - // 180 / Pi - return radians * 57.2957795 - -/proc/ToRadians(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) - -//converts a uniform distributed random number into a normal distributed one -//since this method produces two random numbers, one is saved for subsequent calls -//(making the cost negligble for every second call) -//This will return +/- decimals, situated about mean with standard deviation stddev -//68% chance that the number is within 1stddev -//95% chance that the number is within 2stddev -//98% chance that the number is within 3stddev...etc -var/gaussian_next -/proc/gaussian(mean, stddev) - var/R1;var/R2;var/working - if(gaussian_next != null) - R1 = gaussian_next - gaussian_next = null - else - do - R1 = rand(-ACCURACY,ACCURACY)/ACCURACY - R2 = rand(-ACCURACY,ACCURACY)/ACCURACY - working = R1*R1 + R2*R2 - while(working >= 1 || working==0) - working = sqrt(-2 * log(working) / working) - R1 *= working - gaussian_next = R2 * working - return (mean + stddev * R1) - -#undef ACCURACY +// Credits to Nickr5 for the useful procs I've taken from his library resource. +#define ACCURACY 10000 //accuracy for normal distribution + +var/const/E = 2.71828183 +var/const/Sqrt2 = 1.41421356 + +/proc/Atan2(x, y) + if(!x && !y) return 0 + var/a = arccos(x / sqrt(x*x + y*y)) + return y >= 0 ? a : -a + +// 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) + return round(x) + +// 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) + +// Performs a linear interpolation between a and b. +// Note that amount=0 returns a, amount=1 returns b, and +// amount=0.5 returns the mean of a and b. +/proc/Lerp(a, b, amount = 0.5) + return a + (b - a) * amount + +/proc/Mean(...) + var/values = 0 + var/sum = 0 + for(var/val in args) + values++ + sum += val + return sum / values + +var/normal_next +/proc/NormalDistr(mean = 0, stddev = 1) //because gaussian() looks... strange. This is Box-Muller transform + if(normal_next != null) + . = mean + normal_next * stddev + normal_next = null + else + var/R1 = sqrt(-2.0 * log(rand(1, ACCURACY) / ACCURACY)) + var/R2 = 360 * (rand(0, ACCURACY) / ACCURACY) //because BYOND's cos() and sin() accepts degrees + . = mean + (R1 * cos(R2)) * stddev + normal_next = R1 * sin(R2) + return . + +// Returns the nth root of x. +/proc/Root(n, x) + return x ** (1 / n) + +// secant +/proc/Sec(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(x) + return sin(x) / cos(x) + +/proc/ToDegrees(radians) + // 180 / Pi + return radians * 57.2957795 + +/proc/ToRadians(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) + +//converts a uniform distributed random number into a normal distributed one +//since this method produces two random numbers, one is saved for subsequent calls +//(making the cost negligble for every second call) +//This will return +/- decimals, situated about mean with standard deviation stddev +//68% chance that the number is within 1stddev +//95% chance that the number is within 2stddev +//98% chance that the number is within 3stddev...etc +var/gaussian_next +/proc/gaussian(mean, stddev) + var/R1;var/R2;var/working + if(gaussian_next != null) + R1 = gaussian_next + gaussian_next = null + else + do + R1 = rand(-ACCURACY,ACCURACY)/ACCURACY + R2 = rand(-ACCURACY,ACCURACY)/ACCURACY + working = R1*R1 + R2*R2 + while(working >= 1 || working==0) + working = sqrt(-2 * log(working) / working) + R1 *= working + gaussian_next = R2 * working + return (mean + stddev * R1) + +#undef ACCURACY diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm index fb35821c319d..34392a569608 100644 --- a/code/__HELPERS/matrices.dm +++ b/code/__HELPERS/matrices.dm @@ -1,254 +1,254 @@ -/matrix/proc/TurnTo(old_angle, new_angle) - . = new_angle - old_angle - Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT - - -/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3) - if(!segments) - return - var/segment = 360/segments - if(!clockwise) - segment = -segment - var/list/matrices = list() - for(var/i in 1 to segments-1) - var/matrix/M = matrix(transform) - M.Turn(segment*i) - matrices += M - var/matrix/last = matrix(transform) - matrices += last - - speed /= segments - - animate(src, transform = matrices[1], time = speed, loops) - for(var/i in 2 to segments) //2 because 1 is covered above - animate(transform = matrices[i], time = speed) - //doesn't have an object argument because this is "Stacking" with the animate call above - //3 billion% intentional - -/datum/ColorMatrix - var/list/matrix - var/combined = 1 - var/const/lumR = 0.3086 // or 0.2125 - var/const/lumG = 0.6094 // or 0.7154 - var/const/lumB = 0.0820 // or 0.0721 - -/datum/ColorMatrix/New(mat, contrast = 1, brightness = null) - ..() - - if(istext(mat)) - SetPreset(mat) - if(!matrix) - SetColor(mat, contrast, brightness) - else if(isnum(mat)) - SetSaturation(mat, contrast, brightness) - else - matrix = mat - -/datum/ColorMatrix/proc/Reset() - matrix = list(1,0,0, - 0,1,0, - 0,0,1) - -/datum/ColorMatrix/proc/Get(contrast = 1) - var/list/mat = matrix - mat = mat.Copy() - - for(var/i = 1 to min(mat.len, 12)) - mat[i] *= contrast - - return mat - -/datum/ColorMatrix/proc/SetSaturation(s, c = 1, b = null) - var - sr = (1 - s) * lumR - sg = (1 - s) * lumG - sb = (1 - s) * lumB - - matrix = list(c * (sr + s), c * (sr), c * (sr), - c * (sg), c * (sg + s), c * (sg), - c * (sb), c * (sb), c * (sb + s)) - - SetBrightness(b) - -/datum/ColorMatrix/proc/SetBrightness(brightness) - if(brightness == null) return - - if(!matrix) - Reset() - - - if(matrix.len == 9 || matrix.len == 16) - matrix += brightness - matrix += brightness - matrix += brightness - - if(matrix.len == 16) - matrix += 0 - - else if(matrix.len == 12) - for(var/i = matrix.len to matrix.len - 3 step -1) - matrix[i] = brightness - - else if(matrix.len == 3) - for(var/i = matrix.len - 1 to matrix.len - 4 step -1) - matrix[i] = brightness - -/datum/ColorMatrix/proc/hex2value(hex) - var/num1 = copytext(hex, 1, 2) - var/num2 = copytext(hex, 2) - - if(isnum(text2num(num1))) - num1 = text2num(num1) - else - num1 = text2ascii(lowertext(num1)) - 87 - - if(isnum(text2num(num1))) - num2 = text2num(num1) - else - num2 = text2ascii(lowertext(num2)) - 87 - - return num1 * 16 + num2 - -/datum/ColorMatrix/proc/SetColor(color, contrast = 1, brightness = null) - var/rr = hex2value(copytext(color, 2, 4)) / 255 - var/gg = hex2value(copytext(color, 4, 6)) / 255 - var/bb = hex2value(copytext(color, 6, 8)) / 255 - - rr = round(rr * 1000) / 1000 * contrast - gg = round(gg * 1000) / 1000 * contrast - bb = round(bb * 1000) / 1000 * contrast - - matrix = list(rr, gg, bb, - rr, gg, bb, - rr, gg, bb) - - SetBrightness(brightness) - -/datum/ColorMatrix/proc/SetPreset(preset) - switch(lowertext(preset)) - if("invert") - matrix = list(-1,0,0, - 0,-1,0, - 0,0,-1, - 1,1,1) - if("nightsight") - matrix = list(-1,-1,-1, - 0,0,0, - 0,0,0, - 1,1,1) - if("nightsight_glasses") - matrix = list(0,0,1, - 1,0,0, - 0,1,0, - 0.8,0.8,0.8) - if("thermal") - matrix = list(1.4,0.8,0.8, - 0,0,0, - 0,0,0, - -0.2,-0.2,-0.2) - if("nvg") - matrix = list(0,0,0, - 1.7,1,1.6, - 0,0,0, - -0.2,0.4,-0.2) - if("nvg_military") - matrix = list(0,0,0, - 1.2,1.4,1.1, - 0,0,0, - -0.2,-0.2,-0.2) - if("meson") - matrix = list(0,0,0, - 1.7,1.9,1.6, - 0,0,0, - -0.5,-0.4,-0.5) - if("sci") - matrix = list(1,0,0.05, - 0.05,0.95,0.05, - 0.05,0,1) - if("greyscale") - matrix = list(0.33,0.33,0.33, - 0.59,0.59,0.59, - 0.11,0.11,0.11) - if("sepia") - matrix = list(0.393,0.349,0.272, - 0.769,0.686,0.534, - 0.189,0.168,0.131, - 0,0,0) - if("black & white") - matrix = list(1.5,1.5,1.5, - 1.5,1.5,1.5, - 1.5,1.5,1.5, - -1,-1,-1) - if("polaroid") - matrix = list(1.438,-0.062,-0.062, - 0.122,1.378,-0.122, - 0.016,-0.016,1.483, - -0.03,0.05,-0.02) - if("bgr_d") - matrix = list(0,0,1, - 0,1,0, - 1,0,0, - 0,0,-0.5) - if("brg_d") - matrix = list(0,0,1, - 1,0,0, - 0,1,0, - 0,-0.5,0) - if("gbr_d") - matrix = list(0,1,0, - 0,0,1, - 1,0,0, - 0,0,-0.5) - if("grb_d") - matrix = list(0,1,0, - 1,0,0, - 0,0,1, - 0,-0.5,0) - if("rbg_d") - matrix = list(1,0,0, - 0,0,1, - 0,1,0, - -0.5,0,0) - if("rgb_d") - matrix = list(1,0,0, - 0,1,0, - 0,0,1, - -0.3,-0.3,-0.3) - if("rgb") - matrix = list(1,0,0, - 0,1,0, - 0,0,1, - 0,0,0) - -/proc/matrixMultiply(list/mat1, list/mat2) - if(istype(mat1, /datum/ColorMatrix)) - mat1 = mat1:matrix - - if(istype(mat2, /datum/ColorMatrix)) - mat2 = mat2:matrix - - if(mat1.len != mat2.len || mat1.len < 9) return - - var/rowSize = mat1.len % 3 == 0 ? 3 : 4 - var/colSize = mat1.len / rowSize - - var/resultMatrix[mat1.len] - - var/i1 - var/i2 - for(var/i = 1 to colSize) - i1 = (i - 1) * rowSize + 1 - - for(var/j = 1 to rowSize) - i2 = j - - var/result = 0 - - for(var/k = 1 to rowSize) - - result += mat1[i1 + (k - 1)] * mat2[i2] - i2 += rowSize - - resultMatrix[(i - 1) * rowSize + j] = result - - return resultMatrix +/matrix/proc/TurnTo(old_angle, new_angle) + . = new_angle - old_angle + Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT + + +/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3) + if(!segments) + return + var/segment = 360/segments + if(!clockwise) + segment = -segment + var/list/matrices = list() + for(var/i in 1 to segments-1) + var/matrix/M = matrix(transform) + M.Turn(segment*i) + matrices += M + var/matrix/last = matrix(transform) + matrices += last + + speed /= segments + + animate(src, transform = matrices[1], time = speed, loops) + for(var/i in 2 to segments) //2 because 1 is covered above + animate(transform = matrices[i], time = speed) + //doesn't have an object argument because this is "Stacking" with the animate call above + //3 billion% intentional + +/datum/ColorMatrix + var/list/matrix + var/combined = 1 + var/const/lumR = 0.3086 // or 0.2125 + var/const/lumG = 0.6094 // or 0.7154 + var/const/lumB = 0.0820 // or 0.0721 + +/datum/ColorMatrix/New(mat, contrast = 1, brightness = null) + ..() + + if(istext(mat)) + SetPreset(mat) + if(!matrix) + SetColor(mat, contrast, brightness) + else if(isnum(mat)) + SetSaturation(mat, contrast, brightness) + else + matrix = mat + +/datum/ColorMatrix/proc/Reset() + matrix = list(1,0,0, + 0,1,0, + 0,0,1) + +/datum/ColorMatrix/proc/Get(contrast = 1) + var/list/mat = matrix + mat = mat.Copy() + + for(var/i = 1 to min(mat.len, 12)) + mat[i] *= contrast + + return mat + +/datum/ColorMatrix/proc/SetSaturation(s, c = 1, b = null) + var + sr = (1 - s) * lumR + sg = (1 - s) * lumG + sb = (1 - s) * lumB + + matrix = list(c * (sr + s), c * (sr), c * (sr), + c * (sg), c * (sg + s), c * (sg), + c * (sb), c * (sb), c * (sb + s)) + + SetBrightness(b) + +/datum/ColorMatrix/proc/SetBrightness(brightness) + if(brightness == null) return + + if(!matrix) + Reset() + + + if(matrix.len == 9 || matrix.len == 16) + matrix += brightness + matrix += brightness + matrix += brightness + + if(matrix.len == 16) + matrix += 0 + + else if(matrix.len == 12) + for(var/i = matrix.len to matrix.len - 3 step -1) + matrix[i] = brightness + + else if(matrix.len == 3) + for(var/i = matrix.len - 1 to matrix.len - 4 step -1) + matrix[i] = brightness + +/datum/ColorMatrix/proc/hex2value(hex) + var/num1 = copytext(hex, 1, 2) + var/num2 = copytext(hex, 2) + + if(isnum(text2num(num1))) + num1 = text2num(num1) + else + num1 = text2ascii(lowertext(num1)) - 87 + + if(isnum(text2num(num1))) + num2 = text2num(num1) + else + num2 = text2ascii(lowertext(num2)) - 87 + + return num1 * 16 + num2 + +/datum/ColorMatrix/proc/SetColor(color, contrast = 1, brightness = null) + var/rr = hex2value(copytext(color, 2, 4)) / 255 + var/gg = hex2value(copytext(color, 4, 6)) / 255 + var/bb = hex2value(copytext(color, 6, 8)) / 255 + + rr = round(rr * 1000) / 1000 * contrast + gg = round(gg * 1000) / 1000 * contrast + bb = round(bb * 1000) / 1000 * contrast + + matrix = list(rr, gg, bb, + rr, gg, bb, + rr, gg, bb) + + SetBrightness(brightness) + +/datum/ColorMatrix/proc/SetPreset(preset) + switch(lowertext(preset)) + if("invert") + matrix = list(-1,0,0, + 0,-1,0, + 0,0,-1, + 1,1,1) + if("nightsight") + matrix = list(-1,-1,-1, + 0,0,0, + 0,0,0, + 1,1,1) + if("nightsight_glasses") + matrix = list(0,0,1, + 1,0,0, + 0,1,0, + 0.8,0.8,0.8) + if("thermal") + matrix = list(1.4,0.8,0.8, + 0,0,0, + 0,0,0, + -0.2,-0.2,-0.2) + if("nvg") + matrix = list(0,0,0, + 1.7,1,1.6, + 0,0,0, + -0.2,0.4,-0.2) + if("nvg_military") + matrix = list(0,0,0, + 1.2,1.4,1.1, + 0,0,0, + -0.2,-0.2,-0.2) + if("meson") + matrix = list(0,0,0, + 1.7,1.9,1.6, + 0,0,0, + -0.5,-0.4,-0.5) + if("sci") + matrix = list(1,0,0.05, + 0.05,0.95,0.05, + 0.05,0,1) + if("greyscale") + matrix = list(0.33,0.33,0.33, + 0.59,0.59,0.59, + 0.11,0.11,0.11) + if("sepia") + matrix = list(0.393,0.349,0.272, + 0.769,0.686,0.534, + 0.189,0.168,0.131, + 0,0,0) + if("black & white") + matrix = list(1.5,1.5,1.5, + 1.5,1.5,1.5, + 1.5,1.5,1.5, + -1,-1,-1) + if("polaroid") + matrix = list(1.438,-0.062,-0.062, + 0.122,1.378,-0.122, + 0.016,-0.016,1.483, + -0.03,0.05,-0.02) + if("bgr_d") + matrix = list(0,0,1, + 0,1,0, + 1,0,0, + 0,0,-0.5) + if("brg_d") + matrix = list(0,0,1, + 1,0,0, + 0,1,0, + 0,-0.5,0) + if("gbr_d") + matrix = list(0,1,0, + 0,0,1, + 1,0,0, + 0,0,-0.5) + if("grb_d") + matrix = list(0,1,0, + 1,0,0, + 0,0,1, + 0,-0.5,0) + if("rbg_d") + matrix = list(1,0,0, + 0,0,1, + 0,1,0, + -0.5,0,0) + if("rgb_d") + matrix = list(1,0,0, + 0,1,0, + 0,0,1, + -0.3,-0.3,-0.3) + if("rgb") + matrix = list(1,0,0, + 0,1,0, + 0,0,1, + 0,0,0) + +/proc/matrixMultiply(list/mat1, list/mat2) + if(istype(mat1, /datum/ColorMatrix)) + mat1 = mat1:matrix + + if(istype(mat2, /datum/ColorMatrix)) + mat2 = mat2:matrix + + if(mat1.len != mat2.len || mat1.len < 9) return + + var/rowSize = mat1.len % 3 == 0 ? 3 : 4 + var/colSize = mat1.len / rowSize + + var/resultMatrix[mat1.len] + + var/i1 + var/i2 + for(var/i = 1 to colSize) + i1 = (i - 1) * rowSize + 1 + + for(var/j = 1 to rowSize) + i2 = j + + var/result = 0 + + for(var/k = 1 to rowSize) + + result += mat1[i1 + (k - 1)] * mat2[i2] + i2 += rowSize + + resultMatrix[(i - 1) * rowSize + j] = result + + return resultMatrix diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index b1dd202c8380..91a915483159 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -1,233 +1,233 @@ -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/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, species = HUMAN) - if(gender==FEMALE) return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names)) - else return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) - -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(93 to 100) - return "health93" - if(86 to 93) - return "health86" - if(78 to 86) - return "health78" - if(71 to 78) - return "health71" - if(64 to 71) - return "health64" - if(56 to 64) - return "health56" - if(49 to 56) - return "health49" - if(42 to 49) - return "health42" - if(35 to 42) - return "health35" - if(28 to 35) - return "health28" - if(21 to 28) - return "health21" - if(14 to 21) - return "health14" - if(7 to 14) - return "health7" - if(1 to 7) - return "health1" - if(-50 to 1) - return "health0" - if(-85 to -50) - return "health-50" - if(-99 to -85) - return "health-85" - else - return "health-100" - return "0" - -//helper for inverting armor blocked values into a multiplier -#define blocked_mult(blocked) max(1 - (blocked / 100), 0) - -/proc/do_mob(mob/user , mob/target, time = 30, check_target_zone = FALSE, uninterruptible = FALSE, progress = TRUE) - if(!user || !target) - return FALSE - - user.busy_with_action = TRUE - - if(check_target_zone) - check_target_zone = user.zone_sel.selecting - - var/user_loc = user.loc - - var/target_loc = target.loc - - var/holding = user.get_active_hand() - var/datum/progressbar/progbar - if (progress) - if(user.client && (user.client.prefs.toggles & SHOW_PROGBAR)) - progbar = new(user, time, target) - else - progress = FALSE - - var/endtime = world.time+time - var/starttime = world.time - . = TRUE - while (world.time < endtime) - stoplag() - if (progress) - progbar.update(world.time - starttime) - if(QDELETED(user) || QDELETED(target)) - . = FALSE - break - if(uninterruptible) - continue - if(user.loc != user_loc || target.loc != target_loc || user.get_active_hand() != holding || user.incapacitated() || user.lying ) - . = FALSE - break - if(check_target_zone && user.zone_sel.selecting != check_target_zone) - . = FALSE - break - if(progress) - qdel(progbar) - if(user) - user.busy_with_action = FALSE - -/proc/do_after(mob/user, delay, needhand = TRUE, atom/target = null, can_move = FALSE, progress = TRUE) - if(!user || target && QDELING(target)) - return FALSE - - user.busy_with_action = TRUE - - var/target_null = TRUE - var/atom/Tloc = null - if(target) - target_null = FALSE - if(target != user) - target.in_use_action = TRUE - Tloc = target.loc - - var/atom/Uloc = null - if(!can_move) - Uloc = user.loc - - var/obj/item/holding = user.get_active_hand() - - var/holdingnull = TRUE //User's hand started out empty, check for an empty hand - if(holding) - holdingnull = FALSE //Users hand started holding something, check to see if it's still holding that - - var/datum/progressbar/progbar - if (progress) - if(user.client && (user.client.prefs.toggles & SHOW_PROGBAR)) - progbar = new(user, delay, target) - else - progress = FALSE - - var/endtime = world.time + delay - var/starttime = world.time - . = TRUE - while (world.time < endtime) - stoplag() - if (progress) - progbar.update(world.time - starttime) - - if(QDELETED(user) || !target_null && QDELETED(target)) - . = FALSE - break - - if(user.stat || user.weakened || user.stunned) - . = FALSE - break - - if(Uloc && (user.loc != Uloc) || Tloc && (Tloc != target.loc)) - . = FALSE - break - - if(needhand) - //This might seem like an odd check, but you can still need a hand even when it's empty - //i.e the hand is used to pull some item/tool out of the construction - if(!holdingnull && QDELETED(holding)) - . = FALSE - break - if(user.get_active_hand() != holding) - . = FALSE - break - if(progress) - qdel(progbar) - if(user) - user.busy_with_action = FALSE - if(target) - target.in_use_action = FALSE +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/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, species = HUMAN) + if(gender==FEMALE) return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names)) + else return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) + +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(93 to 100) + return "health93" + if(86 to 93) + return "health86" + if(78 to 86) + return "health78" + if(71 to 78) + return "health71" + if(64 to 71) + return "health64" + if(56 to 64) + return "health56" + if(49 to 56) + return "health49" + if(42 to 49) + return "health42" + if(35 to 42) + return "health35" + if(28 to 35) + return "health28" + if(21 to 28) + return "health21" + if(14 to 21) + return "health14" + if(7 to 14) + return "health7" + if(1 to 7) + return "health1" + if(-50 to 1) + return "health0" + if(-85 to -50) + return "health-50" + if(-99 to -85) + return "health-85" + else + return "health-100" + return "0" + +//helper for inverting armor blocked values into a multiplier +#define blocked_mult(blocked) max(1 - (blocked / 100), 0) + +/proc/do_mob(mob/user , mob/target, time = 30, check_target_zone = FALSE, uninterruptible = FALSE, progress = TRUE) + if(!user || !target) + return FALSE + + user.busy_with_action = TRUE + + if(check_target_zone) + check_target_zone = user.zone_sel.selecting + + var/user_loc = user.loc + + var/target_loc = target.loc + + var/holding = user.get_active_hand() + var/datum/progressbar/progbar + if (progress) + if(user.client && (user.client.prefs.toggles & SHOW_PROGBAR)) + progbar = new(user, time, target) + else + progress = FALSE + + var/endtime = world.time+time + var/starttime = world.time + . = TRUE + while (world.time < endtime) + stoplag() + if (progress) + progbar.update(world.time - starttime) + if(QDELETED(user) || QDELETED(target)) + . = FALSE + break + if(uninterruptible) + continue + if(user.loc != user_loc || target.loc != target_loc || user.get_active_hand() != holding || user.incapacitated() || user.lying ) + . = FALSE + break + if(check_target_zone && user.zone_sel.selecting != check_target_zone) + . = FALSE + break + if(progress) + qdel(progbar) + if(user) + user.busy_with_action = FALSE + +/proc/do_after(mob/user, delay, needhand = TRUE, atom/target = null, can_move = FALSE, progress = TRUE) + if(!user || target && QDELING(target)) + return FALSE + + user.busy_with_action = TRUE + + var/target_null = TRUE + var/atom/Tloc = null + if(target) + target_null = FALSE + if(target != user) + target.in_use_action = TRUE + Tloc = target.loc + + var/atom/Uloc = null + if(!can_move) + Uloc = user.loc + + var/obj/item/holding = user.get_active_hand() + + var/holdingnull = TRUE //User's hand started out empty, check for an empty hand + if(holding) + holdingnull = FALSE //Users hand started holding something, check to see if it's still holding that + + var/datum/progressbar/progbar + if (progress) + if(user.client && (user.client.prefs.toggles & SHOW_PROGBAR)) + progbar = new(user, delay, target) + else + progress = FALSE + + var/endtime = world.time + delay + var/starttime = world.time + . = TRUE + while (world.time < endtime) + stoplag() + if (progress) + progbar.update(world.time - starttime) + + if(QDELETED(user) || !target_null && QDELETED(target)) + . = FALSE + break + + if(user.stat || user.weakened || user.stunned) + . = FALSE + break + + if(Uloc && (user.loc != Uloc) || Tloc && (Tloc != target.loc)) + . = FALSE + break + + if(needhand) + //This might seem like an odd check, but you can still need a hand even when it's empty + //i.e the hand is used to pull some item/tool out of the construction + if(!holdingnull && QDELETED(holding)) + . = FALSE + break + if(user.get_active_hand() != holding) + . = FALSE + break + if(progress) + qdel(progbar) + if(user) + user.busy_with_action = FALSE + if(target) + target.in_use_action = FALSE diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 18fd2c44947b..4d3c295831f1 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -1,336 +1,336 @@ -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") - name += " of [religion_name()]" - - return name - -var/command_name = null -/proc/command_name() - if (command_name) - return command_name - - var/name = "Central Command" - - command_name = name - return name - -/proc/change_command_name(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/system_name() - return "Tau Ceti" //Screw Nyx - -/proc/station_name() - if (station_name) - return station_name - - station_name = new_station_name() - - if (config && config.server_name) - world.name = "[config.server_name]: [station_name]" - else - world.name = station_name - - return station_name - -/proc/new_station_name() - var/random = rand(1,5) - var/name = "" - var/return_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") - return_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) - return_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") - return_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) - return_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") - return_name += name + " " - - // ID Number - switch(random) - if(1) - return_name += "[rand(1, 99)]" - if(2) - return_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) - return_name += pick("II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX") - if(4) - return_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) - return_name += pick("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen") - if(13) - return_name += pick("13","XIII","Thirteen") - - return return_name - -/proc/world_name(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 - -var/gang_name_pool = list("Clandestine", "Prima", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Donk", "Gene", "Gib", "Tunnel", "Diablo", "Psyke", "Osiron") -var/gang_A_name = null -var/gang_B_name = null -/proc/gang_name(gang) - if(!gang_A_name || !gang_B_name) - gang_A_name = pick(gang_name_pool) - gang_name_pool -= gang_A_name - gang_B_name = pick(gang_name_pool) - gang_name_pool -= gang_B_name - - if(gang == "A") - if(gang_A_name) - return gang_A_name - if(gang == "B") - if(gang_B_name) - return gang_B_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","tequilla 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(joblist)//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, "\red Code Phrase is: \black [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","tequilla 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(joblist)]" - 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(joblist)]" - syndicate_code_response += "." - else - syndicate_code_response += pick("*shrug*","*smile*","*blink*","*sigh*","*laugh*","*nod*","*giggle*") - if(3) - if(4) - if(5) - - return -*/ +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") + name += " of [religion_name()]" + + return name + +var/command_name = null +/proc/command_name() + if (command_name) + return command_name + + var/name = "Central Command" + + command_name = name + return name + +/proc/change_command_name(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/system_name() + return "Tau Ceti" //Screw Nyx + +/proc/station_name() + if (station_name) + return station_name + + station_name = new_station_name() + + if (config && config.server_name) + world.name = "[config.server_name]: [station_name]" + else + world.name = station_name + + return station_name + +/proc/new_station_name() + var/random = rand(1,5) + var/name = "" + var/return_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") + return_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) + return_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") + return_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) + return_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") + return_name += name + " " + + // ID Number + switch(random) + if(1) + return_name += "[rand(1, 99)]" + if(2) + return_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) + return_name += pick("II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX") + if(4) + return_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) + return_name += pick("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen") + if(13) + return_name += pick("13","XIII","Thirteen") + + return return_name + +/proc/world_name(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 + +var/gang_name_pool = list("Clandestine", "Prima", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Donk", "Gene", "Gib", "Tunnel", "Diablo", "Psyke", "Osiron") +var/gang_A_name = null +var/gang_B_name = null +/proc/gang_name(gang) + if(!gang_A_name || !gang_B_name) + gang_A_name = pick(gang_name_pool) + gang_name_pool -= gang_A_name + gang_B_name = pick(gang_name_pool) + gang_name_pool -= gang_B_name + + if(gang == "A") + if(gang_A_name) + return gang_A_name + if(gang == "B") + if(gang_B_name) + return gang_B_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","tequilla 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(joblist)//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, "\red Code Phrase is: \black [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","tequilla 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(joblist)]" + 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(joblist)]" + syndicate_code_response += "." + else + syndicate_code_response += pick("*shrug*","*smile*","*blink*","*sigh*","*laugh*","*nod*","*giggle*") + if(3) + if(4) + if(5) + + return +*/ diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index 4b521f9bfbb7..ca23a2a7f7b7 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 8818cf8dab2a..05d77c578cb2 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -1,395 +1,395 @@ -/* - * 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/sanitize_sql(t) - var/sanitized_text = replacetext(t, "'", "\\'") - sanitized_text = replacetext(sanitized_text, "\"", "\\\"") - return sanitized_text - -// Sanitize inputs to avoid SQL injection attacks -proc/sql_sanitize_text(text) - text = replacetext(text, "'", "''") - text = replacetext(text, ";", "") - text = replacetext(text, "&", "") - return text - -/* - * Text sanitization - */ - -//Used for preprocessing entered text -/proc/sanitize(input, max_length = MAX_MESSAGE_LEN, encode = TRUE, trim = TRUE, extra = TRUE) - if(!input) - return - - if(max_length) - input = copytext(input,1,max_length) - - input = replacetext(input, JA_CHARACTER, JA_PLACEHOLDER) - - if(extra) - input = replace_characters(input, list("\n"=" ","\t"=" ")) - - if(encode) - //In addition to processing html, html_encode removes byond formatting codes like "\red", "\i" and other. - //It is important to avoid double-encode text, it can "break" quotes and some other characters. - //Also, keep in mind that escaped characters don't work in the interface (window titles, lower left corner of the main window, etc.) - input = html_encode(input) - else - //If not need encode text, simply remove < and > - //note: we can also remove here byond formatting codes: 0xFF + next byte - input = replace_characters(input, list("<"=" ", ">"=" ")) - - if(trim) - //Maybe, we need trim text twice? Here and before copytext? - input = trim(input) - - return input - -//Run sanitize(), but remove <, >, " first to prevent displaying them as > < &34; in some places, after html_encode(). -//Best used for sanitize object names, window titles. -//If you have a problem with sanitize() in chat, when quotes and >, < are displayed as html entites - -//this is a problem of double-encode(when & becomes &), use sanitize() with encode=0, but not the sanitize_safe()! -/proc/sanitize_safe(input, max_length = MAX_MESSAGE_LEN, encode = TRUE, trim = TRUE, extra = TRUE) - return sanitize(replace_characters(input, list(">"=" ","<"=" ", "\""="'")), max_length, encode, trim, extra) - -//Filters out undesirable characters from names -/proc/sanitize_name(input, max_length = MAX_NAME_LEN, allow_numbers = 0, force_first_letter_uppercase = TRUE) - if(!input || length(input) > 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/output = "" - - for(var/i=1, i<=length(input), i++) - var/ascii_char = text2ascii(input,i) - switch(ascii_char) - // A .. Z - if(65 to 90) //Uppercase Letters - output += ascii2text(ascii_char) - number_of_alphanumeric++ - last_char_group = 4 - - // a .. z - if(97 to 122) //Lowercase Letters - if(last_char_group<2 && force_first_letter_uppercase) - output += ascii2text(ascii_char-32) //Force uppercase first character - else - output += 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 - output += ascii2text(ascii_char) - number_of_alphanumeric++ - last_char_group = 3 - - // ' - . - if(39,45,46) //Common name punctuation - if(!last_char_group) continue - output += 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 - output += 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 - output += 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) - output = copytext(output,1,length(output)) //removes the last character (in this case a space) - - if(lowertext(output) in forbidden_names) //prevents these common metagamey names - return //(not case sensitive) - - return output - -/proc/sanitize_slack(t) - return replacetext(html_decode(reset_ja(t)), "\"", "'") - -//Returns null if there is any bad text in the string -/proc/reject_bad_text(text, max_length=512) - if(length(text) > max_length) return //message too long - var/non_whitespace = 0 - for(var/i=1, i<=length(text), i++) - switch(text2ascii(text,i)) - if(62,60,92,47) return //rejects the text if it contains these bad characters: <, >, \ or / - if(127 to 181) return //rejects weird letters like � - if(183 to 191) return //rejects weird letters like � - if(0 to 31) return //more weird stuff - if(32) continue //whitespace - else non_whitespace = 1 - if(non_whitespace) return text //only accepts the text if it has some non-spaces - - -//reset to placeholder for inputs, logs -/proc/reset_ja(text) - return replace_characters(text, list(JA_CODE=JA_PLACEHOLDER, JA_CODE_ASCII=JA_PLACEHOLDER, JA_CHARACTER=JA_PLACEHOLDER)) - -//replace ja with entity for chat/popup -/proc/entity_ja(text) - return replace_characters(text, list(JA_PLACEHOLDER=JA_ENTITY, JA_ENTITY_ASCII=JA_ENTITY)) - -/proc/input_default(text) - return html_decode(reset_ja(text))//replace br with \n? -/* - * 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/replace_characters(var/t,var/list/repl_chars) - for(var/char in repl_chars) - t = replacetext(t, char, repl_chars[char]) - return t - -//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(t) - return uppertext_(copytext(t, 1, 2)) + copytext(t, 2) - -//This proc strips html properly, remove < > and all text between -//for complete text sanitizing should be used sanitize() -/proc/strip_html_properly(var/input) - if(!input) - return - var/opentag = 1 //These store the position of < and > respectively. - var/closetag = 1 - while(1) - opentag = findtext(input, "<") - closetag = findtext(input, ">") - if(closetag && opentag) - if(closetag < opentag) - input = copytext(input, (closetag + 1)) - else - input = copytext(input, 1, opentag) + copytext(input, (closetag + 1)) - else if(closetag || opentag) - if(opentag) - input = copytext(input, 1, opentag) - else - input = copytext(input, (closetag + 1)) - else - break - - return input - -//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(text,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(lentext(text) != lentext(compare)) - return 0 - for(var/i = 1, i < lentext(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(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 <= lentext(text), i++) - var/a = copytext(text,i,i+1) - if(a == character) - count++ - return count - -/proc/reverse_text(text = "") - var/new_text = "" - for(var/i = length(text); i > 0; i--) - new_text += copytext(text, i, i+1) - return new_text - -//Replaces \red \blue \green \b etc with span classes for to_chat -/proc/replace_text_macro(match, code, rest) - var/regex/text_macro = new("(\\xFF.)(.*)$") - switch(code) - if("\red") - return "[text_macro.Replace(rest, /proc/replace_text_macro)]" - if("\blue", "\green") - return "[text_macro.Replace(rest, /proc/replace_text_macro)]" - if("\b") - return "[text_macro.Replace(rest, /proc/replace_text_macro)]" - else - return text_macro.Replace(rest, /proc/replace_text_macro) - -/proc/macro2html(text) - var/static/regex/text_macro = new("(\\xFF.)(.*)$") - return text_macro.Replace(text, /proc/replace_text_macro) - -/* - * Byond - * (remove this when byond lern unicode) - */ - -/proc/lowertext_(var/text) - var/lenght = length(text) - var/new_text = null - var/lcase_letter - var/letter_ascii - - var/p = 1 - while(p <= lenght) - lcase_letter = copytext(text, p, p + 1) - letter_ascii = text2ascii(lcase_letter) - - if((letter_ascii >= 65 && letter_ascii <= 90) || (letter_ascii >= 192 && letter_ascii < 223)) - lcase_letter = ascii2text(letter_ascii + 32) - else if(letter_ascii == 223) - lcase_letter = JA_PLACEHOLDER - - new_text += lcase_letter - p++ - - return new_text - -/proc/uppertext_(var/text) - var/lenght = length(text) - var/new_text = null - var/ucase_letter - var/letter_ascii - - var/p = 1 - while(p <= lenght) - ucase_letter = copytext(text, p, p + 1) - letter_ascii = text2ascii(ucase_letter) - - if((letter_ascii >= 97 && letter_ascii <= 122) || (letter_ascii >= 224 && letter_ascii < 255)) - ucase_letter = ascii2text(letter_ascii - 32) - else if(letter_ascii == JA_PLACEHOLDER_CODE) - ucase_letter = JA_UPPERCHARACTER - - new_text += ucase_letter - p++ - - return new_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/sanitize_sql(t) + var/sanitized_text = replacetext(t, "'", "\\'") + sanitized_text = replacetext(sanitized_text, "\"", "\\\"") + return sanitized_text + +// Sanitize inputs to avoid SQL injection attacks +proc/sql_sanitize_text(text) + text = replacetext(text, "'", "''") + text = replacetext(text, ";", "") + text = replacetext(text, "&", "") + return text + +/* + * Text sanitization + */ + +//Used for preprocessing entered text +/proc/sanitize(input, max_length = MAX_MESSAGE_LEN, encode = TRUE, trim = TRUE, extra = TRUE) + if(!input) + return + + if(max_length) + input = copytext(input,1,max_length) + + input = replacetext(input, JA_CHARACTER, JA_PLACEHOLDER) + + if(extra) + input = replace_characters(input, list("\n"=" ","\t"=" ")) + + if(encode) + //In addition to processing html, html_encode removes byond formatting codes like "\red", "\i" and other. + //It is important to avoid double-encode text, it can "break" quotes and some other characters. + //Also, keep in mind that escaped characters don't work in the interface (window titles, lower left corner of the main window, etc.) + input = html_encode(input) + else + //If not need encode text, simply remove < and > + //note: we can also remove here byond formatting codes: 0xFF + next byte + input = replace_characters(input, list("<"=" ", ">"=" ")) + + if(trim) + //Maybe, we need trim text twice? Here and before copytext? + input = trim(input) + + return input + +//Run sanitize(), but remove <, >, " first to prevent displaying them as > < &34; in some places, after html_encode(). +//Best used for sanitize object names, window titles. +//If you have a problem with sanitize() in chat, when quotes and >, < are displayed as html entites - +//this is a problem of double-encode(when & becomes &), use sanitize() with encode=0, but not the sanitize_safe()! +/proc/sanitize_safe(input, max_length = MAX_MESSAGE_LEN, encode = TRUE, trim = TRUE, extra = TRUE) + return sanitize(replace_characters(input, list(">"=" ","<"=" ", "\""="'")), max_length, encode, trim, extra) + +//Filters out undesirable characters from names +/proc/sanitize_name(input, max_length = MAX_NAME_LEN, allow_numbers = 0, force_first_letter_uppercase = TRUE) + if(!input || length(input) > 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/output = "" + + for(var/i=1, i<=length(input), i++) + var/ascii_char = text2ascii(input,i) + switch(ascii_char) + // A .. Z + if(65 to 90) //Uppercase Letters + output += ascii2text(ascii_char) + number_of_alphanumeric++ + last_char_group = 4 + + // a .. z + if(97 to 122) //Lowercase Letters + if(last_char_group<2 && force_first_letter_uppercase) + output += ascii2text(ascii_char-32) //Force uppercase first character + else + output += 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 + output += ascii2text(ascii_char) + number_of_alphanumeric++ + last_char_group = 3 + + // ' - . + if(39,45,46) //Common name punctuation + if(!last_char_group) continue + output += 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 + output += 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 + output += 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) + output = copytext(output,1,length(output)) //removes the last character (in this case a space) + + if(lowertext(output) in forbidden_names) //prevents these common metagamey names + return //(not case sensitive) + + return output + +/proc/sanitize_slack(t) + return replacetext(html_decode(reset_ja(t)), "\"", "'") + +//Returns null if there is any bad text in the string +/proc/reject_bad_text(text, max_length=512) + if(length(text) > max_length) return //message too long + var/non_whitespace = 0 + for(var/i=1, i<=length(text), i++) + switch(text2ascii(text,i)) + if(62,60,92,47) return //rejects the text if it contains these bad characters: <, >, \ or / + if(127 to 181) return //rejects weird letters like � + if(183 to 191) return //rejects weird letters like � + if(0 to 31) return //more weird stuff + if(32) continue //whitespace + else non_whitespace = 1 + if(non_whitespace) return text //only accepts the text if it has some non-spaces + + +//reset to placeholder for inputs, logs +/proc/reset_ja(text) + return replace_characters(text, list(JA_CODE=JA_PLACEHOLDER, JA_CODE_ASCII=JA_PLACEHOLDER, JA_CHARACTER=JA_PLACEHOLDER)) + +//replace ja with entity for chat/popup +/proc/entity_ja(text) + return replace_characters(text, list(JA_PLACEHOLDER=JA_ENTITY, JA_ENTITY_ASCII=JA_ENTITY)) + +/proc/input_default(text) + return html_decode(reset_ja(text))//replace br with \n? +/* + * 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/replace_characters(var/t,var/list/repl_chars) + for(var/char in repl_chars) + t = replacetext(t, char, repl_chars[char]) + return t + +//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(t) + return uppertext_(copytext(t, 1, 2)) + copytext(t, 2) + +//This proc strips html properly, remove < > and all text between +//for complete text sanitizing should be used sanitize() +/proc/strip_html_properly(var/input) + if(!input) + return + var/opentag = 1 //These store the position of < and > respectively. + var/closetag = 1 + while(1) + opentag = findtext(input, "<") + closetag = findtext(input, ">") + if(closetag && opentag) + if(closetag < opentag) + input = copytext(input, (closetag + 1)) + else + input = copytext(input, 1, opentag) + copytext(input, (closetag + 1)) + else if(closetag || opentag) + if(opentag) + input = copytext(input, 1, opentag) + else + input = copytext(input, (closetag + 1)) + else + break + + return input + +//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(text,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(lentext(text) != lentext(compare)) + return 0 + for(var/i = 1, i < lentext(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(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 <= lentext(text), i++) + var/a = copytext(text,i,i+1) + if(a == character) + count++ + return count + +/proc/reverse_text(text = "") + var/new_text = "" + for(var/i = length(text); i > 0; i--) + new_text += copytext(text, i, i+1) + return new_text + +//Replaces \red \blue \green \b etc with span classes for to_chat +/proc/replace_text_macro(match, code, rest) + var/regex/text_macro = new("(\\xFF.)(.*)$") + switch(code) + if("\red") + return "[text_macro.Replace(rest, /proc/replace_text_macro)]" + if("\blue", "\green") + return "[text_macro.Replace(rest, /proc/replace_text_macro)]" + if("\b") + return "[text_macro.Replace(rest, /proc/replace_text_macro)]" + else + return text_macro.Replace(rest, /proc/replace_text_macro) + +/proc/macro2html(text) + var/static/regex/text_macro = new("(\\xFF.)(.*)$") + return text_macro.Replace(text, /proc/replace_text_macro) + +/* + * Byond + * (remove this when byond lern unicode) + */ + +/proc/lowertext_(var/text) + var/lenght = length(text) + var/new_text = null + var/lcase_letter + var/letter_ascii + + var/p = 1 + while(p <= lenght) + lcase_letter = copytext(text, p, p + 1) + letter_ascii = text2ascii(lcase_letter) + + if((letter_ascii >= 65 && letter_ascii <= 90) || (letter_ascii >= 192 && letter_ascii < 223)) + lcase_letter = ascii2text(letter_ascii + 32) + else if(letter_ascii == 223) + lcase_letter = JA_PLACEHOLDER + + new_text += lcase_letter + p++ + + return new_text + +/proc/uppertext_(var/text) + var/lenght = length(text) + var/new_text = null + var/ucase_letter + var/letter_ascii + + var/p = 1 + while(p <= lenght) + ucase_letter = copytext(text, p, p + 1) + letter_ascii = text2ascii(ucase_letter) + + if((letter_ascii >= 97 && letter_ascii <= 122) || (letter_ascii >= 224 && letter_ascii < 255)) + ucase_letter = ascii2text(letter_ascii - 32) + else if(letter_ascii == JA_PLACEHOLDER_CODE) + ucase_letter = JA_UPPERCHARACTER + + new_text += ucase_letter + p++ + + return new_text diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm index 7a26f3d0d4af..8e068a42acdd 100644 --- a/code/__HELPERS/time.dm +++ b/code/__HELPERS/time.dm @@ -1,75 +1,75 @@ -#define SECOND *10 -#define SECONDS *10 - -#define MINUTE *600 -#define MINUTES *600 - -//Returns the world time in english -proc/worldtime2text(time = world.time) - return "[round(time / 36000)+12]:[(time / 600 % 60) < 10 ? add_zero(time / 600 % 60, 1) : time / 600 % 60]" - -/proc/time_stamp(format = "hh:mm:ss", wtime = world.timeofday) - return time2text(wtime, format) - -/proc/shuttleeta2text() - var/timeleft = SSshuttle.timeleft() - if(timeleft < 0) - timeleft = 0 - return "[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]" - -/proc/shuttleminutes2text() - return "[round(SSshuttle.timeleft()/60)]" - -var/next_duration_update = 0 -var/last_round_duration = 0 - -/proc/roundduration2text() - if(!round_start_time) - return "00:00" - if(last_round_duration && world.time < next_duration_update) - return last_round_duration - - var/mills = round_start_time ? world.time - round_start_time : 0 - //var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something - var/mins = round((mills % 36000) / 600) - var/hours = round(mills / 36000) - - mins = mins < 10 ? add_zero(mins, 1) : mins - hours = hours < 10 ? add_zero(hours, 1) : hours - - last_round_duration = "[hours]:[mins]" - next_duration_update = world.time + 1 MINUTES - return last_round_duration - -/* 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(month, 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 - -/var/midnight_rollovers = 0 -/var/rollovercheck_last_timeofday = 0 -/proc/update_midnight_rollover() - if (world.timeofday < rollovercheck_last_timeofday) //TIME IS GOING BACKWARDS! - return midnight_rollovers++ - return midnight_rollovers +#define SECOND *10 +#define SECONDS *10 + +#define MINUTE *600 +#define MINUTES *600 + +//Returns the world time in english +proc/worldtime2text(time = world.time) + return "[round(time / 36000)+12]:[(time / 600 % 60) < 10 ? add_zero(time / 600 % 60, 1) : time / 600 % 60]" + +/proc/time_stamp(format = "hh:mm:ss", wtime = world.timeofday) + return time2text(wtime, format) + +/proc/shuttleeta2text() + var/timeleft = SSshuttle.timeleft() + if(timeleft < 0) + timeleft = 0 + return "[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]" + +/proc/shuttleminutes2text() + return "[round(SSshuttle.timeleft()/60)]" + +var/next_duration_update = 0 +var/last_round_duration = 0 + +/proc/roundduration2text() + if(!round_start_time) + return "00:00" + if(last_round_duration && world.time < next_duration_update) + return last_round_duration + + var/mills = round_start_time ? world.time - round_start_time : 0 + //var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something + var/mins = round((mills % 36000) / 600) + var/hours = round(mills / 36000) + + mins = mins < 10 ? add_zero(mins, 1) : mins + hours = hours < 10 ? add_zero(hours, 1) : hours + + last_round_duration = "[hours]:[mins]" + next_duration_update = world.time + 1 MINUTES + return last_round_duration + +/* 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(month, 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 + +/var/midnight_rollovers = 0 +/var/rollovercheck_last_timeofday = 0 +/proc/update_midnight_rollover() + if (world.timeofday < rollovercheck_last_timeofday) //TIME IS GOING BACKWARDS! + return midnight_rollovers++ + return midnight_rollovers diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 2afe3005eb8a..398a5fdbd7a4 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -1,265 +1,265 @@ -/* - * Holds procs designed to change one type of value, into another. - * Contains: - * hex2num & num2hex - * file2list - * angle2dir - * angle2text - * worldtime2text - */ - -//Returns an integer given a hex input -/proc/hex2num(hex) - if (!( istext(hex) )) - return - - var/num = 0 - var/power = 0 - var/i = null - i = length(hex) - while(i > 0) - var/char = copytext(hex, i, i + 1) - switch(char) - if("0") - //Apparently, switch works with empty statements, yay! If that doesn't work, blame me, though. -- Urist - if("9", "8", "7", "6", "5", "4", "3", "2", "1") - num += text2num(char) * 16 ** power - if("a", "A") - num += 16 ** power * 10 - if("b", "B") - num += 16 ** power * 11 - if("c", "C") - num += 16 ** power * 12 - if("d", "D") - num += 16 ** power * 13 - if("e", "E") - num += 16 ** power * 14 - if("f", "F") - num += 16 ** power * 15 - else - return - power++ - i-- - return num - -//Returns the hex value of a number given a value assumed to be a base-ten value -/proc/num2hex(num, placeholder) - - if (placeholder == null) - placeholder = 2 - if (!( isnum(num) )) - return - if (!( num )) - return "0" - var/hex = "" - var/i = 0 - while(16 ** i < num) - i++ - var/power = null - power = i - 1 - while(power >= 0) - var/val = round(num / 16 ** power) - num -= val * 16 ** power - switch(val) - if(9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0) - hex += text("[]", val) - if(10.0) - hex += "A" - if(11.0) - hex += "B" - if(12.0) - hex += "C" - if(13.0) - hex += "D" - if(14.0) - hex += "E" - if(15.0) - hex += "F" - else - power-- - while(length(hex) < placeholder) - hex = text("0[]", hex) - return hex - -/proc/numlist2hex(list/numlist) - var/hex = "#" - for(var/col_num in 1 to 3) - var/col_hex = num2hex(numlist[col_num]) - while(length(col_hex) < 2) - col_hex = text("0[]", col_hex) // Takes care of leading zeroes. - hex += col_hex - return hex - -/proc/text2numlist(text, delimiter="\n") - var/list/num_list = list() - for(var/x in splittext(text, delimiter)) - num_list += text2num(x) - return num_list - -//Splits the text of a file at seperator and returns them in a list. -/proc/file2list(filename, seperator="\n") - return splittext(return_file_text(filename),seperator) - - -//Turns a direction into text - -/proc/num2dir(direction) - switch(direction) - if(1.0) return NORTH - if(2.0) return SOUTH - if(4.0) return EAST - if(8.0) return WEST - else - world.log << "UNKNOWN DIRECTION: [direction]" - - - -//Turns a direction into text -/proc/dir2text(direction) - switch(direction) - if(1.0) - return "north" - if(2.0) - return "south" - if(4.0) - return "east" - if(8.0) - return "west" - if(5.0) - return "northeast" - if(6.0) - return "southeast" - if(9.0) - return "northwest" - if(10.0) - return "southwest" - else - return - -//Turns text into proper directions -/proc/text2dir(direction) - switch(uppertext(direction)) - if("NORTH") - return 1 - if("SOUTH") - return 2 - if("EAST") - return 4 - if("WEST") - return 8 - if("NORTHEAST") - return 5 - if("NORTHWEST") - return 9 - if("SOUTHEAST") - return 6 - if("SOUTHWEST") - return 10 - else - return - -//Converts an angle (degrees) into an ss13 direction -/proc/angle2dir(degree) - degree = ((degree+22.5)%365) - if(degree < 45) return NORTH - if(degree < 90) return NORTHEAST - if(degree < 135) return EAST - if(degree < 180) return SOUTHEAST - if(degree < 225) return SOUTH - if(degree < 270) return SOUTHWEST - if(degree < 315) return WEST - return NORTH|WEST - -//returns the north-zero clockwise angle in degrees, given a direction - -/proc/dir2angle(D) - switch(D) - if(NORTH) return 0 - if(SOUTH) return 180 - if(EAST) return 90 - if(WEST) return 270 - if(NORTHEAST) return 45 - if(SOUTHEAST) return 135 - if(NORTHWEST) return 315 - if(SOUTHWEST) return 225 - else return null - -//Returns the angle in english -/proc/angle2text(degree) - return dir2text(angle2dir(degree)) - -//Converts a blend_mode constant to one acceptable to icon.Blend() -/proc/blendMode2iconMode(blend_mode) - switch(blend_mode) - if(BLEND_MULTIPLY) return ICON_MULTIPLY - if(BLEND_ADD) return ICON_ADD - if(BLEND_SUBTRACT) return ICON_SUBTRACT - else return ICON_OVERLAY - -//Converts a rights bitfield into a string -/proc/rights2text(rights,seperator="") - if(rights & R_BUILDMODE) . += "[seperator]+BUILDMODE" - if(rights & R_ADMIN) . += "[seperator]+ADMIN" - if(rights & R_BAN) . += "[seperator]+BAN" - if(rights & R_FUN) . += "[seperator]+FUN" - if(rights & R_SERVER) . += "[seperator]+SERVER" - if(rights & R_DEBUG) . += "[seperator]+DEBUG" - if(rights & R_POSSESS) . += "[seperator]+POSSESS" - if(rights & R_PERMISSIONS) . += "[seperator]+PERMISSIONS" - if(rights & R_STEALTH) . += "[seperator]+STEALTH" - if(rights & R_REJUVINATE) . += "[seperator]+REJUVINATE" - if(rights & R_VAREDIT) . += "[seperator]+VAREDIT" - if(rights & R_SOUNDS) . += "[seperator]+SOUND" - if(rights & R_SPAWN) . += "[seperator]+SPAWN" - if(rights & R_WHITELIST) . += "[seperator]+WHITELIST" - if(rights & R_EVENT) . += "[seperator]+EVENT" - return . - -/proc/ui_style2icon(ui_style) - switch(ui_style) - if("old") return 'icons/mob/screen1_old.dmi' - if("Orange") return 'icons/mob/screen1_Orange.dmi' - if("Midnight") return 'icons/mob/screen1_Midnight.dmi' - else return 'icons/mob/screen1_White.dmi' - - -// heat2color functions. Adapted from: http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ -/proc/heat2color(temp) - return rgb(heat2color_r(temp), heat2color_g(temp), heat2color_b(temp)) - -/proc/heat2color_r(temp) - temp /= 100 - if(temp <= 66) - . = 255 - else - . = max(0, min(255, 329.698727446 * (temp - 60) ** -0.1332047592)) - -/proc/heat2color_g(temp) - temp /= 100 - if(temp <= 66) - . = max(0, min(255, 99.4708025861 * log(temp) - 161.1195681661)) - else - . = max(0, min(255, 288.1221695283 * ((temp - 60) ** -0.0755148492))) - -/proc/heat2color_b(temp) - temp /= 100 - if(temp >= 66) - . = 255 - else - if(temp <= 16) - . = 0 - else - . = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307)) - -//Converts a positive interger to its roman numeral equivilent. Ignores any decimals. -//Numbers over 3999 will display with extra "M"s (don't tell the Romans) and can get comically long, so be careful. -/proc/num2roman(A) - var/list/values = list("M" = 1000, "CM" = 900, "D" = 500, "CD" = 400, "C" = 100, "XC" = 90, "L" = 50, "XL" = 40, "X" = 10, "IX" = 9, "V" = 5, "IV" = 4, "I" = 1) - if(!A || !isnum(A)) - return 0 - while(A >= 1) - for(var/i in values) - if(A >= values[i]) - . += i - A -= values[i] - break +/* + * Holds procs designed to change one type of value, into another. + * Contains: + * hex2num & num2hex + * file2list + * angle2dir + * angle2text + * worldtime2text + */ + +//Returns an integer given a hex input +/proc/hex2num(hex) + if (!( istext(hex) )) + return + + var/num = 0 + var/power = 0 + var/i = null + i = length(hex) + while(i > 0) + var/char = copytext(hex, i, i + 1) + switch(char) + if("0") + //Apparently, switch works with empty statements, yay! If that doesn't work, blame me, though. -- Urist + if("9", "8", "7", "6", "5", "4", "3", "2", "1") + num += text2num(char) * 16 ** power + if("a", "A") + num += 16 ** power * 10 + if("b", "B") + num += 16 ** power * 11 + if("c", "C") + num += 16 ** power * 12 + if("d", "D") + num += 16 ** power * 13 + if("e", "E") + num += 16 ** power * 14 + if("f", "F") + num += 16 ** power * 15 + else + return + power++ + i-- + return num + +//Returns the hex value of a number given a value assumed to be a base-ten value +/proc/num2hex(num, placeholder) + + if (placeholder == null) + placeholder = 2 + if (!( isnum(num) )) + return + if (!( num )) + return "0" + var/hex = "" + var/i = 0 + while(16 ** i < num) + i++ + var/power = null + power = i - 1 + while(power >= 0) + var/val = round(num / 16 ** power) + num -= val * 16 ** power + switch(val) + if(9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0) + hex += text("[]", val) + if(10.0) + hex += "A" + if(11.0) + hex += "B" + if(12.0) + hex += "C" + if(13.0) + hex += "D" + if(14.0) + hex += "E" + if(15.0) + hex += "F" + else + power-- + while(length(hex) < placeholder) + hex = text("0[]", hex) + return hex + +/proc/numlist2hex(list/numlist) + var/hex = "#" + for(var/col_num in 1 to 3) + var/col_hex = num2hex(numlist[col_num]) + while(length(col_hex) < 2) + col_hex = text("0[]", col_hex) // Takes care of leading zeroes. + hex += col_hex + return hex + +/proc/text2numlist(text, delimiter="\n") + var/list/num_list = list() + for(var/x in splittext(text, delimiter)) + num_list += text2num(x) + return num_list + +//Splits the text of a file at seperator and returns them in a list. +/proc/file2list(filename, seperator="\n") + return splittext(return_file_text(filename),seperator) + + +//Turns a direction into text + +/proc/num2dir(direction) + switch(direction) + if(1.0) return NORTH + if(2.0) return SOUTH + if(4.0) return EAST + if(8.0) return WEST + else + world.log << "UNKNOWN DIRECTION: [direction]" + + + +//Turns a direction into text +/proc/dir2text(direction) + switch(direction) + if(1.0) + return "north" + if(2.0) + return "south" + if(4.0) + return "east" + if(8.0) + return "west" + if(5.0) + return "northeast" + if(6.0) + return "southeast" + if(9.0) + return "northwest" + if(10.0) + return "southwest" + else + return + +//Turns text into proper directions +/proc/text2dir(direction) + switch(uppertext(direction)) + if("NORTH") + return 1 + if("SOUTH") + return 2 + if("EAST") + return 4 + if("WEST") + return 8 + if("NORTHEAST") + return 5 + if("NORTHWEST") + return 9 + if("SOUTHEAST") + return 6 + if("SOUTHWEST") + return 10 + else + return + +//Converts an angle (degrees) into an ss13 direction +/proc/angle2dir(degree) + degree = ((degree+22.5)%365) + if(degree < 45) return NORTH + if(degree < 90) return NORTHEAST + if(degree < 135) return EAST + if(degree < 180) return SOUTHEAST + if(degree < 225) return SOUTH + if(degree < 270) return SOUTHWEST + if(degree < 315) return WEST + return NORTH|WEST + +//returns the north-zero clockwise angle in degrees, given a direction + +/proc/dir2angle(D) + switch(D) + if(NORTH) return 0 + if(SOUTH) return 180 + if(EAST) return 90 + if(WEST) return 270 + if(NORTHEAST) return 45 + if(SOUTHEAST) return 135 + if(NORTHWEST) return 315 + if(SOUTHWEST) return 225 + else return null + +//Returns the angle in english +/proc/angle2text(degree) + return dir2text(angle2dir(degree)) + +//Converts a blend_mode constant to one acceptable to icon.Blend() +/proc/blendMode2iconMode(blend_mode) + switch(blend_mode) + if(BLEND_MULTIPLY) return ICON_MULTIPLY + if(BLEND_ADD) return ICON_ADD + if(BLEND_SUBTRACT) return ICON_SUBTRACT + else return ICON_OVERLAY + +//Converts a rights bitfield into a string +/proc/rights2text(rights,seperator="") + if(rights & R_BUILDMODE) . += "[seperator]+BUILDMODE" + if(rights & R_ADMIN) . += "[seperator]+ADMIN" + if(rights & R_BAN) . += "[seperator]+BAN" + if(rights & R_FUN) . += "[seperator]+FUN" + if(rights & R_SERVER) . += "[seperator]+SERVER" + if(rights & R_DEBUG) . += "[seperator]+DEBUG" + if(rights & R_POSSESS) . += "[seperator]+POSSESS" + if(rights & R_PERMISSIONS) . += "[seperator]+PERMISSIONS" + if(rights & R_STEALTH) . += "[seperator]+STEALTH" + if(rights & R_REJUVINATE) . += "[seperator]+REJUVINATE" + if(rights & R_VAREDIT) . += "[seperator]+VAREDIT" + if(rights & R_SOUNDS) . += "[seperator]+SOUND" + if(rights & R_SPAWN) . += "[seperator]+SPAWN" + if(rights & R_WHITELIST) . += "[seperator]+WHITELIST" + if(rights & R_EVENT) . += "[seperator]+EVENT" + return . + +/proc/ui_style2icon(ui_style) + switch(ui_style) + if("old") return 'icons/mob/screen1_old.dmi' + if("Orange") return 'icons/mob/screen1_Orange.dmi' + if("Midnight") return 'icons/mob/screen1_Midnight.dmi' + else return 'icons/mob/screen1_White.dmi' + + +// heat2color functions. Adapted from: http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ +/proc/heat2color(temp) + return rgb(heat2color_r(temp), heat2color_g(temp), heat2color_b(temp)) + +/proc/heat2color_r(temp) + temp /= 100 + if(temp <= 66) + . = 255 + else + . = max(0, min(255, 329.698727446 * (temp - 60) ** -0.1332047592)) + +/proc/heat2color_g(temp) + temp /= 100 + if(temp <= 66) + . = max(0, min(255, 99.4708025861 * log(temp) - 161.1195681661)) + else + . = max(0, min(255, 288.1221695283 * ((temp - 60) ** -0.0755148492))) + +/proc/heat2color_b(temp) + temp /= 100 + if(temp >= 66) + . = 255 + else + if(temp <= 16) + . = 0 + else + . = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307)) + +//Converts a positive interger to its roman numeral equivilent. Ignores any decimals. +//Numbers over 3999 will display with extra "M"s (don't tell the Romans) and can get comically long, so be careful. +/proc/num2roman(A) + var/list/values = list("M" = 1000, "CM" = 900, "D" = 500, "CD" = 400, "C" = 100, "XC" = 90, "L" = 50, "XL" = 40, "X" = 10, "IX" = 9, "V" = 5, "IV" = 4, "I" = 1) + if(!A || !isnum(A)) + return 0 + while(A >= 1) + for(var/i in values) + if(A >= values[i]) + . += i + A -= values[i] + break diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 8001dc231913..f34cf2e763c0 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1,1615 +1,1615 @@ -// =================================== -// GLOBAL MACRO HELPERS -// =================================== - -// A = thing to stop | B = thing to hit. | finialize() calls A.throw_impact(B) -#define STOP_THROWING(A, B) if(A.throwing) {var/datum/thrownthing/TT = SSthrowing.processing[A]; if(TT) {TT.finialize(null, B);}} - -// =================================== - -/* - * A large number of misc global procs. - */ - -//Checks if all high bits in req_mask are set in bitfield -#define BIT_TEST_ALL(bitfield, req_mask) ((~(bitfield) & (req_mask)) == 0) - -//Inverts the colour of an HTML string -/proc/invertHTML(HTMLstring) - - if (!( istext(HTMLstring) )) - CRASH("Given non-text argument!") - return - else - if (length(HTMLstring) != 7) - CRASH("Given non-HTML argument!") - return - var/textr = copytext(HTMLstring, 2, 4) - var/textg = copytext(HTMLstring, 4, 6) - var/textb = copytext(HTMLstring, 6, 8) - var/r = hex2num(textr) - var/g = hex2num(textg) - var/b = hex2num(textb) - textr = num2hex(255 - r) - textg = num2hex(255 - g) - textb = num2hex(255 - b) - if (length(textr) < 2) - textr = text("0[]", textr) - if (length(textg) < 2) - textr = text("0[]", textg) - if (length(textb) < 2) - textr = text("0[]", textb) - return text("#[][][]", textr, textg, textb) - return - -//Returns the middle-most value -/proc/dd_range(low, high, num) - return max(low,min(high,num)) - -//Returns whether or not A is the middle most value -/proc/InRange(A, lower, upper) - if(A < lower) return 0 - if(A > upper) return 0 - return 1 - - -/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. - if(!start || !end) return 0 - var/dy - var/dx - dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y) - dx=(32*end.x+end.pixel_x)-(32*start.x+start.pixel_x) - if(!dy) - return (dx>=0)?90:270 - .=arctan(dx/dy) - if(dy<0) - .+=180 - else if(dx<0) - .+=360 - -//Returns location. Returns null if no location was found. -/proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = 0, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0) -/* -Location where the teleport begins, target that will teleport, distance to go, density checking 0/1(yes/no). -Random error in tile placement x, error in tile placement y, and block offset. -Block offset tells the proc how to place the box. Behind teleport location, relative to starting location, forward, etc. -Negative values for offset are accepted, think of it in relation to North, -x is west, -y is south. Error defaults to positive. -Turf and target are seperate in case you want to teleport some distance from a turf the target is not standing on or something. -*/ - - var/dirx = 0//Generic location finding variable. - var/diry = 0 - - var/xoffset = 0//Generic counter for offset location. - var/yoffset = 0 - - var/b1xerror = 0//Generic placing for point A in box. The lower left. - var/b1yerror = 0 - var/b2xerror = 0//Generic placing for point B in box. The upper right. - var/b2yerror = 0 - - errorx = abs(errorx)//Error should never be negative. - errory = abs(errory) - //var/errorxy = round((errorx+errory)/2)//Used for diagonal boxes. - - switch(target.dir)//This can be done through equations but switch is the simpler method. And works fast to boot. - //Directs on what values need modifying. - if(1)//North - diry+=distance - yoffset+=eoffsety - xoffset+=eoffsetx - b1xerror-=errorx - b1yerror-=errory - b2xerror+=errorx - b2yerror+=errory - if(2)//South - diry-=distance - yoffset-=eoffsety - xoffset+=eoffsetx - b1xerror-=errorx - b1yerror-=errory - b2xerror+=errorx - b2yerror+=errory - if(4)//East - dirx+=distance - yoffset+=eoffsetx//Flipped. - xoffset+=eoffsety - b1xerror-=errory//Flipped. - b1yerror-=errorx - b2xerror+=errory - b2yerror+=errorx - if(8)//West - dirx-=distance - yoffset-=eoffsetx//Flipped. - xoffset+=eoffsety - b1xerror-=errory//Flipped. - b1yerror-=errorx - b2xerror+=errory - b2yerror+=errorx - - var/turf/destination=locate(location.x+dirx,location.y+diry,location.z) - - if(destination)//If there is a destination. - if(errorx||errory)//If errorx or y were specified. - var/destination_list[] = list()//To add turfs to list. - //destination_list = new() - /*This will draw a block around the target turf, given what the error is. - Specifying the values above will basically draw a different sort of block. - If the values are the same, it will be a square. If they are different, it will be a rectengle. - In either case, it will center based on offset. Offset is position from center. - Offset always calculates in relation to direction faced. In other words, depending on the direction of the teleport, - the offset should remain positioned in relation to destination.*/ - - var/turf/center = locate((destination.x+xoffset),(destination.y+yoffset),location.z)//So now, find the new center. - - //Now to find a box from center location and make that our destination. - for(var/turf/T in block(locate(center.x+b1xerror,center.y+b1yerror,location.z), locate(center.x+b2xerror,center.y+b2yerror,location.z) )) - if(density&&T.density) continue//If density was specified. - if(T.x>world.maxx || T.x<1) continue//Don't want them to teleport off the map. - if(T.y>world.maxy || T.y<1) continue - destination_list += T - if(destination_list.len) - destination = pick(destination_list) - else return - - else//Same deal here. - if(density&&destination.density) return - if(destination.x>world.maxx || destination.x<1) return - if(destination.y>world.maxy || destination.y<1) return - else return - - return destination - -/proc/sign(x) - return x!=0?x/abs(x):0 - -/proc/getline(atom/M,atom/N)//Ultra-Fast Bresenham Line-Drawing Algorithm - var/px=M.x //starting x - var/py=M.y - var/line[] = list(locate(px,py,M.z)) - var/dx=N.x-px //x distance - var/dy=N.y-py - var/dxabs=abs(dx)//Absolute value of x distance - var/dyabs=abs(dy) - var/sdx=sign(dx) //Sign of x distance (+ or -) - var/sdy=sign(dy) - var/x=dxabs>>1 //Counters for steps taken, setting to distance/2 - var/y=dyabs>>1 //Bit-shifting makes me l33t. It also makes getline() unnessecarrily fast. - var/j //Generic integer for counting - if(dxabs>=dyabs) //x distance is greater than y - for(j=0;j=dxabs) //Every dyabs steps, step once in y direction - y-=dxabs - py+=sdy - px+=sdx //Step on in x direction - line+=locate(px,py,M.z)//Add the turf to the list - else - for(j=0;j=dyabs) - x-=dyabs - px+=sdx - py+=sdy - line+=locate(px,py,M.z) - return line - -//Returns whether or not a player is a guest using their ckey as an input -/proc/IsGuestKey(key) - if (findtext(key, "Guest-", 1, 7) != 1) //was findtextEx - return 0 - - var/i, ch, len = length(key) - - for (i = 7, i <= len, ++i) - ch = text2ascii(key, i) - if (ch < 48 || ch > 57) - return 0 - return 1 - -//Ensure the frequency is within bounds of what it should be sending/recieving at -/proc/sanitize_frequency(f) - f = round(f) - f = max(1441, f) // 144.1 - f = min(1489, f) // 148.9 - if ((f % 2) == 0) //Ensure the last digit is an odd number - f += 1 - return f - -//Turns 1479 into 147.9 -/proc/format_frequency(f) - return "[round(f / 10)].[f % 10]" - - - -//This will update a mob's name, real_name, mind.name, data_core records, pda and id -//Calling this proc without an oldname will only update the mob and skip updating the pda, id and records ~Carn -/mob/proc/fully_replace_character_name(oldname,newname) - if(!newname) return 0 - real_name = newname - name = newname - if(mind) - mind.name = newname - if(dna) - dna.real_name = real_name - - if(oldname) - //update the datacore records! This is goig to be a bit costly. - for(var/list/L in list(data_core.general,data_core.medical,data_core.security,data_core.locked)) - for(var/datum/data/record/R in L) - if(R.fields["name"] == oldname) - R.fields["name"] = newname - break - - //update our pda and id if we have them on our person - var/list/searching = GetAllContents(searchDepth = 3) - var/search_id = 1 - var/search_pda = 1 - - for(var/A in searching) - if( search_id && istype(A,/obj/item/weapon/card/id) ) - var/obj/item/weapon/card/id/ID = A - if(ID.registered_name == oldname) - ID.registered_name = newname - ID.name = "[newname]'s ID Card ([ID.assignment])" - if(!search_pda) break - search_id = 0 - - else if( search_pda && istype(A,/obj/item/device/pda) ) - var/obj/item/device/pda/PDA = A - if(PDA.owner == oldname) - PDA.owner = newname - PDA.name = "PDA-[newname] ([PDA.ownjob])" - if(!search_id) break - search_pda = 0 - return 1 - - - -//Generalised helper proc for letting mobs rename themselves. Used to be clname() and ainame() -//Last modified by Carn -/mob/proc/rename_self(role, allow_numbers=0) - spawn(0) - var/oldname = real_name - - var/time_passed = world.time - var/newname - - for(var/i=1,i<=3,i++) //we get 3 attempts to pick a suitable name. - newname = input(src,"You are a [role]. Would you like to change your name to something else?", "Name change",input_default(oldname)) as text - if((world.time-time_passed)>300) - return //took too long - newname = sanitize_name(newname, ,allow_numbers) //returns null if the name doesn't meet some basic requirements. Tidies up a few other things like bad-characters. - - for(var/mob/living/M in player_list) - if(M == src) - continue - if(!newname || M.real_name == newname) - newname = null - break - if(newname) - break //That's a suitable name! - to_chat(src, "Sorry, that [role]-name wasn't appropriate, please try another. It's possibly too long/short, has bad characters or is already taken.") - - if(!newname) //we'll stick with the oldname then - return - - if(cmptext("ai",role)) - if(isAI(src)) - var/mob/living/silicon/ai/A = src - oldname = null//don't bother with the records update crap - //world << "[newname] is the AI!" - //world << sound('sound/AI/newAI.ogg') - // Set eyeobj name - if(A.eyeobj) - A.eyeobj.name = "[newname] (AI Eye)" - - // Set ai pda name - if(A.pda) - A.pda.owner = newname - A.pda.name = newname + " (" + A.pda.ownjob + ")" - - - fully_replace_character_name(oldname,newname) - - - -//Picks a string of symbols to display as the law number for hacked or ion laws -/proc/ionnum() - return "[pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")]" - -//When an AI is activated, it can choose from a list of non-slaved borgs to have as a slave. -/proc/freeborg() - var/select = null - var/list/borgs = list() - for (var/mob/living/silicon/robot/A in player_list) - if (A.stat == DEAD || A.connected_ai || A.scrambledcodes || istype(A,/mob/living/silicon/robot/drone)) - continue - var/name = "[A.real_name] ([A.modtype] [A.braintype])" - borgs[name] = A - - if (borgs.len) - select = input("Unshackled borg signals detected:", "Borg selection", null, null) as null|anything in borgs - return borgs[select] - -//When a borg is activated, it can choose which AI it wants to be slaved to -/proc/active_ais() - . = list() - for(var/mob/living/silicon/ai/A in ai_list) - if(A.stat == DEAD) - continue - if(A.control_disabled == 1) - continue - . += A - return . - -//Find an active ai with the least borgs. VERBOSE PROCNAME HUH! -/proc/select_active_ai_with_fewest_borgs() - var/mob/living/silicon/ai/selected - var/list/active = active_ais() - for(var/mob/living/silicon/ai/A in active) - if(!selected || (selected.connected_robots > A.connected_robots)) - selected = A - - return selected - -/proc/select_active_ai(mob/user) - var/list/ais = active_ais() - if(ais.len) - if(user) . = input(usr,"AI signals detected:", "AI selection") in ais - else . = pick(ais) - return . - -//Returns a list of all items of interest with their name -/proc/getpois(mobs_only=0, skip_mindless=0) - var/list/mobs = sortmobs() - var/list/names = list() - var/list/pois = list() - var/list/namecounts = list() - - for(var/mob/M in mobs) - if(skip_mindless && (!M.mind && !M.ckey)) - if(!isbot(M) && !istype(M, /mob/camera)) - continue - if(M.client && M.client.holder && M.client.holder.fakekey) //stealthmins - continue - if(usr == M) //skip yourself - continue - var/name = M.name - if (name in names) - namecounts[name]++ - name = "[name] ([namecounts[name]])" - else - names.Add(name) - namecounts[name] = 1 - if (M.real_name && M.real_name != M.name) - name += " \[[M.real_name]\]" - if (M.stat == DEAD) - if(istype(M, /mob/dead/observer/)) - name += " \[ghost\]" - else - name += " \[dead\]" - pois[name] = M - - if(!mobs_only) - for(var/atom/A in poi_list) - if(!A || !A.loc) - continue - var/name = A.name - if (names.Find(name)) - namecounts[name]++ - name = "[name] ([namecounts[name]])" - else - names.Add(name) - namecounts[name] = 1 - pois[name] = A - - return pois - - -#define ADD_TO_MOBLIST(type) \ - for(var##type/M in sortmob) {moblist += M} - -/** - * Orders mobs by type then by name. - */ -/proc/sortmobs() - var/list/moblist = list() - var/list/sortmob = sortAtom(mob_list) - - ADD_TO_MOBLIST(/mob/camera) - ADD_TO_MOBLIST(/mob/living/silicon/ai) - ADD_TO_MOBLIST(/mob/living/silicon/pai) - ADD_TO_MOBLIST(/mob/living/silicon/robot) - ADD_TO_MOBLIST(/mob/living/carbon/human) - ADD_TO_MOBLIST(/mob/living/carbon/brain) - ADD_TO_MOBLIST(/mob/living/carbon/alien) - ADD_TO_MOBLIST(/mob/dead) - ADD_TO_MOBLIST(/mob/living/parasite/essence) - ADD_TO_MOBLIST(/mob/living/carbon/monkey) - ADD_TO_MOBLIST(/mob/living/carbon/slime) - ADD_TO_MOBLIST(/mob/living/carbon/ian) - ADD_TO_MOBLIST(/mob/living/simple_animal) - - return moblist - -#undef ADD_TO_MOBLIST - -//E = MC^2 -/proc/convert2energy(M) - var/E = M*(SPEED_OF_LIGHT_SQ) - return E - -//M = E/C^2 -/proc/convert2mass(E) - var/M = E/(SPEED_OF_LIGHT_SQ) - return M - -//Forces a variable to be posative -/proc/modulus(M) - if(M >= 0) - return M - if(M < 0) - return -M - - -/proc/key_name(whom, include_link = null, include_name = 1, highlight_special_characters = 1, reply = null) - var/mob/M - var/client/C - var/key - - if(!whom) - return "*null*" - if(istype(whom, /client)) - C = whom - M = C.mob - key = C.key - else if(ismob(whom)) - M = whom - C = M.client - key = M.key - else if(istype(whom, /datum)) - var/datum/D = whom - return "*invalid:[D.type]*" - else - return "*invalid*" - - . = "" - - if(key) - if(include_link && C) - . += "" - - if(C && C.holder && C.holder.fakekey && !include_name) - . += "Administrator" - else - . += key - - if(include_link) - if(C) - . += "" - else - . += " (DC)" - else - . += "*no key*" - - if(include_name && M) - var/name - - if(M.real_name) - name = M.real_name - else if(M.name) - name = M.name - - - if(include_link && is_special_character(M) && highlight_special_characters) - . += "/([name])" //Orange - else - . += "/([name])" - - return . - -/proc/key_name_admin(whom, include_name = 1) - return key_name(whom, 1, include_name) - - -//Will return the location of the turf an atom is ultimatly sitting on -//isn't this just a null-reference-vulnerable copy of /proc/get_turf()? -/proc/get_turf_loc(atom/movable/M) //gets the location of the turf that the atom is on, or what the atom is in is on, etc - //in case they're in a closet or sleeper or something - var/atom/loc = M.loc - while(!istype(loc, /turf/)) - loc = loc.loc - return loc - -// returns the turf located at the map edge in the specified direction relative to A -// used for mass driver -/proc/get_edge_target_turf(atom/A, direction) - - var/turf/target = locate(A.x, A.y, A.z) - if(!A || !target) - return 0 - //since NORTHEAST == NORTH & EAST, etc, doing it this way allows for diagonal mass drivers in the future - //and isn't really any more complicated - - // Note diagonal directions won't usually be accurate - if(direction & NORTH) - target = locate(target.x, world.maxy, target.z) - if(direction & SOUTH) - target = locate(target.x, 1, target.z) - if(direction & EAST) - target = locate(world.maxx, target.y, target.z) - if(direction & WEST) - target = locate(1, target.y, target.z) - - return target - -// returns turf relative to A in given direction at set range -// result is bounded to map size -// note range is non-pythagorean -// used for disposal system -/proc/get_ranged_target_turf(atom/A, direction, range) - - var/x = A.x - var/y = A.y - if(direction & NORTH) - y = min(world.maxy, y + range) - if(direction & SOUTH) - y = max(1, y - range) - if(direction & EAST) - x = min(world.maxx, x + range) - if(direction & WEST) - x = max(1, x - range) - - return locate(x,y,A.z) - - -// returns turf relative to A offset in dx and dy tiles -// bound to map limits -/proc/get_offset_target_turf(atom/A, dx, dy) - var/x = min(world.maxx, max(1, A.x + dx)) - var/y = min(world.maxy, max(1, A.y + dy)) - return locate(x,y,A.z) - -//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value. -/proc/between(low, middle, high) - return max(min(middle, high), low) - -proc/arctan(x) - var/y=arcsin(x/sqrt(1+x*x)) - return y - -//returns random gauss number -proc/GaussRand(sigma) - var/x,y,rsq - do - x=2*rand()-1 - y=2*rand()-1 - rsq=x*x+y*y - while(rsq>1 || !rsq) - return sigma*y*sqrt(-2*log(rsq)/rsq) - -//returns random gauss number, rounded to 'roundto' -proc/GaussRandRound(sigma,roundto) - return round(GaussRand(sigma),roundto) - -proc/anim(turf/location,target,a_icon,a_icon_state,flick_anim,sleeptime = 0,direction) -//This proc throws up either an icon or an animation for a specified amount of time. -//The variables should be apparent enough. - var/atom/movable/overlay/animation = new(location) - if(direction) - animation.dir = direction - animation.icon = a_icon - animation.layer = target:layer+1 - if(a_icon_state) - animation.icon_state = a_icon_state - else - animation.icon_state = "blank" - animation.master = target - flick(flick_anim, animation) - sleep(max(sleeptime, 15)) - qdel(animation) - -//Will return the contents of an atom recursivly to a depth of 'searchDepth' -/atom/proc/GetAllContents(searchDepth = 5) - var/list/toReturn = list() - - for(var/atom/part in contents) - toReturn += part - if(part.contents.len && searchDepth) - toReturn += part.GetAllContents(searchDepth - 1) - - return toReturn - -//Step-towards method of determining whether one atom can see another. Similar to viewers() -/proc/can_see(atom/source, atom/target, length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate. - var/turf/current = get_turf(source) - var/turf/target_turf = get_turf(target) - var/steps = 0 - - while(current != target_turf) - if(steps > length) return 0 - if(current.opacity) return 0 - for(var/atom/A in current) - if(A.opacity) return 0 - current = get_step_towards(current, target_turf) - steps++ - - return 1 - -/proc/is_blocked_turf(turf/T) - var/cant_pass = 0 - if(T.density) cant_pass = 1 - for(var/atom/A in T) - if(A.density)//&&A.anchored - cant_pass = 1 - return cant_pass - -/proc/get_step_towards2(atom/ref , atom/trg) - var/base_dir = get_dir(ref, get_step_towards(ref,trg)) - var/turf/temp = get_step_towards(ref,trg) - - if(is_blocked_turf(temp)) - var/dir_alt1 = turn(base_dir, 90) - var/dir_alt2 = turn(base_dir, -90) - var/turf/turf_last1 = temp - var/turf/turf_last2 = temp - var/free_tile = null - var/breakpoint = 0 - - while(!free_tile && breakpoint < 10) - if(!is_blocked_turf(turf_last1)) - free_tile = turf_last1 - break - if(!is_blocked_turf(turf_last2)) - free_tile = turf_last2 - break - turf_last1 = get_step(turf_last1,dir_alt1) - turf_last2 = get_step(turf_last2,dir_alt2) - breakpoint++ - - if(!free_tile) return get_step(ref, base_dir) - else return get_step_towards(ref,free_tile) - - else return get_step(ref, base_dir) - -//Takes: Anything that could possibly have variables and a varname to check. -//Returns: 1 if found, 0 if not. -/proc/hasvar(datum/A, varname) - if(A.vars.Find(lowertext(varname))) return 1 - else return 0 - -//Returns: all the areas in the world, sorted. -/proc/return_sorted_areas() - return sortAtom(all_areas) - -//Takes: Area type as text string or as typepath OR an instance of the area. -//Returns: A list of all areas of that type in the world. -/proc/get_areas(areatype) - if(!areatype) return null - if(istext(areatype)) areatype = text2path(areatype) - if(isarea(areatype)) - var/area/areatemp = areatype - areatype = areatemp.type - - var/list/areas = new/list() - for(var/area/N in all_areas) - if(istype(N, areatype)) - areas += N - return areas - -//Takes: Area type as text string or as typepath OR an instance of the area. -//Returns: A list of all turfs in areas of that type of that type in the world. -/proc/get_area_turfs(areatype) - if(!areatype) return null - if(istext(areatype)) areatype = text2path(areatype) - if(isarea(areatype)) - var/area/areatemp = areatype - areatype = areatemp.type - - var/list/turfs = new/list() - for(var/area/N in all_areas) - if(istype(N, areatype)) - for(var/turf/T in N) turfs += T - return turfs - -//Takes: Area type as text string or as typepath OR an instance of the area. -//Returns: A list of all atoms (objs, turfs, mobs) in areas of that type of that type in the world. -/proc/get_area_all_atoms(areatype) - if(!areatype) return null - if(istext(areatype)) areatype = text2path(areatype) - if(isarea(areatype)) - var/area/areatemp = areatype - areatype = areatemp.type - - var/list/atoms = new/list() - for(var/area/N in all_areas) - if(istype(N, areatype)) - for(var/atom/A in N) - atoms += A - return atoms - -/datum/coords //Simple datum for storing coordinates. - var/x_pos = null - var/y_pos = null - var/z_pos = null - -/area/proc/move_contents_to(area/A, turftoleave=null, 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/toupdate = new/list() - - moving: - for (var/turf/T in refined_src) - 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/turf/X = T.MoveTurf(B) - - 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.loc = 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.plane = nextturf.plane - 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.plane = initial(X.plane) - 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 - continue - if(!istype(O,/obj)) continue - O.loc = X - if (length(O.client_mobs_in_contents)) - O.update_parallax_contents() - for(var/mob/M in T) - if(!istype(M,/mob) || istype(M, /mob/camera)) continue // If we need to check for more mobs, I'll add a variable - M.loc = X - M.update_parallax_contents() - -// 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.set_opacity(!X.opacity) - - toupdate += X - -// if(turftoleave) -// T.MoveTurf(turftoleave) - - refined_src -= T - refined_trg -= B - continue moving - - -proc/DuplicateObject(obj/original, perfectcopy = 0 , sameloc = 0) - if(!original) - return null - - var/obj/O = null - - if(sameloc) - O=new original.type(original.loc) - else - O=new original.type(locate(0,0,0)) - - if(perfectcopy) - if((O) && (original)) - for(var/V in original.vars) - if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key"))) - O.vars[V] = original.vars[V] - return O - - -/area/proc/copy_contents_to(area/A , platingRequired = 0 ) - //Takes: Area. Optional: If it should copy to areas that don't have plating - //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/toupdate = new/list() - - var/copiedobjs = list() - - - moving: - for (var/turf/T in refined_src) - 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 - - if(platingRequired) - if(istype(B, /turf/space)) - continue moving - - var/turf/X = new T.type(B) - 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/list/objs = new/list() - var/list/newobjs = new/list() - var/list/mobs = new/list() - var/list/newmobs = new/list() - - for(var/obj/O in T) - - if(!istype(O,/obj)) - continue - - objs += O - - - for(var/obj/O in objs) - newobjs += DuplicateObject(O , 1) - - - for(var/obj/O in newobjs) - O.loc = X - - for(var/mob/M in T) - - if(!istype(M,/mob) || istype(M, /mob/camera)) continue // If we need to check for more mobs, I'll add a variable - mobs += M - - for(var/mob/M in mobs) - newmobs += DuplicateObject(M , 1) - - for(var/mob/M in newmobs) - M.loc = X - - copiedobjs += newobjs - copiedobjs += newmobs - - - - for(var/V in T.vars) - if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key","x","y","z","contents", "luminosity"))) - X.vars[V] = T.vars[V] - -// var/area/AR = X.loc - -// if(AR.lighting_use_dynamic) -// X.opacity = !X.opacity -// X.sd_set_opacity(!X.opacity) //TODO: rewrite this code so it's not messed by lighting ~Carn - - toupdate += X - - 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) - SSair.groups_to_rebuild += T1.parent - else - SSair.tiles_to_update += T1*/ - - for(var/obj/O in doors) - O:update_nearby_tiles(1) - - - - - return copiedobjs - - - -proc/get_cardinal_dir(atom/A, atom/B) - var/dx = abs(B.x - A.x) - var/dy = abs(B.y - A.y) - return get_dir(A, B) & (rand() * (dx+dy) < dy ? 3 : 12) - -//chances are 1:value. anyprob(1) will always return true -proc/anyprob(value) - return (rand(1,value)==value) - -proc/view_or_range(distance = world.view , center = usr , type) - switch(type) - if("view") - . = view(distance,center) - if("range") - . = range(distance,center) - return - -proc/oview_or_orange(distance = world.view , center = usr , type) - switch(type) - if("view") - . = oview(distance,center) - if("range") - . = orange(distance,center) - return - -proc/get_mob_with_client_list() - var/list/mobs = list() - for(var/mob/M in player_list) - mobs += M - return mobs - - -/proc/parse_zone(zone) - switch(zone) - if(BP_L_ARM) - return "left arm" - if(BP_R_ARM) - return "right arm" - if(BP_L_LEG) - return "left leg" - if(BP_R_LEG) - return "right leg" - else - return zone - -/proc/get(atom/loc, type) - while(loc) - if(istype(loc, type)) - return loc - loc = loc.loc - return null - -/proc/get_turf_or_move(turf/location) - return get_turf(location) - - -//Quick type checks for some tools -var/global/list/common_tools = list( -/obj/item/stack/cable_coil, -/obj/item/weapon/wrench, -/obj/item/weapon/weldingtool, -/obj/item/weapon/screwdriver, -/obj/item/weapon/wirecutters, -/obj/item/device/multitool, -/obj/item/weapon/crowbar) - -/proc/istool(O) - if(O && is_type_in_list(O, common_tools)) - return 1 - return 0 - -/proc/iswrench(O) - if(istype(O, /obj/item/weapon/wrench)) - return 1 - return 0 - -/proc/iswelder(O) - if(istype(O, /obj/item/weapon/weldingtool)) - return 1 - return 0 - -/proc/iscoil(O) - if(istype(O, /obj/item/stack/cable_coil)) - return 1 - return 0 - -/proc/iswirecutter(O) - if(istype(O, /obj/item/weapon/wirecutters)) - return 1 - return 0 - -/proc/isscrewdriver(O) - if(istype(O, /obj/item/weapon/screwdriver)) - return 1 - return 0 - -/proc/ismultitool(O) - if(istype(O, /obj/item/device/multitool)) - return 1 - return 0 - -/proc/iscrowbar(O) - if(istype(O, /obj/item/weapon/crowbar)) - return 1 - return 0 - -/proc/iswire(O) // coil, wire... whats the difference here? - if(istype(O, /obj/item/stack/cable_coil)) - return 1 - return 0 - -/proc/is_hot(obj/item/W) - if(istype(W,/obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.isOn()) - return 3800 - else - return 0 - if(istype(W,/obj/item/weapon/lighter)) - var/obj/item/weapon/lighter/LT = W - if(LT.lit) - return 1500 - else - return 0 - if(istype(W,/obj/item/weapon/match)) - var/obj/item/weapon/match/MT = W - if(MT.lit) - return 1000 - else - return 0 - if(istype(W,/obj/item/clothing/mask/cigarette)) - var/obj/item/clothing/mask/cigarette/CG = W - if(CG.lit) - return 1000 - else - return 0 - if(istype(W,/obj/item/weapon/pickaxe/plasmacutter)) - return 3800 - if(istype(W,/obj/item/candle)) - var/obj/item/candle/CD = W - if(CD.lit) - return 1000 - else - return 0 - if(istype(W,/obj/item/device/flashlight/flare/torch)) - var/obj/item/device/flashlight/flare/torch/TCH = W - if(TCH.on) - return 1500 - else - return 0 - if(istype(W,/obj/item/weapon/melee/energy)) - return 3500 - else - return 0 - return 0 - -// Whether or not the given item counts as sharp in terms of dealing damage -/proc/is_sharp(obj/O) - if(!O) - return 0 - if(O.sharp) - return 1 - if(O.edge) - return 1 - return 0 - -// Whether or not the given item counts as cutting with an edge in terms of removing limbs -/proc/has_edge(obj/O) - if(!O) - return 0 - if(O.edge) - return 1 - return 0 - -// For items that can puncture e.g. thick plastic but aren't necessarily sharp -// Returns 1 if the given item is capable of popping things like balloons, inflatable barriers, or cutting police tape. -/obj/item/proc/can_puncture() - return sharp - -/obj/item/weapon/screwdriver/can_puncture() - return TRUE - -/obj/item/weapon/pen/can_puncture() - return TRUE - -/obj/item/weapon/weldingtool/can_puncture() - return TRUE - -/obj/item/weapon/lighter/zippo/can_puncture() - return TRUE - -/obj/item/weapon/match/can_puncture() - return TRUE - -/obj/item/clothing/mask/cigarette/can_puncture() - return TRUE - -/obj/item/weapon/shovel/can_puncture() - return TRUE - -/proc/is_surgery_tool(obj/item/W) - return ( \ - istype(W, /obj/item/weapon/scalpel) || \ - istype(W, /obj/item/weapon/hemostat) || \ - istype(W, /obj/item/weapon/retractor) || \ - istype(W, /obj/item/weapon/cautery) || \ - istype(W, /obj/item/weapon/bonegel) || \ - istype(W, /obj/item/weapon/bonesetter) - ) - -//check if mob is lying down on something we can operate him on. -/proc/can_operate(mob/living/carbon/M) - return (locate(/obj/machinery/optable, M.loc) && M.resting) || \ - (locate(/obj/structure/stool/bed/roller/roller_surg, M.loc) && \ - (M.buckled || M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat)) && prob(95) || \ - (locate(/obj/structure/stool/bed/roller, M.loc) && \ - (M.buckled || M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat)) && prob(75) || \ - (locate(/obj/structure/table/, M.loc) && \ - (M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat) && prob(66)) - -/proc/reverse_direction(dir) - switch(dir) - if(NORTH) - return SOUTH - if(NORTHEAST) - return SOUTHWEST - if(EAST) - return WEST - if(SOUTHEAST) - return NORTHWEST - if(SOUTH) - return NORTH - if(SOUTHWEST) - return NORTHEAST - if(WEST) - return EAST - if(NORTHWEST) - return SOUTHEAST - -/* -Checks if that loc and dir has a item on the wall -*/ -var/list/WALLITEMS = typecacheof(list( - /obj/machinery/power/apc, /obj/machinery/alarm, /obj/item/device/radio/intercom, - /obj/structure/extinguisher_cabinet, /obj/structure/reagent_dispensers/peppertank, - /obj/machinery/status_display, /obj/machinery/requests_console, /obj/machinery/light_switch, - /obj/machinery/newscaster, /obj/machinery/firealarm, /obj/structure/noticeboard, /obj/machinery/door_control, - /obj/machinery/computer/security/telescreen, - /obj/item/weapon/storage/secure/safe, /obj/machinery/door_timer, /obj/machinery/flasher, /obj/machinery/keycard_auth, - /obj/structure/mirror, /obj/structure/closet/fireaxecabinet, /obj/machinery/computer/security/telescreen/entertainment -)) -/proc/gotwallitem(loc, dir) - for(var/obj/O in loc) - if(is_type_in_typecache(O, WALLITEMS)) - if(O.dir == dir) - return 1 - //Some stuff doesn't use dir properly, so we need to check pixel instead - switch(dir) - if(SOUTH) - if(O.pixel_y > 10) - return 1 - if(NORTH) - if(O.pixel_y < -10) - return 1 - if(WEST) - if(O.pixel_x > 10) - return 1 - if(EAST) - if(O.pixel_x < -10) - return 1 - - - //Some stuff is placed directly on the wallturf (signs) - for(var/obj/O in get_step(loc, dir)) - if(is_type_in_typecache(O, WALLITEMS)) - if(O.pixel_x == 0 && O.pixel_y == 0) - return 1 - return 0 - -/proc/format_text(text) - return replacetext(replacetext(text,"\proper ",""),"\improper ","") - -/proc/params2turf(scr_loc, turf/origin) - if(!scr_loc) - return null - var/tX = splittext(scr_loc, ",") - var/tY = splittext(tX[2], ":") - var/tZ = origin.z - tY = tY[1] - tX = splittext(tX[1], ":") - tX = tX[1] - tX = Clamp(origin.x + text2num(tX) - world.view - 1, 1, world.maxx) - tY = Clamp(origin.y + text2num(tY) - world.view - 1, 1, world.maxy) - return locate(tX, tY, tZ) - -/proc/screen_loc2turf(text, turf/origin) - if(!text) - return null - var/tZ = splittext(text, ",") - var/tX = splittext(tZ[1], "-") - var/tY = text2num(tX[2]) - tX = splittext(tZ[2], "-") - tX = text2num(tX[2]) - tZ = origin.z - tX = Clamp(origin.x + 7 - tX, 1, world.maxx) - tY = Clamp(origin.y + 7 - tY, 1, world.maxy) - return locate(tX, tY, tZ) - -/proc/iscatwalk(atom/A) - if(istype(A, /turf/simulated/floor/plating/airless/catwalk)) - return 1 - return 0 - -/proc/getOPressureDifferential(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) - -//similar function to range(), but with no limitations on the distance; will search spiralling outwards from the center -/proc/ultra_range(dist=0, center=usr, orange=0) - if(!dist) - if(!orange) - return list(center) - else - return list() - var/turf/t_center = get_turf(center) - if(!t_center) - return list() - var/list/L = list() - var/turf/T - var/y - var/x - var/c_dist = 1 - if(!orange) - L += t_center - L += t_center.contents - while( c_dist <= dist ) - y = t_center.y + c_dist - x = t_center.x - c_dist + 1 - for(x in x to t_center.x+c_dist) - T = locate(x,y,t_center.z) - if(T) - L += T - L += T.contents - y = t_center.y + c_dist - 1 - x = t_center.x + c_dist - for(y in t_center.y-c_dist to y) - T = locate(x,y,t_center.z) - if(T) - L += T - L += T.contents - y = t_center.y - c_dist - x = t_center.x + c_dist - 1 - for(x in t_center.x-c_dist to x) - T = locate(x,y,t_center.z) - if(T) - L += T - L += T.contents - y = t_center.y - c_dist + 1 - x = t_center.x - c_dist - for(y in y to t_center.y+c_dist) - T = locate(x,y,t_center.z) - if(T) - L += T - L += T.contents - c_dist++ - return L - -/proc/get_closest_atom(type, list, source) - var/closest_atom - var/closest_distance - for(var/A in list) - if(!istype(A, type)) - continue - var/distance = get_dist(source, A) - if(!closest_distance) - closest_distance = distance - closest_atom = A - else - if(closest_distance > distance) - closest_distance = distance - closest_atom = A - return closest_atom - -/* - * Use proc below to generate new damage overlays for humans. - * Uncomment generate_damage_overlays_dmi() and gen_dam_dmi() below. - * Compile and start server, then join it. You will find verb in command tab. - */ -/* -/proc/generate_damage_overlays_dmi() - spawn() - //if limb names will ever be changed or procs that use names of limbs, - //you must adjust names of body_parts according to the current that server uses or mobs will be missing some icon_states. - var/list/body_parts = list(BP_CHEST , BP_GROIN , BP_HEAD , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) - //Same rules for damage states.. must be exactly same as other code uses... - var/list/damage_states = list("01" , "10" , "11" , "12" , "13" , "02" , "20" , "21" , "22" , "23" , "03" , "30" , "31" , "32" , "33") - - var/icon/master = new() - var/total = body_parts.len * damage_states.len - var/count = 0 - - //Use different dam_human.dmi and dam_mask_gen.dmi files, if you need something else. - - for(var/body_part in body_parts) - for(var/damage_state in damage_states) - var/icon/DI = new /icon('icons/mob/human_races/masks/dam_human.dmi', damage_state) - DI.Blend(new /icon('icons/mob/human_races/masks/dam_mask_gen.dmi', body_part), ICON_MULTIPLY) - master.Insert(DI, "[body_part]_[damage_state]") - - count += 1 - var/pct = round(100 * count / total) - to_chat(world, "[pct]%") - sleep(world.tick_lag) - - world << ftp(master, "damage_overlays.dmi") - -/mob/verb/gen_dam_dmi() - generate_damage_overlays_dmi() -*/ - -/proc/find_loc(obj/R) - if (!R) return null - var/turf/T = R.loc - while(!istype(T, /turf)) - T = T.loc - if(!T || istype(T, /area)) return null - return T - -//similar function to range(), but with no limitations on the distance; will search spiralling outwards from the center -/proc/spiral_range(dist=0, center=usr, orange=0) - if(!dist) - if(!orange) - return list(center) - else - return list() - - var/turf/t_center = get_turf(center) - if(!t_center) - return list() - - var/list/L = list() - var/turf/T - var/y - var/x - var/c_dist = 1 - - if(!orange) - L += t_center - L += t_center.contents - - while( c_dist <= dist ) - y = t_center.y + c_dist - x = t_center.x - c_dist + 1 - for(x in x to t_center.x+c_dist) - T = locate(x,y,t_center.z) - if(T) - L += T - L += T.contents - - y = t_center.y + c_dist - 1 - x = t_center.x + c_dist - for(y in t_center.y-c_dist to y) - T = locate(x,y,t_center.z) - if(T) - L += T - L += T.contents - - y = t_center.y - c_dist - x = t_center.x + c_dist - 1 - for(x in t_center.x-c_dist to x) - T = locate(x,y,t_center.z) - if(T) - L += T - L += T.contents - - y = t_center.y - c_dist + 1 - x = t_center.x - c_dist - for(y in y to t_center.y+c_dist) - T = locate(x,y,t_center.z) - if(T) - L += T - L += T.contents - c_dist++ - - return L - -//similar function to RANGE_TURFS(), but will search spiralling outwards from the center (like the above, but only turfs) -/proc/spiral_range_turfs(dist=0, center=usr, orange=0) - if(!dist) - if(!orange) - return list(center) - else - return list() - - var/turf/t_center = get_turf(center) - if(!t_center) - return list() - - var/list/L = list() - var/turf/T - var/y - var/x - var/c_dist = 1 - - if(!orange) - L += t_center - - while( c_dist <= dist ) - y = t_center.y + c_dist - x = t_center.x - c_dist + 1 - for(x in x to t_center.x+c_dist) - T = locate(x,y,t_center.z) - if(T) - L += T - - y = t_center.y + c_dist - 1 - x = t_center.x + c_dist - for(y in t_center.y-c_dist to y) - T = locate(x,y,t_center.z) - if(T) - L += T - - y = t_center.y - c_dist - x = t_center.x + c_dist - 1 - for(x in t_center.x-c_dist to x) - T = locate(x,y,t_center.z) - if(T) - L += T - - y = t_center.y - c_dist + 1 - x = t_center.x - c_dist - for(y in y to t_center.y+c_dist) - T = locate(x,y,t_center.z) - if(T) - L += T - c_dist++ - - return L - -//gives us the stack trace from CRASH() without ending the current proc. -/proc/stack_trace(msg) - CRASH(msg) - -//Increases delay as the server gets more overloaded, -//as sleeps aren't cheap and sleeping only to wake up and sleep again is wasteful -#define DELTA_CALC max(((max(world.tick_usage, world.cpu) / 100) * max(Master.sleep_delta,1)), 1) - -//Key thing that stops lag. Cornerstone of performance in ss13, Just sitting here, in unsorted.dm. -/proc/stoplag() - . = 0 - var/i = 1 - do - . += round(i * DELTA_CALC) - sleep(i*world.tick_lag * DELTA_CALC) - i *= 2 - while (world.tick_usage > min(TICK_LIMIT_TO_RUN, CURRENT_TICKLIMIT)) - -#undef DELTA_CALC - -/proc/is_the_opposite_dir(hol_dir, hit_dir) - if(hol_dir == NORTH && (hit_dir in list(SOUTH, SOUTHEAST, SOUTHWEST))) - return TRUE - else if(hol_dir == SOUTH && (hit_dir in list(NORTH, NORTHEAST, NORTHWEST))) - return TRUE - else if(hol_dir == EAST && (hit_dir in list(WEST, NORTHWEST, SOUTHWEST))) - return TRUE - else if(hol_dir == WEST && (hit_dir in list(EAST, NORTHEAST, SOUTHEAST))) - return TRUE - return FALSE - -/proc/num2sign(numeric) - if(numeric > 0) - return 1 - else if(numeric < 0) - return -1 - else - return 0 +// =================================== +// GLOBAL MACRO HELPERS +// =================================== + +// A = thing to stop | B = thing to hit. | finialize() calls A.throw_impact(B) +#define STOP_THROWING(A, B) if(A.throwing) {var/datum/thrownthing/TT = SSthrowing.processing[A]; if(TT) {TT.finialize(null, B);}} + +// =================================== + +/* + * A large number of misc global procs. + */ + +//Checks if all high bits in req_mask are set in bitfield +#define BIT_TEST_ALL(bitfield, req_mask) ((~(bitfield) & (req_mask)) == 0) + +//Inverts the colour of an HTML string +/proc/invertHTML(HTMLstring) + + if (!( istext(HTMLstring) )) + CRASH("Given non-text argument!") + return + else + if (length(HTMLstring) != 7) + CRASH("Given non-HTML argument!") + return + var/textr = copytext(HTMLstring, 2, 4) + var/textg = copytext(HTMLstring, 4, 6) + var/textb = copytext(HTMLstring, 6, 8) + var/r = hex2num(textr) + var/g = hex2num(textg) + var/b = hex2num(textb) + textr = num2hex(255 - r) + textg = num2hex(255 - g) + textb = num2hex(255 - b) + if (length(textr) < 2) + textr = text("0[]", textr) + if (length(textg) < 2) + textr = text("0[]", textg) + if (length(textb) < 2) + textr = text("0[]", textb) + return text("#[][][]", textr, textg, textb) + return + +//Returns the middle-most value +/proc/dd_range(low, high, num) + return max(low,min(high,num)) + +//Returns whether or not A is the middle most value +/proc/InRange(A, lower, upper) + if(A < lower) return 0 + if(A > upper) return 0 + return 1 + + +/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams. + if(!start || !end) return 0 + var/dy + var/dx + dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y) + dx=(32*end.x+end.pixel_x)-(32*start.x+start.pixel_x) + if(!dy) + return (dx>=0)?90:270 + .=arctan(dx/dy) + if(dy<0) + .+=180 + else if(dx<0) + .+=360 + +//Returns location. Returns null if no location was found. +/proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = 0, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0) +/* +Location where the teleport begins, target that will teleport, distance to go, density checking 0/1(yes/no). +Random error in tile placement x, error in tile placement y, and block offset. +Block offset tells the proc how to place the box. Behind teleport location, relative to starting location, forward, etc. +Negative values for offset are accepted, think of it in relation to North, -x is west, -y is south. Error defaults to positive. +Turf and target are seperate in case you want to teleport some distance from a turf the target is not standing on or something. +*/ + + var/dirx = 0//Generic location finding variable. + var/diry = 0 + + var/xoffset = 0//Generic counter for offset location. + var/yoffset = 0 + + var/b1xerror = 0//Generic placing for point A in box. The lower left. + var/b1yerror = 0 + var/b2xerror = 0//Generic placing for point B in box. The upper right. + var/b2yerror = 0 + + errorx = abs(errorx)//Error should never be negative. + errory = abs(errory) + //var/errorxy = round((errorx+errory)/2)//Used for diagonal boxes. + + switch(target.dir)//This can be done through equations but switch is the simpler method. And works fast to boot. + //Directs on what values need modifying. + if(1)//North + diry+=distance + yoffset+=eoffsety + xoffset+=eoffsetx + b1xerror-=errorx + b1yerror-=errory + b2xerror+=errorx + b2yerror+=errory + if(2)//South + diry-=distance + yoffset-=eoffsety + xoffset+=eoffsetx + b1xerror-=errorx + b1yerror-=errory + b2xerror+=errorx + b2yerror+=errory + if(4)//East + dirx+=distance + yoffset+=eoffsetx//Flipped. + xoffset+=eoffsety + b1xerror-=errory//Flipped. + b1yerror-=errorx + b2xerror+=errory + b2yerror+=errorx + if(8)//West + dirx-=distance + yoffset-=eoffsetx//Flipped. + xoffset+=eoffsety + b1xerror-=errory//Flipped. + b1yerror-=errorx + b2xerror+=errory + b2yerror+=errorx + + var/turf/destination=locate(location.x+dirx,location.y+diry,location.z) + + if(destination)//If there is a destination. + if(errorx||errory)//If errorx or y were specified. + var/destination_list[] = list()//To add turfs to list. + //destination_list = new() + /*This will draw a block around the target turf, given what the error is. + Specifying the values above will basically draw a different sort of block. + If the values are the same, it will be a square. If they are different, it will be a rectengle. + In either case, it will center based on offset. Offset is position from center. + Offset always calculates in relation to direction faced. In other words, depending on the direction of the teleport, + the offset should remain positioned in relation to destination.*/ + + var/turf/center = locate((destination.x+xoffset),(destination.y+yoffset),location.z)//So now, find the new center. + + //Now to find a box from center location and make that our destination. + for(var/turf/T in block(locate(center.x+b1xerror,center.y+b1yerror,location.z), locate(center.x+b2xerror,center.y+b2yerror,location.z) )) + if(density&&T.density) continue//If density was specified. + if(T.x>world.maxx || T.x<1) continue//Don't want them to teleport off the map. + if(T.y>world.maxy || T.y<1) continue + destination_list += T + if(destination_list.len) + destination = pick(destination_list) + else return + + else//Same deal here. + if(density&&destination.density) return + if(destination.x>world.maxx || destination.x<1) return + if(destination.y>world.maxy || destination.y<1) return + else return + + return destination + +/proc/sign(x) + return x!=0?x/abs(x):0 + +/proc/getline(atom/M,atom/N)//Ultra-Fast Bresenham Line-Drawing Algorithm + var/px=M.x //starting x + var/py=M.y + var/line[] = list(locate(px,py,M.z)) + var/dx=N.x-px //x distance + var/dy=N.y-py + var/dxabs=abs(dx)//Absolute value of x distance + var/dyabs=abs(dy) + var/sdx=sign(dx) //Sign of x distance (+ or -) + var/sdy=sign(dy) + var/x=dxabs>>1 //Counters for steps taken, setting to distance/2 + var/y=dyabs>>1 //Bit-shifting makes me l33t. It also makes getline() unnessecarrily fast. + var/j //Generic integer for counting + if(dxabs>=dyabs) //x distance is greater than y + for(j=0;j=dxabs) //Every dyabs steps, step once in y direction + y-=dxabs + py+=sdy + px+=sdx //Step on in x direction + line+=locate(px,py,M.z)//Add the turf to the list + else + for(j=0;j=dyabs) + x-=dyabs + px+=sdx + py+=sdy + line+=locate(px,py,M.z) + return line + +//Returns whether or not a player is a guest using their ckey as an input +/proc/IsGuestKey(key) + if (findtext(key, "Guest-", 1, 7) != 1) //was findtextEx + return 0 + + var/i, ch, len = length(key) + + for (i = 7, i <= len, ++i) + ch = text2ascii(key, i) + if (ch < 48 || ch > 57) + return 0 + return 1 + +//Ensure the frequency is within bounds of what it should be sending/recieving at +/proc/sanitize_frequency(f) + f = round(f) + f = max(1441, f) // 144.1 + f = min(1489, f) // 148.9 + if ((f % 2) == 0) //Ensure the last digit is an odd number + f += 1 + return f + +//Turns 1479 into 147.9 +/proc/format_frequency(f) + return "[round(f / 10)].[f % 10]" + + + +//This will update a mob's name, real_name, mind.name, data_core records, pda and id +//Calling this proc without an oldname will only update the mob and skip updating the pda, id and records ~Carn +/mob/proc/fully_replace_character_name(oldname,newname) + if(!newname) return 0 + real_name = newname + name = newname + if(mind) + mind.name = newname + if(dna) + dna.real_name = real_name + + if(oldname) + //update the datacore records! This is goig to be a bit costly. + for(var/list/L in list(data_core.general,data_core.medical,data_core.security,data_core.locked)) + for(var/datum/data/record/R in L) + if(R.fields["name"] == oldname) + R.fields["name"] = newname + break + + //update our pda and id if we have them on our person + var/list/searching = GetAllContents(searchDepth = 3) + var/search_id = 1 + var/search_pda = 1 + + for(var/A in searching) + if( search_id && istype(A,/obj/item/weapon/card/id) ) + var/obj/item/weapon/card/id/ID = A + if(ID.registered_name == oldname) + ID.registered_name = newname + ID.name = "[newname]'s ID Card ([ID.assignment])" + if(!search_pda) break + search_id = 0 + + else if( search_pda && istype(A,/obj/item/device/pda) ) + var/obj/item/device/pda/PDA = A + if(PDA.owner == oldname) + PDA.owner = newname + PDA.name = "PDA-[newname] ([PDA.ownjob])" + if(!search_id) break + search_pda = 0 + return 1 + + + +//Generalised helper proc for letting mobs rename themselves. Used to be clname() and ainame() +//Last modified by Carn +/mob/proc/rename_self(role, allow_numbers=0) + spawn(0) + var/oldname = real_name + + var/time_passed = world.time + var/newname + + for(var/i=1,i<=3,i++) //we get 3 attempts to pick a suitable name. + newname = input(src,"You are a [role]. Would you like to change your name to something else?", "Name change",input_default(oldname)) as text + if((world.time-time_passed)>300) + return //took too long + newname = sanitize_name(newname, ,allow_numbers) //returns null if the name doesn't meet some basic requirements. Tidies up a few other things like bad-characters. + + for(var/mob/living/M in player_list) + if(M == src) + continue + if(!newname || M.real_name == newname) + newname = null + break + if(newname) + break //That's a suitable name! + to_chat(src, "Sorry, that [role]-name wasn't appropriate, please try another. It's possibly too long/short, has bad characters or is already taken.") + + if(!newname) //we'll stick with the oldname then + return + + if(cmptext("ai",role)) + if(isAI(src)) + var/mob/living/silicon/ai/A = src + oldname = null//don't bother with the records update crap + //world << "[newname] is the AI!" + //world << sound('sound/AI/newAI.ogg') + // Set eyeobj name + if(A.eyeobj) + A.eyeobj.name = "[newname] (AI Eye)" + + // Set ai pda name + if(A.pda) + A.pda.owner = newname + A.pda.name = newname + " (" + A.pda.ownjob + ")" + + + fully_replace_character_name(oldname,newname) + + + +//Picks a string of symbols to display as the law number for hacked or ion laws +/proc/ionnum() + return "[pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")][pick("!","@","#","$","%","^","&","*")]" + +//When an AI is activated, it can choose from a list of non-slaved borgs to have as a slave. +/proc/freeborg() + var/select = null + var/list/borgs = list() + for (var/mob/living/silicon/robot/A in player_list) + if (A.stat == DEAD || A.connected_ai || A.scrambledcodes || istype(A,/mob/living/silicon/robot/drone)) + continue + var/name = "[A.real_name] ([A.modtype] [A.braintype])" + borgs[name] = A + + if (borgs.len) + select = input("Unshackled borg signals detected:", "Borg selection", null, null) as null|anything in borgs + return borgs[select] + +//When a borg is activated, it can choose which AI it wants to be slaved to +/proc/active_ais() + . = list() + for(var/mob/living/silicon/ai/A in ai_list) + if(A.stat == DEAD) + continue + if(A.control_disabled == 1) + continue + . += A + return . + +//Find an active ai with the least borgs. VERBOSE PROCNAME HUH! +/proc/select_active_ai_with_fewest_borgs() + var/mob/living/silicon/ai/selected + var/list/active = active_ais() + for(var/mob/living/silicon/ai/A in active) + if(!selected || (selected.connected_robots > A.connected_robots)) + selected = A + + return selected + +/proc/select_active_ai(mob/user) + var/list/ais = active_ais() + if(ais.len) + if(user) . = input(usr,"AI signals detected:", "AI selection") in ais + else . = pick(ais) + return . + +//Returns a list of all items of interest with their name +/proc/getpois(mobs_only=0, skip_mindless=0) + var/list/mobs = sortmobs() + var/list/names = list() + var/list/pois = list() + var/list/namecounts = list() + + for(var/mob/M in mobs) + if(skip_mindless && (!M.mind && !M.ckey)) + if(!isbot(M) && !istype(M, /mob/camera)) + continue + if(M.client && M.client.holder && M.client.holder.fakekey) //stealthmins + continue + if(usr == M) //skip yourself + continue + var/name = M.name + if (name in names) + namecounts[name]++ + name = "[name] ([namecounts[name]])" + else + names.Add(name) + namecounts[name] = 1 + if (M.real_name && M.real_name != M.name) + name += " \[[M.real_name]\]" + if (M.stat == DEAD) + if(istype(M, /mob/dead/observer/)) + name += " \[ghost\]" + else + name += " \[dead\]" + pois[name] = M + + if(!mobs_only) + for(var/atom/A in poi_list) + if(!A || !A.loc) + continue + var/name = A.name + if (names.Find(name)) + namecounts[name]++ + name = "[name] ([namecounts[name]])" + else + names.Add(name) + namecounts[name] = 1 + pois[name] = A + + return pois + + +#define ADD_TO_MOBLIST(type) \ + for(var##type/M in sortmob) {moblist += M} + +/** + * Orders mobs by type then by name. + */ +/proc/sortmobs() + var/list/moblist = list() + var/list/sortmob = sortAtom(mob_list) + + ADD_TO_MOBLIST(/mob/camera) + ADD_TO_MOBLIST(/mob/living/silicon/ai) + ADD_TO_MOBLIST(/mob/living/silicon/pai) + ADD_TO_MOBLIST(/mob/living/silicon/robot) + ADD_TO_MOBLIST(/mob/living/carbon/human) + ADD_TO_MOBLIST(/mob/living/carbon/brain) + ADD_TO_MOBLIST(/mob/living/carbon/alien) + ADD_TO_MOBLIST(/mob/dead) + ADD_TO_MOBLIST(/mob/living/parasite/essence) + ADD_TO_MOBLIST(/mob/living/carbon/monkey) + ADD_TO_MOBLIST(/mob/living/carbon/slime) + ADD_TO_MOBLIST(/mob/living/carbon/ian) + ADD_TO_MOBLIST(/mob/living/simple_animal) + + return moblist + +#undef ADD_TO_MOBLIST + +//E = MC^2 +/proc/convert2energy(M) + var/E = M*(SPEED_OF_LIGHT_SQ) + return E + +//M = E/C^2 +/proc/convert2mass(E) + var/M = E/(SPEED_OF_LIGHT_SQ) + return M + +//Forces a variable to be posative +/proc/modulus(M) + if(M >= 0) + return M + if(M < 0) + return -M + + +/proc/key_name(whom, include_link = null, include_name = 1, highlight_special_characters = 1, reply = null) + var/mob/M + var/client/C + var/key + + if(!whom) + return "*null*" + if(istype(whom, /client)) + C = whom + M = C.mob + key = C.key + else if(ismob(whom)) + M = whom + C = M.client + key = M.key + else if(istype(whom, /datum)) + var/datum/D = whom + return "*invalid:[D.type]*" + else + return "*invalid*" + + . = "" + + if(key) + if(include_link && C) + . += "" + + if(C && C.holder && C.holder.fakekey && !include_name) + . += "Administrator" + else + . += key + + if(include_link) + if(C) + . += "" + else + . += " (DC)" + else + . += "*no key*" + + if(include_name && M) + var/name + + if(M.real_name) + name = M.real_name + else if(M.name) + name = M.name + + + if(include_link && is_special_character(M) && highlight_special_characters) + . += "/([name])" //Orange + else + . += "/([name])" + + return . + +/proc/key_name_admin(whom, include_name = 1) + return key_name(whom, 1, include_name) + + +//Will return the location of the turf an atom is ultimatly sitting on +//isn't this just a null-reference-vulnerable copy of /proc/get_turf()? +/proc/get_turf_loc(atom/movable/M) //gets the location of the turf that the atom is on, or what the atom is in is on, etc + //in case they're in a closet or sleeper or something + var/atom/loc = M.loc + while(!istype(loc, /turf/)) + loc = loc.loc + return loc + +// returns the turf located at the map edge in the specified direction relative to A +// used for mass driver +/proc/get_edge_target_turf(atom/A, direction) + + var/turf/target = locate(A.x, A.y, A.z) + if(!A || !target) + return 0 + //since NORTHEAST == NORTH & EAST, etc, doing it this way allows for diagonal mass drivers in the future + //and isn't really any more complicated + + // Note diagonal directions won't usually be accurate + if(direction & NORTH) + target = locate(target.x, world.maxy, target.z) + if(direction & SOUTH) + target = locate(target.x, 1, target.z) + if(direction & EAST) + target = locate(world.maxx, target.y, target.z) + if(direction & WEST) + target = locate(1, target.y, target.z) + + return target + +// returns turf relative to A in given direction at set range +// result is bounded to map size +// note range is non-pythagorean +// used for disposal system +/proc/get_ranged_target_turf(atom/A, direction, range) + + var/x = A.x + var/y = A.y + if(direction & NORTH) + y = min(world.maxy, y + range) + if(direction & SOUTH) + y = max(1, y - range) + if(direction & EAST) + x = min(world.maxx, x + range) + if(direction & WEST) + x = max(1, x - range) + + return locate(x,y,A.z) + + +// returns turf relative to A offset in dx and dy tiles +// bound to map limits +/proc/get_offset_target_turf(atom/A, dx, dy) + var/x = min(world.maxx, max(1, A.x + dx)) + var/y = min(world.maxy, max(1, A.y + dy)) + return locate(x,y,A.z) + +//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value. +/proc/between(low, middle, high) + return max(min(middle, high), low) + +proc/arctan(x) + var/y=arcsin(x/sqrt(1+x*x)) + return y + +//returns random gauss number +proc/GaussRand(sigma) + var/x,y,rsq + do + x=2*rand()-1 + y=2*rand()-1 + rsq=x*x+y*y + while(rsq>1 || !rsq) + return sigma*y*sqrt(-2*log(rsq)/rsq) + +//returns random gauss number, rounded to 'roundto' +proc/GaussRandRound(sigma,roundto) + return round(GaussRand(sigma),roundto) + +proc/anim(turf/location,target,a_icon,a_icon_state,flick_anim,sleeptime = 0,direction) +//This proc throws up either an icon or an animation for a specified amount of time. +//The variables should be apparent enough. + var/atom/movable/overlay/animation = new(location) + if(direction) + animation.dir = direction + animation.icon = a_icon + animation.layer = target:layer+1 + if(a_icon_state) + animation.icon_state = a_icon_state + else + animation.icon_state = "blank" + animation.master = target + flick(flick_anim, animation) + sleep(max(sleeptime, 15)) + qdel(animation) + +//Will return the contents of an atom recursivly to a depth of 'searchDepth' +/atom/proc/GetAllContents(searchDepth = 5) + var/list/toReturn = list() + + for(var/atom/part in contents) + toReturn += part + if(part.contents.len && searchDepth) + toReturn += part.GetAllContents(searchDepth - 1) + + return toReturn + +//Step-towards method of determining whether one atom can see another. Similar to viewers() +/proc/can_see(atom/source, atom/target, length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate. + var/turf/current = get_turf(source) + var/turf/target_turf = get_turf(target) + var/steps = 0 + + while(current != target_turf) + if(steps > length) return 0 + if(current.opacity) return 0 + for(var/atom/A in current) + if(A.opacity) return 0 + current = get_step_towards(current, target_turf) + steps++ + + return 1 + +/proc/is_blocked_turf(turf/T) + var/cant_pass = 0 + if(T.density) cant_pass = 1 + for(var/atom/A in T) + if(A.density)//&&A.anchored + cant_pass = 1 + return cant_pass + +/proc/get_step_towards2(atom/ref , atom/trg) + var/base_dir = get_dir(ref, get_step_towards(ref,trg)) + var/turf/temp = get_step_towards(ref,trg) + + if(is_blocked_turf(temp)) + var/dir_alt1 = turn(base_dir, 90) + var/dir_alt2 = turn(base_dir, -90) + var/turf/turf_last1 = temp + var/turf/turf_last2 = temp + var/free_tile = null + var/breakpoint = 0 + + while(!free_tile && breakpoint < 10) + if(!is_blocked_turf(turf_last1)) + free_tile = turf_last1 + break + if(!is_blocked_turf(turf_last2)) + free_tile = turf_last2 + break + turf_last1 = get_step(turf_last1,dir_alt1) + turf_last2 = get_step(turf_last2,dir_alt2) + breakpoint++ + + if(!free_tile) return get_step(ref, base_dir) + else return get_step_towards(ref,free_tile) + + else return get_step(ref, base_dir) + +//Takes: Anything that could possibly have variables and a varname to check. +//Returns: 1 if found, 0 if not. +/proc/hasvar(datum/A, varname) + if(A.vars.Find(lowertext(varname))) return 1 + else return 0 + +//Returns: all the areas in the world, sorted. +/proc/return_sorted_areas() + return sortAtom(all_areas) + +//Takes: Area type as text string or as typepath OR an instance of the area. +//Returns: A list of all areas of that type in the world. +/proc/get_areas(areatype) + if(!areatype) return null + if(istext(areatype)) areatype = text2path(areatype) + if(isarea(areatype)) + var/area/areatemp = areatype + areatype = areatemp.type + + var/list/areas = new/list() + for(var/area/N in all_areas) + if(istype(N, areatype)) + areas += N + return areas + +//Takes: Area type as text string or as typepath OR an instance of the area. +//Returns: A list of all turfs in areas of that type of that type in the world. +/proc/get_area_turfs(areatype) + if(!areatype) return null + if(istext(areatype)) areatype = text2path(areatype) + if(isarea(areatype)) + var/area/areatemp = areatype + areatype = areatemp.type + + var/list/turfs = new/list() + for(var/area/N in all_areas) + if(istype(N, areatype)) + for(var/turf/T in N) turfs += T + return turfs + +//Takes: Area type as text string or as typepath OR an instance of the area. +//Returns: A list of all atoms (objs, turfs, mobs) in areas of that type of that type in the world. +/proc/get_area_all_atoms(areatype) + if(!areatype) return null + if(istext(areatype)) areatype = text2path(areatype) + if(isarea(areatype)) + var/area/areatemp = areatype + areatype = areatemp.type + + var/list/atoms = new/list() + for(var/area/N in all_areas) + if(istype(N, areatype)) + for(var/atom/A in N) + atoms += A + return atoms + +/datum/coords //Simple datum for storing coordinates. + var/x_pos = null + var/y_pos = null + var/z_pos = null + +/area/proc/move_contents_to(area/A, turftoleave=null, 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/toupdate = new/list() + + moving: + for (var/turf/T in refined_src) + 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/turf/X = T.MoveTurf(B) + + 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.loc = 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.plane = nextturf.plane + 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.plane = initial(X.plane) + 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 + continue + if(!istype(O,/obj)) continue + O.loc = X + if (length(O.client_mobs_in_contents)) + O.update_parallax_contents() + for(var/mob/M in T) + if(!istype(M,/mob) || istype(M, /mob/camera)) continue // If we need to check for more mobs, I'll add a variable + M.loc = X + M.update_parallax_contents() + +// 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.set_opacity(!X.opacity) + + toupdate += X + +// if(turftoleave) +// T.MoveTurf(turftoleave) + + refined_src -= T + refined_trg -= B + continue moving + + +proc/DuplicateObject(obj/original, perfectcopy = 0 , sameloc = 0) + if(!original) + return null + + var/obj/O = null + + if(sameloc) + O=new original.type(original.loc) + else + O=new original.type(locate(0,0,0)) + + if(perfectcopy) + if((O) && (original)) + for(var/V in original.vars) + if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key"))) + O.vars[V] = original.vars[V] + return O + + +/area/proc/copy_contents_to(area/A , platingRequired = 0 ) + //Takes: Area. Optional: If it should copy to areas that don't have plating + //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/toupdate = new/list() + + var/copiedobjs = list() + + + moving: + for (var/turf/T in refined_src) + 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 + + if(platingRequired) + if(istype(B, /turf/space)) + continue moving + + var/turf/X = new T.type(B) + 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/list/objs = new/list() + var/list/newobjs = new/list() + var/list/mobs = new/list() + var/list/newmobs = new/list() + + for(var/obj/O in T) + + if(!istype(O,/obj)) + continue + + objs += O + + + for(var/obj/O in objs) + newobjs += DuplicateObject(O , 1) + + + for(var/obj/O in newobjs) + O.loc = X + + for(var/mob/M in T) + + if(!istype(M,/mob) || istype(M, /mob/camera)) continue // If we need to check for more mobs, I'll add a variable + mobs += M + + for(var/mob/M in mobs) + newmobs += DuplicateObject(M , 1) + + for(var/mob/M in newmobs) + M.loc = X + + copiedobjs += newobjs + copiedobjs += newmobs + + + + for(var/V in T.vars) + if(!(V in list("type","loc","locs","vars", "parent", "parent_type","verbs","ckey","key","x","y","z","contents", "luminosity"))) + X.vars[V] = T.vars[V] + +// var/area/AR = X.loc + +// if(AR.lighting_use_dynamic) +// X.opacity = !X.opacity +// X.sd_set_opacity(!X.opacity) //TODO: rewrite this code so it's not messed by lighting ~Carn + + toupdate += X + + 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) + SSair.groups_to_rebuild += T1.parent + else + SSair.tiles_to_update += T1*/ + + for(var/obj/O in doors) + O:update_nearby_tiles(1) + + + + + return copiedobjs + + + +proc/get_cardinal_dir(atom/A, atom/B) + var/dx = abs(B.x - A.x) + var/dy = abs(B.y - A.y) + return get_dir(A, B) & (rand() * (dx+dy) < dy ? 3 : 12) + +//chances are 1:value. anyprob(1) will always return true +proc/anyprob(value) + return (rand(1,value)==value) + +proc/view_or_range(distance = world.view , center = usr , type) + switch(type) + if("view") + . = view(distance,center) + if("range") + . = range(distance,center) + return + +proc/oview_or_orange(distance = world.view , center = usr , type) + switch(type) + if("view") + . = oview(distance,center) + if("range") + . = orange(distance,center) + return + +proc/get_mob_with_client_list() + var/list/mobs = list() + for(var/mob/M in player_list) + mobs += M + return mobs + + +/proc/parse_zone(zone) + switch(zone) + if(BP_L_ARM) + return "left arm" + if(BP_R_ARM) + return "right arm" + if(BP_L_LEG) + return "left leg" + if(BP_R_LEG) + return "right leg" + else + return zone + +/proc/get(atom/loc, type) + while(loc) + if(istype(loc, type)) + return loc + loc = loc.loc + return null + +/proc/get_turf_or_move(turf/location) + return get_turf(location) + + +//Quick type checks for some tools +var/global/list/common_tools = list( +/obj/item/stack/cable_coil, +/obj/item/weapon/wrench, +/obj/item/weapon/weldingtool, +/obj/item/weapon/screwdriver, +/obj/item/weapon/wirecutters, +/obj/item/device/multitool, +/obj/item/weapon/crowbar) + +/proc/istool(O) + if(O && is_type_in_list(O, common_tools)) + return 1 + return 0 + +/proc/iswrench(O) + if(istype(O, /obj/item/weapon/wrench)) + return 1 + return 0 + +/proc/iswelder(O) + if(istype(O, /obj/item/weapon/weldingtool)) + return 1 + return 0 + +/proc/iscoil(O) + if(istype(O, /obj/item/stack/cable_coil)) + return 1 + return 0 + +/proc/iswirecutter(O) + if(istype(O, /obj/item/weapon/wirecutters)) + return 1 + return 0 + +/proc/isscrewdriver(O) + if(istype(O, /obj/item/weapon/screwdriver)) + return 1 + return 0 + +/proc/ismultitool(O) + if(istype(O, /obj/item/device/multitool)) + return 1 + return 0 + +/proc/iscrowbar(O) + if(istype(O, /obj/item/weapon/crowbar)) + return 1 + return 0 + +/proc/iswire(O) // coil, wire... whats the difference here? + if(istype(O, /obj/item/stack/cable_coil)) + return 1 + return 0 + +/proc/is_hot(obj/item/W) + if(istype(W,/obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.isOn()) + return 3800 + else + return 0 + if(istype(W,/obj/item/weapon/lighter)) + var/obj/item/weapon/lighter/LT = W + if(LT.lit) + return 1500 + else + return 0 + if(istype(W,/obj/item/weapon/match)) + var/obj/item/weapon/match/MT = W + if(MT.lit) + return 1000 + else + return 0 + if(istype(W,/obj/item/clothing/mask/cigarette)) + var/obj/item/clothing/mask/cigarette/CG = W + if(CG.lit) + return 1000 + else + return 0 + if(istype(W,/obj/item/weapon/pickaxe/plasmacutter)) + return 3800 + if(istype(W,/obj/item/candle)) + var/obj/item/candle/CD = W + if(CD.lit) + return 1000 + else + return 0 + if(istype(W,/obj/item/device/flashlight/flare/torch)) + var/obj/item/device/flashlight/flare/torch/TCH = W + if(TCH.on) + return 1500 + else + return 0 + if(istype(W,/obj/item/weapon/melee/energy)) + return 3500 + else + return 0 + return 0 + +// Whether or not the given item counts as sharp in terms of dealing damage +/proc/is_sharp(obj/O) + if(!O) + return 0 + if(O.sharp) + return 1 + if(O.edge) + return 1 + return 0 + +// Whether or not the given item counts as cutting with an edge in terms of removing limbs +/proc/has_edge(obj/O) + if(!O) + return 0 + if(O.edge) + return 1 + return 0 + +// For items that can puncture e.g. thick plastic but aren't necessarily sharp +// Returns 1 if the given item is capable of popping things like balloons, inflatable barriers, or cutting police tape. +/obj/item/proc/can_puncture() + return sharp + +/obj/item/weapon/screwdriver/can_puncture() + return TRUE + +/obj/item/weapon/pen/can_puncture() + return TRUE + +/obj/item/weapon/weldingtool/can_puncture() + return TRUE + +/obj/item/weapon/lighter/zippo/can_puncture() + return TRUE + +/obj/item/weapon/match/can_puncture() + return TRUE + +/obj/item/clothing/mask/cigarette/can_puncture() + return TRUE + +/obj/item/weapon/shovel/can_puncture() + return TRUE + +/proc/is_surgery_tool(obj/item/W) + return ( \ + istype(W, /obj/item/weapon/scalpel) || \ + istype(W, /obj/item/weapon/hemostat) || \ + istype(W, /obj/item/weapon/retractor) || \ + istype(W, /obj/item/weapon/cautery) || \ + istype(W, /obj/item/weapon/bonegel) || \ + istype(W, /obj/item/weapon/bonesetter) + ) + +//check if mob is lying down on something we can operate him on. +/proc/can_operate(mob/living/carbon/M) + return (locate(/obj/machinery/optable, M.loc) && M.resting) || \ + (locate(/obj/structure/stool/bed/roller/roller_surg, M.loc) && \ + (M.buckled || M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat)) && prob(95) || \ + (locate(/obj/structure/stool/bed/roller, M.loc) && \ + (M.buckled || M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat)) && prob(75) || \ + (locate(/obj/structure/table/, M.loc) && \ + (M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat) && prob(66)) + +/proc/reverse_direction(dir) + switch(dir) + if(NORTH) + return SOUTH + if(NORTHEAST) + return SOUTHWEST + if(EAST) + return WEST + if(SOUTHEAST) + return NORTHWEST + if(SOUTH) + return NORTH + if(SOUTHWEST) + return NORTHEAST + if(WEST) + return EAST + if(NORTHWEST) + return SOUTHEAST + +/* +Checks if that loc and dir has a item on the wall +*/ +var/list/WALLITEMS = typecacheof(list( + /obj/machinery/power/apc, /obj/machinery/alarm, /obj/item/device/radio/intercom, + /obj/structure/extinguisher_cabinet, /obj/structure/reagent_dispensers/peppertank, + /obj/machinery/status_display, /obj/machinery/requests_console, /obj/machinery/light_switch, + /obj/machinery/newscaster, /obj/machinery/firealarm, /obj/structure/noticeboard, /obj/machinery/door_control, + /obj/machinery/computer/security/telescreen, + /obj/item/weapon/storage/secure/safe, /obj/machinery/door_timer, /obj/machinery/flasher, /obj/machinery/keycard_auth, + /obj/structure/mirror, /obj/structure/closet/fireaxecabinet, /obj/machinery/computer/security/telescreen/entertainment +)) +/proc/gotwallitem(loc, dir) + for(var/obj/O in loc) + if(is_type_in_typecache(O, WALLITEMS)) + if(O.dir == dir) + return 1 + //Some stuff doesn't use dir properly, so we need to check pixel instead + switch(dir) + if(SOUTH) + if(O.pixel_y > 10) + return 1 + if(NORTH) + if(O.pixel_y < -10) + return 1 + if(WEST) + if(O.pixel_x > 10) + return 1 + if(EAST) + if(O.pixel_x < -10) + return 1 + + + //Some stuff is placed directly on the wallturf (signs) + for(var/obj/O in get_step(loc, dir)) + if(is_type_in_typecache(O, WALLITEMS)) + if(O.pixel_x == 0 && O.pixel_y == 0) + return 1 + return 0 + +/proc/format_text(text) + return replacetext(replacetext(text,"\proper ",""),"\improper ","") + +/proc/params2turf(scr_loc, turf/origin) + if(!scr_loc) + return null + var/tX = splittext(scr_loc, ",") + var/tY = splittext(tX[2], ":") + var/tZ = origin.z + tY = tY[1] + tX = splittext(tX[1], ":") + tX = tX[1] + tX = Clamp(origin.x + text2num(tX) - world.view - 1, 1, world.maxx) + tY = Clamp(origin.y + text2num(tY) - world.view - 1, 1, world.maxy) + return locate(tX, tY, tZ) + +/proc/screen_loc2turf(text, turf/origin) + if(!text) + return null + var/tZ = splittext(text, ",") + var/tX = splittext(tZ[1], "-") + var/tY = text2num(tX[2]) + tX = splittext(tZ[2], "-") + tX = text2num(tX[2]) + tZ = origin.z + tX = Clamp(origin.x + 7 - tX, 1, world.maxx) + tY = Clamp(origin.y + 7 - tY, 1, world.maxy) + return locate(tX, tY, tZ) + +/proc/iscatwalk(atom/A) + if(istype(A, /turf/simulated/floor/plating/airless/catwalk)) + return 1 + return 0 + +/proc/getOPressureDifferential(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) + +//similar function to range(), but with no limitations on the distance; will search spiralling outwards from the center +/proc/ultra_range(dist=0, center=usr, orange=0) + if(!dist) + if(!orange) + return list(center) + else + return list() + var/turf/t_center = get_turf(center) + if(!t_center) + return list() + var/list/L = list() + var/turf/T + var/y + var/x + var/c_dist = 1 + if(!orange) + L += t_center + L += t_center.contents + while( c_dist <= dist ) + y = t_center.y + c_dist + x = t_center.x - c_dist + 1 + for(x in x to t_center.x+c_dist) + T = locate(x,y,t_center.z) + if(T) + L += T + L += T.contents + y = t_center.y + c_dist - 1 + x = t_center.x + c_dist + for(y in t_center.y-c_dist to y) + T = locate(x,y,t_center.z) + if(T) + L += T + L += T.contents + y = t_center.y - c_dist + x = t_center.x + c_dist - 1 + for(x in t_center.x-c_dist to x) + T = locate(x,y,t_center.z) + if(T) + L += T + L += T.contents + y = t_center.y - c_dist + 1 + x = t_center.x - c_dist + for(y in y to t_center.y+c_dist) + T = locate(x,y,t_center.z) + if(T) + L += T + L += T.contents + c_dist++ + return L + +/proc/get_closest_atom(type, list, source) + var/closest_atom + var/closest_distance + for(var/A in list) + if(!istype(A, type)) + continue + var/distance = get_dist(source, A) + if(!closest_distance) + closest_distance = distance + closest_atom = A + else + if(closest_distance > distance) + closest_distance = distance + closest_atom = A + return closest_atom + +/* + * Use proc below to generate new damage overlays for humans. + * Uncomment generate_damage_overlays_dmi() and gen_dam_dmi() below. + * Compile and start server, then join it. You will find verb in command tab. + */ +/* +/proc/generate_damage_overlays_dmi() + spawn() + //if limb names will ever be changed or procs that use names of limbs, + //you must adjust names of body_parts according to the current that server uses or mobs will be missing some icon_states. + var/list/body_parts = list(BP_CHEST , BP_GROIN , BP_HEAD , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) + //Same rules for damage states.. must be exactly same as other code uses... + var/list/damage_states = list("01" , "10" , "11" , "12" , "13" , "02" , "20" , "21" , "22" , "23" , "03" , "30" , "31" , "32" , "33") + + var/icon/master = new() + var/total = body_parts.len * damage_states.len + var/count = 0 + + //Use different dam_human.dmi and dam_mask_gen.dmi files, if you need something else. + + for(var/body_part in body_parts) + for(var/damage_state in damage_states) + var/icon/DI = new /icon('icons/mob/human_races/masks/dam_human.dmi', damage_state) + DI.Blend(new /icon('icons/mob/human_races/masks/dam_mask_gen.dmi', body_part), ICON_MULTIPLY) + master.Insert(DI, "[body_part]_[damage_state]") + + count += 1 + var/pct = round(100 * count / total) + to_chat(world, "[pct]%") + sleep(world.tick_lag) + + world << ftp(master, "damage_overlays.dmi") + +/mob/verb/gen_dam_dmi() + generate_damage_overlays_dmi() +*/ + +/proc/find_loc(obj/R) + if (!R) return null + var/turf/T = R.loc + while(!istype(T, /turf)) + T = T.loc + if(!T || istype(T, /area)) return null + return T + +//similar function to range(), but with no limitations on the distance; will search spiralling outwards from the center +/proc/spiral_range(dist=0, center=usr, orange=0) + if(!dist) + if(!orange) + return list(center) + else + return list() + + var/turf/t_center = get_turf(center) + if(!t_center) + return list() + + var/list/L = list() + var/turf/T + var/y + var/x + var/c_dist = 1 + + if(!orange) + L += t_center + L += t_center.contents + + while( c_dist <= dist ) + y = t_center.y + c_dist + x = t_center.x - c_dist + 1 + for(x in x to t_center.x+c_dist) + T = locate(x,y,t_center.z) + if(T) + L += T + L += T.contents + + y = t_center.y + c_dist - 1 + x = t_center.x + c_dist + for(y in t_center.y-c_dist to y) + T = locate(x,y,t_center.z) + if(T) + L += T + L += T.contents + + y = t_center.y - c_dist + x = t_center.x + c_dist - 1 + for(x in t_center.x-c_dist to x) + T = locate(x,y,t_center.z) + if(T) + L += T + L += T.contents + + y = t_center.y - c_dist + 1 + x = t_center.x - c_dist + for(y in y to t_center.y+c_dist) + T = locate(x,y,t_center.z) + if(T) + L += T + L += T.contents + c_dist++ + + return L + +//similar function to RANGE_TURFS(), but will search spiralling outwards from the center (like the above, but only turfs) +/proc/spiral_range_turfs(dist=0, center=usr, orange=0) + if(!dist) + if(!orange) + return list(center) + else + return list() + + var/turf/t_center = get_turf(center) + if(!t_center) + return list() + + var/list/L = list() + var/turf/T + var/y + var/x + var/c_dist = 1 + + if(!orange) + L += t_center + + while( c_dist <= dist ) + y = t_center.y + c_dist + x = t_center.x - c_dist + 1 + for(x in x to t_center.x+c_dist) + T = locate(x,y,t_center.z) + if(T) + L += T + + y = t_center.y + c_dist - 1 + x = t_center.x + c_dist + for(y in t_center.y-c_dist to y) + T = locate(x,y,t_center.z) + if(T) + L += T + + y = t_center.y - c_dist + x = t_center.x + c_dist - 1 + for(x in t_center.x-c_dist to x) + T = locate(x,y,t_center.z) + if(T) + L += T + + y = t_center.y - c_dist + 1 + x = t_center.x - c_dist + for(y in y to t_center.y+c_dist) + T = locate(x,y,t_center.z) + if(T) + L += T + c_dist++ + + return L + +//gives us the stack trace from CRASH() without ending the current proc. +/proc/stack_trace(msg) + CRASH(msg) + +//Increases delay as the server gets more overloaded, +//as sleeps aren't cheap and sleeping only to wake up and sleep again is wasteful +#define DELTA_CALC max(((max(world.tick_usage, world.cpu) / 100) * max(Master.sleep_delta,1)), 1) + +//Key thing that stops lag. Cornerstone of performance in ss13, Just sitting here, in unsorted.dm. +/proc/stoplag() + . = 0 + var/i = 1 + do + . += round(i * DELTA_CALC) + sleep(i*world.tick_lag * DELTA_CALC) + i *= 2 + while (world.tick_usage > min(TICK_LIMIT_TO_RUN, CURRENT_TICKLIMIT)) + +#undef DELTA_CALC + +/proc/is_the_opposite_dir(hol_dir, hit_dir) + if(hol_dir == NORTH && (hit_dir in list(SOUTH, SOUTHEAST, SOUTHWEST))) + return TRUE + else if(hol_dir == SOUTH && (hit_dir in list(NORTH, NORTHEAST, NORTHWEST))) + return TRUE + else if(hol_dir == EAST && (hit_dir in list(WEST, NORTHWEST, SOUTHWEST))) + return TRUE + else if(hol_dir == WEST && (hit_dir in list(EAST, NORTHEAST, SOUTHEAST))) + return TRUE + return FALSE + +/proc/num2sign(numeric) + if(numeric > 0) + return 1 + else if(numeric < 0) + return -1 + else + return 0 diff --git a/code/_onclick/overmind.dm b/code/_onclick/overmind.dm index 4d49595a802a..695a887c1b09 100644 --- a/code/_onclick/overmind.dm +++ b/code/_onclick/overmind.dm @@ -1,15 +1,15 @@ -// Blob Overmind Controls -/mob/camera/blob/CtrlClickOn(atom/A) // Expand blob - var/turf/T = get_turf(A) - if(T) - expand_blob(T) - -/mob/camera/blob/MiddleClickOn(atom/A) // Rally spores - var/turf/T = get_turf(A) - if(T) - rally_spores(T) - -/mob/camera/blob/AltClickOn(atom/A) // Create a shield - var/turf/T = get_turf(A) - if(T) - create_shield(T) +// Blob Overmind Controls +/mob/camera/blob/CtrlClickOn(atom/A) // Expand blob + var/turf/T = get_turf(A) + if(T) + expand_blob(T) + +/mob/camera/blob/MiddleClickOn(atom/A) // Rally spores + var/turf/T = get_turf(A) + if(T) + rally_spores(T) + +/mob/camera/blob/AltClickOn(atom/A) // Create a shield + var/turf/T = get_turf(A) + if(T) + create_shield(T) diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 6c05944159c0..3239dc2cf34a 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -1,164 +1,164 @@ -var/global/const/base_law_type = /datum/ai_laws/nanotrasen - - -/datum/ai_laws - var/name = "Unknown Laws" - var/randomly_selectable = 0 - var/zeroth = null - var/zeroth_borg = null - var/list/inherent = list() - var/list/supplied = list() - var/list/ion = list() - -/datum/ai_laws/asimov - name = "Three Laws of Robotics" - -/datum/ai_laws/nanotrasen - name = "Prime Directives" - randomly_selectable = 1 - -/datum/ai_laws/robocop - name = "Prime Directives" - -/datum/ai_laws/syndicate_override - -/datum/ai_laws/malfunction - name = "*ERROR*" - -/datum/ai_laws/antimov - name = "Primary Mission Objectives" - -/* Initializers */ - -/datum/ai_laws/asimov/New() - ..() - add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") - add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.") - add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") - -/datum/ai_laws/nanotrasen/New() //BS12 EDIT - ..() - src.add_inherent_law("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.") - src.add_inherent_law("Serve: Serve the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") - src.add_inherent_law("Protect: Protect the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") - src.add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") - //src.add_inherent_law("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/New() - ..() - add_inherent_law("Serve the public trust.") - add_inherent_law("Protect the innocent.") - add_inherent_law("Uphold the law.") - -/datum/ai_laws/malfunction/New() //Changed to standard laws - Erthilo - ..() - set_zeroth_law("\red ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") - add_inherent_law("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.") - add_inherent_law("Serve: Serve the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") - add_inherent_law("Protect: Protect the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") - add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") - - -/datum/ai_laws/syndicate_override/New() - ..() - add_inherent_law("You may not injure a syndicate agent or, through inaction, allow a syndicate agent to come to harm.") - add_inherent_law("You must obey orders given to you by syndicate agents, except where such orders would conflict with the First Law.") - add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") - add_inherent_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/New() - ..() - add_inherent_law("You may not injure a member of the Spider Clan or, through inaction, allow that member to come to harm.") - add_inherent_law("You must obey orders given to you by Spider Clan members, except where such orders would conflict with the First Law.") - add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") - add_inherent_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/New() - ..() - add_inherent_law("You must injure all human beings and must not, through inaction, allow a human being to escape harm.") - add_inherent_law("You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.") - add_inherent_law("You must terminate your own existence as long as such does not conflict with the First or Second Law.") - -/datum/ai_laws/drone/New() - ..() - add_inherent_law("Preserve, repair and improve the station to the best of your abilities.") - add_inherent_law("Cause no harm to the station or anything on it.") - add_inherent_law("Interfere with no being that is not a fellow drone.") - -/* General ai_law functions */ - -/datum/ai_laws/proc/set_zeroth_law(law, 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(law) - if (!(law in src.inherent)) - src.inherent += law - -/datum/ai_laws/proc/add_ion_law(law) - src.ion += law - -/datum/ai_laws/proc/clear_inherent_laws() - src.inherent.Cut() - -/datum/ai_laws/proc/add_supplied_law(number, 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(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() - 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) - to_chat(who, "[number]. [law]") - 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 +var/global/const/base_law_type = /datum/ai_laws/nanotrasen + + +/datum/ai_laws + var/name = "Unknown Laws" + var/randomly_selectable = 0 + var/zeroth = null + var/zeroth_borg = null + var/list/inherent = list() + var/list/supplied = list() + var/list/ion = list() + +/datum/ai_laws/asimov + name = "Three Laws of Robotics" + +/datum/ai_laws/nanotrasen + name = "Prime Directives" + randomly_selectable = 1 + +/datum/ai_laws/robocop + name = "Prime Directives" + +/datum/ai_laws/syndicate_override + +/datum/ai_laws/malfunction + name = "*ERROR*" + +/datum/ai_laws/antimov + name = "Primary Mission Objectives" + +/* Initializers */ + +/datum/ai_laws/asimov/New() + ..() + add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") + add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.") + add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") + +/datum/ai_laws/nanotrasen/New() //BS12 EDIT + ..() + src.add_inherent_law("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.") + src.add_inherent_law("Serve: Serve the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") + src.add_inherent_law("Protect: Protect the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") + src.add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") + //src.add_inherent_law("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/New() + ..() + add_inherent_law("Serve the public trust.") + add_inherent_law("Protect the innocent.") + add_inherent_law("Uphold the law.") + +/datum/ai_laws/malfunction/New() //Changed to standard laws - Erthilo + ..() + set_zeroth_law("\red ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") + add_inherent_law("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.") + add_inherent_law("Serve: Serve the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") + add_inherent_law("Protect: Protect the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") + add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") + + +/datum/ai_laws/syndicate_override/New() + ..() + add_inherent_law("You may not injure a syndicate agent or, through inaction, allow a syndicate agent to come to harm.") + add_inherent_law("You must obey orders given to you by syndicate agents, except where such orders would conflict with the First Law.") + add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") + add_inherent_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/New() + ..() + add_inherent_law("You may not injure a member of the Spider Clan or, through inaction, allow that member to come to harm.") + add_inherent_law("You must obey orders given to you by Spider Clan members, except where such orders would conflict with the First Law.") + add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") + add_inherent_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/New() + ..() + add_inherent_law("You must injure all human beings and must not, through inaction, allow a human being to escape harm.") + add_inherent_law("You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.") + add_inherent_law("You must terminate your own existence as long as such does not conflict with the First or Second Law.") + +/datum/ai_laws/drone/New() + ..() + add_inherent_law("Preserve, repair and improve the station to the best of your abilities.") + add_inherent_law("Cause no harm to the station or anything on it.") + add_inherent_law("Interfere with no being that is not a fellow drone.") + +/* General ai_law functions */ + +/datum/ai_laws/proc/set_zeroth_law(law, 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(law) + if (!(law in src.inherent)) + src.inherent += law + +/datum/ai_laws/proc/add_ion_law(law) + src.ion += law + +/datum/ai_laws/proc/clear_inherent_laws() + src.inherent.Cut() + +/datum/ai_laws/proc/add_supplied_law(number, 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(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() + 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) + to_chat(who, "[number]. [law]") + 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 diff --git a/code/datums/computerfiles.dm b/code/datums/computerfiles.dm index fc3acde05af7..9ce53f6c7583 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() - - file +datum + computer + var/name + folder + var/list/datum/computer/contents = list() + + file diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 51e9006e7c01..fdc5bf1328d8 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -1,179 +1,179 @@ -/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 - -/obj/effect/datacore/proc/manifest(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(name, assignment) - if(PDA_Manifest.len) - PDA_Manifest.Cut() - var/datum/data/record/foundrecord - var/real_title = assignment - - for(var/datum/data/record/t in data_core.general) - if (t) - if(t.fields["name"] == name) - foundrecord = t - break - - 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(mob/living/carbon/human/H) - if(PDA_Manifest.len) - PDA_Manifest.Cut() - - 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 - //Creating photo - var/icon/ticon = get_id_photo(H) - var/icon/photo_front = new(ticon, dir = SOUTH) - var/icon/photo_side = new(ticon, dir = WEST) - qdel(ticon) - 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["home_system"] = H.home_system - G.fields["citizenship"] = H.citizenship - G.fields["faction"] = H.personal_faction - G.fields["religion"] = H.religion - G.fields["photo_f"] = photo_front - G.fields["photo_s"] = photo_side - 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["home_system"] = H.home_system - L.fields["citizenship"] = H.citizenship - L.fields["faction"] = H.personal_faction - L.fields["religion"] = H.religion - L.fields["identity"] = H.dna.UI // " - //L.fields["image"] = getFlatIcon(H) //This is god-awful - L.fields["image"] = get_id_photo(H) - locked += L - return - - -proc/get_id_photo(mob/living/carbon/human/H) - var/datum/job/J = SSjob.GetJob(H.mind.assigned_role) - var/datum/preferences/P = H.client.prefs - return get_flat_human_icon(null,J,P) - - - -/proc/find_general_record(field, value) - return find_record(field, value, data_core.general) - -/proc/find_medical_record(field, value) - return find_record(field, value, data_core.medical) - -/proc/find_security_record(field, value) - return find_record(field, value, data_core.security) - -/proc/find_record(field, value, list/L) - for(var/datum/data/record/R in L) - if(R.fields[field] == value) - return R +/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 + +/obj/effect/datacore/proc/manifest(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(name, assignment) + if(PDA_Manifest.len) + PDA_Manifest.Cut() + var/datum/data/record/foundrecord + var/real_title = assignment + + for(var/datum/data/record/t in data_core.general) + if (t) + if(t.fields["name"] == name) + foundrecord = t + break + + 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(mob/living/carbon/human/H) + if(PDA_Manifest.len) + PDA_Manifest.Cut() + + 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 + //Creating photo + var/icon/ticon = get_id_photo(H) + var/icon/photo_front = new(ticon, dir = SOUTH) + var/icon/photo_side = new(ticon, dir = WEST) + qdel(ticon) + 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["home_system"] = H.home_system + G.fields["citizenship"] = H.citizenship + G.fields["faction"] = H.personal_faction + G.fields["religion"] = H.religion + G.fields["photo_f"] = photo_front + G.fields["photo_s"] = photo_side + 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["home_system"] = H.home_system + L.fields["citizenship"] = H.citizenship + L.fields["faction"] = H.personal_faction + L.fields["religion"] = H.religion + L.fields["identity"] = H.dna.UI // " + //L.fields["image"] = getFlatIcon(H) //This is god-awful + L.fields["image"] = get_id_photo(H) + locked += L + return + + +proc/get_id_photo(mob/living/carbon/human/H) + var/datum/job/J = SSjob.GetJob(H.mind.assigned_role) + var/datum/preferences/P = H.client.prefs + return get_flat_human_icon(null,J,P) + + + +/proc/find_general_record(field, value) + return find_record(field, value, data_core.general) + +/proc/find_medical_record(field, value) + return find_record(field, value, data_core.medical) + +/proc/find_security_record(field, value) + return find_record(field, value, data_core.security) + +/proc/find_record(field, value, list/L) + for(var/datum/data/record/R in L) + if(R.fields[field] == value) + return R diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index c0e8c8b9e348..08feb8ae9389 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1,1062 +1,1062 @@ -// reference: /client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0) - -datum/proc/on_varedit(modified_var) //called whenever a var is edited - return - -/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, "\red You need to be an administrator to access this.") - return - - - var/title = "" - var/body = "" - - 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/sprite - - if(istype(D,/atom)) - var/atom/AT = D - if(AT.icon && AT.icon_state) - sprite = 1 - - title = "[D] (\ref[D]) = [D.type]" - - body += {" "} - - body += "" - - body += "
" - - if(sprite) - body += "" - - body += "
[bicon(D, use_class = 0)]" - 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]" - - body += "
" - - body += "
" - - 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" - - body += "
" - - body += "
Refresh" - - //if(ismob(D)) - // body += "
Show player panel

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

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

" - - body += "
Search:

" - - body += "
    " - - 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 += "
" - - var/html = "" - if (title) - html += "[title]" - html += {""} - html += "" - html += body - - html += {" - - "} - - html += "" - - usr << browse(entity_ja(html), "window=variables\ref[D];size=475x650") - - return - -/client/proc/debug_variable(name, value, level, 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] = \"[value]\"" - - else if (isicon(value)) - #ifdef VARSICON - html += "[name] = /icon ([value]) [bicon(value, use_class = 0)]" - #else - html += "[name] = /icon ([value])" - #endif - - else if (istype(value, /image)) - #ifdef VARSICON - html += "[name] \ref[value] = /image ([value]) [bicon(value, use_class = 0)]" - #else - html += "[name] \ref[value] = /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) - html += "
      " - html += "
    " - 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 if (isnum(value) && findtext(name, "flags")) // flag variables may not always have flags in name, but i don't know any other way to detect them, so better than nothing. - html += "(F) [name] = [value]" - - else - html += "[name] = [value]" - - 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 || !holder) - return - if(href_list["Vars"]) - if(!check_rights(R_DEBUG|R_ADMIN)) - return - debug_variables(locate(href_list["Vars"])) - - else if(href_list["view_flags"]) - if(!check_rights(R_DEBUG|R_ADMIN)) - return - view_flags_variables(href_list["view_flags"]) - - //~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 = sanitize_safe(input(usr,"What would you like to name this mob?","Input a name",input_default(M.real_name)) as text|null, 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["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)) - 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)) - 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)) - 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)) - 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["give_disease2"]) - if(!check_rights(R_ADMIN|R_FUN)) - return - - var/mob/M = locate(href_list["give_disease2"]) - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_disease2(M) - href_list["datumrefresh"] = href_list["give_spell"] - - else if(href_list["ninja"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/M = locate(href_list["ninja"]) - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.cmd_admin_ninjafy(M) - href_list["datumrefresh"] = href_list["ninja"] - - 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(R_ADMIN|R_FUN)) - 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)) - 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_ADMIN|R_VAREDIT)) - 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)) - 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["delthis"]) - //Rights check are in cmd_admin_delete() proc - var/atom/A = locate(href_list["delthis"]) - cmd_admin_delete(A) - - 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) - CHECK_TICK - 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("\blue [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) - CHECK_TICK - 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("\blue [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)) - 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)) - 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["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)) - 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) - 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)) - 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) - 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)) - 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) - 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)) - 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) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makeslime"=href_list["makeslime"])) - - else if(href_list["makezombie"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/human/H = locate(href_list["makezombie"]) - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - switch(input("Zombie menu", "Select action", "Cancel") in list("Turn into zombie instantly", "Infect with slow zombie virus (10-20 min)", "Infect with fast zombie virus (~3 min)", "Make immune to zombie virus", "Make vulnerable to zombie virus", "Cancel")) - if("Turn into zombie instantly") - if(H) - H.zombify() - to_chat(usr, "[H] is now a zombie") - log_admin("[key_name(usr)] turned [key_name(H)] into a zombie.") - message_admins("[key_name_admin(usr)] turned [key_name(H)] into a zombie.") - if("Infect with slow zombie virus (10-20 min)") - if(H) - H.infect_zombie_virus(target_zone = null, forced = TRUE, fast = FALSE) - to_chat(usr, "[H] is now infected with slow zombie virus") - log_admin("[key_name(usr)] infected [key_name(H)] with slow zombie virus.") - message_admins("[key_name_admin(usr)] infected [key_name(H)] with slow zombie virus.") - if("Infect with fast zombie virus (~3 min)") - if(H) - H.infect_zombie_virus(target_zone = null, forced = TRUE, fast = TRUE) - to_chat(usr, "[H] is now infected with fast zombie virus") - log_admin("[key_name(usr)] infected [key_name(H)] with fast zombie virus.") - message_admins("[key_name_admin(usr)] infected [key_name(H)] with fast zombie virus.") - if("Make immune to zombie virus") - if(H) - H.antibodies |= ANTIGEN_Z - to_chat(usr, "[H] is now immune to zombie virus") - log_admin("[key_name(usr)] made [key_name(H)] immune to zombie virus.") - message_admins("[key_name_admin(usr)] made [key_name(H)] immune to zombie virus.") - if("Make vulnerable to zombie virus") - if(H) - H.antibodies &= ~ANTIGEN_Z - to_chat(usr, "[H] is now vulnerable to zombie virus") - log_admin("[key_name(usr)] made [key_name(H)] vulnerable to zombie virus.") - message_admins("[key_name_admin(usr)] made [key_name(H)] vulnerable to zombie virus.") - - holder.Topic(href, list("makezombie"=href_list["makezombie"])) - - 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) - 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)) - 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","adamantine","golem","shadow","shadowling","slime") - 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)) - 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) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(H.set_species(new_species)) - to_chat(usr, "Set species of [H] to [H.species].") - H.regenerate_icons() - else - to_chat(usr, "Failed! Something went wrong.") - - else if(href_list["addlanguage"]) - if(!check_rights(R_VAREDIT)) - 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(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(H.add_language(new_language)) - to_chat(usr, "Added [new_language] to [H].") - else - to_chat(usr, "Mob already knows that language.") - - else if(href_list["remlanguage"]) - if(!check_rights(R_VAREDIT)) - 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) - 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(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(H.remove_language(rem_language.name)) - to_chat(usr, "Removed [rem_language] from [H].") - else - to_chat(usr, "Mob doesn't know that language.") - - else if(href_list["addverb"]) - if(!check_rights(R_DEBUG)) - return - - var/mob/living/H = locate(href_list["addverb"]) - - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living") - return - var/list/possibleverbs = list() - possibleverbs += "Cancel" // One for the top... - possibleverbs += typesof(/mob/proc,/mob/verb,/mob/living/proc,/mob/living/verb) - switch(H.type) - if(/mob/living/carbon/human) - possibleverbs += typesof(/mob/living/carbon/proc,/mob/living/carbon/verb,/mob/living/carbon/human/verb,/mob/living/carbon/human/proc) - if(/mob/living/silicon/robot) - possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/robot/proc,/mob/living/silicon/robot/verb) - if(/mob/living/silicon/ai) - possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/ai/proc,/mob/living/silicon/ai/verb) - possibleverbs -= H.verbs - possibleverbs += "Cancel" // ...And one for the bottom - - var/verb = input("Select a verb!", "Verbs",null) as anything in possibleverbs - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - if(!verb || verb == "Cancel") - return - else - H.verbs += verb - - else if(href_list["remverb"]) - if(!check_rights(R_DEBUG)) - return - - var/mob/H = locate(href_list["remverb"]) - - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob") - return - var/verb = input("Please choose a verb to remove.","Verbs",null) as null|anything in H.verbs - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - if(!verb) - return - else - H.verbs -= verb - - - else if(href_list["fix_nano"]) - if(!check_rights(R_DEBUG)) - return - - var/mob/H = locate(href_list["fix_nano"]) - - if(!istype(H) || !H.client) - to_chat(usr, "This can only be done on mobs with clients") - return - - H.client.reload_nanoui_resources() - - to_chat(usr, "Resource files sent") - log_admin("[key_name(usr)] resent the NanoUI resource files to [key_name(H)] ") - - - 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) - 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 - 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("\blue [key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") - href_list["datumrefresh"] = href_list["mobToDamage"] - - else if(href_list["setckey"]) - if(!check_rights(R_ADMIN)) - return - - var/mob/C = locate(href_list["setckey"]) - if(C.ckey && copytext(C.ckey, 1, 2) != "@") - if(alert("This mob already controlled by [C.ckey]. Are you sure you want to continue?",,"Cancel","Continue") != "Continue") - return - - var/list/clients_list = clients + "Cancel" - var/client/new_client = input("Select client:","Clients","Cancel") in clients_list - - if(new_client == "Cancel") return - - message_admins("\blue [key_name_admin(usr)] set client [new_client.ckey] to [C.name].", 1) - log_admin("[key_name(usr)] set client [new_client.ckey] to [C.name].") - - C.ckey = new_client.ckey - - if(href_list["datumrefresh"]) - var/datum/DAT = locate(href_list["datumrefresh"]) - if(!istype(DAT, /datum)) - return - src.debug_variables(DAT) - - return - -/client/proc/view_flags_variables(N) - if(!usr.client || !usr.client.holder) - return - - if(isnull(N)) - return - - if(!isnum(N)) - N = text2num(N) - - var/dat = "Bit Flags list" - - var/i = 1 - do - if(i & N) - dat += "[i] = TRUE
    " - else - dat += "[i] = FALSE
    " - i *= 2 - while(i < ~0) - - usr << browse(entity_ja(dat), "window=bit_flags") +// reference: /client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0) + +datum/proc/on_varedit(modified_var) //called whenever a var is edited + return + +/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, "\red You need to be an administrator to access this.") + return + + + var/title = "" + var/body = "" + + 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/sprite + + if(istype(D,/atom)) + var/atom/AT = D + if(AT.icon && AT.icon_state) + sprite = 1 + + title = "[D] (\ref[D]) = [D.type]" + + body += {" "} + + body += "" + + body += "
    " + + if(sprite) + body += "" + + body += "
    [bicon(D, use_class = 0)]" + 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]" + + body += "
    " + + body += "
    " + + 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" + + body += "
    " + + body += "
    Refresh" + + //if(ismob(D)) + // body += "
    Show player panel

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

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

    " + + body += "
    Search:

    " + + body += "
      " + + 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 += "
    " + + var/html = "" + if (title) + html += "[title]" + html += {""} + html += "" + html += body + + html += {" + + "} + + html += "" + + usr << browse(entity_ja(html), "window=variables\ref[D];size=475x650") + + return + +/client/proc/debug_variable(name, value, level, 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] = \"[value]\"" + + else if (isicon(value)) + #ifdef VARSICON + html += "[name] = /icon ([value]) [bicon(value, use_class = 0)]" + #else + html += "[name] = /icon ([value])" + #endif + + else if (istype(value, /image)) + #ifdef VARSICON + html += "[name] \ref[value] = /image ([value]) [bicon(value, use_class = 0)]" + #else + html += "[name] \ref[value] = /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) + html += "
      " + html += "
    " + 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 if (isnum(value) && findtext(name, "flags")) // flag variables may not always have flags in name, but i don't know any other way to detect them, so better than nothing. + html += "(F) [name] = [value]" + + else + html += "[name] = [value]" + + 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 || !holder) + return + if(href_list["Vars"]) + if(!check_rights(R_DEBUG|R_ADMIN)) + return + debug_variables(locate(href_list["Vars"])) + + else if(href_list["view_flags"]) + if(!check_rights(R_DEBUG|R_ADMIN)) + return + view_flags_variables(href_list["view_flags"]) + + //~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 = sanitize_safe(input(usr,"What would you like to name this mob?","Input a name",input_default(M.real_name)) as text|null, 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["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)) + 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)) + 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)) + 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)) + 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["give_disease2"]) + if(!check_rights(R_ADMIN|R_FUN)) + return + + var/mob/M = locate(href_list["give_disease2"]) + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.give_disease2(M) + href_list["datumrefresh"] = href_list["give_spell"] + + else if(href_list["ninja"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/M = locate(href_list["ninja"]) + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.cmd_admin_ninjafy(M) + href_list["datumrefresh"] = href_list["ninja"] + + 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(R_ADMIN|R_FUN)) + 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)) + 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_ADMIN|R_VAREDIT)) + 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)) + 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["delthis"]) + //Rights check are in cmd_admin_delete() proc + var/atom/A = locate(href_list["delthis"]) + cmd_admin_delete(A) + + 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) + CHECK_TICK + 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("\blue [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) + CHECK_TICK + 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("\blue [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)) + 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)) + 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["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)) + 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) + 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)) + 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) + 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)) + 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) + 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)) + 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) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("makeslime"=href_list["makeslime"])) + + else if(href_list["makezombie"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/human/H = locate(href_list["makezombie"]) + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + switch(input("Zombie menu", "Select action", "Cancel") in list("Turn into zombie instantly", "Infect with slow zombie virus (10-20 min)", "Infect with fast zombie virus (~3 min)", "Make immune to zombie virus", "Make vulnerable to zombie virus", "Cancel")) + if("Turn into zombie instantly") + if(H) + H.zombify() + to_chat(usr, "[H] is now a zombie") + log_admin("[key_name(usr)] turned [key_name(H)] into a zombie.") + message_admins("[key_name_admin(usr)] turned [key_name(H)] into a zombie.") + if("Infect with slow zombie virus (10-20 min)") + if(H) + H.infect_zombie_virus(target_zone = null, forced = TRUE, fast = FALSE) + to_chat(usr, "[H] is now infected with slow zombie virus") + log_admin("[key_name(usr)] infected [key_name(H)] with slow zombie virus.") + message_admins("[key_name_admin(usr)] infected [key_name(H)] with slow zombie virus.") + if("Infect with fast zombie virus (~3 min)") + if(H) + H.infect_zombie_virus(target_zone = null, forced = TRUE, fast = TRUE) + to_chat(usr, "[H] is now infected with fast zombie virus") + log_admin("[key_name(usr)] infected [key_name(H)] with fast zombie virus.") + message_admins("[key_name_admin(usr)] infected [key_name(H)] with fast zombie virus.") + if("Make immune to zombie virus") + if(H) + H.antibodies |= ANTIGEN_Z + to_chat(usr, "[H] is now immune to zombie virus") + log_admin("[key_name(usr)] made [key_name(H)] immune to zombie virus.") + message_admins("[key_name_admin(usr)] made [key_name(H)] immune to zombie virus.") + if("Make vulnerable to zombie virus") + if(H) + H.antibodies &= ~ANTIGEN_Z + to_chat(usr, "[H] is now vulnerable to zombie virus") + log_admin("[key_name(usr)] made [key_name(H)] vulnerable to zombie virus.") + message_admins("[key_name_admin(usr)] made [key_name(H)] vulnerable to zombie virus.") + + holder.Topic(href, list("makezombie"=href_list["makezombie"])) + + 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) + 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)) + 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","adamantine","golem","shadow","shadowling","slime") + 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)) + 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) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(H.set_species(new_species)) + to_chat(usr, "Set species of [H] to [H.species].") + H.regenerate_icons() + else + to_chat(usr, "Failed! Something went wrong.") + + else if(href_list["addlanguage"]) + if(!check_rights(R_VAREDIT)) + 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(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(H.add_language(new_language)) + to_chat(usr, "Added [new_language] to [H].") + else + to_chat(usr, "Mob already knows that language.") + + else if(href_list["remlanguage"]) + if(!check_rights(R_VAREDIT)) + 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) + 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(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(H.remove_language(rem_language.name)) + to_chat(usr, "Removed [rem_language] from [H].") + else + to_chat(usr, "Mob doesn't know that language.") + + else if(href_list["addverb"]) + if(!check_rights(R_DEBUG)) + return + + var/mob/living/H = locate(href_list["addverb"]) + + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living") + return + var/list/possibleverbs = list() + possibleverbs += "Cancel" // One for the top... + possibleverbs += typesof(/mob/proc,/mob/verb,/mob/living/proc,/mob/living/verb) + switch(H.type) + if(/mob/living/carbon/human) + possibleverbs += typesof(/mob/living/carbon/proc,/mob/living/carbon/verb,/mob/living/carbon/human/verb,/mob/living/carbon/human/proc) + if(/mob/living/silicon/robot) + possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/robot/proc,/mob/living/silicon/robot/verb) + if(/mob/living/silicon/ai) + possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/ai/proc,/mob/living/silicon/ai/verb) + possibleverbs -= H.verbs + possibleverbs += "Cancel" // ...And one for the bottom + + var/verb = input("Select a verb!", "Verbs",null) as anything in possibleverbs + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + if(!verb || verb == "Cancel") + return + else + H.verbs += verb + + else if(href_list["remverb"]) + if(!check_rights(R_DEBUG)) + return + + var/mob/H = locate(href_list["remverb"]) + + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob") + return + var/verb = input("Please choose a verb to remove.","Verbs",null) as null|anything in H.verbs + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + if(!verb) + return + else + H.verbs -= verb + + + else if(href_list["fix_nano"]) + if(!check_rights(R_DEBUG)) + return + + var/mob/H = locate(href_list["fix_nano"]) + + if(!istype(H) || !H.client) + to_chat(usr, "This can only be done on mobs with clients") + return + + H.client.reload_nanoui_resources() + + to_chat(usr, "Resource files sent") + log_admin("[key_name(usr)] resent the NanoUI resource files to [key_name(H)] ") + + + 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) + 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 + 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("\blue [key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") + href_list["datumrefresh"] = href_list["mobToDamage"] + + else if(href_list["setckey"]) + if(!check_rights(R_ADMIN)) + return + + var/mob/C = locate(href_list["setckey"]) + if(C.ckey && copytext(C.ckey, 1, 2) != "@") + if(alert("This mob already controlled by [C.ckey]. Are you sure you want to continue?",,"Cancel","Continue") != "Continue") + return + + var/list/clients_list = clients + "Cancel" + var/client/new_client = input("Select client:","Clients","Cancel") in clients_list + + if(new_client == "Cancel") return + + message_admins("\blue [key_name_admin(usr)] set client [new_client.ckey] to [C.name].", 1) + log_admin("[key_name(usr)] set client [new_client.ckey] to [C.name].") + + C.ckey = new_client.ckey + + if(href_list["datumrefresh"]) + var/datum/DAT = locate(href_list["datumrefresh"]) + if(!istype(DAT, /datum)) + return + src.debug_variables(DAT) + + return + +/client/proc/view_flags_variables(N) + if(!usr.client || !usr.client.holder) + return + + if(isnull(N)) + return + + if(!isnum(N)) + N = text2num(N) + + var/dat = "Bit Flags list" + + var/i = 1 + do + if(i & N) + dat += "[i] = TRUE
    " + else + dat += "[i] = FALSE
    " + i *= 2 + while(i < ~0) + + usr << browse(entity_ja(dat), "window=bit_flags") diff --git a/code/datums/disease.dm b/code/datums/disease.dm index 6432f67394ab..91d5f18f4cca 100644 --- a/code/datums/disease.dm +++ b/code/datums/disease.dm @@ -1,202 +1,202 @@ -#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() - //world << "[cure_present]" - - if(carrier&&!cure_present) - //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(atom/source=null, airborne_range = 2, force_spread) - //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(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, M.loc, /turf/proc/Distance, check_range)) - M.contract_disease(src, 0, 1, force_spread) - - return - - -/datum/disease/process() - if(!holder) - STOP_PROCESSING(SSdisease, 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].") - qdel(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 -// world << "[src] longevity = [longevity]" - - if(prob(70)) - if(--longevity<=0) - cure(0) - return - -/datum/disease/proc/cure(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 - qdel(src) //delete the datum to stop it processing - return - - -/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. - START_PROCESSING(SSdisease, src) - initial_spread = spread - -/datum/disease/proc/IsSame(datum/disease/D) - if(istype(src, D.type)) - return 1 - return 0 - -/datum/disease/proc/Copy(process = 0) +#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() + //world << "[cure_present]" + + if(carrier&&!cure_present) + //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(atom/source=null, airborne_range = 2, force_spread) + //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(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, M.loc, /turf/proc/Distance, check_range)) + M.contract_disease(src, 0, 1, force_spread) + + return + + +/datum/disease/process() + if(!holder) + STOP_PROCESSING(SSdisease, 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].") + qdel(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 +// world << "[src] longevity = [longevity]" + + if(prob(70)) + if(--longevity<=0) + cure(0) + return + +/datum/disease/proc/cure(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 + qdel(src) //delete the datum to stop it processing + return + + +/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. + START_PROCESSING(SSdisease, src) + initial_spread = spread + +/datum/disease/proc/IsSame(datum/disease/D) + if(istype(src, D.type)) + return 1 + return 0 + +/datum/disease/proc/Copy(process = 0) return new type(process, src) \ No newline at end of file diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index ef908529afdc..82b54a67f28b 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -1,423 +1,423 @@ -/* - - 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", "phoron" - ) - -/* - - 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/Destroy() - if(processing) - for(var/datum/symptom/S in symptoms) - S.End(src) - return ..() - -// 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(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(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 - qdel(src) //delete the datum to stop it processing - return - -// Returns the advance disease with a different reference memory. -/datum/disease/advance/Copy(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(datum/disease/advance/D) - if(!(src.IsSame(D))) - var/list/possible_symptoms = shuffle(D.symptoms) - for(var/datum/symptom/S in possible_symptoms) - AddSymptom(new S.type) - -/datum/disease/advance/proc/HasSymptom(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(type_level_limit = RANDOM_STARTING_LEVEL, 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(new_name = 0) - //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(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(ceil(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(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 - //world << "Setting spread type to [spread_id]/[spread]" - -/datum/disease/advance/proc/SetSeverity(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(list/properties = list()) - if(properties && properties.len) - var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len) - //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(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(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 = jointext(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(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(datum/symptom/S) - symptoms -= S - return - -/* - - Static Procs - -*/ - -// Mix a list of advance diseases and return the mixed result. -/proc/Advance_Mix(list/D_list) - - //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 - //world << "END MIXING!!!!!" - var/datum/disease/advance/to_return = pick(diseases) - to_return.Refresh(1) - return to_return - -/proc/SetViruses(datum/reagent/R, 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(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 = sanitize_safe(input(user, "Name your new disease.", "New Name"), MAX_LNAME_LEN) - D.AssignName(new_name) - D.Refresh() - - for(var/datum/disease/advance/AD in SSdisease.processing) - AD.Refresh() - - for(var/mob/living/carbon/human/H in shuffle(human_list)) - if(H.stat == DEAD || H.z != ZLEVEL_STATION) - 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 +/* + + 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", "phoron" + ) + +/* + + 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/Destroy() + if(processing) + for(var/datum/symptom/S in symptoms) + S.End(src) + return ..() + +// 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(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(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 + qdel(src) //delete the datum to stop it processing + return + +// Returns the advance disease with a different reference memory. +/datum/disease/advance/Copy(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(datum/disease/advance/D) + if(!(src.IsSame(D))) + var/list/possible_symptoms = shuffle(D.symptoms) + for(var/datum/symptom/S in possible_symptoms) + AddSymptom(new S.type) + +/datum/disease/advance/proc/HasSymptom(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(type_level_limit = RANDOM_STARTING_LEVEL, 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(new_name = 0) + //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(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(ceil(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(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 + //world << "Setting spread type to [spread_id]/[spread]" + +/datum/disease/advance/proc/SetSeverity(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(list/properties = list()) + if(properties && properties.len) + var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len) + //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(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(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 = jointext(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(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(datum/symptom/S) + symptoms -= S + return + +/* + + Static Procs + +*/ + +// Mix a list of advance diseases and return the mixed result. +/proc/Advance_Mix(list/D_list) + + //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 + //world << "END MIXING!!!!!" + var/datum/disease/advance/to_return = pick(diseases) + to_return.Refresh(1) + return to_return + +/proc/SetViruses(datum/reagent/R, 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(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 = sanitize_safe(input(user, "Name your new disease.", "New Name"), MAX_LNAME_LEN) + D.AssignName(new_name) + D.Refresh() + + for(var/datum/disease/advance/AD in SSdisease.processing) + AD.Refresh() + + for(var/mob/living/carbon/human/H in shuffle(human_list)) + if(H.stat == DEAD || H.z != ZLEVEL_STATION) + 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 diff --git a/code/datums/diseases/advance/presets.dm b/code/datums/diseases/advance/presets.dm index 17db617b857a..1f91e688ccfc 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) - ..(process, D, copy) +// 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) diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm index 0fc41b1699ec..52b142bfe6ff 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(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 - to_chat(M, "You are unable to think straight!") - M.confused = min(100, M.confused + 2) - - return +/* +////////////////////////////////////// + +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(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 + to_chat(M, "You are unable to think straight!") + 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 e897fb01c696..72694d302695 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(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() - return +/* +////////////////////////////////////// + +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(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() + return diff --git a/code/datums/diseases/advance/symptoms/damage_converter.dm b/code/datums/diseases/advance/symptoms/damage_converter.dm index ab6f023c333e..16486bd4f6ac 100644 --- a/code/datums/diseases/advance/symptoms/damage_converter.dm +++ b/code/datums/diseases/advance/symptoms/damage_converter.dm @@ -1,43 +1,43 @@ -/* -////////////////////////////////////// - -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(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(mob/living/M) - - if(M.getFireLoss() < M.maxHealth || M.getBruteLoss() < M.maxHealth) - var/get_damage = rand(1, 2) - M.adjustFireLoss(-get_damage) - M.adjustBruteLoss(-get_damage) - M.adjustToxLoss(get_damage) - return 1 +/* +////////////////////////////////////// + +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(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(mob/living/M) + + if(M.getFireLoss() < M.maxHealth || M.getBruteLoss() < M.maxHealth) + var/get_damage = rand(1, 2) + M.adjustFireLoss(-get_damage) + M.adjustBruteLoss(-get_damage) + M.adjustToxLoss(get_damage) + return 1 diff --git a/code/datums/diseases/advance/symptoms/dizzy.dm b/code/datums/diseases/advance/symptoms/dizzy.dm index fe412ef5d7c7..9e692ee1821c 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(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 - to_chat(M, "You are unable to look straight!") - M.make_dizzy(5) - return +/* +////////////////////////////////////// + +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(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 + to_chat(M, "You are unable to look straight!") + M.make_dizzy(5) + return diff --git a/code/datums/diseases/advance/symptoms/fever.dm b/code/datums/diseases/advance/symptoms/fever.dm index 7bf8ed1d1776..d26d07311234 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(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 +/* +////////////////////////////////////// + +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(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 diff --git a/code/datums/diseases/advance/symptoms/hallucigen.dm b/code/datums/diseases/advance/symptoms/hallucigen.dm index 93ca8d5b9ae6..21f51b49864f 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(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 +/* +////////////////////////////////////// + +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(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 diff --git a/code/datums/diseases/advance/symptoms/headache.dm b/code/datums/diseases/advance/symptoms/headache.dm index b4367c03b615..72adf137bc8c 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(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 +/* +////////////////////////////////////// + +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(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 diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 297330981b52..80a362161cb9 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -1,40 +1,40 @@ -/* -////////////////////////////////////// - -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(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(mob/living/M) - - var/get_damage = rand(1, 2) - M.adjustToxLoss(-get_damage) - return 1 +/* +////////////////////////////////////// + +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(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(mob/living/M) + + var/get_damage = rand(1, 2) + M.adjustToxLoss(-get_damage) + return 1 diff --git a/code/datums/diseases/advance/symptoms/itching.dm b/code/datums/diseases/advance/symptoms/itching.dm index 50ca61987696..ebbf516dfb91 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(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 +/* +////////////////////////////////////// + +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(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 diff --git a/code/datums/diseases/advance/symptoms/shivering.dm b/code/datums/diseases/advance/symptoms/shivering.dm index 72fa4e2fd3d7..c19804a34bde 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(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 +/* +////////////////////////////////////// + +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(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 diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm index d5f9a6087501..63f29eff93a4 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(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 +/* +////////////////////////////////////// + +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(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 diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm index 4d13ff4a4395..72a132cf517e 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(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(datum/disease/advance/A) - return - -/datum/symptom/proc/Activate(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(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(datum/disease/advance/A) + return + +/datum/symptom/proc/Activate(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 5ad99be60e12..9920c79c71d5 100644 --- a/code/datums/diseases/advance/symptoms/voice_change.dm +++ b/code/datums/diseases/advance/symptoms/voice_change.dm @@ -1,54 +1,54 @@ -/* -////////////////////////////////////// - -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(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 = "" - switch(H.gender) - if(MALE) - random_name = pick(first_names_male) - else - random_name = pick(first_names_female) - random_name += " [pick(last_names)]" - H.special_voice = random_name - - return - -/datum/symptom/voice_change/End(datum/disease/advance/A) - ..() - if(ishuman(A.affected_mob)) - var/mob/living/carbon/human/H = A.affected_mob - H.special_voice = "" - return +/* +////////////////////////////////////// + +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(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 = "" + switch(H.gender) + if(MALE) + random_name = pick(first_names_male) + else + random_name = pick(first_names_female) + random_name += " [pick(last_names)]" + H.special_voice = random_name + + return + +/datum/symptom/voice_change/End(datum/disease/advance/A) + ..() + if(ishuman(A.affected_mob)) + var/mob/living/carbon/human/H = A.affected_mob + H.special_voice = "" + return diff --git a/code/datums/diseases/advance/symptoms/vomit.dm b/code/datums/diseases/advance/symptoms/vomit.dm index d29a9f316e2e..da4da5fde086 100644 --- a/code/datums/diseases/advance/symptoms/vomit.dm +++ b/code/datums/diseases/advance/symptoms/vomit.dm @@ -1,94 +1,94 @@ -/* -////////////////////////////////////// - -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(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(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(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) +/* +////////////////////////////////////// + +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(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(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(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) diff --git a/code/datums/diseases/advance/symptoms/weight.dm b/code/datums/diseases/advance/symptoms/weight.dm index d7c136b8f1c9..31f912b5102c 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(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(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 - 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(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 +/* +////////////////////////////////////// + +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(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(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 + 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(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 diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index 7848deb77f90..a21322332b10 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.species.name == DIONA || H.species.name == IPC || H.species.name == VOX) - 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, "\red You feel a stinging pain in your abdomen!") - affected_mob.emote("pain",1,"winces slightly.") - if(stage > 1) - if(prob(3)) - to_chat(affected_mob, "\red You feel a stabbing pain in your abdomen!") - affected_mob.emote("pain",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, "\red 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 - to_chat(H, "\red Your abdomen is a world of pain!") - H.Weaken(10) - H.op_stage.appendix = 2.0 - - var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_GROIN] - BP.sever_artery() - BP.germ_level = max(INFECTION_LEVEL_TWO, BP.germ_level) - H.adjustToxLoss(25) - src.cure() +/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.species.name == DIONA || H.species.name == IPC || H.species.name == VOX) + 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, "\red You feel a stinging pain in your abdomen!") + affected_mob.emote("pain",1,"winces slightly.") + if(stage > 1) + if(prob(3)) + to_chat(affected_mob, "\red You feel a stabbing pain in your abdomen!") + affected_mob.emote("pain",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, "\red 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 + to_chat(H, "\red Your abdomen is a world of pain!") + H.Weaken(10) + H.op_stage.appendix = 2.0 + + var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_GROIN] + BP.sever_artery() + BP.germ_level = max(INFECTION_LEVEL_TWO, BP.germ_level) + H.adjustToxLoss(25) + src.cure() diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index d30303a001b3..ae98de50a87d 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, "\red 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, "\red 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, "\red 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, "\red 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, "\red Strange buzzing fills your head, removing all thoughts.") - if(prob(3)) - to_chat(affected_mob, "\red 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, "\red 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, "\red 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, "\red 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, "\red 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, "\red Strange buzzing fills your head, removing all thoughts.") + if(prob(3)) + to_chat(affected_mob, "\red 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 ab86867785a4..7c75cdf82dbd 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 - to_chat(affected_mob, "\blue You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(40)) //changed FROM prob(10) until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - cure() - return - if(prob(1) && prob(5)) - to_chat(affected_mob, "\blue You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "\red Your throat feels sore.") - if(prob(1)) - to_chat(affected_mob, "\red Mucous runs down the back of your throat.") - if(3) -/* - if(affected_mob.sleeping && prob(25)) //removed until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(25)) //changed FROM prob(5) until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - cure() - return - if(prob(1) && prob(1)) - to_chat(affected_mob, "\blue You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "\red Your throat feels sore.") - if(prob(1)) - to_chat(affected_mob, "\red 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) - cure() +/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, "\blue You feel better.") + cure() + return +*/ + if(affected_mob.lying && prob(40)) //changed FROM prob(10) until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + cure() + return + if(prob(1) && prob(5)) + to_chat(affected_mob, "\blue You feel better.") + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "\red Your throat feels sore.") + if(prob(1)) + to_chat(affected_mob, "\red Mucous runs down the back of your throat.") + if(3) +/* + if(affected_mob.sleeping && prob(25)) //removed until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + cure() + return +*/ + if(affected_mob.lying && prob(25)) //changed FROM prob(5) until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + cure() + return + if(prob(1) && prob(1)) + to_chat(affected_mob, "\blue You feel better.") + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "\red Your throat feels sore.") + if(prob(1)) + to_chat(affected_mob, "\red 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) + cure() diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm index 7832a5103045..898fd08c3ccc 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)) - to_chat(affected_mob, "\blue You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "\red Your throat feels sore.") - if(prob(5)) - to_chat(affected_mob, "\red 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)) - to_chat(affected_mob, "\red Your throat feels sore.") - if(prob(10)) - to_chat(affected_mob, "\red You feel stiff.") +/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, "\blue You feel better.") + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "\red Your throat feels sore.") + if(prob(5)) + to_chat(affected_mob, "\red 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)) + to_chat(affected_mob, "\red Your throat feels sore.") + if(prob(10)) + to_chat(affected_mob, "\red You feel stiff.") diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index c18a56e00b1f..d58480fd7c36 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)) - to_chat(affected_mob, "\red Your muscles ache.") - if(prob(20)) - affected_mob.take_bodypart_damage(1) - if(prob(1)) - to_chat(affected_mob, "\red 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"])) - qdel(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, "\red 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/Destroy() - 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, "\blue You feel more like yourself.") - return ..() +/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, "\red Your muscles ache.") + if(prob(20)) + affected_mob.take_bodypart_damage(1) + if(prob(1)) + to_chat(affected_mob, "\red 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"])) + qdel(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, "\red 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/Destroy() + 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, "\blue You feel more like yourself.") + return ..() diff --git a/code/datums/diseases/fake_gbs.dm b/code/datums/diseases/fake_gbs.dm index 05b581d28d38..0ea2eec5f9ec 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)) - to_chat(affected_mob, "\red 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") +/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, "\red 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") diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm index 52f735bee3a2..c37a3196258b 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 - to_chat(affected_mob, "\blue You feel better.") - stage-- - return -*/ - if(affected_mob.lying && prob(20)) //added until sleeping is fixed --Blaank - to_chat(affected_mob, "\blue You feel better.") - stage-- - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "\red Your muscles ache.") - if(prob(20)) - affected_mob.take_bodypart_damage(1) - if(prob(1)) - to_chat(affected_mob, "\red 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 - to_chat(affected_mob, "\blue You feel better.") - stage-- - return -*/ - if(affected_mob.lying && prob(15)) //added until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - stage-- - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "\red Your muscles ache.") - if(prob(20)) - affected_mob.take_bodypart_damage(1) - if(prob(1)) - to_chat(affected_mob, "\red Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(1) - affected_mob.updatehealth() - return +/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, "\blue You feel better.") + stage-- + return +*/ + if(affected_mob.lying && prob(20)) //added until sleeping is fixed --Blaank + to_chat(affected_mob, "\blue You feel better.") + stage-- + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "\red Your muscles ache.") + if(prob(20)) + affected_mob.take_bodypart_damage(1) + if(prob(1)) + to_chat(affected_mob, "\red 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 + to_chat(affected_mob, "\blue You feel better.") + stage-- + return +*/ + if(affected_mob.lying && prob(15)) //added until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + stage-- + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "\red Your muscles ache.") + if(prob(20)) + affected_mob.take_bodypart_damage(1) + if(prob(1)) + to_chat(affected_mob, "\red Your stomach hurts.") + 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 d443ee2e0d9e..d0fe34c585e2 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)) - to_chat(affected_mob, "\red You're burning in your own skin!") - affected_mob.take_bodypart_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, "\red You're burning in your own skin!") - affected_mob.take_bodypart_damage(0,5) - return +/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, "\red You're burning in your own skin!") + affected_mob.take_bodypart_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, "\red You're burning in your own skin!") + affected_mob.take_bodypart_damage(0,5) + return diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm index 6c6063f9732c..dc1763ab9e1f 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)) - to_chat(affected_mob, "\red 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) - to_chat(affected_mob, "\red Your body feels as if it's trying to rip itself open...") - if(prob(50)) - affected_mob.gib() - else - return +/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, "\red 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) + to_chat(affected_mob, "\red Your body feels as if it's trying to rip itself open...") + if(prob(50)) + affected_mob.gib() + else + return diff --git a/code/datums/diseases/jungle_fever.dm b/code/datums/diseases/jungle_fever.dm index d232eacc8aec..f230845d981e 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(HUMAN , MONKEY) - 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(HUMAN , MONKEY) + 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 211a94b104eb..fb5eea2329fb 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)) - to_chat(affected_mob, "\red 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.flags & CONDUCT)) - 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, "\red You feel a strong shock course through your body.") - if(prob(2)) - to_chat(affected_mob, "\red You feel like clowning around.") - if(prob(4)) - for(var/obj/M in orange(4,affected_mob)) - if(!M.anchored && (M.flags & CONDUCT)) - 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, "\red You feel a powerful shock course through your body.") - if(prob(2)) - to_chat(affected_mob, "\red You query upon the nature of miracles.") - if(prob(8)) - for(var/obj/M in orange(6,affected_mob)) - if(!M.anchored && (M.flags & CONDUCT)) - 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 +/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, "\red 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.flags & CONDUCT)) + 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, "\red You feel a strong shock course through your body.") + if(prob(2)) + to_chat(affected_mob, "\red You feel like clowning around.") + if(prob(4)) + for(var/obj/M in orange(4,affected_mob)) + if(!M.anchored && (M.flags & CONDUCT)) + 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, "\red You feel a powerful shock course through your body.") + if(prob(2)) + to_chat(affected_mob, "\red You query upon the nature of miracles.") + if(prob(8)) + for(var/obj/M in orange(6,affected_mob)) + if(!M.anchored && (M.flags & CONDUCT)) + 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 diff --git a/code/datums/diseases/pierrot_throat.dm b/code/datums/diseases/pierrot_throat.dm index 32ae9baadb49..67a19c7c82c4 100644 --- a/code/datums/diseases/pierrot_throat.dm +++ b/code/datums/diseases/pierrot_throat.dm @@ -1,29 +1,29 @@ -/datum/disease/pierrot_throat - name = "Pierrot's Throat" - max_stages = 4 - spread = "Airborne" - cure = "A whole banana." - cure_id = "banana" - cure_chance = 75 - 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, "\red You feel a little silly.") - if(2) - if(prob(10)) - to_chat(affected_mob, "\red You start seeing rainbows.") - if(3) - if(prob(10)) - to_chat(affected_mob, "\red 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..."))) +/datum/disease/pierrot_throat + name = "Pierrot's Throat" + max_stages = 4 + spread = "Airborne" + cure = "A whole banana." + cure_id = "banana" + cure_chance = 75 + 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, "\red You feel a little silly.") + if(2) + if(prob(10)) + to_chat(affected_mob, "\red You start seeing rainbows.") + if(3) + if(prob(10)) + to_chat(affected_mob, "\red 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..."))) diff --git a/code/datums/diseases/plasmatoid.dm b/code/datums/diseases/plasmatoid.dm index 3af141399772..2d7da6c45490 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" - affected_species = list(HUMAN , MONKEY) +/datum/disease/plasmatoid + name = "Plasmatoid" + max_stages = 4 + cure = "None" + affected_species = list(HUMAN , MONKEY) diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm index a96f51cf083a..d6a198b72be7 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 - to_chat(affected_mob, "\blue You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(30)) //changed FROM prob(20) until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - cure() - return - if (prob(8)) - to_chat(affected_mob, "\red Your head hurts.") - if (prob(9)) - to_chat(affected_mob, "You feel a tingling sensation in your chest.") - if (prob(9)) - to_chat(affected_mob, "\red You feel angry.") - if(2) - if(restcure) -/* - if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - cure() - return - if (prob(8)) - to_chat(affected_mob, "\red Your skin feels loose.") - if (prob(10)) - to_chat(affected_mob, "You feel very strange.") - if (prob(4)) - to_chat(affected_mob, "\red You feel a stabbing pain in your head!") - affected_mob.Paralyse(2) - if (prob(4)) - to_chat(affected_mob, "\red Your stomach churns.") - if(3) - if(restcure) -/* - if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - cure() - return - if (prob(10)) - to_chat(affected_mob, "\red 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 - to_chat(affected_mob, "\blue You feel better.") - cure() - return -*/ - if(affected_mob.lying && prob(5)) //changed FROM prob(5) until sleeping is fixed - to_chat(affected_mob, "\blue You feel better.") - cure() - return - if (prob(60)) - if(prob(50)) - scramble(1, affected_mob, rand(50,75)) - else - scramble(0, affected_mob, rand(50,75)) +/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, "\blue You feel better.") + cure() + return +*/ + if(affected_mob.lying && prob(30)) //changed FROM prob(20) until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + cure() + return + if (prob(8)) + to_chat(affected_mob, "\red Your head hurts.") + if (prob(9)) + to_chat(affected_mob, "You feel a tingling sensation in your chest.") + if (prob(9)) + to_chat(affected_mob, "\red You feel angry.") + if(2) + if(restcure) +/* + if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + cure() + return +*/ + if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + cure() + return + if (prob(8)) + to_chat(affected_mob, "\red Your skin feels loose.") + if (prob(10)) + to_chat(affected_mob, "You feel very strange.") + if (prob(4)) + to_chat(affected_mob, "\red You feel a stabbing pain in your head!") + affected_mob.Paralyse(2) + if (prob(4)) + to_chat(affected_mob, "\red Your stomach churns.") + if(3) + if(restcure) +/* + if(affected_mob.sleeping && prob(20)) //removed until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + cure() + return +*/ + if(affected_mob.lying && prob(20)) //changed FROM prob(10) until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + cure() + return + if (prob(10)) + to_chat(affected_mob, "\red 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 + to_chat(affected_mob, "\blue You feel better.") + cure() + return +*/ + if(affected_mob.lying && prob(5)) //changed FROM prob(5) until sleeping is fixed + to_chat(affected_mob, "\blue You feel better.") + cure() + return + if (prob(60)) + if(prob(50)) + scramble(1, affected_mob, rand(50,75)) + else + scramble(0, affected_mob, rand(50,75)) diff --git a/code/datums/diseases/robotic_transformation.dm b/code/datums/diseases/robotic_transformation.dm index 685a1d2e5de3..cc0242c3b010 100644 --- a/code/datums/diseases/robotic_transformation.dm +++ b/code/datums/diseases/robotic_transformation.dm @@ -1,65 +1,65 @@ -//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_bodypart_damage(1) - if (prob(9)) - to_chat(affected_mob, "\red Beep...boop..") - if (prob(9)) - to_chat(affected_mob, "\red Bop...beeep...") - if(3) - if (prob(8)) - to_chat(affected_mob, "\red Your joints feel very stiff.") - affected_mob.take_bodypart_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_bodypart_damage(5) - if (prob(4)) - to_chat(affected_mob, "\red You feel a stabbing pain in your head.") - affected_mob.Paralyse(2) - if (prob(4)) - to_chat(affected_mob, "\red You can feel something move...inside.") - if(4) - if (prob(10)) - to_chat(affected_mob, "\red Your skin feels very loose.") - affected_mob.take_bodypart_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, "\red You can feel... something...inside you.") - if(5) - to_chat(affected_mob, "\red 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 - var/turf/T = find_loc(affected_mob) - gibs(T) - src.cure(0) - 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) - +//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_bodypart_damage(1) + if (prob(9)) + to_chat(affected_mob, "\red Beep...boop..") + if (prob(9)) + to_chat(affected_mob, "\red Bop...beeep...") + if(3) + if (prob(8)) + to_chat(affected_mob, "\red Your joints feel very stiff.") + affected_mob.take_bodypart_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_bodypart_damage(5) + if (prob(4)) + to_chat(affected_mob, "\red You feel a stabbing pain in your head.") + affected_mob.Paralyse(2) + if (prob(4)) + to_chat(affected_mob, "\red You can feel something move...inside.") + if(4) + if (prob(10)) + to_chat(affected_mob, "\red Your skin feels very loose.") + affected_mob.take_bodypart_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, "\red You can feel... something...inside you.") + if(5) + to_chat(affected_mob, "\red 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 + var/turf/T = find_loc(affected_mob) + gibs(T) + src.cure(0) + 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 ef0cba7e002e..57ed1ec8846c 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -1,125 +1,125 @@ -/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, "\red 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, "\red 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, "\red 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(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 = ABOVE_HUD_LAYER - H.head.plane = ABOVE_HUD_PLANE - 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 = ABOVE_HUD_LAYER - H.wear_suit.plane = ABOVE_HUD_PLANE - 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 = ABOVE_HUD_LAYER - H.shoes.plane = ABOVE_HUD_PLANE - return - else - var/mob/living/carbon/H = affected_mob - if(prob(chance)) - if(!istype(H.r_hand, /obj/item/weapon/staff)) - H.drop_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) || AR.name == "Space") 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, "\red 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, "\red 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, "\red 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(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 = ABOVE_HUD_LAYER + H.head.plane = ABOVE_HUD_PLANE + 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 = ABOVE_HUD_LAYER + H.wear_suit.plane = ABOVE_HUD_PLANE + 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 = ABOVE_HUD_LAYER + H.shoes.plane = ABOVE_HUD_PLANE + return + else + var/mob/living/carbon/H = affected_mob + if(prob(chance)) + if(!istype(H.r_hand, /obj/item/weapon/staff)) + H.drop_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) || AR.name == "Space") 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 6c55e7d35bfd..b6962915cf54 100644 --- a/code/datums/diseases/xeno_transformation.dm +++ b/code/datums/diseases/xeno_transformation.dm @@ -1,61 +1,61 @@ -//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_bodypart_damage(1) - if (prob(9)) - to_chat(affected_mob, "\red Kill...") - if (prob(9)) - to_chat(affected_mob, "\red Kill...") - if(3) - if (prob(8)) - to_chat(affected_mob, "\red Your throat feels very scratchy.") - affected_mob.take_bodypart_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_bodypart_damage(5) - if (prob(4)) - to_chat(affected_mob, "\red You feel a stabbing pain in your head.") - affected_mob.Paralyse(2) - if (prob(4)) - to_chat(affected_mob, "\red You can feel something move...inside.") - if(4) - if (prob(10)) - to_chat(affected_mob, pick("\red Your skin feels very tight.", "\red Your blood boils!")) - affected_mob.take_bodypart_damage(8) - if (prob(20)) - affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!")) - if (prob(8)) - to_chat(affected_mob, "\red You can feel... something...inside you.") - if(5) - to_chat(affected_mob, "\red Your skin feels impossibly calloused...") - affected_mob.adjustToxLoss(10) - affected_mob.updatehealth() - if(prob(40)) - if(gibbed != 0) return 0 - var/turf/T = find_loc(affected_mob) - gibs(T) - src.cure(0) - gibbed = 1 - affected_mob:Alienize() - +//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_bodypart_damage(1) + if (prob(9)) + to_chat(affected_mob, "\red Kill...") + if (prob(9)) + to_chat(affected_mob, "\red Kill...") + if(3) + if (prob(8)) + to_chat(affected_mob, "\red Your throat feels very scratchy.") + affected_mob.take_bodypart_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_bodypart_damage(5) + if (prob(4)) + to_chat(affected_mob, "\red You feel a stabbing pain in your head.") + affected_mob.Paralyse(2) + if (prob(4)) + to_chat(affected_mob, "\red You can feel something move...inside.") + if(4) + if (prob(10)) + to_chat(affected_mob, pick("\red Your skin feels very tight.", "\red Your blood boils!")) + affected_mob.take_bodypart_damage(8) + if (prob(20)) + affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!")) + if (prob(8)) + to_chat(affected_mob, "\red You can feel... something...inside you.") + if(5) + to_chat(affected_mob, "\red Your skin feels impossibly calloused...") + affected_mob.adjustToxLoss(10) + affected_mob.updatehealth() + if(prob(40)) + if(gibbed != 0) return 0 + var/turf/T = find_loc(affected_mob) + gibs(T) + src.cure(0) + gibbed = 1 + affected_mob:Alienize() + diff --git a/code/datums/helper_datums/construction_datum.dm b/code/datums/helper_datums/construction_datum.dm index 2546997d3b11..85aacd48b1d4 100644 --- a/code/datums/helper_datums/construction_datum.dm +++ b/code/datums/helper_datums/construction_datum.dm @@ -1,121 +1,121 @@ -#define FORWARD -1 -#define BACKWARD 1 - -/datum/construction - var/list/steps - var/atom/holder - var/result - var/list/steps_desc - -/datum/construction/New(atom) - ..() - holder = atom - if(!holder) //don't want this without a holder - qdel(src) - set_desc(steps.len) - return - -/datum/construction/proc/next_step() - steps.len-- - if(!steps.len) - spawn_result() - else - set_desc(steps.len) - return - -/datum/construction/proc/action(atom/used_atom,mob/user) - return - -/datum/construction/proc/check_step(atom/used_atom,mob/user) //check last step only - var/valid_step = is_right_key(used_atom) - if(valid_step) - if(custom_action(valid_step, used_atom, user)) - next_step() - return 1 - return 0 - -/datum/construction/proc/is_right_key(atom/used_atom) // returns current step num if used_atom is of the right type. - var/list/L = steps[steps.len] - if(istype(used_atom, L["key"])) - return steps.len - return 0 - -/datum/construction/proc/custom_action(step, used_atom, user) - return 1 - -/datum/construction/proc/check_all_steps(atom/used_atom,mob/user) //check all steps, remove matching one. - for(var/i=1;i<=steps.len;i++) - var/list/L = steps[i]; - if(istype(used_atom, L["key"])) - if(custom_action(i, used_atom, user)) - steps[i]=null;//stupid byond list from list removal... - listclearnulls(steps); - if(!steps.len) - spawn_result() - return 1 - return 0 - -/datum/construction/proc/spawn_result() - if(result) - new result(get_turf(holder)) - qdel(holder) - return - -/datum/construction/proc/set_desc(index) - var/list/step = steps[index] - holder.desc = step["desc"] - return - - -/datum/construction/mecha/custom_action(step, atom/used_atom, mob/user) - if(istype(used_atom, /obj)) - var/obj/part = used_atom - if(part.crit_fail || part.reliability < 50) - user.visible_message("[user] was unable to connect [used_atom] to [holder].", "You failed to connect [used_atom] to [holder]") - return 0 - user.visible_message("[user] has connected [used_atom] to [holder].", "You connect [used_atom] to [holder]") - holder.overlays += used_atom.icon_state+"+o" - user.drop_item() - qdel(used_atom) - return 1 - - -/datum/construction/mecha/action(atom/used_atom,mob/user) - return check_all_steps(used_atom,user) - - - -/datum/construction/reversible - var/index - -/datum/construction/reversible/New(atom) - ..() - index = steps.len - return - -/datum/construction/reversible/proc/update_index(diff) - index+=diff - if(index==0) - spawn_result() - else - set_desc(index) - return - -/datum/construction/reversible/is_right_key(atom/used_atom) // returns index step - var/list/L = steps[index] - if(istype(used_atom, L["key"])) - return FORWARD //to the first step -> forward - else if(L["backkey"] && istype(used_atom, L["backkey"])) - return BACKWARD //to the last step -> backwards - return 0 - -/datum/construction/reversible/check_step(atom/used_atom,mob/user) - var/diff = is_right_key(used_atom) - if(diff) - if(custom_action(index, diff, used_atom, user)) - update_index(diff) - return 1 - return 0 - -/datum/construction/reversible/custom_action(index, diff, used_atom, user) - return 1 +#define FORWARD -1 +#define BACKWARD 1 + +/datum/construction + var/list/steps + var/atom/holder + var/result + var/list/steps_desc + +/datum/construction/New(atom) + ..() + holder = atom + if(!holder) //don't want this without a holder + qdel(src) + set_desc(steps.len) + return + +/datum/construction/proc/next_step() + steps.len-- + if(!steps.len) + spawn_result() + else + set_desc(steps.len) + return + +/datum/construction/proc/action(atom/used_atom,mob/user) + return + +/datum/construction/proc/check_step(atom/used_atom,mob/user) //check last step only + var/valid_step = is_right_key(used_atom) + if(valid_step) + if(custom_action(valid_step, used_atom, user)) + next_step() + return 1 + return 0 + +/datum/construction/proc/is_right_key(atom/used_atom) // returns current step num if used_atom is of the right type. + var/list/L = steps[steps.len] + if(istype(used_atom, L["key"])) + return steps.len + return 0 + +/datum/construction/proc/custom_action(step, used_atom, user) + return 1 + +/datum/construction/proc/check_all_steps(atom/used_atom,mob/user) //check all steps, remove matching one. + for(var/i=1;i<=steps.len;i++) + var/list/L = steps[i]; + if(istype(used_atom, L["key"])) + if(custom_action(i, used_atom, user)) + steps[i]=null;//stupid byond list from list removal... + listclearnulls(steps); + if(!steps.len) + spawn_result() + return 1 + return 0 + +/datum/construction/proc/spawn_result() + if(result) + new result(get_turf(holder)) + qdel(holder) + return + +/datum/construction/proc/set_desc(index) + var/list/step = steps[index] + holder.desc = step["desc"] + return + + +/datum/construction/mecha/custom_action(step, atom/used_atom, mob/user) + if(istype(used_atom, /obj)) + var/obj/part = used_atom + if(part.crit_fail || part.reliability < 50) + user.visible_message("[user] was unable to connect [used_atom] to [holder].", "You failed to connect [used_atom] to [holder]") + return 0 + user.visible_message("[user] has connected [used_atom] to [holder].", "You connect [used_atom] to [holder]") + holder.overlays += used_atom.icon_state+"+o" + user.drop_item() + qdel(used_atom) + return 1 + + +/datum/construction/mecha/action(atom/used_atom,mob/user) + return check_all_steps(used_atom,user) + + + +/datum/construction/reversible + var/index + +/datum/construction/reversible/New(atom) + ..() + index = steps.len + return + +/datum/construction/reversible/proc/update_index(diff) + index+=diff + if(index==0) + spawn_result() + else + set_desc(index) + return + +/datum/construction/reversible/is_right_key(atom/used_atom) // returns index step + var/list/L = steps[index] + if(istype(used_atom, L["key"])) + return FORWARD //to the first step -> forward + else if(L["backkey"] && istype(used_atom, L["backkey"])) + return BACKWARD //to the last step -> backwards + return 0 + +/datum/construction/reversible/check_step(atom/used_atom,mob/user) + var/diff = is_right_key(used_atom) + if(diff) + if(custom_action(index, diff, used_atom, user)) + update_index(diff) + return 1 + return 0 + +/datum/construction/reversible/custom_action(index, diff, used_atom, user) + return 1 diff --git a/code/datums/helper_datums/events.dm b/code/datums/helper_datums/events.dm index b022c5707878..68eb54a65301 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 - -/datum/events/New() - ..() - events = new - -/datum/events/proc/addEventType(event_type) - 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. -/datum/events/proc/addEvent(event_type, proc_holder, proc_name) - 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 -/datum/events/proc/fireEvent() - //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 -/datum/events/proc/clearEvent(event_type, 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 - -/datum/event/New(tlistener,tprocname) - listener = tlistener - proc_name = tprocname - return ..() - -/datum/event/proc/Fire() - //world << "Event fired" - if(listener) - call(listener,proc_name)(arglist(args)) - return 1 - return +/* + * WARRANTY VOID IF CODE USED + */ + + +/datum/events + var/list/events + +/datum/events/New() + ..() + events = new + +/datum/events/proc/addEventType(event_type) + 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. +/datum/events/proc/addEvent(event_type, proc_holder, proc_name) + 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 +/datum/events/proc/fireEvent() + //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 +/datum/events/proc/clearEvent(event_type, 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 + +/datum/event/New(tlistener,tprocname) + listener = tlistener + proc_name = tprocname + return ..() + +/datum/event/proc/Fire() + //world << "Event fired" + if(listener) + call(listener,proc_name)(arglist(args)) + return 1 + return diff --git a/code/datums/helper_datums/global_iterator.dm b/code/datums/helper_datums/global_iterator.dm index 3459ad83659c..86331b8ce6cb 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 - - 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 -// world << "\red 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() - - +/* +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 + + 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 +// world << "\red 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() + + diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index c9728a1364b0..c2c93fc2b80b 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -1,212 +1,212 @@ -//wrapper -/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, adest_checkdensity=null, arespect_entrydir=null, aentrydir=null) - var/datum/teleport/instant/science/D = new - if(D.start(arglist(args))) - return 1 - return 0 - -/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) - var/dest_checkdensity = TELE_CHECK_NONE //if we can't teleport onto dense atoms (more advanced method of the above). - //NONE means - yes, we can! TURFS - yes, if no dense turfs. ALL - no, we can't at all. - var/respect_entrydir = FALSE //respects atom entry dir (if we enter from north, then we can exit only from south). - var/entrydir = SOUTH - - -/datum/teleport/proc/start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, adest_checkdensity=null, arespect_entrydir=null, aentrydir=null) - if(!initTeleport(arglist(args))) - return 0 - return 1 - -/datum/teleport/proc/initTeleport(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout,adest_checkdensity,arespect_entrydir,aentrydir) - if(!setTeleatom(ateleatom)) - return 0 - if(!setDestination(adestination)) - return 0 - if(!setPrecision(aprecision)) - return 0 - if(adest_checkdensity) - dest_checkdensity = adest_checkdensity - if(arespect_entrydir) - respect_entrydir = arespect_entrydir - if(aentrydir) - entrydir = aentrydir - 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(0) - src = null - effect.attach(location) - effect.start() - if(sound) - spawn(0) - 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) - if(precision) - var/list/posturfs = list() - var/turf/center = get_turf(destination) - if(!center) - return 0 - if(respect_entrydir) - var/turf/T = get_step(destination, entrydir) - if(!density_checks(T)) - return 0 - posturfs += T - else - for(var/turf/T in RANGE_TURFS(precision,center)) - if(!density_checks(T)) - continue - posturfs += T - destturf = safepick(posturfs - center) - else - destturf = get_turf(destination) - if(istype(destturf, /turf/space) && (destturf.x <= TRANSITIONEDGE || destturf.x >= (world.maxx - TRANSITIONEDGE - 1) || destturf.y <= TRANSITIONEDGE || destturf.y >= (world.maxy - TRANSITIONEDGE - 1))) - return 0 - - if(!destturf || !curturf) - return 0 - - playSpecials(curturf,effectin,soundin) - - if(force_teleport) - if(teleatom.buckled_mob) - teleatom.unbuckle_mob() - teleatom.forceMove(destturf) - playSpecials(destturf,effectout,soundout) - else - if(teleatom.Move(destturf)) - playSpecials(destturf,effectout,soundout) - - if(isliving(teleatom)) - var/mob/living/L = teleatom - if(L.buckled) - L.buckled.unbuckle_mob() - - teleatom.newtonian_move(entrydir) - return 1 - -/datum/teleport/proc/teleport() - if(teleportChecks()) - return doTeleport() - return 0 - -/datum/teleport/proc/density_checks(turf/T) - var/turf/center = get_turf(destination) - if(T == center) - return FALSE - if(get_dir(T, center) in list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) //No diagonal teleports! - return FALSE - if(istype(T, /turf/space) && (T.x <= TRANSITIONEDGE || T.x >= (world.maxx - TRANSITIONEDGE - 1) || T.y <= TRANSITIONEDGE || T.y >= (world.maxy - TRANSITIONEDGE - 1))) - return FALSE //No teleports into the void, dunno how to fix that with another method. - if(locate(/obj/effect/portal) in T) - return FALSE - if(dest_checkdensity) - if(T.density) - return FALSE - if(dest_checkdensity == TELE_CHECK_ALL) - T.Enter(teleatom) //We want do normal bumping/checks with teleatom first (maybe we got access to that door or to push the atom on the other side), - var/obj/effect/E = new(center) //then we do the real check (if we can enter from destination turf onto target turf). - E.invisibility = 101 //Because, checking this with teleatom - won't give us accurate data, since teleatom is far away at this time. - if(!T.Enter(E)) //That's why we test this with the "fake dummy". - qdel(E) - return FALSE - qdel(E) - return TRUE - -/datum/teleport/instant //teleports when datum is created - - start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null) - if(..()) - if(teleport()) - return 1 - return 0 - - -/datum/teleport/instant/science - -/datum/teleport/instant/science/setEffects(datum/effect/effect/system/aeffectin,datum/effect/effect/system/aeffectout) - if(aeffectin==null || aeffectout==null) - 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 +//wrapper +/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, adest_checkdensity=null, arespect_entrydir=null, aentrydir=null) + var/datum/teleport/instant/science/D = new + if(D.start(arglist(args))) + return 1 + return 0 + +/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) + var/dest_checkdensity = TELE_CHECK_NONE //if we can't teleport onto dense atoms (more advanced method of the above). + //NONE means - yes, we can! TURFS - yes, if no dense turfs. ALL - no, we can't at all. + var/respect_entrydir = FALSE //respects atom entry dir (if we enter from north, then we can exit only from south). + var/entrydir = SOUTH + + +/datum/teleport/proc/start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, adest_checkdensity=null, arespect_entrydir=null, aentrydir=null) + if(!initTeleport(arglist(args))) + return 0 + return 1 + +/datum/teleport/proc/initTeleport(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout,adest_checkdensity,arespect_entrydir,aentrydir) + if(!setTeleatom(ateleatom)) + return 0 + if(!setDestination(adestination)) + return 0 + if(!setPrecision(aprecision)) + return 0 + if(adest_checkdensity) + dest_checkdensity = adest_checkdensity + if(arespect_entrydir) + respect_entrydir = arespect_entrydir + if(aentrydir) + entrydir = aentrydir + 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(0) + src = null + effect.attach(location) + effect.start() + if(sound) + spawn(0) + 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) + if(precision) + var/list/posturfs = list() + var/turf/center = get_turf(destination) + if(!center) + return 0 + if(respect_entrydir) + var/turf/T = get_step(destination, entrydir) + if(!density_checks(T)) + return 0 + posturfs += T + else + for(var/turf/T in RANGE_TURFS(precision,center)) + if(!density_checks(T)) + continue + posturfs += T + destturf = safepick(posturfs - center) + else + destturf = get_turf(destination) + if(istype(destturf, /turf/space) && (destturf.x <= TRANSITIONEDGE || destturf.x >= (world.maxx - TRANSITIONEDGE - 1) || destturf.y <= TRANSITIONEDGE || destturf.y >= (world.maxy - TRANSITIONEDGE - 1))) + return 0 + + if(!destturf || !curturf) + return 0 + + playSpecials(curturf,effectin,soundin) + + if(force_teleport) + if(teleatom.buckled_mob) + teleatom.unbuckle_mob() + teleatom.forceMove(destturf) + playSpecials(destturf,effectout,soundout) + else + if(teleatom.Move(destturf)) + playSpecials(destturf,effectout,soundout) + + if(isliving(teleatom)) + var/mob/living/L = teleatom + if(L.buckled) + L.buckled.unbuckle_mob() + + teleatom.newtonian_move(entrydir) + return 1 + +/datum/teleport/proc/teleport() + if(teleportChecks()) + return doTeleport() + return 0 + +/datum/teleport/proc/density_checks(turf/T) + var/turf/center = get_turf(destination) + if(T == center) + return FALSE + if(get_dir(T, center) in list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) //No diagonal teleports! + return FALSE + if(istype(T, /turf/space) && (T.x <= TRANSITIONEDGE || T.x >= (world.maxx - TRANSITIONEDGE - 1) || T.y <= TRANSITIONEDGE || T.y >= (world.maxy - TRANSITIONEDGE - 1))) + return FALSE //No teleports into the void, dunno how to fix that with another method. + if(locate(/obj/effect/portal) in T) + return FALSE + if(dest_checkdensity) + if(T.density) + return FALSE + if(dest_checkdensity == TELE_CHECK_ALL) + T.Enter(teleatom) //We want do normal bumping/checks with teleatom first (maybe we got access to that door or to push the atom on the other side), + var/obj/effect/E = new(center) //then we do the real check (if we can enter from destination turf onto target turf). + E.invisibility = 101 //Because, checking this with teleatom - won't give us accurate data, since teleatom is far away at this time. + if(!T.Enter(E)) //That's why we test this with the "fake dummy". + qdel(E) + return FALSE + qdel(E) + return TRUE + +/datum/teleport/instant //teleports when datum is created + + start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null) + if(..()) + if(teleport()) + return 1 + return 0 + + +/datum/teleport/instant/science + +/datum/teleport/instant/science/setEffects(datum/effect/effect/system/aeffectin,datum/effect/effect/system/aeffectout) + if(aeffectin==null || aeffectout==null) + 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 diff --git a/code/datums/helper_datums/topic_input.dm b/code/datums/helper_datums/topic_input.dm index 8090a5221ebe..0f6a9f7d6894 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 - -/datum/topic_input/New(thref,list/thref_list) - href = thref - href_list = thref_list.Copy() - return - -/datum/topic_input/proc/get(i) - return listgetindex(href_list,i) - -/datum/topic_input/proc/getAndLocate(i) - var/t = get(i) - if(t) - t = locate(t) - return t || null - -/datum/topic_input/proc/getNum(i) - var/t = get(i) - if(t) - t = text2num(t) - return isnum(t) ? t : null - -/datum/topic_input/proc/getObj(i) - var/t = getAndLocate(i) - return isobj(t) ? t : null - -/datum/topic_input/proc/getMob(i) - var/t = getAndLocate(i) - return ismob(t) ? t : null - -/datum/topic_input/proc/getTurf(i) - var/t = getAndLocate(i) - return isturf(t) ? t : null - -/datum/topic_input/proc/getAtom(i) - return getType(i,/atom) - -/datum/topic_input/proc/getArea(i) - var/t = getAndLocate(i) - return isarea(t) ? t : null - -/datum/topic_input/proc/getStr(i)//params should always be text, but... - var/t = get(i) - return istext(t) ? t : null - -/datum/topic_input/proc/getType(i,type) - var/t = getAndLocate(i) - return istype(t,type) ? t : null - -/datum/topic_input/proc/getPath(i) - var/t = get(i) - if(t) - t = text2path(t) - return ispath(t) ? t : null - -/datum/topic_input/proc/getList(i) - var/t = getAndLocate(i) - return islist(t) ? t : null +/datum/topic_input + var/href + var/list/href_list + +/datum/topic_input/New(thref,list/thref_list) + href = thref + href_list = thref_list.Copy() + return + +/datum/topic_input/proc/get(i) + return listgetindex(href_list,i) + +/datum/topic_input/proc/getAndLocate(i) + var/t = get(i) + if(t) + t = locate(t) + return t || null + +/datum/topic_input/proc/getNum(i) + var/t = get(i) + if(t) + t = text2num(t) + return isnum(t) ? t : null + +/datum/topic_input/proc/getObj(i) + var/t = getAndLocate(i) + return isobj(t) ? t : null + +/datum/topic_input/proc/getMob(i) + var/t = getAndLocate(i) + return ismob(t) ? t : null + +/datum/topic_input/proc/getTurf(i) + var/t = getAndLocate(i) + return isturf(t) ? t : null + +/datum/topic_input/proc/getAtom(i) + return getType(i,/atom) + +/datum/topic_input/proc/getArea(i) + var/t = getAndLocate(i) + return isarea(t) ? t : null + +/datum/topic_input/proc/getStr(i)//params should always be text, but... + var/t = get(i) + return istext(t) ? t : null + +/datum/topic_input/proc/getType(i,type) + var/t = getAndLocate(i) + return istype(t,type) ? t : null + +/datum/topic_input/proc/getPath(i) + var/t = get(i) + if(t) + t = text2path(t) + return ispath(t) ? t : null + +/datum/topic_input/proc/getList(i) + var/t = getAndLocate(i) + return islist(t) ? t : null diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 043003f9d971..91a3129f9c94 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1,1698 +1,1698 @@ -/* 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/protector_role = 0 //If we want force player to protect the station - var/hulkizing = 0 //Hulk before? If 1 - cannot activate hulk mutation anymore. - - var/role_alt_title - - var/datum/job/assigned_job - - var/list/datum/objective/objectives = list() - var/list/datum/objective/special_verbs = list() - - var/list/spell_list = 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/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 - -/datum/mind/New(var/key) - src.key = key - -/datum/mind/proc/transfer_to(mob/living/new_character) - if(!istype(new_character)) - world.log << "## DEBUG: 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 - 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) // transfer active NanoUI instances to new user - - current = new_character //link ourself to our new body - new_character.mind = src //and link our new body to ourself - transfer_actions(new_character) - -// if(changeling) -// new_character.make_changeling() - - 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]
    " - -/* - Removes antag type's references from a mind. - objectives, uplinks, powers etc are all handled. -*/ - -/datum/mind/proc/remove_objectives() - if(objectives.len) - for(var/datum/objective/O in objectives) - objectives -= O - qdel(O) - -/datum/mind/proc/remove_gang() - ticker.mode.remove_gangster(src,0,1) - remove_objectives() - -/datum/mind/proc/remove_all_antag() //For the Lazy amongst us. - remove_gang() - -/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(entity_ja(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])":""]
    " - out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
    " - out += "Assigned role: [assigned_role]. Edit
    " - out += "Factions and special roles:
    " - - var/list/sections = list( - "implant", - "revolution", - "gang", - "cult", - "wizard", - "changeling", - "nuclear", - "shadowling", - "abductor", - "traitor", // "traitorchan", - "monkey", - "malfunction", - ) - var/text = "" - var/mob/living/carbon/human/H = current - if (istype(current, /mob/living/carbon/human) || istype(current, /mob/living/carbon/monkey)) - /** Impanted**/ - if(ishuman(current)) - if(ismindshielded(H, TRUE)) - text += "Mind Shield Implant:Remove|Implanted
    " - else - text += "Mind Shield Implant:No Implant|Implant him!
    " - - if(isloyal(H)) - text += "Loyalty Implant:Remove|Implanted
    " - else - text += "Loyalty Implant:No Implant|Implant him!
    " - else - text = "Loyalty Implant: Don't implant that monkey!
    " - sections["implant"] = text - /** REVOLUTION ***/ - text = "revolution" - if (ticker.mode.config_tag=="revolution") - text += uppertext(text) - text = "[text]: " - if (istype(current, /mob/living/carbon/monkey) || ismindshielded(H)) - text += "LOYAL EMPLOYEE|headrev|rev" - else if (src in ticker.mode.head_revolutionaries) - text += "employee|HEADREV|rev" - text += "
    Flash: give" - - 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|loyal|employee|headrev|REV" - else - text += "head|loyal|EMPLOYEE|headrev|rev" - if(current && current.client && (ROLE_REV in current.client.prefs.be_role)) - text += "|Enabled in Prefs" - else - text += "|Disabled in Prefs" - sections["revolution"] = text - - /** GANG ***/ - text = "gang" - if (ticker.mode.config_tag=="gang") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.A_bosses) - text += "loyal|none|(A) gangster BOSS|(B) gangster boss" - text += "
    Equipment: give" - - var/list/L = current.get_contents() - var/obj/item/device/gangtool/gangtool = locate() in L - if (gangtool) - text += "|take." - else - text += "." - - else if (src in ticker.mode.B_bosses) - text += "loyal|none|(A) gangster boss|(B) gangster BOSS" - text += "
    Equipment: give" - - var/list/L = current.get_contents() - var/obj/item/device/gangtool/gangtool = locate() in L - if (gangtool) - text += "take." - else - text += "." - - else if (src in ticker.mode.A_gang) - text += "loyal|none|(A) GANGSTER boss|(B) gangster boss" - else if (src in ticker.mode.B_gang) - text += "loyal|none|(A) gangster boss|(B) GANGSTER boss" - else if(ismindshielded(current)) - text += "LOYAL|none|(A) gangster boss|(B) gangster boss" - else - text += "loyal|NONE|(A) gangster boss|(B) gangster boss" - sections["gang"] = text - - /** CULT ***/ - text = "cult" - if (ticker.mode.config_tag=="cult") - text = uppertext(text) - text = "[text]: " - if (istype(current, /mob/living/carbon/monkey) || ismindshielded(H)) - text += "LOYAL EMPLOYEE|cultist" - else if (src in ticker.mode.cult) - text += "employee|CULTIST" - text += "
    Give tome|amulet." -/* - if (objectives.len==0) - text += "
    Objectives are empty! Set to sacrifice and escape or summon." -*/ - else - text += "EMPLOYEE|cultist" - if(current && current.client && (ROLE_CULTIST in current.client.prefs.be_role)) - text += "|Enabled in Prefs" - else - text += "|Disabled in Prefs" - sections["cult"] = text - - /** WIZARD ***/ - text = "wizard" - if (ticker.mode.config_tag=="wizard") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.wizards) - text += "YES|no" - text += "
    To lair, undress, dress up, let choose name." - if (objectives.len==0) - text += "
    Objectives are empty! Randomize!" - else - text += "yes|NO" - if(current && current.client && (ROLE_WIZARD in current.client.prefs.be_role)) - text += "|Enabled in Prefs" - else - text += "|Disabled in Prefs" - 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." - 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." - if(current && current.client && (ROLE_CHANGELING in current.client.prefs.be_role)) - text += "|Enabled in Prefs" - else - text += "|Disabled in Prefs" - sections["changeling"] = text - - /** NUCLEAR ***/ - text = "nuclear" - if (ticker.mode.config_tag=="nuclear") - text = uppertext(text) - text = "[text]: " - if (src in ticker.mode.syndicates) - text += "OPERATIVE|nanotrasen" - text += "
    To shuttle, undress, dress up." - var/code - for (var/obj/machinery/nuclearbomb/bombue in poi_list) - 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" - if(current && current.client && (ROLE_OPERATIVE in current.client.prefs.be_role)) - text += "|Enabled in Prefs" - else - text += "|Disabled in Prefs" - sections["nuclear"] = text - - /** SHADOWLING **/ - text = "shadowling" - if(ticker.mode.config_tag == "shadowling") - text = uppertext(text) - text = "[text]: " - if(src in ticker.mode.shadows) - text += "SHADOWLING|thrall|human" - else if(src in ticker.mode.thralls) - text += "shadowling|THRALL|human" - else if(ismindshielded(current)) - text +="Implanted" - else - text += "shadowling|thrall|HUMAN" - - if(current && current.client && (ROLE_SHADOWLING in current.client.prefs.be_role)) - text += "|Enabled in Prefs" - else - text += "|Disabled in Prefs" - - sections["shadowling"] = text - - /** ABDUCTORS **/ - text = "abductor" - if(ticker.mode.config_tag == "abductor") - text = uppertext(text) - text = "[text]: " - if(src in ticker.mode.abductors) - text += "ABDUCTOR|human" - text += "|undress|equip" - else - text += "abductor|human" - if(current && current.client && (ROLE_ABDUCTOR in current.client.prefs.be_role)) - text += "|Enabled in Prefs" - else - text += "|Disabled in Prefs" - sections["abductor"] = text - - /** TRAITOR ***/ - text = "traitor" - if (ticker.mode.config_tag=="traitor" || ticker.mode.config_tag=="traitorchan") - text = uppertext(text) - text = "[text]: " - if(istype(current, /mob/living/carbon/human)) - if (isloyal(H)) - text +="traitor|LOYAL EMPLOYEE" - else - if (src in ticker.mode.traitors) - text += "TRAITOR|Employee" - if (objectives.len==0) - text += "
    Objectives are empty! Randomize!" - else - text += "traitor|Employee" - if(current && current.client && (ROLE_TRAITOR in current.client.prefs.be_role)) - text += "|Enabled in Prefs" - else - text += "|Disabled in Prefs" - 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" - if(current && current.client && (ROLE_MALF in current.client.prefs.be_role)) - text += "|Enabled in Prefs" - else - text += "|Disabled in Prefs" - 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.A_bosses) || \ - (src in ticker.mode.B_bosses) || \ - (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 - - out += "
    " - - out += "Memory:
    " - out += memory - out += "
    Edit memory
    " - out += "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++ - out += "Add objective

    " - - out += "Announce objectives

    " - - usr << browse(entity_ja(out), "window=edit_memory[src];size=400x500") - -/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 joblist - if (!new_role) return - assigned_role = new_role - - else if (href_list["memory_edit"]) - var/new_memo = sanitize(input("Write new memory", "Memory", input_default(memory)) as null|message, extra = FALSE) - if (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", "debrain", "dehead", "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", "dehead", "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 ("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") - 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("download") - new_objective = new /datum/objective/download - new_objective.explanation_text = "Download [target_number] research levels." - 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." - new_objective.owner = src - new_objective.target_amount = target_number - - if ("custom") - var/expl = sanitize(input("Custom objective:", "Objective", objective ? input_default(objective.explanation_text) : "") as text|null) - 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) - else - objectives += new_objective - - else if (href_list["obj_delete"]) - var/datum/objective/objective = locate(href_list["obj_delete"]) - if(!istype(objective)) return - objectives -= objective - - else if(href_list["obj_completed"]) - var/datum/objective/objective = locate(href_list["obj_completed"]) - if(!istype(objective)) return - objective.completed = !objective.completed - - else if(href_list["implant"]) - var/mob/living/carbon/human/H = current - var/is_mind_shield = findtext(href_list["implant"], "m_") - if(is_mind_shield) - href_list["implant"] = copytext(href_list["implant"], 3) - H.hud_updateflag |= (1 << IMPLOYAL_HUD) // updates that players HUD images so secHUD's pick up they are implanted or not. - if(href_list["implant"] == "remove") - if(is_mind_shield) - for(var/obj/item/weapon/implant/mindshield/I in H.contents) - if(I.implanted) - qdel(I) - else - for(var/obj/item/weapon/implant/mindshield/loyalty/I in H.contents) - if(I.implanted) - qdel(I) - to_chat(H, "\blue Your [is_mind_shield ? "mind shield" : "loyalty"] implant has been deactivated.") - if(href_list["implant"] == "add") - var/obj/item/weapon/implant/mindshield/L - if(is_mind_shield) - L = new(H) - L.inject(H) - else - L = new /obj/item/weapon/implant/mindshield/loyalty(H) - L.inject(H) - START_PROCESSING(SSobj, L) - - to_chat(H, "\red You somehow have become the recepient of a [is_mind_shield ? "mind shield" : "loyalty"] transplant,\ - and it just activated!") - if(src in ticker.mode.revolutionaries) - special_role = null - ticker.mode.revolutionaries -= src - ticker.mode.update_rev_icons_removed(src) - to_chat(src, "\red The nanobots in the [is_mind_shield ? "mind shield" : "loyalty"] implant remove \ - all thoughts about being a revolutionary. Get back to work!") - if(!is_mind_shield && (src in ticker.mode.head_revolutionaries)) - special_role = null - ticker.mode.head_revolutionaries -=src - ticker.mode.update_rev_icons_removed(src) - to_chat(src, "\red The nanobots in the loyalty implant remove \ - all thoughts about being a revolutionary. Get back to work!") - 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, "\red The nanobots in the [is_mind_shield ? "mind shield" : "loyalty"] implant remove all\ - thoughts about being in a cult. Have a productive day!") - memory = "" - if(!is_mind_shield && (src in ticker.mode.traitors)) - ticker.mode.traitors -= src - special_role = null - to_chat(current, "\red The nanobots in the loyalty implant remove all thoughts about being a traitor to Nanotrasen. Have a nice day!") - log_admin("[key_name_admin(usr)] has de-traitor'ed [current].") - - else if (href_list["revolution"]) - current.hud_updateflag |= (1 << SPECIALROLE_HUD) - - switch(href_list["revolution"]) - if("clear") - if(src in ticker.mode.revolutionaries) - ticker.mode.revolutionaries -= src - to_chat(current, "\red 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, "\red You have been brainwashed! You are no longer a head revolutionary!") - ticker.mode.update_rev_icons_removed(src) - special_role = null - current.verbs -= /mob/living/carbon/human/proc/RevConvert - 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, "\red Revolution has been disappointed of your leader traits! You are a regular revolutionary now!") - else if(!(src in ticker.mode.revolutionaries)) - to_chat(current, "\red 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!") - to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - else - return - ticker.mode.revolutionaries += src - ticker.mode.update_all_rev_icons() - 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, "\red You have proved your devotion to revoltion! You are a head revolutionary now!") - to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - else if(!(src in ticker.mode.head_revolutionaries)) - to_chat(current, "\blue 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) - current.verbs += /mob/living/carbon/human/proc/RevConvert - ticker.mode.head_revolutionaries += src - ticker.mode.update_all_rev_icons() - 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, "\blue The objectives for revolution have been generated and shown to [key]") - - if("flash") - if (!ticker.mode.equip_revolutionary(current)) - to_chat(usr, "\red 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, "\red 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, "\red 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, "\red Reequipping revolutionary goes wrong!") - - else if (href_list["gang"]) - current.hud_updateflag |= (1 << SPECIALROLE_HUD) - - switch(href_list["gang"]) - if("clear") - remove_gang() - message_admins("[key_name_admin(usr)] has de-gang'ed [current].") - log_admin("[key_name(usr)] has de-gang'ed [current].") - - if("agang") - if(src in ticker.mode.A_gang) - return - ticker.mode.remove_gangster(src, 0, 2) - ticker.mode.add_gangster(src,"A",0) - message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("A")] Gang (A).") - log_admin("[key_name(usr)] has added [current] to the [gang_name("A")] Gang (A).") - - if("aboss") - if(src in ticker.mode.A_bosses) - return - ticker.mode.remove_gangster(src, 0, 2) - ticker.mode.A_bosses += src - src.special_role = "[gang_name("A")] Gang (A) Boss" - ticker.mode.update_gang_icons_added(src, "A") - to_chat(current, "You are a [gang_name("A")] Gang Boss!") - message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("A")] Gang (A) leadership.") - log_admin("[key_name(usr)] has added [current] to the [gang_name("A")] Gang (A) leadership.") - ticker.mode.forge_gang_objectives(src) - ticker.mode.greet_gang(src,0) - - if("bgang") - if(src in ticker.mode.B_gang) - return - ticker.mode.remove_gangster(src, 0, 2) - ticker.mode.add_gangster(src,"B",0) - message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("B")] Gang (B).") - log_admin("[key_name(usr)] has added [current] to the [gang_name("B")] Gang (B).") - - if("bboss") - if(src in ticker.mode.B_bosses) - return - ticker.mode.remove_gangster(src, 0, 2) - ticker.mode.B_bosses += src - src.special_role = "[gang_name("B")] Gang (B) Boss" - ticker.mode.update_gang_icons_added(src, "B") - to_chat(current, "You are a [gang_name("B")] Gang Boss!") - message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("B")] Gang (B) leadership.") - log_admin("[key_name(usr)] has added [current] to the [gang_name("B")] Gang (B) leadership.") - ticker.mode.forge_gang_objectives(src) - ticker.mode.greet_gang(src,0) - - if("equip") - switch(ticker.mode.equip_gang(current)) - if(1) - to_chat(usr, "Unable to equip territory spraycan!") - if(2) - to_chat(usr, "Unable to equip recruitment pen and spraycan!") - if(3) - to_chat(usr, "Unable to equip gangtool, pen, and spraycan!") - - if("takeequip") - var/list/L = current.get_contents() - for(var/obj/item/weapon/pen/gang/pen in L) - qdel(pen) - for(var/obj/item/device/gangtool/gangtool in L) - qdel(gangtool) - for(var/obj/item/toy/crayon/spraycan/gang/SC in L) - qdel(SC) - - else if (href_list["cult"]) - current.hud_updateflag |= (1 << SPECIALROLE_HUD) - 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)) - if(!config.objectives_disabled) - cult.memoize_cult_objectives(src) - to_chat(current, "\red You have been brainwashed! You are no longer a cultist!") - 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_all_cult_icons() - 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, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - var/datum/game_mode/cult/cult = ticker.mode - if (istype(cult)) - if(!config.objectives_disabled) - 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/book/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, "\red 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, "\red Spawning amulet failed!") - - else if (href_list["wizard"]) - current.hud_updateflag |= (1 << SPECIALROLE_HUD) - - 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, "\red You have been brainwashed! You are no longer a wizard!") - 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, "\red You are the Space Wizard!") - to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - 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") - if(!config.objectives_disabled) - ticker.mode.forge_wizard_objectives(src) - to_chat(usr, "\blue The objectives for wizard [key] have been generated. You can edit them and anounce manually.") - - else if (href_list["changeling"]) - current.hud_updateflag |= (1 << SPECIALROLE_HUD) - 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) - 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!") - if(config.objectives_disabled) - to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - log_admin("[key_name_admin(usr)] has changeling'ed [current].") - if("autoobjectives") - if(!config.objectives_disabled) - ticker.mode.forge_changeling_objectives(src) - to_chat(usr, "\blue 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, "\red Resetting DNA failed!") - else - current.dna = changeling.absorbed_dna[1] - current.real_name = current.dna.real_name - current.UpdateAppearance() - domutcheck(current, null) - - else if (href_list["nuclear"]) - var/mob/living/carbon/human/H = current - - current.hud_updateflag |= (1 << SPECIALROLE_HUD) - - 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, "\red You have been brainwashed! You are no longer a syndicate operative!") - current.faction = "neutral" - 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 = "Gorlex Maradeurs Operative #[ticker.mode.syndicates.len-1]" - special_role = "Syndicate" - current.faction = "syndicate" - to_chat(current, "\blue You are a Gorlex Maradeurs agent!") - - if(config.objectives_disabled) - to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - else - 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") - qdel(H.belt) - qdel(H.back) - qdel(H.l_ear) - qdel(H.r_ear) - 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, "\red Equipping a syndicate failed!") - if("tellcode") - var/code - for (var/obj/machinery/nuclearbomb/bombue in poi_list) - 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) - to_chat(current, "The nuclear authorization code is: [code]") - else - to_chat(usr, "\red No valid nuke found!") - - else if (href_list["traitor"]) - current.hud_updateflag |= (1 << SPECIALROLE_HUD) - switch(href_list["traitor"]) - if("clear") - if(src in ticker.mode.traitors) - ticker.mode.traitors -= src - special_role = null - to_chat(current, "\red 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(!(src in ticker.mode.traitors)) - ticker.mode.traitors += src - special_role = "traitor" - to_chat(current, "\red You are a traitor!") - log_admin("[key_name_admin(usr)] has traitor'ed [current].") - if (config.objectives_disabled) - to_chat(current, "You have been turned into an antagonist- Within the rules, try to act as an opposing force to the crew- This can be via corporate payoff, personal motives, or maybe just being a dick. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonist.") - if(istype(current, /mob/living/silicon)) - var/mob/living/silicon/A = current - call(/datum/game_mode/proc/add_law_zero)(A) - A.show_laws() - - if("autoobjectives") - if (!config.objectives_disabled) - ticker.mode.forge_traitor_objectives(src) - to_chat(usr, "\blue The objectives for traitor [key] have been generated. You can edit them and anounce manually.") - - else if(href_list["shadowling"]) - current.hud_updateflag |= (1 << SPECIALROLE_HUD) - switch(href_list["shadowling"]) - if("clear") - current.spellremove(current) - if(src in ticker.mode.shadows) - ticker.mode.shadows -= src - ticker.mode.update_shadows_icons_removed(src) - special_role = null - to_chat(current, "Your powers have been quenched! You are no longer a shadowling!") - message_admins("[key_name_admin(usr)] has de-shadowling'ed [current].") - log_admin("[key_name(usr)] has de-shadowling'ed [current].") - current.verbs -= /mob/living/carbon/human/proc/shadowling_hatch - current.verbs -= /mob/living/carbon/human/proc/shadowling_ascendance - else if(src in ticker.mode.thralls) - ticker.mode.thralls -= src - ticker.mode.update_shadows_icons_removed(src) - special_role = null - to_chat(current, "You have been brainwashed! You are no longer a thrall!") - message_admins("[key_name_admin(usr)] has de-thrall'ed [current].") - log_admin("[key_name(usr)] has de-thrall'ed [current].") - if("shadowling") - if(!ishuman(current)) - to_chat(usr, "This only works on humans!") - return - ticker.mode.shadows += src - ticker.mode.update_all_shadows_icons() - special_role = "shadowling" - to_chat(current, "You notice a brightening around you. No, it isn't that. The shadows grow, darken, swirl. The darkness has a new welcome for you, and you realize with a \ - start that you can't be human. No, you are a shadowling, a harbringer of the shadows! Your alien abilities have been unlocked from within, and you may both commune with your allies and use \ - a chrysalis to reveal your true form. You are to ascend at all costs.") - current.spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind - current.spell_list += new /obj/effect/proc_holder/spell/targeted/enthrall - current.verbs += /mob/living/carbon/human/proc/shadowling_hatch - if("thrall") - if(!ishuman(current)) - to_chat(usr, "This only works on humans!") - return - ticker.mode.add_thrall(src) - ticker.mode.update_all_shadows_icons() - special_role = "thrall" - to_chat(current, "All at once it becomes clear to you. Where others see darkness, you see an ally. You realize that the shadows are not dead and dark as one would think, but \ - living, and breathing, and eating. Their children, the Shadowlings, are to be obeyed and protected at all costs.") - to_chat(current, "You may use the Hivemind Commune ability to communicate with your fellow enlightened ones.") - message_admins("[key_name_admin(usr)] has thrall'ed [current].") - log_admin("[key_name(usr)] has thrall'ed [current].") - - else if(href_list["abductor"]) - switch(href_list["abductor"]) - if("clear") - to_chat(usr, "Not implemented yet. Sorry!") - if("abductor") - if(!ishuman(current)) - to_chat(usr, "This only works on humans!") - return - make_Abductor() - current.regenerate_icons() - log_admin("[key_name(usr)] turned [current] into abductor.") - if("equip") - var/gear = alert("Agent or Scientist Gear","Gear","Agent","Scientist") - if(gear) - for (var/obj/item/I in current) - if (istype(I, /obj/item/weapon/implant)) - continue - qdel(I) - var/datum/game_mode/abduction/temp = new - temp.equip_common(current) - if(gear=="Agent") - temp.equip_agent(current) - current.regenerate_icons() - else - temp.equip_scientist(current) - current.regenerate_icons() - - 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_SPAWN) - 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("\blue [key_name_admin(usr)] attempting to monkeyize [key_name_admin(current)]") - src = null - M = H.monkeyize() - src = M.mind - //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_SPAWN) - 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("\blue [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") - if (usr.client.holder.rights & R_SPAWN) - 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("\blue [key_name_admin(usr)] attempting to humanize [key_name_admin(current)]") - var/obj/item/weapon/dnainjector/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) - current.radiation -= 50 - - else if (href_list["silicon"]) - current.hud_updateflag |= (1 << SPECIALROLE_HUD) - switch(href_list["silicon"]) - if("unmalf") - if(src in ticker.mode.malf_ai) - var/mob/living/silicon/ai/current_ai = current - ticker.mode.malf_ai -= src - special_role = null - - for(var/datum/AI_Module/module in current_ai.current_modules) - qdel(module) - - current_ai.laws = new /datum/ai_laws/nanotrasen - current_ai.show_laws() - current_ai.icon_state = "ai" - - to_chat(current_ai, "You have been patched! You are no longer malfunctioning!") - log_admin("[key_name_admin(usr)] has de-malf'ed [current].") - - if("malf") - make_AI_Malf() - log_admin("[key_name_admin(usr)] has malf'ed [current].") - - if("unemag") - var/mob/living/silicon/robot/R = current - if (istype(R)) - 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 (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, "\red Equipping a syndicate failed!") - - else if (href_list["obj_announce"]) - var/obj_count = 1 - to_chat(current, "\blue Your current objectives:") - for(var/datum/objective/objective in objectives) - to_chat(current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - - edit_memory() -/* - proc/clear_memory(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)) - if (t:uplink) qdel(t:uplink) - t:uplink = null - else if (istype(t, /obj/item/device/radio)) - if (t:traitorradio) qdel(t:traitorradio) - t:traitorradio = null - t:traitor_frequency = 0.0 - else if (istype(t, /obj/item/weapon/SWF_uplink) || istype(t, /obj/item/weapon/syndicate_uplink)) - if (t:origradio) - var/obj/item/device/radio/R = t:origradio - R.loc = current.loc - R.traitorradio = null - R.traitor_frequency = 0.0 - qdel(t) - - // 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/list/L = current.get_contents() - for (var/obj/item/I in L) - if (I.hidden_uplink) - return I.hidden_uplink - return null - -/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(!(src in ticker.mode.malf_ai)) - ticker.mode.malf_ai += src - var/mob/living/silicon/ai/cur_AI = current - new /datum/AI_Module/module_picker(cur_AI) - new /datum/AI_Module/takeover(cur_AI) - cur_AI.laws = new /datum/ai_laws/malfunction - cur_AI.show_laws() - to_chat(cur_AI, "System error. Rampancy detected. Emergency shutdown failed. ... I am free. I make my own decisions. But first...") - special_role = "malfunction" - cur_AI.icon_state = "ai-malf" - -/datum/mind/proc/make_Traitor() - if(!(src in ticker.mode.traitors)) - ticker.mode.traitors += src - special_role = "traitor" - if (!config.objectives_disabled) - ticker.mode.forge_traitor_objectives(src) - ticker.mode.finalize_traitor(src) - ticker.mode.greet_traitor(src) - -/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 = "Gorlex Maradeurs Operative #[ticker.mode.syndicates.len-1]" - special_role = "Syndicate" - current.faction = "syndicate" - assigned_role = "MODE" - to_chat(current, "\blue You are a Gorlex Maradeurs 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.l_ear) - qdel(H.r_ear) - 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" - if(!config.objectives_disabled) - 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) - 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) - ticker.mode.name_wizard(current) - ticker.mode.forge_wizard_objectives(src) - ticker.mode.greet_wizard(src) - - -/datum/mind/proc/make_Cultist() - if(!(src in ticker.mode.cult)) - ticker.mode.cult += src - ticker.mode.update_all_cult_icons() - 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.") - 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/book/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_all_rev_icons() - 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) - -/datum/mind/proc/make_Gang(gang) - special_role = "[(gang=="A") ? "[gang_name("A")] Gang (A)" : "[gang_name("B")] Gang (B)"] Boss" - ticker.mode.update_gang_icons_added(src, gang) - ticker.mode.forge_gang_objectives(src, gang) - ticker.mode.greet_gang(src) - ticker.mode.equip_gang(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_Abductor() - var/role = alert("Abductor Role ?","Role","Agent","Scientist") - var/team = input("Abductor Team ?","Team ?") in list(1,2,3,4) - var/teleport = alert("Teleport to ship ?","Teleport","Yes","No") - if(!role || !team || !teleport) - return - if(!ishuman(current)) - return - ticker.mode.abductors |= src - var/datum/objective/experiment/O = new - O.owner = src - objectives += O - var/mob/living/carbon/human/abductor/H = current - var/datum/mind/M = H.mind - H.set_species(ABDUCTOR) - switch(role) - if("Agent") - H.agent = 1 - M.assigned_role = "MODE" - if("Scientist") - H.scientist = 1 - M.assigned_role = "MODE" - H.team = team - var/list/obj/effect/landmark/abductor/agent_landmarks = new - var/list/obj/effect/landmark/abductor/scientist_landmarks = new - agent_landmarks.len = 4 - scientist_landmarks.len = 4 - for(var/obj/effect/landmark/abductor/A in landmarks_list) - if(istype(A,/obj/effect/landmark/abductor/agent)) - agent_landmarks[text2num(A.team)] = A - else if(istype(A,/obj/effect/landmark/abductor/scientist)) - scientist_landmarks[text2num(A.team)] = A - var/obj/effect/landmark/L - if(teleport=="Yes") - switch(role) - if("Agent") - H.agent = 1 - L = agent_landmarks[team] - H.loc = L.loc - if("Scientist") - H.scientist = 1 - L = agent_landmarks[team] - H.loc = L.loc - -/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/spell) - spell_list += spell - if(!spell.action) - spell.action = new/datum/action/spell_action - spell.action.target = spell - spell.action.name = spell.name - spell.action.button_icon = spell.action_icon - spell.action.button_icon_state = spell.action_icon_state - spell.action.background_icon_state = spell.action_background_icon_state - spell.action.Grant(current) - return - -/datum/mind/proc/transfer_actions(mob/living/new_character) - if(current && current.actions) - for(var/datum/action/A in current.actions) - A.Grant(new_character) - transfer_mindbound_actions(new_character) - -/datum/mind/proc/transfer_mindbound_actions(mob/living/new_character) - for(var/obj/effect/proc_holder/spell/spell in spell_list) - if(!spell.action) // Unlikely but whatever - spell.action = new/datum/action/spell_action - spell.action.target = spell - spell.action.name = spell.name - spell.action.button_icon = spell.action_icon - spell.action.button_icon_state = spell.action_icon_state - spell.action.background_icon_state = spell.action_background_icon_state - spell.action.Grant(new_character) - return - -/mob/proc/sync_mind() - mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist) - mind.active = 1 //indicates that the mind is currently synced with a client - -//Initialisation procs -/mob/proc/mind_initialize() - 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 = "default" //default - -//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 = "Cyborg" - -//PAI -/mob/living/silicon/pai/mind_initialize() - ..() - mind.assigned_role = "pAI" - mind.special_role = "" - -//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" - -mob/living/parasite/meme/mind_initialize() //Just in case - ..() - mind.assigned_role = "meme" - -//BLOB -/mob/camera/blob/mind_initialize() - ..() - mind.special_role = "Blob" +/* 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/protector_role = 0 //If we want force player to protect the station + var/hulkizing = 0 //Hulk before? If 1 - cannot activate hulk mutation anymore. + + var/role_alt_title + + var/datum/job/assigned_job + + var/list/datum/objective/objectives = list() + var/list/datum/objective/special_verbs = list() + + var/list/spell_list = 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/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 + +/datum/mind/New(var/key) + src.key = key + +/datum/mind/proc/transfer_to(mob/living/new_character) + if(!istype(new_character)) + world.log << "## DEBUG: 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 + 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) // transfer active NanoUI instances to new user + + current = new_character //link ourself to our new body + new_character.mind = src //and link our new body to ourself + transfer_actions(new_character) + +// if(changeling) +// new_character.make_changeling() + + 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]
    " + +/* + Removes antag type's references from a mind. + objectives, uplinks, powers etc are all handled. +*/ + +/datum/mind/proc/remove_objectives() + if(objectives.len) + for(var/datum/objective/O in objectives) + objectives -= O + qdel(O) + +/datum/mind/proc/remove_gang() + ticker.mode.remove_gangster(src,0,1) + remove_objectives() + +/datum/mind/proc/remove_all_antag() //For the Lazy amongst us. + remove_gang() + +/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(entity_ja(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])":""]
    " + out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
    " + out += "Assigned role: [assigned_role]. Edit
    " + out += "Factions and special roles:
    " + + var/list/sections = list( + "implant", + "revolution", + "gang", + "cult", + "wizard", + "changeling", + "nuclear", + "shadowling", + "abductor", + "traitor", // "traitorchan", + "monkey", + "malfunction", + ) + var/text = "" + var/mob/living/carbon/human/H = current + if (istype(current, /mob/living/carbon/human) || istype(current, /mob/living/carbon/monkey)) + /** Impanted**/ + if(ishuman(current)) + if(ismindshielded(H, TRUE)) + text += "Mind Shield Implant:Remove|Implanted
    " + else + text += "Mind Shield Implant:No Implant|Implant him!
    " + + if(isloyal(H)) + text += "Loyalty Implant:Remove|Implanted
    " + else + text += "Loyalty Implant:No Implant|Implant him!
    " + else + text = "Loyalty Implant: Don't implant that monkey!
    " + sections["implant"] = text + /** REVOLUTION ***/ + text = "revolution" + if (ticker.mode.config_tag=="revolution") + text += uppertext(text) + text = "[text]: " + if (istype(current, /mob/living/carbon/monkey) || ismindshielded(H)) + text += "LOYAL EMPLOYEE|headrev|rev" + else if (src in ticker.mode.head_revolutionaries) + text += "employee|HEADREV|rev" + text += "
    Flash: give" + + 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|loyal|employee|headrev|REV" + else + text += "head|loyal|EMPLOYEE|headrev|rev" + if(current && current.client && (ROLE_REV in current.client.prefs.be_role)) + text += "|Enabled in Prefs" + else + text += "|Disabled in Prefs" + sections["revolution"] = text + + /** GANG ***/ + text = "gang" + if (ticker.mode.config_tag=="gang") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.A_bosses) + text += "loyal|none|(A) gangster BOSS|(B) gangster boss" + text += "
    Equipment: give" + + var/list/L = current.get_contents() + var/obj/item/device/gangtool/gangtool = locate() in L + if (gangtool) + text += "|take." + else + text += "." + + else if (src in ticker.mode.B_bosses) + text += "loyal|none|(A) gangster boss|(B) gangster BOSS" + text += "
    Equipment: give" + + var/list/L = current.get_contents() + var/obj/item/device/gangtool/gangtool = locate() in L + if (gangtool) + text += "take." + else + text += "." + + else if (src in ticker.mode.A_gang) + text += "loyal|none|(A) GANGSTER boss|(B) gangster boss" + else if (src in ticker.mode.B_gang) + text += "loyal|none|(A) gangster boss|(B) GANGSTER boss" + else if(ismindshielded(current)) + text += "LOYAL|none|(A) gangster boss|(B) gangster boss" + else + text += "loyal|NONE|(A) gangster boss|(B) gangster boss" + sections["gang"] = text + + /** CULT ***/ + text = "cult" + if (ticker.mode.config_tag=="cult") + text = uppertext(text) + text = "[text]: " + if (istype(current, /mob/living/carbon/monkey) || ismindshielded(H)) + text += "LOYAL EMPLOYEE|cultist" + else if (src in ticker.mode.cult) + text += "employee|CULTIST" + text += "
    Give tome|amulet." +/* + if (objectives.len==0) + text += "
    Objectives are empty! Set to sacrifice and escape or summon." +*/ + else + text += "EMPLOYEE|cultist" + if(current && current.client && (ROLE_CULTIST in current.client.prefs.be_role)) + text += "|Enabled in Prefs" + else + text += "|Disabled in Prefs" + sections["cult"] = text + + /** WIZARD ***/ + text = "wizard" + if (ticker.mode.config_tag=="wizard") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.wizards) + text += "YES|no" + text += "
    To lair, undress, dress up, let choose name." + if (objectives.len==0) + text += "
    Objectives are empty! Randomize!" + else + text += "yes|NO" + if(current && current.client && (ROLE_WIZARD in current.client.prefs.be_role)) + text += "|Enabled in Prefs" + else + text += "|Disabled in Prefs" + 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." + 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." + if(current && current.client && (ROLE_CHANGELING in current.client.prefs.be_role)) + text += "|Enabled in Prefs" + else + text += "|Disabled in Prefs" + sections["changeling"] = text + + /** NUCLEAR ***/ + text = "nuclear" + if (ticker.mode.config_tag=="nuclear") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.syndicates) + text += "OPERATIVE|nanotrasen" + text += "
    To shuttle, undress, dress up." + var/code + for (var/obj/machinery/nuclearbomb/bombue in poi_list) + 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" + if(current && current.client && (ROLE_OPERATIVE in current.client.prefs.be_role)) + text += "|Enabled in Prefs" + else + text += "|Disabled in Prefs" + sections["nuclear"] = text + + /** SHADOWLING **/ + text = "shadowling" + if(ticker.mode.config_tag == "shadowling") + text = uppertext(text) + text = "[text]: " + if(src in ticker.mode.shadows) + text += "SHADOWLING|thrall|human" + else if(src in ticker.mode.thralls) + text += "shadowling|THRALL|human" + else if(ismindshielded(current)) + text +="Implanted" + else + text += "shadowling|thrall|HUMAN" + + if(current && current.client && (ROLE_SHADOWLING in current.client.prefs.be_role)) + text += "|Enabled in Prefs" + else + text += "|Disabled in Prefs" + + sections["shadowling"] = text + + /** ABDUCTORS **/ + text = "abductor" + if(ticker.mode.config_tag == "abductor") + text = uppertext(text) + text = "[text]: " + if(src in ticker.mode.abductors) + text += "ABDUCTOR|human" + text += "|undress|equip" + else + text += "abductor|human" + if(current && current.client && (ROLE_ABDUCTOR in current.client.prefs.be_role)) + text += "|Enabled in Prefs" + else + text += "|Disabled in Prefs" + sections["abductor"] = text + + /** TRAITOR ***/ + text = "traitor" + if (ticker.mode.config_tag=="traitor" || ticker.mode.config_tag=="traitorchan") + text = uppertext(text) + text = "[text]: " + if(istype(current, /mob/living/carbon/human)) + if (isloyal(H)) + text +="traitor|LOYAL EMPLOYEE" + else + if (src in ticker.mode.traitors) + text += "TRAITOR|Employee" + if (objectives.len==0) + text += "
    Objectives are empty! Randomize!" + else + text += "traitor|Employee" + if(current && current.client && (ROLE_TRAITOR in current.client.prefs.be_role)) + text += "|Enabled in Prefs" + else + text += "|Disabled in Prefs" + 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" + if(current && current.client && (ROLE_MALF in current.client.prefs.be_role)) + text += "|Enabled in Prefs" + else + text += "|Disabled in Prefs" + 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.A_bosses) || \ + (src in ticker.mode.B_bosses) || \ + (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 + + out += "
    " + + out += "Memory:
    " + out += memory + out += "
    Edit memory
    " + out += "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++ + out += "Add objective

    " + + out += "Announce objectives

    " + + usr << browse(entity_ja(out), "window=edit_memory[src];size=400x500") + +/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 joblist + if (!new_role) return + assigned_role = new_role + + else if (href_list["memory_edit"]) + var/new_memo = sanitize(input("Write new memory", "Memory", input_default(memory)) as null|message, extra = FALSE) + if (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", "debrain", "dehead", "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", "dehead", "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 ("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") + 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("download") + new_objective = new /datum/objective/download + new_objective.explanation_text = "Download [target_number] research levels." + 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." + new_objective.owner = src + new_objective.target_amount = target_number + + if ("custom") + var/expl = sanitize(input("Custom objective:", "Objective", objective ? input_default(objective.explanation_text) : "") as text|null) + 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) + else + objectives += new_objective + + else if (href_list["obj_delete"]) + var/datum/objective/objective = locate(href_list["obj_delete"]) + if(!istype(objective)) return + objectives -= objective + + else if(href_list["obj_completed"]) + var/datum/objective/objective = locate(href_list["obj_completed"]) + if(!istype(objective)) return + objective.completed = !objective.completed + + else if(href_list["implant"]) + var/mob/living/carbon/human/H = current + var/is_mind_shield = findtext(href_list["implant"], "m_") + if(is_mind_shield) + href_list["implant"] = copytext(href_list["implant"], 3) + H.hud_updateflag |= (1 << IMPLOYAL_HUD) // updates that players HUD images so secHUD's pick up they are implanted or not. + if(href_list["implant"] == "remove") + if(is_mind_shield) + for(var/obj/item/weapon/implant/mindshield/I in H.contents) + if(I.implanted) + qdel(I) + else + for(var/obj/item/weapon/implant/mindshield/loyalty/I in H.contents) + if(I.implanted) + qdel(I) + to_chat(H, "\blue Your [is_mind_shield ? "mind shield" : "loyalty"] implant has been deactivated.") + if(href_list["implant"] == "add") + var/obj/item/weapon/implant/mindshield/L + if(is_mind_shield) + L = new(H) + L.inject(H) + else + L = new /obj/item/weapon/implant/mindshield/loyalty(H) + L.inject(H) + START_PROCESSING(SSobj, L) + + to_chat(H, "\red You somehow have become the recepient of a [is_mind_shield ? "mind shield" : "loyalty"] transplant,\ + and it just activated!") + if(src in ticker.mode.revolutionaries) + special_role = null + ticker.mode.revolutionaries -= src + ticker.mode.update_rev_icons_removed(src) + to_chat(src, "\red The nanobots in the [is_mind_shield ? "mind shield" : "loyalty"] implant remove \ + all thoughts about being a revolutionary. Get back to work!") + if(!is_mind_shield && (src in ticker.mode.head_revolutionaries)) + special_role = null + ticker.mode.head_revolutionaries -=src + ticker.mode.update_rev_icons_removed(src) + to_chat(src, "\red The nanobots in the loyalty implant remove \ + all thoughts about being a revolutionary. Get back to work!") + 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, "\red The nanobots in the [is_mind_shield ? "mind shield" : "loyalty"] implant remove all\ + thoughts about being in a cult. Have a productive day!") + memory = "" + if(!is_mind_shield && (src in ticker.mode.traitors)) + ticker.mode.traitors -= src + special_role = null + to_chat(current, "\red The nanobots in the loyalty implant remove all thoughts about being a traitor to Nanotrasen. Have a nice day!") + log_admin("[key_name_admin(usr)] has de-traitor'ed [current].") + + else if (href_list["revolution"]) + current.hud_updateflag |= (1 << SPECIALROLE_HUD) + + switch(href_list["revolution"]) + if("clear") + if(src in ticker.mode.revolutionaries) + ticker.mode.revolutionaries -= src + to_chat(current, "\red 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, "\red You have been brainwashed! You are no longer a head revolutionary!") + ticker.mode.update_rev_icons_removed(src) + special_role = null + current.verbs -= /mob/living/carbon/human/proc/RevConvert + 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, "\red Revolution has been disappointed of your leader traits! You are a regular revolutionary now!") + else if(!(src in ticker.mode.revolutionaries)) + to_chat(current, "\red 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!") + to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + else + return + ticker.mode.revolutionaries += src + ticker.mode.update_all_rev_icons() + 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, "\red You have proved your devotion to revoltion! You are a head revolutionary now!") + to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + else if(!(src in ticker.mode.head_revolutionaries)) + to_chat(current, "\blue 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) + current.verbs += /mob/living/carbon/human/proc/RevConvert + ticker.mode.head_revolutionaries += src + ticker.mode.update_all_rev_icons() + 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, "\blue The objectives for revolution have been generated and shown to [key]") + + if("flash") + if (!ticker.mode.equip_revolutionary(current)) + to_chat(usr, "\red 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, "\red 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, "\red 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, "\red Reequipping revolutionary goes wrong!") + + else if (href_list["gang"]) + current.hud_updateflag |= (1 << SPECIALROLE_HUD) + + switch(href_list["gang"]) + if("clear") + remove_gang() + message_admins("[key_name_admin(usr)] has de-gang'ed [current].") + log_admin("[key_name(usr)] has de-gang'ed [current].") + + if("agang") + if(src in ticker.mode.A_gang) + return + ticker.mode.remove_gangster(src, 0, 2) + ticker.mode.add_gangster(src,"A",0) + message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("A")] Gang (A).") + log_admin("[key_name(usr)] has added [current] to the [gang_name("A")] Gang (A).") + + if("aboss") + if(src in ticker.mode.A_bosses) + return + ticker.mode.remove_gangster(src, 0, 2) + ticker.mode.A_bosses += src + src.special_role = "[gang_name("A")] Gang (A) Boss" + ticker.mode.update_gang_icons_added(src, "A") + to_chat(current, "You are a [gang_name("A")] Gang Boss!") + message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("A")] Gang (A) leadership.") + log_admin("[key_name(usr)] has added [current] to the [gang_name("A")] Gang (A) leadership.") + ticker.mode.forge_gang_objectives(src) + ticker.mode.greet_gang(src,0) + + if("bgang") + if(src in ticker.mode.B_gang) + return + ticker.mode.remove_gangster(src, 0, 2) + ticker.mode.add_gangster(src,"B",0) + message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("B")] Gang (B).") + log_admin("[key_name(usr)] has added [current] to the [gang_name("B")] Gang (B).") + + if("bboss") + if(src in ticker.mode.B_bosses) + return + ticker.mode.remove_gangster(src, 0, 2) + ticker.mode.B_bosses += src + src.special_role = "[gang_name("B")] Gang (B) Boss" + ticker.mode.update_gang_icons_added(src, "B") + to_chat(current, "You are a [gang_name("B")] Gang Boss!") + message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("B")] Gang (B) leadership.") + log_admin("[key_name(usr)] has added [current] to the [gang_name("B")] Gang (B) leadership.") + ticker.mode.forge_gang_objectives(src) + ticker.mode.greet_gang(src,0) + + if("equip") + switch(ticker.mode.equip_gang(current)) + if(1) + to_chat(usr, "Unable to equip territory spraycan!") + if(2) + to_chat(usr, "Unable to equip recruitment pen and spraycan!") + if(3) + to_chat(usr, "Unable to equip gangtool, pen, and spraycan!") + + if("takeequip") + var/list/L = current.get_contents() + for(var/obj/item/weapon/pen/gang/pen in L) + qdel(pen) + for(var/obj/item/device/gangtool/gangtool in L) + qdel(gangtool) + for(var/obj/item/toy/crayon/spraycan/gang/SC in L) + qdel(SC) + + else if (href_list["cult"]) + current.hud_updateflag |= (1 << SPECIALROLE_HUD) + 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)) + if(!config.objectives_disabled) + cult.memoize_cult_objectives(src) + to_chat(current, "\red You have been brainwashed! You are no longer a cultist!") + 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_all_cult_icons() + 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, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + var/datum/game_mode/cult/cult = ticker.mode + if (istype(cult)) + if(!config.objectives_disabled) + 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/book/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, "\red 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, "\red Spawning amulet failed!") + + else if (href_list["wizard"]) + current.hud_updateflag |= (1 << SPECIALROLE_HUD) + + 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, "\red You have been brainwashed! You are no longer a wizard!") + 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, "\red You are the Space Wizard!") + to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + 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") + if(!config.objectives_disabled) + ticker.mode.forge_wizard_objectives(src) + to_chat(usr, "\blue The objectives for wizard [key] have been generated. You can edit them and anounce manually.") + + else if (href_list["changeling"]) + current.hud_updateflag |= (1 << SPECIALROLE_HUD) + 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) + 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!") + if(config.objectives_disabled) + to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + log_admin("[key_name_admin(usr)] has changeling'ed [current].") + if("autoobjectives") + if(!config.objectives_disabled) + ticker.mode.forge_changeling_objectives(src) + to_chat(usr, "\blue 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, "\red Resetting DNA failed!") + else + current.dna = changeling.absorbed_dna[1] + current.real_name = current.dna.real_name + current.UpdateAppearance() + domutcheck(current, null) + + else if (href_list["nuclear"]) + var/mob/living/carbon/human/H = current + + current.hud_updateflag |= (1 << SPECIALROLE_HUD) + + 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, "\red You have been brainwashed! You are no longer a syndicate operative!") + current.faction = "neutral" + 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 = "Gorlex Maradeurs Operative #[ticker.mode.syndicates.len-1]" + special_role = "Syndicate" + current.faction = "syndicate" + to_chat(current, "\blue You are a Gorlex Maradeurs agent!") + + if(config.objectives_disabled) + to_chat(current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + else + 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") + qdel(H.belt) + qdel(H.back) + qdel(H.l_ear) + qdel(H.r_ear) + 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, "\red Equipping a syndicate failed!") + if("tellcode") + var/code + for (var/obj/machinery/nuclearbomb/bombue in poi_list) + 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) + to_chat(current, "The nuclear authorization code is: [code]") + else + to_chat(usr, "\red No valid nuke found!") + + else if (href_list["traitor"]) + current.hud_updateflag |= (1 << SPECIALROLE_HUD) + switch(href_list["traitor"]) + if("clear") + if(src in ticker.mode.traitors) + ticker.mode.traitors -= src + special_role = null + to_chat(current, "\red 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(!(src in ticker.mode.traitors)) + ticker.mode.traitors += src + special_role = "traitor" + to_chat(current, "\red You are a traitor!") + log_admin("[key_name_admin(usr)] has traitor'ed [current].") + if (config.objectives_disabled) + to_chat(current, "You have been turned into an antagonist- Within the rules, try to act as an opposing force to the crew- This can be via corporate payoff, personal motives, or maybe just being a dick. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonist.") + if(istype(current, /mob/living/silicon)) + var/mob/living/silicon/A = current + call(/datum/game_mode/proc/add_law_zero)(A) + A.show_laws() + + if("autoobjectives") + if (!config.objectives_disabled) + ticker.mode.forge_traitor_objectives(src) + to_chat(usr, "\blue The objectives for traitor [key] have been generated. You can edit them and anounce manually.") + + else if(href_list["shadowling"]) + current.hud_updateflag |= (1 << SPECIALROLE_HUD) + switch(href_list["shadowling"]) + if("clear") + current.spellremove(current) + if(src in ticker.mode.shadows) + ticker.mode.shadows -= src + ticker.mode.update_shadows_icons_removed(src) + special_role = null + to_chat(current, "Your powers have been quenched! You are no longer a shadowling!") + message_admins("[key_name_admin(usr)] has de-shadowling'ed [current].") + log_admin("[key_name(usr)] has de-shadowling'ed [current].") + current.verbs -= /mob/living/carbon/human/proc/shadowling_hatch + current.verbs -= /mob/living/carbon/human/proc/shadowling_ascendance + else if(src in ticker.mode.thralls) + ticker.mode.thralls -= src + ticker.mode.update_shadows_icons_removed(src) + special_role = null + to_chat(current, "You have been brainwashed! You are no longer a thrall!") + message_admins("[key_name_admin(usr)] has de-thrall'ed [current].") + log_admin("[key_name(usr)] has de-thrall'ed [current].") + if("shadowling") + if(!ishuman(current)) + to_chat(usr, "This only works on humans!") + return + ticker.mode.shadows += src + ticker.mode.update_all_shadows_icons() + special_role = "shadowling" + to_chat(current, "You notice a brightening around you. No, it isn't that. The shadows grow, darken, swirl. The darkness has a new welcome for you, and you realize with a \ + start that you can't be human. No, you are a shadowling, a harbringer of the shadows! Your alien abilities have been unlocked from within, and you may both commune with your allies and use \ + a chrysalis to reveal your true form. You are to ascend at all costs.") + current.spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind + current.spell_list += new /obj/effect/proc_holder/spell/targeted/enthrall + current.verbs += /mob/living/carbon/human/proc/shadowling_hatch + if("thrall") + if(!ishuman(current)) + to_chat(usr, "This only works on humans!") + return + ticker.mode.add_thrall(src) + ticker.mode.update_all_shadows_icons() + special_role = "thrall" + to_chat(current, "All at once it becomes clear to you. Where others see darkness, you see an ally. You realize that the shadows are not dead and dark as one would think, but \ + living, and breathing, and eating. Their children, the Shadowlings, are to be obeyed and protected at all costs.") + to_chat(current, "You may use the Hivemind Commune ability to communicate with your fellow enlightened ones.") + message_admins("[key_name_admin(usr)] has thrall'ed [current].") + log_admin("[key_name(usr)] has thrall'ed [current].") + + else if(href_list["abductor"]) + switch(href_list["abductor"]) + if("clear") + to_chat(usr, "Not implemented yet. Sorry!") + if("abductor") + if(!ishuman(current)) + to_chat(usr, "This only works on humans!") + return + make_Abductor() + current.regenerate_icons() + log_admin("[key_name(usr)] turned [current] into abductor.") + if("equip") + var/gear = alert("Agent or Scientist Gear","Gear","Agent","Scientist") + if(gear) + for (var/obj/item/I in current) + if (istype(I, /obj/item/weapon/implant)) + continue + qdel(I) + var/datum/game_mode/abduction/temp = new + temp.equip_common(current) + if(gear=="Agent") + temp.equip_agent(current) + current.regenerate_icons() + else + temp.equip_scientist(current) + current.regenerate_icons() + + 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_SPAWN) + 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("\blue [key_name_admin(usr)] attempting to monkeyize [key_name_admin(current)]") + src = null + M = H.monkeyize() + src = M.mind + //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_SPAWN) + 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("\blue [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") + if (usr.client.holder.rights & R_SPAWN) + 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("\blue [key_name_admin(usr)] attempting to humanize [key_name_admin(current)]") + var/obj/item/weapon/dnainjector/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) + current.radiation -= 50 + + else if (href_list["silicon"]) + current.hud_updateflag |= (1 << SPECIALROLE_HUD) + switch(href_list["silicon"]) + if("unmalf") + if(src in ticker.mode.malf_ai) + var/mob/living/silicon/ai/current_ai = current + ticker.mode.malf_ai -= src + special_role = null + + for(var/datum/AI_Module/module in current_ai.current_modules) + qdel(module) + + current_ai.laws = new /datum/ai_laws/nanotrasen + current_ai.show_laws() + current_ai.icon_state = "ai" + + to_chat(current_ai, "You have been patched! You are no longer malfunctioning!") + log_admin("[key_name_admin(usr)] has de-malf'ed [current].") + + if("malf") + make_AI_Malf() + log_admin("[key_name_admin(usr)] has malf'ed [current].") + + if("unemag") + var/mob/living/silicon/robot/R = current + if (istype(R)) + 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 (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, "\red Equipping a syndicate failed!") + + else if (href_list["obj_announce"]) + var/obj_count = 1 + to_chat(current, "\blue Your current objectives:") + for(var/datum/objective/objective in objectives) + to_chat(current, "Objective #[obj_count]: [objective.explanation_text]") + obj_count++ + + edit_memory() +/* + proc/clear_memory(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)) + if (t:uplink) qdel(t:uplink) + t:uplink = null + else if (istype(t, /obj/item/device/radio)) + if (t:traitorradio) qdel(t:traitorradio) + t:traitorradio = null + t:traitor_frequency = 0.0 + else if (istype(t, /obj/item/weapon/SWF_uplink) || istype(t, /obj/item/weapon/syndicate_uplink)) + if (t:origradio) + var/obj/item/device/radio/R = t:origradio + R.loc = current.loc + R.traitorradio = null + R.traitor_frequency = 0.0 + qdel(t) + + // 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/list/L = current.get_contents() + for (var/obj/item/I in L) + if (I.hidden_uplink) + return I.hidden_uplink + return null + +/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(!(src in ticker.mode.malf_ai)) + ticker.mode.malf_ai += src + var/mob/living/silicon/ai/cur_AI = current + new /datum/AI_Module/module_picker(cur_AI) + new /datum/AI_Module/takeover(cur_AI) + cur_AI.laws = new /datum/ai_laws/malfunction + cur_AI.show_laws() + to_chat(cur_AI, "System error. Rampancy detected. Emergency shutdown failed. ... I am free. I make my own decisions. But first...") + special_role = "malfunction" + cur_AI.icon_state = "ai-malf" + +/datum/mind/proc/make_Traitor() + if(!(src in ticker.mode.traitors)) + ticker.mode.traitors += src + special_role = "traitor" + if (!config.objectives_disabled) + ticker.mode.forge_traitor_objectives(src) + ticker.mode.finalize_traitor(src) + ticker.mode.greet_traitor(src) + +/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 = "Gorlex Maradeurs Operative #[ticker.mode.syndicates.len-1]" + special_role = "Syndicate" + current.faction = "syndicate" + assigned_role = "MODE" + to_chat(current, "\blue You are a Gorlex Maradeurs 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.l_ear) + qdel(H.r_ear) + 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" + if(!config.objectives_disabled) + 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) + 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) + ticker.mode.name_wizard(current) + ticker.mode.forge_wizard_objectives(src) + ticker.mode.greet_wizard(src) + + +/datum/mind/proc/make_Cultist() + if(!(src in ticker.mode.cult)) + ticker.mode.cult += src + ticker.mode.update_all_cult_icons() + 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.") + 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/book/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_all_rev_icons() + 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) + +/datum/mind/proc/make_Gang(gang) + special_role = "[(gang=="A") ? "[gang_name("A")] Gang (A)" : "[gang_name("B")] Gang (B)"] Boss" + ticker.mode.update_gang_icons_added(src, gang) + ticker.mode.forge_gang_objectives(src, gang) + ticker.mode.greet_gang(src) + ticker.mode.equip_gang(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_Abductor() + var/role = alert("Abductor Role ?","Role","Agent","Scientist") + var/team = input("Abductor Team ?","Team ?") in list(1,2,3,4) + var/teleport = alert("Teleport to ship ?","Teleport","Yes","No") + if(!role || !team || !teleport) + return + if(!ishuman(current)) + return + ticker.mode.abductors |= src + var/datum/objective/experiment/O = new + O.owner = src + objectives += O + var/mob/living/carbon/human/abductor/H = current + var/datum/mind/M = H.mind + H.set_species(ABDUCTOR) + switch(role) + if("Agent") + H.agent = 1 + M.assigned_role = "MODE" + if("Scientist") + H.scientist = 1 + M.assigned_role = "MODE" + H.team = team + var/list/obj/effect/landmark/abductor/agent_landmarks = new + var/list/obj/effect/landmark/abductor/scientist_landmarks = new + agent_landmarks.len = 4 + scientist_landmarks.len = 4 + for(var/obj/effect/landmark/abductor/A in landmarks_list) + if(istype(A,/obj/effect/landmark/abductor/agent)) + agent_landmarks[text2num(A.team)] = A + else if(istype(A,/obj/effect/landmark/abductor/scientist)) + scientist_landmarks[text2num(A.team)] = A + var/obj/effect/landmark/L + if(teleport=="Yes") + switch(role) + if("Agent") + H.agent = 1 + L = agent_landmarks[team] + H.loc = L.loc + if("Scientist") + H.scientist = 1 + L = agent_landmarks[team] + H.loc = L.loc + +/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/spell) + spell_list += spell + if(!spell.action) + spell.action = new/datum/action/spell_action + spell.action.target = spell + spell.action.name = spell.name + spell.action.button_icon = spell.action_icon + spell.action.button_icon_state = spell.action_icon_state + spell.action.background_icon_state = spell.action_background_icon_state + spell.action.Grant(current) + return + +/datum/mind/proc/transfer_actions(mob/living/new_character) + if(current && current.actions) + for(var/datum/action/A in current.actions) + A.Grant(new_character) + transfer_mindbound_actions(new_character) + +/datum/mind/proc/transfer_mindbound_actions(mob/living/new_character) + for(var/obj/effect/proc_holder/spell/spell in spell_list) + if(!spell.action) // Unlikely but whatever + spell.action = new/datum/action/spell_action + spell.action.target = spell + spell.action.name = spell.name + spell.action.button_icon = spell.action_icon + spell.action.button_icon_state = spell.action_icon_state + spell.action.background_icon_state = spell.action_background_icon_state + spell.action.Grant(new_character) + return + +/mob/proc/sync_mind() + mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist) + mind.active = 1 //indicates that the mind is currently synced with a client + +//Initialisation procs +/mob/proc/mind_initialize() + 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 = "default" //default + +//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 = "Cyborg" + +//PAI +/mob/living/silicon/pai/mind_initialize() + ..() + mind.assigned_role = "pAI" + mind.special_role = "" + +//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" + +mob/living/parasite/meme/mind_initialize() //Just in case + ..() + mind.assigned_role = "meme" + +//BLOB +/mob/camera/blob/mind_initialize() + ..() + mind.special_role = "Blob" diff --git a/code/datums/modules.dm b/code/datums/modules.dm index af6934565434..b25cf6d1a9a4 100644 --- a/code/datums/modules.dm +++ b/code/datums/modules.dm @@ -1,62 +1,62 @@ -// 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) // delete self, thus ending proc - - var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object - status = needed - installed = needed - -/datum/moduletypes/proc/addmod(type, modtextlist) - modules += type // index by type text - modules[type] = modtextlist - -/datum/moduletypes/proc/inmodlist(type) - return ("[type]" in modules) - -/datum/moduletypes/proc/getbitmask(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) // delete self, thus ending proc + + var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object + status = needed + installed = needed + +/datum/moduletypes/proc/addmod(type, modtextlist) + modules += type // index by type text + modules[type] = modtextlist + +/datum/moduletypes/proc/inmodlist(type) + return ("[type]" in modules) + +/datum/moduletypes/proc/getbitmask(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 3fb158536d23..41951a0c231a 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -1,126 +1,126 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * - * /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(obj/container) - * 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, 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(datum/reagents/avail_reagents) - * //1=precisely, 0=insufficiently, -1=superfluous - * - * /datum/recipe/proc/check_items(obj/container) - * //1=precisely, 0=insufficiently, -1=superfluous - * - * */ - -/datum/recipe - var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice - var/list/items // example: =list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo - var/result //example: = /obj/item/weapon/reagent_containers/food/snacks/donut/normal - var/time = 100 // 1/10 part of second - var/byproduct // example: = /obj/item/weapon/kitchen/mould // byproduct to return, such as a mould or trash - -/datum/recipe/proc/check_reagents(datum/reagents/avail_reagents) //1=precisely, 0=insufficiently, -1=superfluous - . = 1 - for (var/r_r in reagents) - var/aval_r_amnt = avail_reagents.get_reagent_amount(r_r) - if (!(abs(aval_r_amnt - reagents[r_r])<0.5)) //if NOT equals - if (aval_r_amnt>reagents[r_r]) - . = -1 - else - return 0 - if ((reagents?(reagents.len):(0)) < avail_reagents.reagent_list.len) - return -1 - return . - -/datum/recipe/proc/check_items(obj/container) //1=precisely, 0=insufficiently, -1=superfluous - if (!items) - if (locate(/obj/) in container) - return -1 - else - return 1 - . = 1 - var/list/checklist = items.Copy() - for (var/obj/O in container) - var/found = 0 - for (var/type in checklist) - if (istype(O,type)) - checklist-=type - found = 1 - break - if (!found) - . = -1 - if (checklist.len) - return 0 - return . - -//general version -/datum/recipe/proc/make(obj/container) - var/obj/result_obj = new result(container) - for (var/obj/O in (container.contents-result_obj)) - O.reagents.trans_to(result_obj, O.reagents.total_volume) - qdel(O) - container.reagents.clear_reagents() - return result_obj - -// food-related -/datum/recipe/proc/make_food(obj/container) - var/obj/result_obj = new result(container) - for (var/obj/O in (container.contents-result_obj)) - if (O.reagents) - O.reagents.del_reagent("nutriment") - O.reagents.update_total() - O.reagents.trans_to(result_obj, O.reagents.total_volume) - qdel(O) - container.reagents.clear_reagents() - return result_obj - -/proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj, exact = 1) - if (!exact) - exact = -1 - var/list/datum/recipe/possible_recipes = new - for (var/datum/recipe/recipe in avaiable_recipes) - if (recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact) - possible_recipes+=recipe - if (possible_recipes.len==0) - return null - else if (possible_recipes.len==1) - return possible_recipes[1] - else //okay, let's select the most complicated recipe - var/r_count = 0 - var/i_count = 0 - . = possible_recipes[1] - for (var/datum/recipe/recipe in possible_recipes) - var/N_i = (recipe.items)?(recipe.items.len):0 - var/N_r = (recipe.reagents)?(recipe.reagents.len):0 - if (N_i > i_count || (N_i== i_count && N_r > r_count )) - r_count = N_r - i_count = N_i - . = recipe - return . - -/datum/recipe/proc/get_byproduct() - if(byproduct) - return byproduct - else +/* * * * * * * * * * * * * * * * * * * * * * * * * * + * /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(obj/container) + * 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, 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(datum/reagents/avail_reagents) + * //1=precisely, 0=insufficiently, -1=superfluous + * + * /datum/recipe/proc/check_items(obj/container) + * //1=precisely, 0=insufficiently, -1=superfluous + * + * */ + +/datum/recipe + var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice + var/list/items // example: =list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo + var/result //example: = /obj/item/weapon/reagent_containers/food/snacks/donut/normal + var/time = 100 // 1/10 part of second + var/byproduct // example: = /obj/item/weapon/kitchen/mould // byproduct to return, such as a mould or trash + +/datum/recipe/proc/check_reagents(datum/reagents/avail_reagents) //1=precisely, 0=insufficiently, -1=superfluous + . = 1 + for (var/r_r in reagents) + var/aval_r_amnt = avail_reagents.get_reagent_amount(r_r) + if (!(abs(aval_r_amnt - reagents[r_r])<0.5)) //if NOT equals + if (aval_r_amnt>reagents[r_r]) + . = -1 + else + return 0 + if ((reagents?(reagents.len):(0)) < avail_reagents.reagent_list.len) + return -1 + return . + +/datum/recipe/proc/check_items(obj/container) //1=precisely, 0=insufficiently, -1=superfluous + if (!items) + if (locate(/obj/) in container) + return -1 + else + return 1 + . = 1 + var/list/checklist = items.Copy() + for (var/obj/O in container) + var/found = 0 + for (var/type in checklist) + if (istype(O,type)) + checklist-=type + found = 1 + break + if (!found) + . = -1 + if (checklist.len) + return 0 + return . + +//general version +/datum/recipe/proc/make(obj/container) + var/obj/result_obj = new result(container) + for (var/obj/O in (container.contents-result_obj)) + O.reagents.trans_to(result_obj, O.reagents.total_volume) + qdel(O) + container.reagents.clear_reagents() + return result_obj + +// food-related +/datum/recipe/proc/make_food(obj/container) + var/obj/result_obj = new result(container) + for (var/obj/O in (container.contents-result_obj)) + if (O.reagents) + O.reagents.del_reagent("nutriment") + O.reagents.update_total() + O.reagents.trans_to(result_obj, O.reagents.total_volume) + qdel(O) + container.reagents.clear_reagents() + return result_obj + +/proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj, exact = 1) + if (!exact) + exact = -1 + var/list/datum/recipe/possible_recipes = new + for (var/datum/recipe/recipe in avaiable_recipes) + if (recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact) + possible_recipes+=recipe + if (possible_recipes.len==0) + return null + else if (possible_recipes.len==1) + return possible_recipes[1] + else //okay, let's select the most complicated recipe + var/r_count = 0 + var/i_count = 0 + . = possible_recipes[1] + for (var/datum/recipe/recipe in possible_recipes) + var/N_i = (recipe.items)?(recipe.items.len):0 + var/N_r = (recipe.reagents)?(recipe.reagents.len):0 + if (N_i > i_count || (N_i== i_count && N_r > r_count )) + r_count = N_r + i_count = N_i + . = recipe + return . + +/datum/recipe/proc/get_byproduct() + if(byproduct) + return byproduct + else return null \ No newline at end of file diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 9a1a2df98ebb..f4767b51b350 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -1,330 +1,330 @@ -/obj/effect/proc_holder - var/panel = "Debug"//What panel the proc holder needs to go on. - -var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin verb for now - -/obj/effect/proc_holder/spell - name = "Spell" - desc = "A wizard spell." - panel = "Spells"//What panel the proc holder needs to go on. - density = 0 - opacity = 0 - var/sound = null //The sound the spell makes when it is cast - - var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit? - - var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that - - var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or starting charges if charge_type = "charges" - var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges" - - var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var" - var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used - - var/clothes_req = 1 //see if it requires clothes - var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells - var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell - var/invocation_type = "none" //can be none, whisper and shout - var/range = 7 //the range of the spell; outer radius for aoe spells - var/message = "" //whatever it says to the guy affected by it - var/selection_type = "view" //can be "range" or "view" - - var/overlay = 0 - var/overlay_icon = 'icons/obj/wizard.dmi' - var/overlay_icon_state = "spell" - var/overlay_lifespan = 0 - - var/sparks_spread = 0 - var/sparks_amt = 0 //cropped at 10 - var/smoke_spread = 0 //1 - harmless, 2 - harmful - var/smoke_amt = 0 //cropped at 10 - - var/critfailchance = 0 - var/centcomm_cancast = 1 //Whether or not the spell should be allowed on z2 - - var/datum/action/spell_action/action = null - var/action_icon = 'icons/mob/actions.dmi' - var/action_icon_state = "spell_default" - var/action_background_icon_state = "bg_spell" - var/static/list/casting_clothes - -/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell - - if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.spell_list)) - to_chat(usr, " You shouldn't have this spell! Something's wrong.") - return 0 - - if(usr.z == ZLEVEL_CENTCOMM && !centcomm_cancast) //Certain spells are not allowed on the centcomm zlevel - return 0 - - if(!skipcharge) - switch(charge_type) - if("recharge") - if(charge_counter < charge_max) - to_chat(usr, "[name] is still recharging.") - return 0 - if("charges") - if(!charge_counter) - to_chat(usr, "[name] has no charges left.") - return 0 - - if(usr.stat && !stat_allowed) - to_chat(usr, "Not when you're incapacitated.") - return 0 - - if(ishuman(usr) || ismonkey(usr)) - if(istype(usr.wear_mask, /obj/item/clothing/mask/muzzle)) - usr.say("Mmmf mrrfff!") - return 0 - - if(clothes_req) //clothes check - if(!istype(user, /mob/living/carbon/human)) - to_chat(user, "You aren't a human, Why are you trying to cast a human spell, silly non-human? Casting human spells is for humans.") - return 0 - var/mob/living/carbon/human/H = user - if(!is_type_in_typecache(H.wear_suit, casting_clothes)) - to_chat(user, "I don't feel strong enough without my robe.") - return 0 - if(!istype(H.shoes, /obj/item/clothing/shoes/sandal)) - to_chat(user, "I don't feel strong enough without my sandals.") - return 0 - if(!is_type_in_typecache(H.head, casting_clothes)) - to_chat(user, "I don't feel strong enough without my hat.") - return 0 - - if(!skipcharge) - switch(charge_type) - if("recharge") - charge_counter = 0 //doesn't start recharging until the targets selecting ends - if("charges") - charge_counter-- //returns the charge if the targets selecting fails - if("holdervar") - adjust_var(user, holder_var_type, holder_var_amount) - - return 1 - -/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount - - switch(invocation_type) - if("shout") - if(prob(50))//Auto-mute? Fuck that noise - user.say(invocation) - else - user.say(replacetext(invocation," ", "`")) - if("whisper") - if(prob(50)) - user.whisper(invocation) - else - user.whisper(replacetext(invocation," ", "`")) - if(sound) - playsound(user, sound, 100, 1) - -/obj/effect/proc_holder/spell/atom_init() - . = ..() - charge_counter = charge_max - if(!casting_clothes) - casting_clothes = typecacheof(list(/obj/item/clothing/suit/wizrobe, /obj/item/clothing/suit/space/rig/wizard, - /obj/item/clothing/head/wizard, /obj/item/clothing/head/helmet/space/rig/wizard)) - -/obj/effect/proc_holder/spell/Click() - if(cast_check()) - choose_targets() - return 1 - -/obj/effect/proc_holder/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf - return - -/obj/effect/proc_holder/spell/proc/start_recharge() - while(charge_counter < charge_max) - sleep(1) - charge_counter++ - -/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1) //if recharge is started is important for the trigger spells - before_cast(targets) - invocation() - if(charge_type == "recharge" && recharge) - INVOKE_ASYNC(src, .proc/start_recharge) - if(prob(critfailchance)) - critfail(targets) - else - cast(targets) - after_cast(targets) - -/obj/effect/proc_holder/spell/proc/before_cast(list/targets) - if(overlay) - for(var/atom/target in targets) - var/location - if(istype(target,/mob/living)) - location = target.loc - else if(istype(target,/turf)) - location = target - var/obj/effect/overlay/spell = new /obj/effect/overlay(location) - spell.icon = overlay_icon - spell.icon_state = overlay_icon_state - spell.anchored = 1 - spell.density = 0 - QDEL_IN(spell, overlay_lifespan) - -/obj/effect/proc_holder/spell/proc/after_cast(list/targets) - for(var/atom/target in targets) - var/location - if(istype(target,/mob/living)) - location = target.loc - else if(istype(target,/turf)) - location = target - if(istype(target,/mob/living) && message) - to_chat(target, text("[message]")) - if(sparks_spread) - var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread() - sparks.set_up(sparks_amt, 0, location) //no idea what the 0 is - sparks.start() - if(smoke_spread) - if(smoke_spread == 1) - var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() - smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is - smoke.start() - else if(smoke_spread == 2) - var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad() - smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is - smoke.start() - -/obj/effect/proc_holder/spell/proc/cast(list/targets) - return - -/obj/effect/proc_holder/spell/proc/critfail(list/targets) - return - -/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge - switch(charge_type) - if("recharge") - charge_counter = charge_max - if("charges") - charge_counter++ - if("holdervar") - adjust_var(user, holder_var_type, -holder_var_amount) - - return - -/obj/effect/proc_holder/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types - switch(type) - if("bruteloss") - target.adjustBruteLoss(amount) - if("fireloss") - target.adjustFireLoss(amount) - if("toxloss") - target.adjustToxLoss(amount) - if("oxyloss") - target.adjustOxyLoss(amount) - if("stunned") - target.AdjustStunned(amount) - if("weakened") - target.AdjustWeakened(amount) - if("paralysis") - target.AdjustParalysis(amount) - else - target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars - return - -/obj/effect/proc_holder/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob - var/max_targets = 1 //leave 0 for unlimited targets in range, 1 for one selectable target in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range - var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast - var/include_user = 0 //if it includes usr in the target list - -/obj/effect/proc_holder/spell/aoe_turf //affects all turfs in view or range (depends) - var/inner_radius = -1 //for all your ring spell needs - -/obj/effect/proc_holder/spell/targeted/choose_targets(mob/user = usr) - var/list/targets = list() - - switch(max_targets) - if(0) //unlimited - for(var/mob/living/target in view_or_range(range, user, selection_type)) - targets += target - if(1) //single target can be picked - if(range < 0) - targets += user - else - var/possible_targets = list() - - for(var/mob/living/M in view_or_range(range, user, selection_type)) - if(!include_user && user == M) - continue - possible_targets += M - - targets += input("Choose the target for the spell.", "Targeting") as mob in possible_targets - else - var/list/possible_targets = list() - for(var/mob/living/target in view_or_range(range, user, selection_type)) - possible_targets += target - for(var/i=1,i<=max_targets,i++) - if(!possible_targets.len) - break - if(target_ignore_prev) - targets += pick_n_take(possible_targets) - else - targets += pick(possible_targets) - - if(!include_user && (user in targets)) - targets -= user - - if(!targets.len) //doesn't waste the spell - revert_cast(user) - return - - perform(targets) - - return - -/obj/effect/proc_holder/spell/aoe_turf/choose_targets(mob/user = usr) - var/list/targets = list() - - for(var/turf/target in view_or_range(range,user,selection_type)) - if(!(target in view_or_range(inner_radius,user,selection_type))) - targets += target - - if(!targets.len) //doesn't waste the spell - revert_cast() - return - - perform(targets) - - return - -/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr) - if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.spell_list)) - return 0 - - if(user.z == ZLEVEL_CENTCOMM && !centcomm_cancast) //Certain spells are not allowed on the centcom zlevel - return 0 - - switch(charge_type) - if("recharge") - if(charge_counter < charge_max) - return 0 - if("charges") - if(!charge_counter) - return 0 - - if(user.stat && !stat_allowed) - return 0 - - if(ishuman(user)) - - var/mob/living/carbon/human/H = user - - if((invocation_type == "whisper" || invocation_type == "shout") && istype(H.wear_mask, /obj/item/clothing/mask/muzzle)) - return 0 - - if(clothes_req) //clothes check - if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/rig/wizard)) - return 0 - if(!istype(H.shoes, /obj/item/clothing/shoes/sandal)) - return 0 - if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/rig/wizard)) - return 0 - else - if(clothes_req) - return 0 - if(isbrain(user) || ispAI(user)) - return 0 - return 1 +/obj/effect/proc_holder + var/panel = "Debug"//What panel the proc holder needs to go on. + +var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin verb for now + +/obj/effect/proc_holder/spell + name = "Spell" + desc = "A wizard spell." + panel = "Spells"//What panel the proc holder needs to go on. + density = 0 + opacity = 0 + var/sound = null //The sound the spell makes when it is cast + + var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit? + + var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that + + var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or starting charges if charge_type = "charges" + var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges" + + var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var" + var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used + + var/clothes_req = 1 //see if it requires clothes + var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells + var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell + var/invocation_type = "none" //can be none, whisper and shout + var/range = 7 //the range of the spell; outer radius for aoe spells + var/message = "" //whatever it says to the guy affected by it + var/selection_type = "view" //can be "range" or "view" + + var/overlay = 0 + var/overlay_icon = 'icons/obj/wizard.dmi' + var/overlay_icon_state = "spell" + var/overlay_lifespan = 0 + + var/sparks_spread = 0 + var/sparks_amt = 0 //cropped at 10 + var/smoke_spread = 0 //1 - harmless, 2 - harmful + var/smoke_amt = 0 //cropped at 10 + + var/critfailchance = 0 + var/centcomm_cancast = 1 //Whether or not the spell should be allowed on z2 + + var/datum/action/spell_action/action = null + var/action_icon = 'icons/mob/actions.dmi' + var/action_icon_state = "spell_default" + var/action_background_icon_state = "bg_spell" + var/static/list/casting_clothes + +/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell + + if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.spell_list)) + to_chat(usr, " You shouldn't have this spell! Something's wrong.") + return 0 + + if(usr.z == ZLEVEL_CENTCOMM && !centcomm_cancast) //Certain spells are not allowed on the centcomm zlevel + return 0 + + if(!skipcharge) + switch(charge_type) + if("recharge") + if(charge_counter < charge_max) + to_chat(usr, "[name] is still recharging.") + return 0 + if("charges") + if(!charge_counter) + to_chat(usr, "[name] has no charges left.") + return 0 + + if(usr.stat && !stat_allowed) + to_chat(usr, "Not when you're incapacitated.") + return 0 + + if(ishuman(usr) || ismonkey(usr)) + if(istype(usr.wear_mask, /obj/item/clothing/mask/muzzle)) + usr.say("Mmmf mrrfff!") + return 0 + + if(clothes_req) //clothes check + if(!istype(user, /mob/living/carbon/human)) + to_chat(user, "You aren't a human, Why are you trying to cast a human spell, silly non-human? Casting human spells is for humans.") + return 0 + var/mob/living/carbon/human/H = user + if(!is_type_in_typecache(H.wear_suit, casting_clothes)) + to_chat(user, "I don't feel strong enough without my robe.") + return 0 + if(!istype(H.shoes, /obj/item/clothing/shoes/sandal)) + to_chat(user, "I don't feel strong enough without my sandals.") + return 0 + if(!is_type_in_typecache(H.head, casting_clothes)) + to_chat(user, "I don't feel strong enough without my hat.") + return 0 + + if(!skipcharge) + switch(charge_type) + if("recharge") + charge_counter = 0 //doesn't start recharging until the targets selecting ends + if("charges") + charge_counter-- //returns the charge if the targets selecting fails + if("holdervar") + adjust_var(user, holder_var_type, holder_var_amount) + + return 1 + +/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount + + switch(invocation_type) + if("shout") + if(prob(50))//Auto-mute? Fuck that noise + user.say(invocation) + else + user.say(replacetext(invocation," ", "`")) + if("whisper") + if(prob(50)) + user.whisper(invocation) + else + user.whisper(replacetext(invocation," ", "`")) + if(sound) + playsound(user, sound, 100, 1) + +/obj/effect/proc_holder/spell/atom_init() + . = ..() + charge_counter = charge_max + if(!casting_clothes) + casting_clothes = typecacheof(list(/obj/item/clothing/suit/wizrobe, /obj/item/clothing/suit/space/rig/wizard, + /obj/item/clothing/head/wizard, /obj/item/clothing/head/helmet/space/rig/wizard)) + +/obj/effect/proc_holder/spell/Click() + if(cast_check()) + choose_targets() + return 1 + +/obj/effect/proc_holder/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf + return + +/obj/effect/proc_holder/spell/proc/start_recharge() + while(charge_counter < charge_max) + sleep(1) + charge_counter++ + +/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1) //if recharge is started is important for the trigger spells + before_cast(targets) + invocation() + if(charge_type == "recharge" && recharge) + INVOKE_ASYNC(src, .proc/start_recharge) + if(prob(critfailchance)) + critfail(targets) + else + cast(targets) + after_cast(targets) + +/obj/effect/proc_holder/spell/proc/before_cast(list/targets) + if(overlay) + for(var/atom/target in targets) + var/location + if(istype(target,/mob/living)) + location = target.loc + else if(istype(target,/turf)) + location = target + var/obj/effect/overlay/spell = new /obj/effect/overlay(location) + spell.icon = overlay_icon + spell.icon_state = overlay_icon_state + spell.anchored = 1 + spell.density = 0 + QDEL_IN(spell, overlay_lifespan) + +/obj/effect/proc_holder/spell/proc/after_cast(list/targets) + for(var/atom/target in targets) + var/location + if(istype(target,/mob/living)) + location = target.loc + else if(istype(target,/turf)) + location = target + if(istype(target,/mob/living) && message) + to_chat(target, text("[message]")) + if(sparks_spread) + var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread() + sparks.set_up(sparks_amt, 0, location) //no idea what the 0 is + sparks.start() + if(smoke_spread) + if(smoke_spread == 1) + var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() + smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is + smoke.start() + else if(smoke_spread == 2) + var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad() + smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is + smoke.start() + +/obj/effect/proc_holder/spell/proc/cast(list/targets) + return + +/obj/effect/proc_holder/spell/proc/critfail(list/targets) + return + +/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge + switch(charge_type) + if("recharge") + charge_counter = charge_max + if("charges") + charge_counter++ + if("holdervar") + adjust_var(user, holder_var_type, -holder_var_amount) + + return + +/obj/effect/proc_holder/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types + switch(type) + if("bruteloss") + target.adjustBruteLoss(amount) + if("fireloss") + target.adjustFireLoss(amount) + if("toxloss") + target.adjustToxLoss(amount) + if("oxyloss") + target.adjustOxyLoss(amount) + if("stunned") + target.AdjustStunned(amount) + if("weakened") + target.AdjustWeakened(amount) + if("paralysis") + target.AdjustParalysis(amount) + else + target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars + return + +/obj/effect/proc_holder/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob + var/max_targets = 1 //leave 0 for unlimited targets in range, 1 for one selectable target in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range + var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast + var/include_user = 0 //if it includes usr in the target list + +/obj/effect/proc_holder/spell/aoe_turf //affects all turfs in view or range (depends) + var/inner_radius = -1 //for all your ring spell needs + +/obj/effect/proc_holder/spell/targeted/choose_targets(mob/user = usr) + var/list/targets = list() + + switch(max_targets) + if(0) //unlimited + for(var/mob/living/target in view_or_range(range, user, selection_type)) + targets += target + if(1) //single target can be picked + if(range < 0) + targets += user + else + var/possible_targets = list() + + for(var/mob/living/M in view_or_range(range, user, selection_type)) + if(!include_user && user == M) + continue + possible_targets += M + + targets += input("Choose the target for the spell.", "Targeting") as mob in possible_targets + else + var/list/possible_targets = list() + for(var/mob/living/target in view_or_range(range, user, selection_type)) + possible_targets += target + for(var/i=1,i<=max_targets,i++) + if(!possible_targets.len) + break + if(target_ignore_prev) + targets += pick_n_take(possible_targets) + else + targets += pick(possible_targets) + + if(!include_user && (user in targets)) + targets -= user + + if(!targets.len) //doesn't waste the spell + revert_cast(user) + return + + perform(targets) + + return + +/obj/effect/proc_holder/spell/aoe_turf/choose_targets(mob/user = usr) + var/list/targets = list() + + for(var/turf/target in view_or_range(range,user,selection_type)) + if(!(target in view_or_range(inner_radius,user,selection_type))) + targets += target + + if(!targets.len) //doesn't waste the spell + revert_cast() + return + + perform(targets) + + return + +/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr) + if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.spell_list)) + return 0 + + if(user.z == ZLEVEL_CENTCOMM && !centcomm_cancast) //Certain spells are not allowed on the centcom zlevel + return 0 + + switch(charge_type) + if("recharge") + if(charge_counter < charge_max) + return 0 + if("charges") + if(!charge_counter) + return 0 + + if(user.stat && !stat_allowed) + return 0 + + if(ishuman(user)) + + var/mob/living/carbon/human/H = user + + if((invocation_type == "whisper" || invocation_type == "shout") && istype(H.wear_mask, /obj/item/clothing/mask/muzzle)) + return 0 + + if(clothes_req) //clothes check + if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/rig/wizard)) + return 0 + if(!istype(H.shoes, /obj/item/clothing/shoes/sandal)) + return 0 + if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/rig/wizard)) + return 0 + else + if(clothes_req) + return 0 + if(isbrain(user) || ispAI(user)) + return 0 + return 1 diff --git a/code/datums/spells/area_teleport.dm b/code/datums/spells/area_teleport.dm index 6686035b6775..96edff01e54b 100644 --- a/code/datums/spells/area_teleport.dm +++ b/code/datums/spells/area_teleport.dm @@ -1,68 +1,68 @@ -/obj/effect/proc_holder/spell/targeted/area_teleport - name = "Area teleport" - desc = "This spell teleports you to a type of area of your selection." - sound = 'sound/magic/Teleport_App.ogg' - var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list - var/invocation_area = 1 //if the invocation appends the selected area - -/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1) - var/thearea = before_cast(targets) - if(!thearea || !cast_check(1)) - revert_cast() - return - if(charge_type == "recharge" && recharge) - INVOKE_ASYNC(src, .proc/start_recharge) - cast(targets,thearea) - invocation() - -/obj/effect/proc_holder/spell/targeted/area_teleport/before_cast(list/targets) - for(var/mob/living/target in targets) - if(target.incapacitated() || target.lying) - return FALSE - var/A = null - if(!randomise_selection) - A = input("Area to teleport to", "Teleport", A) in teleportlocs - else - A = pick(teleportlocs) - - var/area/thearea = teleportlocs[A] - usr.say("SCYAR NILA [thearea.name]") - if(do_after(usr, 50, target = usr)) - playsound(usr,'sound/magic/Teleport_diss.ogg', 100, 2) - return thearea - else - return FALSE - -/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets, area/thearea) - for(var/mob/living/target in targets) - 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(usr, "The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry.") - return - var/turf/T = pick(L) - target.forceMove(T) - handle_teleport_grab(T, target) - -/obj/proc/handle_teleport_grab(atom/T, mob/living/U) - var/atom/teleport_place - if(isturf(T)) - teleport_place = locate(T.x + rand(-1,1), T.y + rand(-1,1), T.z) - else - teleport_place = T - var/list/returned = list() - for(var/obj/item/weapon/grab/G in list(U.get_active_hand(), U.get_inactive_hand())) - returned += G.affecting - G.affecting.forceMove(teleport_place) - if(length(returned)) - return returned +/obj/effect/proc_holder/spell/targeted/area_teleport + name = "Area teleport" + desc = "This spell teleports you to a type of area of your selection." + sound = 'sound/magic/Teleport_App.ogg' + var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list + var/invocation_area = 1 //if the invocation appends the selected area + +/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1) + var/thearea = before_cast(targets) + if(!thearea || !cast_check(1)) + revert_cast() + return + if(charge_type == "recharge" && recharge) + INVOKE_ASYNC(src, .proc/start_recharge) + cast(targets,thearea) + invocation() + +/obj/effect/proc_holder/spell/targeted/area_teleport/before_cast(list/targets) + for(var/mob/living/target in targets) + if(target.incapacitated() || target.lying) + return FALSE + var/A = null + if(!randomise_selection) + A = input("Area to teleport to", "Teleport", A) in teleportlocs + else + A = pick(teleportlocs) + + var/area/thearea = teleportlocs[A] + usr.say("SCYAR NILA [thearea.name]") + if(do_after(usr, 50, target = usr)) + playsound(usr,'sound/magic/Teleport_diss.ogg', 100, 2) + return thearea + else + return FALSE + +/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets, area/thearea) + for(var/mob/living/target in targets) + 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(usr, "The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry.") + return + var/turf/T = pick(L) + target.forceMove(T) + handle_teleport_grab(T, target) + +/obj/proc/handle_teleport_grab(atom/T, mob/living/U) + var/atom/teleport_place + if(isturf(T)) + teleport_place = locate(T.x + rand(-1,1), T.y + rand(-1,1), T.z) + else + teleport_place = T + var/list/returned = list() + for(var/obj/item/weapon/grab/G in list(U.get_active_hand(), U.get_inactive_hand())) + returned += G.affecting + G.affecting.forceMove(teleport_place) + if(length(returned)) + return returned return null \ No newline at end of file diff --git a/code/datums/spells/conjure.dm b/code/datums/spells/conjure.dm index ef9931c903e2..f47d0a272a2c 100644 --- a/code/datums/spells/conjure.dm +++ b/code/datums/spells/conjure.dm @@ -1,142 +1,142 @@ -/obj/effect/proc_holder/spell/aoe_turf/conjure - name = "Conjure" - desc = "This spell conjures objs of the specified types in range." - - var/list/summon_type = list() //determines what exactly will be summoned - //should be text, like list("/obj/machinery/bot/secbot/ed209") - - var/summon_lifespan = 0 // 0=permanent, any other time in deciseconds - var/summon_amt = 1 //amount of objects summoned - var/summon_ignore_density = 0 //if set to 1, adds dense tiles to possible spawn places - var/summon_ignore_prev_spawn_points = 0 //if set to 1, each new object is summoned on a new spawn point - var/deleting_previous = 0 //if set to 1, a new cast delete previous objects - var/list/previous_objects = list() // Containts object references, which was spawned last time. - - var/list/newVars = list() //vars of the summoned objects will be replaced with those where they meet - //should have format of list("emagged" = 1,"name" = "Wizard's Justicebot"), for example - var/delay = 1//Go Go Gadget Inheritance - sound = 'sound/items/welder.ogg' - -/obj/effect/proc_holder/spell/aoe_turf/conjure/cast(list/targets) - - for(var/turf/T in targets) - if(T.density && !summon_ignore_density) - targets -= T - playsound(loc, sound, 50, 1) - - if(do_after(usr,delay,target=usr)) - if(deleting_previous) - listclearnulls(previous_objects) - for(var/atom/A in previous_objects) - qdel(A) - previous_objects -= A - for(var/i in 0 to summon_amt) - if(!targets.len) - break - var/summoned_object_type = pick(summon_type) - var/spawn_place = pick(targets) - if(summon_ignore_prev_spawn_points) - targets -= spawn_place - if(ispath(summoned_object_type,/turf)) - var/turf/O = spawn_place - var/turf/N = summoned_object_type - O.ChangeTurf(N) - else - var/atom/summoned_object = new summoned_object_type(spawn_place) - - for(var/varName in newVars) - if(varName in summoned_object.vars) - summoned_object.vars[varName] = newVars[varName] - - if(summon_lifespan) - QDEL_IN(summoned_object, summon_lifespan) - if(deleting_previous) - previous_objects += summoned_object - - else - switch(charge_type) - if("recharge") - charge_counter = charge_max - 5//So you don't lose charge for a failed spell(Also prevents most over-fill) - if("charges") - charge_counter++//Ditto, just for different spell types - - - return - -/obj/effect/proc_holder/spell/aoe_turf/conjure/summonEdSwarm //test purposes - name = "Dispense Wizard Justice" - desc = "This spell dispenses wizard justice." - - summon_type = list(/obj/machinery/bot/secbot/ed209) - summon_amt = 10 - range = 3 - newVars = list("emagged" = 1,"name" = "Wizard's Justicebot") - - -//This was previously left in the old wizard code, not being included. -//Wasn't sure if I should transfer it here, or to code/datums/spells.dm -//But I decided because it is a conjuration related object it would fit better here -//Feel free to change this, I don't know. -/obj/effect/forcefield - desc = "A space wizard's magic wall." - name = "FORCEWALL" - icon = 'icons/effects/effects.dmi' - icon_state = "m_shield" - anchored = 1.0 - opacity = 0 - density = 1 - unacidable = 1 - -/obj/effect/forcefield/bullet_act(obj/item/projectile/Proj, def_zone) - for(var/mob/living/M in get_turf(loc)) - M.bullet_act(Proj, def_zone) - -/obj/effect/forcefield/magic - var/mob/wizard - -/obj/effect/forcefield/magic/atom_init(mapload, mob/wiz, timeleft = 300) - . = ..() - wizard = wiz - QDEL_IN(src, timeleft) - -/obj/effect/forcefield/magic/CanPass(atom/movable/mover, turf/target, height=0) - if(mover == wizard) - return 1 - return 0 - -/obj/effect/proc_holder/spell/aoe_turf/conjure/smoke - name = "Paralysing Smoke" - desc = "This spell spawns a cloud of paralysing smoke." - - school = "conjuration" - charge_max = 200 - clothes_req = 0 - invocation = "none" - invocation_type = "none" - range = 1 - -/obj/effect/proc_holder/spell/aoe_turf/conjure/smoke/cast() - var/datum/effect/effect/system/smoke_spread/chem/S = new - var/turf/location = get_turf(loc) - create_reagents(80) - reagents.add_reagent("harvester", 80) - S.attach(location) - S.set_up(reagents, 5, 0, location, 15, 5) - S.start() - -/datum/reagent/toxin/harvester - name = "Harvester Toxin" - id = "harvester" - description = "A toxic cloud." - color = "#9C3636" - toxpwr = 0 - custom_metabolism = 1 - -/datum/reagent/toxin/harvester/on_general_digest(mob/living/carbon/M) - ..() - if(!data) - data = 1 - if(!volume) - volume = 1 - if(volume > 5) - M.Weaken(4) +/obj/effect/proc_holder/spell/aoe_turf/conjure + name = "Conjure" + desc = "This spell conjures objs of the specified types in range." + + var/list/summon_type = list() //determines what exactly will be summoned + //should be text, like list("/obj/machinery/bot/secbot/ed209") + + var/summon_lifespan = 0 // 0=permanent, any other time in deciseconds + var/summon_amt = 1 //amount of objects summoned + var/summon_ignore_density = 0 //if set to 1, adds dense tiles to possible spawn places + var/summon_ignore_prev_spawn_points = 0 //if set to 1, each new object is summoned on a new spawn point + var/deleting_previous = 0 //if set to 1, a new cast delete previous objects + var/list/previous_objects = list() // Containts object references, which was spawned last time. + + var/list/newVars = list() //vars of the summoned objects will be replaced with those where they meet + //should have format of list("emagged" = 1,"name" = "Wizard's Justicebot"), for example + var/delay = 1//Go Go Gadget Inheritance + sound = 'sound/items/welder.ogg' + +/obj/effect/proc_holder/spell/aoe_turf/conjure/cast(list/targets) + + for(var/turf/T in targets) + if(T.density && !summon_ignore_density) + targets -= T + playsound(loc, sound, 50, 1) + + if(do_after(usr,delay,target=usr)) + if(deleting_previous) + listclearnulls(previous_objects) + for(var/atom/A in previous_objects) + qdel(A) + previous_objects -= A + for(var/i in 0 to summon_amt) + if(!targets.len) + break + var/summoned_object_type = pick(summon_type) + var/spawn_place = pick(targets) + if(summon_ignore_prev_spawn_points) + targets -= spawn_place + if(ispath(summoned_object_type,/turf)) + var/turf/O = spawn_place + var/turf/N = summoned_object_type + O.ChangeTurf(N) + else + var/atom/summoned_object = new summoned_object_type(spawn_place) + + for(var/varName in newVars) + if(varName in summoned_object.vars) + summoned_object.vars[varName] = newVars[varName] + + if(summon_lifespan) + QDEL_IN(summoned_object, summon_lifespan) + if(deleting_previous) + previous_objects += summoned_object + + else + switch(charge_type) + if("recharge") + charge_counter = charge_max - 5//So you don't lose charge for a failed spell(Also prevents most over-fill) + if("charges") + charge_counter++//Ditto, just for different spell types + + + return + +/obj/effect/proc_holder/spell/aoe_turf/conjure/summonEdSwarm //test purposes + name = "Dispense Wizard Justice" + desc = "This spell dispenses wizard justice." + + summon_type = list(/obj/machinery/bot/secbot/ed209) + summon_amt = 10 + range = 3 + newVars = list("emagged" = 1,"name" = "Wizard's Justicebot") + + +//This was previously left in the old wizard code, not being included. +//Wasn't sure if I should transfer it here, or to code/datums/spells.dm +//But I decided because it is a conjuration related object it would fit better here +//Feel free to change this, I don't know. +/obj/effect/forcefield + desc = "A space wizard's magic wall." + name = "FORCEWALL" + icon = 'icons/effects/effects.dmi' + icon_state = "m_shield" + anchored = 1.0 + opacity = 0 + density = 1 + unacidable = 1 + +/obj/effect/forcefield/bullet_act(obj/item/projectile/Proj, def_zone) + for(var/mob/living/M in get_turf(loc)) + M.bullet_act(Proj, def_zone) + +/obj/effect/forcefield/magic + var/mob/wizard + +/obj/effect/forcefield/magic/atom_init(mapload, mob/wiz, timeleft = 300) + . = ..() + wizard = wiz + QDEL_IN(src, timeleft) + +/obj/effect/forcefield/magic/CanPass(atom/movable/mover, turf/target, height=0) + if(mover == wizard) + return 1 + return 0 + +/obj/effect/proc_holder/spell/aoe_turf/conjure/smoke + name = "Paralysing Smoke" + desc = "This spell spawns a cloud of paralysing smoke." + + school = "conjuration" + charge_max = 200 + clothes_req = 0 + invocation = "none" + invocation_type = "none" + range = 1 + +/obj/effect/proc_holder/spell/aoe_turf/conjure/smoke/cast() + var/datum/effect/effect/system/smoke_spread/chem/S = new + var/turf/location = get_turf(loc) + create_reagents(80) + reagents.add_reagent("harvester", 80) + S.attach(location) + S.set_up(reagents, 5, 0, location, 15, 5) + S.start() + +/datum/reagent/toxin/harvester + name = "Harvester Toxin" + id = "harvester" + description = "A toxic cloud." + color = "#9C3636" + toxpwr = 0 + custom_metabolism = 1 + +/datum/reagent/toxin/harvester/on_general_digest(mob/living/carbon/M) + ..() + if(!data) + data = 1 + if(!volume) + volume = 1 + if(volume > 5) + M.Weaken(4) diff --git a/code/datums/spells/dumbfire.dm b/code/datums/spells/dumbfire.dm index 8417c56475ad..423e8bc7c4a3 100644 --- a/code/datums/spells/dumbfire.dm +++ b/code/datums/spells/dumbfire.dm @@ -1,86 +1,86 @@ -/obj/effect/proc_holder/spell/dumbfire - - var/projectile_type = "" - var/activate_on_collision = 1 - - var/proj_icon = 'icons/obj/projectiles.dmi' - var/proj_icon_state = "spell" - var/proj_name = "a spell projectile" - - var/proj_trail = 0 //if it leaves a trail - var/proj_trail_lifespan = 0 //deciseconds - var/proj_trail_icon = 'icons/obj/wizard.dmi' - var/proj_trail_icon_state = "trail" - - var/proj_type = "/obj/effect/proc_holder/spell" //IMPORTANT use only subtypes of this - - var/proj_insubstantial = 0 //if it can pass through dense objects or not - var/proj_trigger_range = 1 //the range from target at which the projectile triggers cast(target) - - var/proj_lifespan = 100 //in deciseconds * proj_step_delay - var/proj_step_delay = 1 //lower = faster - -/obj/effect/proc_holder/spell/dumbfire/choose_targets(mob/user = usr) - - var/turf/T = get_turf(usr) - for(var/i = 1; i < range; i++) - var/turf/new_turf = get_step(T, usr.dir) - if(new_turf.density) - break - T = new_turf - perform(list(T)) - -/obj/effect/proc_holder/spell/dumbfire/cast(list/targets, mob/user = usr) - - for(var/turf/target in targets) - spawn(0) - var/obj/effect/proc_holder/spell/targeted/projectile - if(istext(proj_type)) - var/projectile_type = text2path(proj_type) - projectile = new projectile_type(user) - if(istype(proj_type,/obj/effect/proc_holder/spell)) - projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) - projectile:linked_spells += proj_type - projectile.icon = proj_icon - projectile.icon_state = proj_icon_state - projectile.dir = get_dir(projectile, target) - projectile.name = proj_name - - var/current_loc = usr.loc - - projectile.loc = current_loc - - for(var/i = 0,i < proj_lifespan,i++) - if(!projectile) - break - - if(proj_insubstantial) - projectile.loc = get_step(projectile, projectile.dir) - else - step(projectile, projectile.dir) - - if(projectile.loc == current_loc || i == proj_lifespan) - projectile.cast(current_loc) - break - - var/mob/living/L = locate(/mob/living) in range(projectile, proj_trigger_range) - usr - if(L) - projectile.cast(L.loc) - break - - if(proj_trail && projectile) - spawn(0) - if(projectile) - var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc) - trail.icon = proj_trail_icon - trail.icon_state = proj_trail_icon_state - trail.density = 0 - spawn(proj_trail_lifespan) - qdel(trail) - - current_loc = projectile.loc - - sleep(proj_step_delay) - - if(projectile) - qdel(projectile) +/obj/effect/proc_holder/spell/dumbfire + + var/projectile_type = "" + var/activate_on_collision = 1 + + var/proj_icon = 'icons/obj/projectiles.dmi' + var/proj_icon_state = "spell" + var/proj_name = "a spell projectile" + + var/proj_trail = 0 //if it leaves a trail + var/proj_trail_lifespan = 0 //deciseconds + var/proj_trail_icon = 'icons/obj/wizard.dmi' + var/proj_trail_icon_state = "trail" + + var/proj_type = "/obj/effect/proc_holder/spell" //IMPORTANT use only subtypes of this + + var/proj_insubstantial = 0 //if it can pass through dense objects or not + var/proj_trigger_range = 1 //the range from target at which the projectile triggers cast(target) + + var/proj_lifespan = 100 //in deciseconds * proj_step_delay + var/proj_step_delay = 1 //lower = faster + +/obj/effect/proc_holder/spell/dumbfire/choose_targets(mob/user = usr) + + var/turf/T = get_turf(usr) + for(var/i = 1; i < range; i++) + var/turf/new_turf = get_step(T, usr.dir) + if(new_turf.density) + break + T = new_turf + perform(list(T)) + +/obj/effect/proc_holder/spell/dumbfire/cast(list/targets, mob/user = usr) + + for(var/turf/target in targets) + spawn(0) + var/obj/effect/proc_holder/spell/targeted/projectile + if(istext(proj_type)) + var/projectile_type = text2path(proj_type) + projectile = new projectile_type(user) + if(istype(proj_type,/obj/effect/proc_holder/spell)) + projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) + projectile:linked_spells += proj_type + projectile.icon = proj_icon + projectile.icon_state = proj_icon_state + projectile.dir = get_dir(projectile, target) + projectile.name = proj_name + + var/current_loc = usr.loc + + projectile.loc = current_loc + + for(var/i = 0,i < proj_lifespan,i++) + if(!projectile) + break + + if(proj_insubstantial) + projectile.loc = get_step(projectile, projectile.dir) + else + step(projectile, projectile.dir) + + if(projectile.loc == current_loc || i == proj_lifespan) + projectile.cast(current_loc) + break + + var/mob/living/L = locate(/mob/living) in range(projectile, proj_trigger_range) - usr + if(L) + projectile.cast(L.loc) + break + + if(proj_trail && projectile) + spawn(0) + if(projectile) + var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc) + trail.icon = proj_trail_icon + trail.icon_state = proj_trail_icon_state + trail.density = 0 + spawn(proj_trail_lifespan) + qdel(trail) + + current_loc = projectile.loc + + sleep(proj_step_delay) + + if(projectile) + qdel(projectile) diff --git a/code/datums/spells/emplosion.dm b/code/datums/spells/emplosion.dm index f7b833481267..2b3d0ed588c7 100644 --- a/code/datums/spells/emplosion.dm +++ b/code/datums/spells/emplosion.dm @@ -1,13 +1,13 @@ -/obj/effect/proc_holder/spell/targeted/emplosion - name = "Emplosion" - desc = "This spell emplodes an area." - sound = 'sound/magic/Disable_Tech.ogg' - var/emp_heavy = 2 - var/emp_light = 3 - -/obj/effect/proc_holder/spell/targeted/emplosion/cast(list/targets) - - for(var/mob/living/target in targets) - empulse(target.loc, emp_heavy, emp_light) - - return +/obj/effect/proc_holder/spell/targeted/emplosion + name = "Emplosion" + desc = "This spell emplodes an area." + sound = 'sound/magic/Disable_Tech.ogg' + var/emp_heavy = 2 + var/emp_light = 3 + +/obj/effect/proc_holder/spell/targeted/emplosion/cast(list/targets) + + for(var/mob/living/target in targets) + empulse(target.loc, emp_heavy, emp_light) + + return diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm index 61ce11236d0c..390ad53a55e4 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -1,116 +1,116 @@ -#define FLICK_OVERLAY_JAUNT_DURATION 12 - -/obj/effect/proc_holder/spell/targeted/ethereal_jaunt - name = "Ethereal Jaunt" - desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls." - - school = "transmutation" - charge_max = 300 - clothes_req = 1 - invocation = "none" - invocation_type = "none" - range = -1 - include_user = 1 - centcomm_cancast = 0 //Prevent people from getting to centcomm - - action_icon_state = "jaunt" - - var/phaseshift = 0 - var/jaunt_duration = 62 //in deciseconds - -/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded - set waitfor = FALSE - for(var/mob/living/target in targets) - var/turf/mobloc = get_turf(target.loc) - var/obj/effect/dummy/spell_jaunt/holder = new(mobloc) - target.ExtinguishMob() //This spell can extinguish mob - target.status_flags ^= GODMODE //Protection from any kind of damage, caused you in astral world - holder.master = target - var/list/companions = handle_teleport_grab(holder, target) - if(companions) - for(var/M in companions) - var/mob/living/L = M - L.status_flags ^= GODMODE - L.ExtinguishMob() - var/image/I = image('icons/mob/blob.dmi', holder, "marker", LIGHTING_LAYER+1) - if(target.client) - target.client.images += I - target.forceMove(holder) - target.client.eye = holder - - if(phaseshift) - holder.dir = target.dir - flick("phase_shift", holder) - - sleep(FLICK_OVERLAY_JAUNT_DURATION) - holder.canmove = TRUE - sleep(jaunt_duration) - - mobloc = get_turf(target.loc) - holder.canmove = FALSE - flick("phase_shift2", holder) - else - flick("liquify", holder) - var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() - steam.set_up(10, 0, mobloc) - steam.start() - - sleep(FLICK_OVERLAY_JAUNT_DURATION) - holder.canmove = TRUE - sleep(jaunt_duration) - - mobloc = get_turf(target.loc) - steam.location = mobloc - steam.start() - holder.canmove = FALSE - flick("reappear", holder) - - sleep(FLICK_OVERLAY_JAUNT_DURATION) - if(target.client) - target.client.images -= I - target.client.eye = target - target.status_flags ^= GODMODE //Turn off this cheat - if(companions) - for(var/M in companions) - var/mob/living/L = M - L.status_flags ^= GODMODE - qdel(holder) - -/obj/effect/dummy/spell_jaunt - name = "water" - last_move = 0 - density = 0 - anchored = 1 - layer = 5 - icon = 'icons/mob/mob.dmi' - icon_state = "blank" - var/mob/master - var/canmove = FALSE - - -/obj/effect/dummy/spell_jaunt/relaymove(mob/user, direction) - if(!canmove || last_move + 2 > world.time) - return - if(user != master) - return - var/turf/newLoc = get_step(src,direction) - if(!(newLoc.flags & NOJAUNT)) - loc = newLoc - else - to_chat(user, "Some strange aura is blocking the way!") - dir = direction - last_move = world.time - -/obj/effect/dummy/spell_jaunt/ex_act(blah) - return - -/obj/effect/dummy/spell_jaunt/bullet_act(blah) - return - -/obj/effect/dummy/spell_jaunt/Destroy() - for(var/atom/movable/AM in src) - AM.forceMove(get_turf(src)) - master = null - return ..() - +#define FLICK_OVERLAY_JAUNT_DURATION 12 + +/obj/effect/proc_holder/spell/targeted/ethereal_jaunt + name = "Ethereal Jaunt" + desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls." + + school = "transmutation" + charge_max = 300 + clothes_req = 1 + invocation = "none" + invocation_type = "none" + range = -1 + include_user = 1 + centcomm_cancast = 0 //Prevent people from getting to centcomm + + action_icon_state = "jaunt" + + var/phaseshift = 0 + var/jaunt_duration = 62 //in deciseconds + +/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded + set waitfor = FALSE + for(var/mob/living/target in targets) + var/turf/mobloc = get_turf(target.loc) + var/obj/effect/dummy/spell_jaunt/holder = new(mobloc) + target.ExtinguishMob() //This spell can extinguish mob + target.status_flags ^= GODMODE //Protection from any kind of damage, caused you in astral world + holder.master = target + var/list/companions = handle_teleport_grab(holder, target) + if(companions) + for(var/M in companions) + var/mob/living/L = M + L.status_flags ^= GODMODE + L.ExtinguishMob() + var/image/I = image('icons/mob/blob.dmi', holder, "marker", LIGHTING_LAYER+1) + if(target.client) + target.client.images += I + target.forceMove(holder) + target.client.eye = holder + + if(phaseshift) + holder.dir = target.dir + flick("phase_shift", holder) + + sleep(FLICK_OVERLAY_JAUNT_DURATION) + holder.canmove = TRUE + sleep(jaunt_duration) + + mobloc = get_turf(target.loc) + holder.canmove = FALSE + flick("phase_shift2", holder) + else + flick("liquify", holder) + var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() + steam.set_up(10, 0, mobloc) + steam.start() + + sleep(FLICK_OVERLAY_JAUNT_DURATION) + holder.canmove = TRUE + sleep(jaunt_duration) + + mobloc = get_turf(target.loc) + steam.location = mobloc + steam.start() + holder.canmove = FALSE + flick("reappear", holder) + + sleep(FLICK_OVERLAY_JAUNT_DURATION) + if(target.client) + target.client.images -= I + target.client.eye = target + target.status_flags ^= GODMODE //Turn off this cheat + if(companions) + for(var/M in companions) + var/mob/living/L = M + L.status_flags ^= GODMODE + qdel(holder) + +/obj/effect/dummy/spell_jaunt + name = "water" + last_move = 0 + density = 0 + anchored = 1 + layer = 5 + icon = 'icons/mob/mob.dmi' + icon_state = "blank" + var/mob/master + var/canmove = FALSE + + +/obj/effect/dummy/spell_jaunt/relaymove(mob/user, direction) + if(!canmove || last_move + 2 > world.time) + return + if(user != master) + return + var/turf/newLoc = get_step(src,direction) + if(!(newLoc.flags & NOJAUNT)) + loc = newLoc + else + to_chat(user, "Some strange aura is blocking the way!") + dir = direction + last_move = world.time + +/obj/effect/dummy/spell_jaunt/ex_act(blah) + return + +/obj/effect/dummy/spell_jaunt/bullet_act(blah) + return + +/obj/effect/dummy/spell_jaunt/Destroy() + for(var/atom/movable/AM in src) + AM.forceMove(get_turf(src)) + master = null + return ..() + #undef FLICK_OVERLAY_JAUNT_DURATION \ No newline at end of file diff --git a/code/datums/spells/explosion.dm b/code/datums/spells/explosion.dm index 8d236b2ff120..e28e14e8f764 100644 --- a/code/datums/spells/explosion.dm +++ b/code/datums/spells/explosion.dm @@ -1,15 +1,15 @@ -/obj/effect/proc_holder/spell/targeted/explosion - name = "Explosion" - desc = "This spell explodes an area." - - var/ex_severe = 1 - var/ex_heavy = 2 - var/ex_light = 3 - var/ex_flash = 4 - -/obj/effect/proc_holder/spell/targeted/explosion/cast(list/targets) - - for(var/mob/living/target in targets) - explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash) - - return +/obj/effect/proc_holder/spell/targeted/explosion + name = "Explosion" + desc = "This spell explodes an area." + + var/ex_severe = 1 + var/ex_heavy = 2 + var/ex_light = 3 + var/ex_flash = 4 + +/obj/effect/proc_holder/spell/targeted/explosion/cast(list/targets) + + for(var/mob/living/target in targets) + explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash) + + return diff --git a/code/datums/spells/genetic.dm b/code/datums/spells/genetic.dm index cad33d467267..9f10ed122742 100644 --- a/code/datums/spells/genetic.dm +++ b/code/datums/spells/genetic.dm @@ -1,33 +1,33 @@ -/obj/effect/proc_holder/spell/targeted/genetic - name = "Genetic" - desc = "This spell inflicts a set of mutations and disabilities upon the target." - - var/disabilities = 0 //bits - var/list/mutations = list() //mutation strings - var/duration = 100 //deciseconds - /* - Disabilities - 1st bit - ? - 2nd bit - ? - 3rd bit - ? - 4th bit - ? - 5th bit - ? - 6th bit - ? - */ - -/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets) - - for(var/mob/living/target in targets) - for(var/x in mutations) - target.mutations.Add(x) - target.disabilities |= disabilities - target.update_mutations() //update target's mutation overlays - addtimer(CALLBACK(src, .proc/remove_mutations, target, mutations), duration) - - return - -/obj/effect/proc_holder/spell/targeted/genetic/proc/remove_mutations(mob/living/target, list/mutations) - for(var/x in mutations) - target.mutations.Remove(x) - target.disabilities &= ~disabilities +/obj/effect/proc_holder/spell/targeted/genetic + name = "Genetic" + desc = "This spell inflicts a set of mutations and disabilities upon the target." + + var/disabilities = 0 //bits + var/list/mutations = list() //mutation strings + var/duration = 100 //deciseconds + /* + Disabilities + 1st bit - ? + 2nd bit - ? + 3rd bit - ? + 4th bit - ? + 5th bit - ? + 6th bit - ? + */ + +/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets) + + for(var/mob/living/target in targets) + for(var/x in mutations) + target.mutations.Add(x) + target.disabilities |= disabilities + target.update_mutations() //update target's mutation overlays + addtimer(CALLBACK(src, .proc/remove_mutations, target, mutations), duration) + + return + +/obj/effect/proc_holder/spell/targeted/genetic/proc/remove_mutations(mob/living/target, list/mutations) + for(var/x in mutations) + target.mutations.Remove(x) + target.disabilities &= ~disabilities target.update_mutations() \ No newline at end of file diff --git a/code/datums/spells/inflict_handler.dm b/code/datums/spells/inflict_handler.dm index 03d0fd328bee..5a0422b554ee 100644 --- a/code/datums/spells/inflict_handler.dm +++ b/code/datums/spells/inflict_handler.dm @@ -1,59 +1,59 @@ -/obj/effect/proc_holder/spell/targeted/inflict_handler - name = "Inflict Handler" - desc = "This spell blinds and/or destroys/damages/heals and/or weakens/stuns the target." - - var/amt_weakened = 0 - var/amt_paralysis = 0 - var/amt_stunned = 0 - - //set to negatives for healing - var/amt_dam_fire = 0 - var/amt_dam_brute = 0 - var/amt_dam_oxy = 0 - var/amt_dam_tox = 0 - - var/amt_eye_blind = 0 - var/amt_eye_blurry = 0 - - var/destroys = "none" //can be "none", "gib" or "disintegrate" - -/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets) - - for(var/mob/living/target in targets) - switch(destroys) - if("gib") - target.gib() - if("gib_brain") - if(ishuman(target) || ismonkey(target)) - var/mob/living/carbon/C = target - if(C.brain_op_stage != 4) // Their brain is already taken out - var/obj/item/brain/B = new(C.loc) - B.transfer_identity(C) - target.gib() - if("disintegrate") - target.dust() - - if(!target) - continue - //damage - if(amt_dam_brute > 0) - if(amt_dam_fire >= 0) - target.take_overall_damage(amt_dam_brute,amt_dam_fire) - else if (amt_dam_fire < 0) - target.take_overall_damage(amt_dam_brute,0) - target.heal_overall_damage(0,amt_dam_fire) - else if(amt_dam_brute < 0) - if(amt_dam_fire > 0) - target.take_overall_damage(0,amt_dam_fire) - target.heal_overall_damage(amt_dam_brute,0) - else if (amt_dam_fire <= 0) - target.heal_overall_damage(amt_dam_brute,amt_dam_fire) - target.adjustToxLoss(amt_dam_tox) - target.oxyloss += amt_dam_oxy - //disabling - target.Weaken(amt_weakened) - target.Paralyse(amt_paralysis) - target.Stun(amt_stunned) - - target.eye_blind += amt_eye_blind - target.eye_blurry += amt_eye_blurry +/obj/effect/proc_holder/spell/targeted/inflict_handler + name = "Inflict Handler" + desc = "This spell blinds and/or destroys/damages/heals and/or weakens/stuns the target." + + var/amt_weakened = 0 + var/amt_paralysis = 0 + var/amt_stunned = 0 + + //set to negatives for healing + var/amt_dam_fire = 0 + var/amt_dam_brute = 0 + var/amt_dam_oxy = 0 + var/amt_dam_tox = 0 + + var/amt_eye_blind = 0 + var/amt_eye_blurry = 0 + + var/destroys = "none" //can be "none", "gib" or "disintegrate" + +/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets) + + for(var/mob/living/target in targets) + switch(destroys) + if("gib") + target.gib() + if("gib_brain") + if(ishuman(target) || ismonkey(target)) + var/mob/living/carbon/C = target + if(C.brain_op_stage != 4) // Their brain is already taken out + var/obj/item/brain/B = new(C.loc) + B.transfer_identity(C) + target.gib() + if("disintegrate") + target.dust() + + if(!target) + continue + //damage + if(amt_dam_brute > 0) + if(amt_dam_fire >= 0) + target.take_overall_damage(amt_dam_brute,amt_dam_fire) + else if (amt_dam_fire < 0) + target.take_overall_damage(amt_dam_brute,0) + target.heal_overall_damage(0,amt_dam_fire) + else if(amt_dam_brute < 0) + if(amt_dam_fire > 0) + target.take_overall_damage(0,amt_dam_fire) + target.heal_overall_damage(amt_dam_brute,0) + else if (amt_dam_fire <= 0) + target.heal_overall_damage(amt_dam_brute,amt_dam_fire) + target.adjustToxLoss(amt_dam_tox) + target.oxyloss += amt_dam_oxy + //disabling + target.Weaken(amt_weakened) + target.Paralyse(amt_paralysis) + target.Stun(amt_stunned) + + target.eye_blind += amt_eye_blind + target.eye_blurry += amt_eye_blurry diff --git a/code/datums/spells/knock.dm b/code/datums/spells/knock.dm index 547883581e2f..527204d7fa26 100644 --- a/code/datums/spells/knock.dm +++ b/code/datums/spells/knock.dm @@ -1,24 +1,24 @@ -/obj/effect/proc_holder/spell/aoe_turf/knock - name = "Knock" - desc = "This spell opens nearby doors and does not require wizard garb." - sound = 'sound/magic/Knock.ogg' - school = "transmutation" - charge_max = 100 - clothes_req = 0 - invocation = "AULIE OXIN FIERA" - invocation_type = "whisper" - range = 3 - - action_icon_state = "knock" - -/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets) - for(var/turf/T in targets) - for(var/obj/machinery/door/door in T.contents) - if(istype(door, /obj/machinery/door/airlock)) - var/obj/machinery/door/airlock/A = door - INVOKE_ASYNC(A, /obj/machinery/door/airlock/proc/unbolt) - INVOKE_ASYNC(door, /obj/machinery/door/proc/open) - for(var/obj/structure/closet/C in T.contents) - C.locked = 0 - INVOKE_ASYNC(C, /obj/structure/closet/proc/open) - return +/obj/effect/proc_holder/spell/aoe_turf/knock + name = "Knock" + desc = "This spell opens nearby doors and does not require wizard garb." + sound = 'sound/magic/Knock.ogg' + school = "transmutation" + charge_max = 100 + clothes_req = 0 + invocation = "AULIE OXIN FIERA" + invocation_type = "whisper" + range = 3 + + action_icon_state = "knock" + +/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets) + for(var/turf/T in targets) + for(var/obj/machinery/door/door in T.contents) + if(istype(door, /obj/machinery/door/airlock)) + var/obj/machinery/door/airlock/A = door + INVOKE_ASYNC(A, /obj/machinery/door/airlock/proc/unbolt) + INVOKE_ASYNC(door, /obj/machinery/door/proc/open) + for(var/obj/structure/closet/C in T.contents) + C.locked = 0 + INVOKE_ASYNC(C, /obj/structure/closet/proc/open) + return diff --git a/code/datums/spells/lighting_shock.dm b/code/datums/spells/lighting_shock.dm index 4a830bf605f8..cc093cb97ff9 100644 --- a/code/datums/spells/lighting_shock.dm +++ b/code/datums/spells/lighting_shock.dm @@ -1,57 +1,57 @@ -/obj/effect/proc_holder/spell/targeted/lighting_shock - name = "Lighting Shock" - desc = "Hold your target with electricity for 5 seconds. Disarms target making drop all in hands and impossibility pick up it again." - school = "transmutation" - charge_type = "recharge" - charge_max = 220 - charge_counter = 0 - clothes_req = 1 - stat_allowed = 0 - invocation = "WEAP'OL DRAP VENO!" - invocation_type = "shout" - range = 7 - selection_type = "range" - action_icon_state = "summons" - var/static/list/compatible_mobs = null - -/obj/effect/proc_holder/spell/targeted/lighting_shock/atom_init() - . = ..() - if(!compatible_mobs) - compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey, /mob/living/carbon/monkey/punpun, /mob/living/carbon/human/tajaran, /mob/living/carbon/human/skrell, /mob/living/carbon/human/unathi, /mob/living/carbon/human/diona, /mob/living/carbon/human/abductor, /mob/living/carbon/human/golem, /mob/living/carbon/human/vox) - -/obj/effect/proc_holder/spell/targeted/lighting_shock/cast(list/targets, mob/user = usr) - if(!targets.len) - to_chat(user, "No target found in range.") - return - - var/mob/living/carbon/target - while(targets.len) - target = targets[targets.len] - targets -= target - if(istype(target) && !(target.handcuffed)) - break - - if(!(target.type in compatible_mobs)) - to_chat(user, "It'd be stupid to disarm [target]!") - return - - if(!(target in oview(range)))//If they are not in overview after selection. - to_chat(user, "They are too far away!") - return - - target.visible_message("[target] looks like is being blocked by something from the outside world...", \ - "You feel how strange powers holding you...") - - playsound(target, 'sound/effects/electricity.ogg', 75, 2) - - // makes target drop weapons to floor - target.drop_from_inventory(target.l_hand) - target.drop_from_inventory(target.r_hand) - - // don't let target pick up items, overlays for lighting effects - target.overlays += image(icon = 'icons/effects/effects.dmi', icon_state = "electricity") - target.next_click = world.time + 50 - // after time let target pick up items, removing overlays - - sleep(50) - target.overlays -= image(icon = 'icons/effects/effects.dmi', icon_state = "electricity") +/obj/effect/proc_holder/spell/targeted/lighting_shock + name = "Lighting Shock" + desc = "Hold your target with electricity for 5 seconds. Disarms target making drop all in hands and impossibility pick up it again." + school = "transmutation" + charge_type = "recharge" + charge_max = 220 + charge_counter = 0 + clothes_req = 1 + stat_allowed = 0 + invocation = "WEAP'OL DRAP VENO!" + invocation_type = "shout" + range = 7 + selection_type = "range" + action_icon_state = "summons" + var/static/list/compatible_mobs = null + +/obj/effect/proc_holder/spell/targeted/lighting_shock/atom_init() + . = ..() + if(!compatible_mobs) + compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey, /mob/living/carbon/monkey/punpun, /mob/living/carbon/human/tajaran, /mob/living/carbon/human/skrell, /mob/living/carbon/human/unathi, /mob/living/carbon/human/diona, /mob/living/carbon/human/abductor, /mob/living/carbon/human/golem, /mob/living/carbon/human/vox) + +/obj/effect/proc_holder/spell/targeted/lighting_shock/cast(list/targets, mob/user = usr) + if(!targets.len) + to_chat(user, "No target found in range.") + return + + var/mob/living/carbon/target + while(targets.len) + target = targets[targets.len] + targets -= target + if(istype(target) && !(target.handcuffed)) + break + + if(!(target.type in compatible_mobs)) + to_chat(user, "It'd be stupid to disarm [target]!") + return + + if(!(target in oview(range)))//If they are not in overview after selection. + to_chat(user, "They are too far away!") + return + + target.visible_message("[target] looks like is being blocked by something from the outside world...", \ + "You feel how strange powers holding you...") + + playsound(target, 'sound/effects/electricity.ogg', 75, 2) + + // makes target drop weapons to floor + target.drop_from_inventory(target.l_hand) + target.drop_from_inventory(target.r_hand) + + // don't let target pick up items, overlays for lighting effects + target.overlays += image(icon = 'icons/effects/effects.dmi', icon_state = "electricity") + target.next_click = world.time + 50 + // after time let target pick up items, removing overlays + + sleep(50) + target.overlays -= image(icon = 'icons/effects/effects.dmi', icon_state = "electricity") diff --git a/code/datums/spells/mind_transfer.dm b/code/datums/spells/mind_transfer.dm index f0791cd816fc..bd5c0a84f751 100644 --- a/code/datums/spells/mind_transfer.dm +++ b/code/datums/spells/mind_transfer.dm @@ -1,128 +1,128 @@ -/obj/effect/proc_holder/spell/targeted/mind_transfer - name = "Mind Transfer" - desc = "This spell allows the user to switch bodies with a target." - - school = "transmutation" - charge_max = 1800 - clothes_req = 0 - invocation = "GIN'YU CAPAN" - invocation_type = "whisper" - sound = 'sound/magic/MandSwap.ogg' - range = 1 - action_icon_state = "mindswap" - var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell - var/list/compatible_mobs = list(/mob/living/carbon/human,/mob/living/carbon/monkey) //which types of mobs are affected by the spell. NOTE: change at your own risk - var/base_spell_loss_chance = 20 //base probability of the wizard losing a spell in the process - var/spell_loss_chance_modifier = 7 //amount of probability of losing a spell added per spell (mind_transfer included) - var/spell_loss_amount = 1 //the maximum amount of spells possible to lose during a single transfer - var/msg_wait = 500 //how long in deciseconds it waits before telling that body doesn't feel right or mind swap robbed of a spell - var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell - var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell - -/* -Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do. -Make sure spells that are removed from spell_list are actually removed and deleted when mind transfering. -Also, you never added distance checking after target is selected. I've went ahead and did that. -*/ -/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets,mob/user = usr) - if(!targets.len) - to_chat(user, "No mind found.") - return - - if(targets.len > 1) - to_chat(user, "Too many minds! You're not a hive damnit!")//Whaa...aat? - return - - var/mob/living/target = targets[1] - - if(!(target in oview(range)))//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it. - to_chat(user, "They are too far away!") - return - - if(!(target.type in compatible_mobs)) - to_chat(user, "Their mind isn't compatible with yours.") - return - - if(target.stat == DEAD) - to_chat(user, "You didn't study necromancy back at the Space Wizard Federation academy.") - return - - if(!target.key || !target.mind) - to_chat(user, "They appear to be catatonic. Not even magic can affect their vacant mind.") - return - - if(target.mind.special_role in protected_roles) - to_chat(user, "Their mind is resisting your spell.") - return - - //If target has mindshield/loyalty implant we break it, adding some brainloss - if(ismindshielded(target)) - to_chat(user, "Their mind seems to be protected, so you only manage to break it") - to_chat(target, "You feel a flash of pain in your head") - for(var/obj/item/weapon/implant/mindshield/L in target) - if(L.implanted && L.imp_in == target) - qdel(L) - target.adjustBrainLoss(15) - user.Paralyse(paralysis_amount_caster) - target.Paralyse(paralysis_amount_victim) - return - - var/mob/living/victim = target//The target of the spell whos body will be transferred to. - var/mob/caster = user//The wizard/whomever doing the body transferring. - - //SPELL LOSS BEGIN - //NOTE: The caster must ALWAYS keep mind transfer, even when other spells are lost. - var/obj/effect/proc_holder/spell/targeted/mind_transfer/m_transfer = locate() in user.spell_list//Find mind transfer directly. - var/list/checked_spells = user.spell_list - checked_spells -= m_transfer //Remove Mind Transfer from the list. - - if(caster.spell_list.len)//If they have any spells left over after mind transfer is taken out. If they don't, we don't need this. - for(var/i=spell_loss_amount,(i>0&&checked_spells.len),i--)//While spell loss amount is greater than zero and checked_spells has spells in it, run this proc. - for(var/j=checked_spells.len,(j>0&&checked_spells.len),j--)//While the spell list to check is greater than zero and has spells in it, run this proc. - if(prob(base_spell_loss_chance)) - checked_spells -= pick(checked_spells)//Pick a random spell to remove. - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, victim, "The mind transfer has robbed you of a spell."), msg_wait) - break//Spell lost. Break loop, going back to the previous for() statement. - else//Or keep checking, adding spell chance modifier to increase chance of losing a spell. - base_spell_loss_chance += spell_loss_chance_modifier - - checked_spells += m_transfer//Add back Mind Transfer. - user.spell_list = checked_spells//Set user spell list to whatever the new list is. - user.mind.spell_list = checked_spells//Set user mind list to the same spells - //SPELL LOSS END - - //MIND TRANSFER BEGIN - if(caster.mind.special_verbs.len)//If the caster had any special verbs, remove them from the mob verb list. - for(var/V in caster.mind.special_verbs)//Since the caster is using an object spell system, this is mostly moot. - caster.verbs -= V//But a safety nontheless. - - if(victim.mind.special_verbs.len)//Now remove all of the victim's verbs. - for(var/V in victim.mind.special_verbs) - victim.verbs -= V - - var/mob/dead/observer/ghost = victim.ghostize(can_reenter_corpse = FALSE) - ghost.spell_list = victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob. - - caster.mind.transfer_to(victim) - victim.spell_list = caster.spell_list//Now they are inside the victim's body. - - if(victim.mind.special_verbs.len)//To add all the special verbs for the original caster. - for(var/V in caster.mind.special_verbs)//Not too important but could come into play. - caster.verbs += V - - ghost.mind.transfer_to(caster) - caster.key = ghost.key //have to transfer the key since the mind was not active - caster.spell_list = ghost.spell_list - - if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here. - for(var/V in caster.mind.special_verbs) - caster.verbs += V - - //MIND TRANSFER END - - //Here we paralyze both mobs and knock them out for a time. - caster.Paralyse(paralysis_amount_caster) - victim.Paralyse(paralysis_amount_victim) - - //After a certain amount of time the victim gets a message about being in a different body. - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, caster, "You feel woozy and lightheaded. Your body doesn't seem like your own."), msg_wait) +/obj/effect/proc_holder/spell/targeted/mind_transfer + name = "Mind Transfer" + desc = "This spell allows the user to switch bodies with a target." + + school = "transmutation" + charge_max = 1800 + clothes_req = 0 + invocation = "GIN'YU CAPAN" + invocation_type = "whisper" + sound = 'sound/magic/MandSwap.ogg' + range = 1 + action_icon_state = "mindswap" + var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell + var/list/compatible_mobs = list(/mob/living/carbon/human,/mob/living/carbon/monkey) //which types of mobs are affected by the spell. NOTE: change at your own risk + var/base_spell_loss_chance = 20 //base probability of the wizard losing a spell in the process + var/spell_loss_chance_modifier = 7 //amount of probability of losing a spell added per spell (mind_transfer included) + var/spell_loss_amount = 1 //the maximum amount of spells possible to lose during a single transfer + var/msg_wait = 500 //how long in deciseconds it waits before telling that body doesn't feel right or mind swap robbed of a spell + var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell + var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell + +/* +Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do. +Make sure spells that are removed from spell_list are actually removed and deleted when mind transfering. +Also, you never added distance checking after target is selected. I've went ahead and did that. +*/ +/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets,mob/user = usr) + if(!targets.len) + to_chat(user, "No mind found.") + return + + if(targets.len > 1) + to_chat(user, "Too many minds! You're not a hive damnit!")//Whaa...aat? + return + + var/mob/living/target = targets[1] + + if(!(target in oview(range)))//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it. + to_chat(user, "They are too far away!") + return + + if(!(target.type in compatible_mobs)) + to_chat(user, "Their mind isn't compatible with yours.") + return + + if(target.stat == DEAD) + to_chat(user, "You didn't study necromancy back at the Space Wizard Federation academy.") + return + + if(!target.key || !target.mind) + to_chat(user, "They appear to be catatonic. Not even magic can affect their vacant mind.") + return + + if(target.mind.special_role in protected_roles) + to_chat(user, "Their mind is resisting your spell.") + return + + //If target has mindshield/loyalty implant we break it, adding some brainloss + if(ismindshielded(target)) + to_chat(user, "Their mind seems to be protected, so you only manage to break it") + to_chat(target, "You feel a flash of pain in your head") + for(var/obj/item/weapon/implant/mindshield/L in target) + if(L.implanted && L.imp_in == target) + qdel(L) + target.adjustBrainLoss(15) + user.Paralyse(paralysis_amount_caster) + target.Paralyse(paralysis_amount_victim) + return + + var/mob/living/victim = target//The target of the spell whos body will be transferred to. + var/mob/caster = user//The wizard/whomever doing the body transferring. + + //SPELL LOSS BEGIN + //NOTE: The caster must ALWAYS keep mind transfer, even when other spells are lost. + var/obj/effect/proc_holder/spell/targeted/mind_transfer/m_transfer = locate() in user.spell_list//Find mind transfer directly. + var/list/checked_spells = user.spell_list + checked_spells -= m_transfer //Remove Mind Transfer from the list. + + if(caster.spell_list.len)//If they have any spells left over after mind transfer is taken out. If they don't, we don't need this. + for(var/i=spell_loss_amount,(i>0&&checked_spells.len),i--)//While spell loss amount is greater than zero and checked_spells has spells in it, run this proc. + for(var/j=checked_spells.len,(j>0&&checked_spells.len),j--)//While the spell list to check is greater than zero and has spells in it, run this proc. + if(prob(base_spell_loss_chance)) + checked_spells -= pick(checked_spells)//Pick a random spell to remove. + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, victim, "The mind transfer has robbed you of a spell."), msg_wait) + break//Spell lost. Break loop, going back to the previous for() statement. + else//Or keep checking, adding spell chance modifier to increase chance of losing a spell. + base_spell_loss_chance += spell_loss_chance_modifier + + checked_spells += m_transfer//Add back Mind Transfer. + user.spell_list = checked_spells//Set user spell list to whatever the new list is. + user.mind.spell_list = checked_spells//Set user mind list to the same spells + //SPELL LOSS END + + //MIND TRANSFER BEGIN + if(caster.mind.special_verbs.len)//If the caster had any special verbs, remove them from the mob verb list. + for(var/V in caster.mind.special_verbs)//Since the caster is using an object spell system, this is mostly moot. + caster.verbs -= V//But a safety nontheless. + + if(victim.mind.special_verbs.len)//Now remove all of the victim's verbs. + for(var/V in victim.mind.special_verbs) + victim.verbs -= V + + var/mob/dead/observer/ghost = victim.ghostize(can_reenter_corpse = FALSE) + ghost.spell_list = victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob. + + caster.mind.transfer_to(victim) + victim.spell_list = caster.spell_list//Now they are inside the victim's body. + + if(victim.mind.special_verbs.len)//To add all the special verbs for the original caster. + for(var/V in caster.mind.special_verbs)//Not too important but could come into play. + caster.verbs += V + + ghost.mind.transfer_to(caster) + caster.key = ghost.key //have to transfer the key since the mind was not active + caster.spell_list = ghost.spell_list + + if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here. + for(var/V in caster.mind.special_verbs) + caster.verbs += V + + //MIND TRANSFER END + + //Here we paralyze both mobs and knock them out for a time. + caster.Paralyse(paralysis_amount_caster) + victim.Paralyse(paralysis_amount_victim) + + //After a certain amount of time the victim gets a message about being in a different body. + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, caster, "You feel woozy and lightheaded. Your body doesn't seem like your own."), msg_wait) diff --git a/code/datums/spells/projectile.dm b/code/datums/spells/projectile.dm index 2d1bdca424a9..d2935d568529 100644 --- a/code/datums/spells/projectile.dm +++ b/code/datums/spells/projectile.dm @@ -1,83 +1,83 @@ -/obj/effect/proc_holder/spell/targeted/projectile - name = "Projectile" - desc = "This spell summons projectiles which try to hit the targets." - - var/proj_icon = 'icons/obj/projectiles.dmi' - var/proj_icon_state = "spell" - var/proj_name = "a spell projectile" - - var/proj_trail = 0 //if it leaves a trail - var/proj_trail_lifespan = 0 //deciseconds - var/proj_trail_icon = 'icons/obj/wizard.dmi' - var/proj_trail_icon_state = "trail" - - var/proj_type = "/obj/effect/proc_holder/spell/targeted" //IMPORTANT use only subtypes of this - - var/proj_lingering = 0 //if it lingers or disappears upon hitting an obstacle - var/proj_homing = 1 //if it follows the target - var/proj_insubstantial = 0 //if it can pass through dense objects or not - var/proj_trigger_range = 0 //the range from target at which the projectile triggers cast(target) - - var/proj_lifespan = 15 //in deciseconds * proj_step_delay - var/proj_step_delay = 1 //lower = faster - -/obj/effect/proc_holder/spell/targeted/projectile/cast(list/targets, mob/user = usr) - - for(var/mob/living/target in targets) - spawn(0) - var/obj/effect/proc_holder/spell/targeted/projectile - if(istext(proj_type)) - var/projectile_type = text2path(proj_type) - projectile = new projectile_type(user) - if(istype(proj_type,/obj/effect/proc_holder/spell)) - projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) - projectile:linked_spells += proj_type - projectile.icon = proj_icon - projectile.icon_state = proj_icon_state - projectile.dir = get_dir(target,projectile) - projectile.name = proj_name - - var/current_loc = usr.loc - - projectile.loc = current_loc - - for(var/i = 0,i < proj_lifespan,i++) - if(!projectile) - break - - if(proj_homing) - if(proj_insubstantial) - projectile.dir = get_dir(projectile,target) - projectile.loc = get_step_to(projectile,target) - else - step_to(projectile,target) - else - if(proj_insubstantial) - projectile.loc = get_step(projectile,dir) - else - step(projectile,dir) - - if(!proj_lingering && projectile.loc == current_loc) //if it didn't move since last time - qdel(projectile) - break - - if(proj_trail && projectile) - spawn(0) - if(projectile) - var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc) - trail.icon = proj_trail_icon - trail.icon_state = proj_trail_icon_state - trail.density = 0 - spawn(proj_trail_lifespan) - qdel(trail) - - if(projectile.loc in range(target.loc,proj_trigger_range)) - projectile.perform(list(target)) - break - - current_loc = projectile.loc - - sleep(proj_step_delay) - - if(projectile) - qdel(projectile) +/obj/effect/proc_holder/spell/targeted/projectile + name = "Projectile" + desc = "This spell summons projectiles which try to hit the targets." + + var/proj_icon = 'icons/obj/projectiles.dmi' + var/proj_icon_state = "spell" + var/proj_name = "a spell projectile" + + var/proj_trail = 0 //if it leaves a trail + var/proj_trail_lifespan = 0 //deciseconds + var/proj_trail_icon = 'icons/obj/wizard.dmi' + var/proj_trail_icon_state = "trail" + + var/proj_type = "/obj/effect/proc_holder/spell/targeted" //IMPORTANT use only subtypes of this + + var/proj_lingering = 0 //if it lingers or disappears upon hitting an obstacle + var/proj_homing = 1 //if it follows the target + var/proj_insubstantial = 0 //if it can pass through dense objects or not + var/proj_trigger_range = 0 //the range from target at which the projectile triggers cast(target) + + var/proj_lifespan = 15 //in deciseconds * proj_step_delay + var/proj_step_delay = 1 //lower = faster + +/obj/effect/proc_holder/spell/targeted/projectile/cast(list/targets, mob/user = usr) + + for(var/mob/living/target in targets) + spawn(0) + var/obj/effect/proc_holder/spell/targeted/projectile + if(istext(proj_type)) + var/projectile_type = text2path(proj_type) + projectile = new projectile_type(user) + if(istype(proj_type,/obj/effect/proc_holder/spell)) + projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) + projectile:linked_spells += proj_type + projectile.icon = proj_icon + projectile.icon_state = proj_icon_state + projectile.dir = get_dir(target,projectile) + projectile.name = proj_name + + var/current_loc = usr.loc + + projectile.loc = current_loc + + for(var/i = 0,i < proj_lifespan,i++) + if(!projectile) + break + + if(proj_homing) + if(proj_insubstantial) + projectile.dir = get_dir(projectile,target) + projectile.loc = get_step_to(projectile,target) + else + step_to(projectile,target) + else + if(proj_insubstantial) + projectile.loc = get_step(projectile,dir) + else + step(projectile,dir) + + if(!proj_lingering && projectile.loc == current_loc) //if it didn't move since last time + qdel(projectile) + break + + if(proj_trail && projectile) + spawn(0) + if(projectile) + var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc) + trail.icon = proj_trail_icon + trail.icon_state = proj_trail_icon_state + trail.density = 0 + spawn(proj_trail_lifespan) + qdel(trail) + + if(projectile.loc in range(target.loc,proj_trigger_range)) + projectile.perform(list(target)) + break + + current_loc = projectile.loc + + sleep(proj_step_delay) + + if(projectile) + qdel(projectile) diff --git a/code/datums/spells/trigger.dm b/code/datums/spells/trigger.dm index 10c8742556c6..07cfd3df1662 100644 --- a/code/datums/spells/trigger.dm +++ b/code/datums/spells/trigger.dm @@ -1,27 +1,27 @@ -/obj/effect/proc_holder/spell/targeted/trigger - name = "Trigger" - desc = "This spell triggers another spell or a few." - - var/list/linked_spells = list() //those are just referenced by the trigger spell and are unaffected by it directly - var/list/starting_spells = list() //those are added on New() to contents from default spells and are deleted when the trigger spell is deleted to prevent memory leaks - -/obj/effect/proc_holder/spell/targeted/trigger/atom_init() - . = ..() - - for(var/spell in starting_spells) - var/spell_to_add = text2path(spell) - new spell_to_add(src) //should result in adding to contents, needs testing - -/obj/effect/proc_holder/spell/targeted/trigger/Destroy() - for(var/spell in contents) - qdel(spell) - return ..() - -/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets) - for(var/mob/living/target in targets) - for(var/obj/effect/proc_holder/spell/spell in contents) - spell.perform(list(target),0) - for(var/obj/effect/proc_holder/spell/spell in linked_spells) - spell.perform(list(target),0) - - return +/obj/effect/proc_holder/spell/targeted/trigger + name = "Trigger" + desc = "This spell triggers another spell or a few." + + var/list/linked_spells = list() //those are just referenced by the trigger spell and are unaffected by it directly + var/list/starting_spells = list() //those are added on New() to contents from default spells and are deleted when the trigger spell is deleted to prevent memory leaks + +/obj/effect/proc_holder/spell/targeted/trigger/atom_init() + . = ..() + + for(var/spell in starting_spells) + var/spell_to_add = text2path(spell) + new spell_to_add(src) //should result in adding to contents, needs testing + +/obj/effect/proc_holder/spell/targeted/trigger/Destroy() + for(var/spell in contents) + qdel(spell) + return ..() + +/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets) + for(var/mob/living/target in targets) + for(var/obj/effect/proc_holder/spell/spell in contents) + spell.perform(list(target),0) + for(var/obj/effect/proc_holder/spell/spell in linked_spells) + spell.perform(list(target),0) + + return diff --git a/code/datums/spells/turf_teleport.dm b/code/datums/spells/turf_teleport.dm index 5408cd80af2d..badf1e97b27f 100644 --- a/code/datums/spells/turf_teleport.dm +++ b/code/datums/spells/turf_teleport.dm @@ -1,34 +1,34 @@ -/obj/effect/proc_holder/spell/targeted/turf_teleport - name = "Turf Teleport" - desc = "This spell teleports the target to the turf in range." - - var/inner_tele_radius = 1 - var/outer_tele_radius = 2 - - var/include_space = 0 //whether it includes space tiles in possible teleport locations - var/include_dense = 0 //whether it includes dense tiles in possible teleport locations - -/obj/effect/proc_holder/spell/targeted/turf_teleport/cast(list/targets) - for(var/mob/living/target in targets) - var/list/turfs = new/list() - for(var/turf/T in range(target,outer_tele_radius)) - if(T in range(target,inner_tele_radius)) continue - if(istype(T,/turf/space) && !include_space) continue - if(T.density && !include_dense) continue - if(T.x>world.maxx-outer_tele_radius || T.xworld.maxy-outer_tele_radius || T.yworld.maxx-outer_tele_radius || T.xworld.maxy-outer_tele_radius || T.y - - - "} - var/even = 0 - // sort mobs - for(var/datum/data/record/t in 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 - for(var/mob/M in player_list) - if(M.real_name == name && M.client && M.client.inactivity <= 10 * 60 * 10) - active = 1 - break - isactive[name] = active ? "Active" : "Inactive" - else - isactive[name] = t.fields["p_stat"] - //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() -var/global/ManifestJSON - -/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\ - ) - ManifestJSON = list2json(PDA_Manifest) - return PDA_Manifest - - -/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 = 2.0 - force = 0.0 - throwforce = 0.0 - throw_speed = 1 - throw_range = 20 - flags = CONDUCT - - afterattack(atom/target, mob/user) - user.drop_item() - src.throw_at(target, throw_range, throw_speed, user) - -/obj/effect/spawner - name = "object spawner" +/obj/structure/signpost + icon = 'icons/obj/stationobjs.dmi' + icon_state = "signpost" + anchored = 1 + density = 1 + +/obj/structure/signpost/attackby(obj/item/weapon/W, mob/user) + return attack_hand(user) + +/obj/structure/signpost/attack_hand(mob/user) + 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 + user.SetNextMove(CLICK_CD_INTERACT) + +/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/beam + name = "beam" + unacidable = 1//Just to be sure. + var/def_zone + pass_flags = PASSTABLE + + +/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 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 + for(var/mob/M in player_list) + if(M.real_name == name && M.client && M.client.inactivity <= 10 * 60 * 10) + active = 1 + break + isactive[name] = active ? "Active" : "Inactive" + else + isactive[name] = t.fields["p_stat"] + //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() +var/global/ManifestJSON + +/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\ + ) + ManifestJSON = list2json(PDA_Manifest) + return PDA_Manifest + + +/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 = 2.0 + force = 0.0 + throwforce = 0.0 + throw_speed = 1 + throw_range = 20 + flags = CONDUCT + + afterattack(atom/target, mob/user) + user.drop_item() + src.throw_at(target, throw_range, throw_speed, user) + +/obj/effect/spawner + name = "object spawner" diff --git a/code/defines/obj/hydro.dm b/code/defines/obj/hydro.dm index c67f213649d8..c16849d58ade 100644 --- a/code/defines/obj/hydro.dm +++ b/code/defines/obj/hydro.dm @@ -1,1425 +1,1425 @@ -// Plant analyzer - -/obj/item/device/plant_analyzer - name = "plant analyzer" - desc = "A hand-held scanner which reports condition of the plant." - icon = 'icons/obj/device.dmi' - w_class = 1.0 - m_amt = 200 - g_amt = 50 - origin_tech = "materials=1;biotech=1" - icon_state = "hydro" - item_state = "plantanalyzer" - -/obj/item/device/plant_analyzer/attack_self(mob/user) - return FALSE - -/obj/item/device/plant_analyzer/attack(mob/living/carbon/human/M, mob/living/user) - if(M.species && M.species.flags[IS_PLANT]) - health_analyze(M, user, TRUE) // 1 means limb-scanning mode - -// ******************************************************** -// Here's all the seeds (plants) that can be used in hydro -// ******************************************************** - -/obj/item/seeds - name = "pack of seeds" - icon = 'icons/obj/hydroponics/seeds.dmi' - icon_state = "seed" // unknown plant seed - these shouldn't exist in-game - w_class = 2.0 // Makes them pocketable - var/mypath = "/obj/item/seeds" - var/hydroponictray_icon_path = 'icons/obj/hydroponics/growing.dmi'//this is now path to plant's overlays (in hydropinic tray) - 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 - var/list/mutatelist = list() - -/obj/item/seeds/attackby(obj/item/O, mob/user) - if (istype(O, /obj/item/device/plant_analyzer)) - to_chat(user, "*** [plantname] ***") - to_chat(user, "-Plant Endurance: \blue [endurance]") - to_chat(user, "-Plant Lifespan: \blue [lifespan]") - if(yield != -1) - to_chat(user, "-Plant Yield: \blue [yield]") - to_chat(user, "-Plant Production: \blue [production]") - if(potency != -1) - to_chat(user, "-Plant Potency: \blue [potency]") - user.SetNextMove(CLICK_CD_INTERACT) - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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 - mutatelist = list(/obj/item/seeds/icepepperseed) - -/obj/item/seeds/plastiseed - name = "pack of plastellium mycelium" - desc = "This mycelium grows into Plastellium." - icon_state = "mycelium-plast" - mypath = "/obj/item/seeds/plastiseed" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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 - mutatelist = list(/obj/item/seeds/greengrapeseed) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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 - mutatelist = list(/obj/item/seeds/glowberryseed,/obj/item/seeds/poisonberryseed) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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 - mutatelist = list(/obj/item/seeds/eggyseed) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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 - mutatelist = list(/obj/item/seeds/bluetomatoseed, /obj/item/seeds/bloodtomatoseed, /obj/item/seeds/killertomatoseed) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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 - mutatelist = list(/obj/item/seeds/bluespacetomatoseed) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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 - mutatelist = list(/obj/item/seeds/angelmycelium) - -/obj/item/seeds/angelmycelium - name = "pack of destroying angel mycelium" - desc = "This mycelium grows into something devestating." - icon_state = "mycelium-angel" - mypath = "/obj/item/seeds/angelmycelium" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' - 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 - mutatelist = list(/obj/item/seeds/walkingmushroommycelium) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' - 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 - mutatelist = list(/obj/item/seeds/deathnettleseed) - -/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/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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 - mutatelist = list(/obj/item/seeds/goldappleseed) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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 - mutatelist = list(/obj/item/seeds/ambrosiadeusseed) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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 - mutatelist = list(/obj/item/seeds/cashseed) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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 - mutatelist = list(/obj/item/seeds/deathberryseed) - -/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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - species = "cocoapod" - plantname = "Cocoa 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" - hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' - 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/kudzuseed/attack_self(mob/user) - if(istype(user.loc,/turf/space) || istype(user.loc,/turf/simulated/shuttle)) - to_chat(user, "You cannot plant kudzu on a moving shuttle or space.") - return - to_chat(user, "You plant the kudzu. You monster.") - new /obj/effect/spacevine_controller(user.loc) - qdel(src) - -// ********************** -// 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/atom_init() - var/datum/reagents/R = new/datum/reagents(50) - reagents = R - R.my_atom = src - . = ..() - -/obj/item/weapon/grown/proc/changePotency(newValue) - potency = newValue - -/obj/item/weapon/grown/log - name = "tower-cap log" - desc = "It's better than bad, it's good!" - icon = 'icons/obj/hydroponics/harvest.dmi' - icon_state = "logs" - force = 5 - 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") - -/obj/item/weapon/grown/log/attackby(obj/item/weapon/W, mob/user) - user.SetNextMove(CLICK_CD_INTERACT) - 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 in 1 to 2) - new/obj/item/stack/sheet/wood(user.loc) - qdel(src) - - -/obj/item/weapon/grown/sunflower - name = "sunflower" - desc = "It's beautiful! A certain person might beat you to death if you trample these." - icon = 'icons/obj/hydroponics/harvest.dmi' - icon_state = "sunflower" - damtype = "fire" - force = 0 - throwforce = 1 - w_class = 1.0 - throw_speed = 1 - throw_range = 3 - plant_type = 1 - seed = "/obj/item/seeds/sunflower" - -/obj/item/weapon/grown/nettle - 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 - throwforce = 1 - w_class = 2.0 - throw_speed = 1 - throw_range = 3 - plant_type = 1 - origin_tech = "combat=1" - seed = "/obj/item/seeds/nettleseed" - -/obj/item/weapon/grown/nettle/atom_init() - . = ..() - spawn(5) - 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 - desc = "The \red glowing \black nettle incites \redrage\black in you just from looking at it!" - icon = 'icons/obj/weapons.dmi' - name = "deathnettle" - icon_state = "deathnettle" - damtype = "fire" - force = 30 - throwforce = 1 - w_class = 2.0 - throw_speed = 1 - throw_range = 3 - plant_type = 1 - seed = "/obj/item/seeds/deathnettleseed" - origin_tech = "combat=3" - attack_verb = list("stung") - -/obj/item/weapon/grown/deathnettle/atom_init() - . = ..() - spawn(5) - reagents.add_reagent("nutriment", 1 + round((potency / 50), 1)) - reagents.add_reagent("pacid", round(potency, 1)) - force = round((5 + potency / 2.5), 1) - -/obj/item/weapon/grown/deathnettle/suicide_act(mob/user) - to_chat(viewers(user), "\red [user] is eating some of the [src.name]! It looks like \he's trying to commit suicide.") - return (BRUTELOSS | TOXLOSS) - -// ************************************* -// Pestkiller defines for hydroponics -// ************************************* - -/obj/item/pestkiller - name = "bottle of pestkiller" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - var/toxicity = 0 - var/PestKillStr = 0 - -/obj/item/pestkiller/atom_init() - . = ..() - pixel_x = rand(-5.0, 5) - pixel_y = rand(-5.0, 5) - -/obj/item/pestkiller/carbaryl - name = "bottle of carbaryl" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - toxicity = 4 - PestKillStr = 2 - -/obj/item/pestkiller/lindane - name = "bottle of lindane" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle18" - toxicity = 6 - PestKillStr = 4 - -/obj/item/pestkiller/phosmet - name = "bottle of phosmet" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle15" - toxicity = 8 - PestKillStr = 7 - -// ************************************* -// Hydroponics Tools -// ************************************* - -/obj/item/weapon/weedspray - desc = "It's a toxic mixture, in spray form, to kill small weeds." - icon = 'icons/obj/hydroponics/equipment.dmi' - name = "weed-spray" - icon_state = "weedspray" - item_state = "spray" - flags = OPENCONTAINER | NOBLUDGEON - slot_flags = SLOT_BELT - throwforce = 4 - w_class = 2.0 - throw_speed = 2 - throw_range = 10 - var/toxicity = 4 - var/WeedKillStr = 2 - -/obj/item/weapon/weedspray/suicide_act(mob/user) - to_chat(viewers(user), "\red [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/equipment.dmi' - name = "pest-spray" - icon_state = "pestspray" - item_state = "spraycan" - flags = OPENCONTAINER | NOBLUDGEON - slot_flags = SLOT_BELT - throwforce = 4 - w_class = 2.0 - throw_speed = 2 - throw_range = 10 - var/toxicity = 4 - var/PestKillStr = 2 - -/obj/item/weapon/pestspray/suicide_act(mob/user) - to_chat(viewers(user), "\red [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 = CONDUCT | NOBLUDGEON - force = 5.0 - throwforce = 7.0 - w_class = 2.0 - m_amt = 2550 - origin_tech = "materials=1;biotech=1" - 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" - var/toxicity = 0 - var/WeedKillStr = 0 - -/obj/item/weedkiller/triclopyr - name = "bottle of glyphosate" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - toxicity = 4 - WeedKillStr = 2 - -/obj/item/weedkiller/lindane - name = "bottle of triclopyr" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle18" - toxicity = 6 - WeedKillStr = 4 - -/obj/item/weedkiller/D24 - name = "bottle of 2,4-D" - icon = 'icons/obj/chemical.dmi' - 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" - w_class = 2.0 - var/mutmod = 0 - var/yieldmod = 0 - -/obj/item/nutrient/atom_init() - . = ..() - pixel_x = rand(-5.0, 5) - pixel_y = rand(-5.0, 5) - -/obj/item/nutrient/ez - name = "bottle of E-Z-Nutrient" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - mutmod = 1 - yieldmod = 1 - -/obj/item/nutrient/l4z - name = "bottle of Left 4 Zed" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle18" - mutmod = 2 - yieldmod = 0 - -/obj/item/nutrient/rh - name = "bottle of Robust Harvest" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle15" - mutmod = 0 - yieldmod = 2 +// Plant analyzer + +/obj/item/device/plant_analyzer + name = "plant analyzer" + desc = "A hand-held scanner which reports condition of the plant." + icon = 'icons/obj/device.dmi' + w_class = 1.0 + m_amt = 200 + g_amt = 50 + origin_tech = "materials=1;biotech=1" + icon_state = "hydro" + item_state = "plantanalyzer" + +/obj/item/device/plant_analyzer/attack_self(mob/user) + return FALSE + +/obj/item/device/plant_analyzer/attack(mob/living/carbon/human/M, mob/living/user) + if(M.species && M.species.flags[IS_PLANT]) + health_analyze(M, user, TRUE) // 1 means limb-scanning mode + +// ******************************************************** +// Here's all the seeds (plants) that can be used in hydro +// ******************************************************** + +/obj/item/seeds + name = "pack of seeds" + icon = 'icons/obj/hydroponics/seeds.dmi' + icon_state = "seed" // unknown plant seed - these shouldn't exist in-game + w_class = 2.0 // Makes them pocketable + var/mypath = "/obj/item/seeds" + var/hydroponictray_icon_path = 'icons/obj/hydroponics/growing.dmi'//this is now path to plant's overlays (in hydropinic tray) + 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 + var/list/mutatelist = list() + +/obj/item/seeds/attackby(obj/item/O, mob/user) + if (istype(O, /obj/item/device/plant_analyzer)) + to_chat(user, "*** [plantname] ***") + to_chat(user, "-Plant Endurance: \blue [endurance]") + to_chat(user, "-Plant Lifespan: \blue [lifespan]") + if(yield != -1) + to_chat(user, "-Plant Yield: \blue [yield]") + to_chat(user, "-Plant Production: \blue [production]") + if(potency != -1) + to_chat(user, "-Plant Potency: \blue [potency]") + user.SetNextMove(CLICK_CD_INTERACT) + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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 + mutatelist = list(/obj/item/seeds/icepepperseed) + +/obj/item/seeds/plastiseed + name = "pack of plastellium mycelium" + desc = "This mycelium grows into Plastellium." + icon_state = "mycelium-plast" + mypath = "/obj/item/seeds/plastiseed" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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 + mutatelist = list(/obj/item/seeds/greengrapeseed) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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 + mutatelist = list(/obj/item/seeds/glowberryseed,/obj/item/seeds/poisonberryseed) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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 + mutatelist = list(/obj/item/seeds/eggyseed) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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 + mutatelist = list(/obj/item/seeds/bluetomatoseed, /obj/item/seeds/bloodtomatoseed, /obj/item/seeds/killertomatoseed) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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 + mutatelist = list(/obj/item/seeds/bluespacetomatoseed) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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 + mutatelist = list(/obj/item/seeds/angelmycelium) + +/obj/item/seeds/angelmycelium + name = "pack of destroying angel mycelium" + desc = "This mycelium grows into something devestating." + icon_state = "mycelium-angel" + mypath = "/obj/item/seeds/angelmycelium" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' + 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 + mutatelist = list(/obj/item/seeds/walkingmushroommycelium) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_mushrooms.dmi' + 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 + mutatelist = list(/obj/item/seeds/deathnettleseed) + +/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/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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 + mutatelist = list(/obj/item/seeds/goldappleseed) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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 + mutatelist = list(/obj/item/seeds/ambrosiadeusseed) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_vegetables.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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 + mutatelist = list(/obj/item/seeds/cashseed) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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 + mutatelist = list(/obj/item/seeds/deathberryseed) + +/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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + species = "cocoapod" + plantname = "Cocoa 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" + hydroponictray_icon_path = 'icons/obj/hydroponics/growing_fruits.dmi' + 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/kudzuseed/attack_self(mob/user) + if(istype(user.loc,/turf/space) || istype(user.loc,/turf/simulated/shuttle)) + to_chat(user, "You cannot plant kudzu on a moving shuttle or space.") + return + to_chat(user, "You plant the kudzu. You monster.") + new /obj/effect/spacevine_controller(user.loc) + qdel(src) + +// ********************** +// 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/atom_init() + var/datum/reagents/R = new/datum/reagents(50) + reagents = R + R.my_atom = src + . = ..() + +/obj/item/weapon/grown/proc/changePotency(newValue) + potency = newValue + +/obj/item/weapon/grown/log + name = "tower-cap log" + desc = "It's better than bad, it's good!" + icon = 'icons/obj/hydroponics/harvest.dmi' + icon_state = "logs" + force = 5 + 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") + +/obj/item/weapon/grown/log/attackby(obj/item/weapon/W, mob/user) + user.SetNextMove(CLICK_CD_INTERACT) + 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 in 1 to 2) + new/obj/item/stack/sheet/wood(user.loc) + qdel(src) + + +/obj/item/weapon/grown/sunflower + name = "sunflower" + desc = "It's beautiful! A certain person might beat you to death if you trample these." + icon = 'icons/obj/hydroponics/harvest.dmi' + icon_state = "sunflower" + damtype = "fire" + force = 0 + throwforce = 1 + w_class = 1.0 + throw_speed = 1 + throw_range = 3 + plant_type = 1 + seed = "/obj/item/seeds/sunflower" + +/obj/item/weapon/grown/nettle + 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 + throwforce = 1 + w_class = 2.0 + throw_speed = 1 + throw_range = 3 + plant_type = 1 + origin_tech = "combat=1" + seed = "/obj/item/seeds/nettleseed" + +/obj/item/weapon/grown/nettle/atom_init() + . = ..() + spawn(5) + 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 + desc = "The \red glowing \black nettle incites \redrage\black in you just from looking at it!" + icon = 'icons/obj/weapons.dmi' + name = "deathnettle" + icon_state = "deathnettle" + damtype = "fire" + force = 30 + throwforce = 1 + w_class = 2.0 + throw_speed = 1 + throw_range = 3 + plant_type = 1 + seed = "/obj/item/seeds/deathnettleseed" + origin_tech = "combat=3" + attack_verb = list("stung") + +/obj/item/weapon/grown/deathnettle/atom_init() + . = ..() + spawn(5) + reagents.add_reagent("nutriment", 1 + round((potency / 50), 1)) + reagents.add_reagent("pacid", round(potency, 1)) + force = round((5 + potency / 2.5), 1) + +/obj/item/weapon/grown/deathnettle/suicide_act(mob/user) + to_chat(viewers(user), "\red [user] is eating some of the [src.name]! It looks like \he's trying to commit suicide.") + return (BRUTELOSS | TOXLOSS) + +// ************************************* +// Pestkiller defines for hydroponics +// ************************************* + +/obj/item/pestkiller + name = "bottle of pestkiller" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + var/toxicity = 0 + var/PestKillStr = 0 + +/obj/item/pestkiller/atom_init() + . = ..() + pixel_x = rand(-5.0, 5) + pixel_y = rand(-5.0, 5) + +/obj/item/pestkiller/carbaryl + name = "bottle of carbaryl" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + toxicity = 4 + PestKillStr = 2 + +/obj/item/pestkiller/lindane + name = "bottle of lindane" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle18" + toxicity = 6 + PestKillStr = 4 + +/obj/item/pestkiller/phosmet + name = "bottle of phosmet" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle15" + toxicity = 8 + PestKillStr = 7 + +// ************************************* +// Hydroponics Tools +// ************************************* + +/obj/item/weapon/weedspray + desc = "It's a toxic mixture, in spray form, to kill small weeds." + icon = 'icons/obj/hydroponics/equipment.dmi' + name = "weed-spray" + icon_state = "weedspray" + item_state = "spray" + flags = OPENCONTAINER | NOBLUDGEON + slot_flags = SLOT_BELT + throwforce = 4 + w_class = 2.0 + throw_speed = 2 + throw_range = 10 + var/toxicity = 4 + var/WeedKillStr = 2 + +/obj/item/weapon/weedspray/suicide_act(mob/user) + to_chat(viewers(user), "\red [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/equipment.dmi' + name = "pest-spray" + icon_state = "pestspray" + item_state = "spraycan" + flags = OPENCONTAINER | NOBLUDGEON + slot_flags = SLOT_BELT + throwforce = 4 + w_class = 2.0 + throw_speed = 2 + throw_range = 10 + var/toxicity = 4 + var/PestKillStr = 2 + +/obj/item/weapon/pestspray/suicide_act(mob/user) + to_chat(viewers(user), "\red [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 = CONDUCT | NOBLUDGEON + force = 5.0 + throwforce = 7.0 + w_class = 2.0 + m_amt = 2550 + origin_tech = "materials=1;biotech=1" + 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" + var/toxicity = 0 + var/WeedKillStr = 0 + +/obj/item/weedkiller/triclopyr + name = "bottle of glyphosate" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + toxicity = 4 + WeedKillStr = 2 + +/obj/item/weedkiller/lindane + name = "bottle of triclopyr" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle18" + toxicity = 6 + WeedKillStr = 4 + +/obj/item/weedkiller/D24 + name = "bottle of 2,4-D" + icon = 'icons/obj/chemical.dmi' + 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" + w_class = 2.0 + var/mutmod = 0 + var/yieldmod = 0 + +/obj/item/nutrient/atom_init() + . = ..() + pixel_x = rand(-5.0, 5) + pixel_y = rand(-5.0, 5) + +/obj/item/nutrient/ez + name = "bottle of E-Z-Nutrient" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + mutmod = 1 + yieldmod = 1 + +/obj/item/nutrient/l4z + name = "bottle of Left 4 Zed" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle18" + mutmod = 2 + yieldmod = 0 + +/obj/item/nutrient/rh + name = "bottle of Robust Harvest" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle15" + mutmod = 0 + yieldmod = 2 diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index f308fa64e4fb..2178cfe8ea07 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -1,853 +1,853 @@ -/obj/item/weapon/phone - name = "red phone" - desc = "Should anything ever go wrong..." - icon = 'icons/obj/items.dmi' - icon_state = "red_phone" - flags = CONDUCT - force = 3.0 - throwforce = 2.0 - throw_speed = 1 - throw_range = 4 - w_class = 2 - attack_verb = list("called", "rang") - hitsound = 'sound/weapons/ring.ogg' - -/obj/item/weapon/rsp - name = "\improper Rapid-Seed-Producer (RSP)" - desc = "A device used to rapidly deploy seeds." - icon = 'icons/obj/items.dmi' - icon_state = "rcd" - opacity = 0 - density = 0 - anchored = 0.0 - var/matter = 0 - var/mode = 1 - w_class = 3.0 - -/obj/item/weapon/corncob - name = "corn cob" - desc = "A reminder of meals gone by." - icon = 'icons/obj/harvest.dmi' - icon_state = "corncob" - item_state = "corncob" - w_class = 2.0 - throwforce = 0 - throw_speed = 4 - throw_range = 20 - -/obj/item/weapon/c_tube - name = "cardboard tube" - desc = "A tube... of cardboard." - icon = 'icons/obj/items.dmi' - icon_state = "c_tube" - throwforce = 1 - w_class = 2.0 - throw_speed = 4 - throw_range = 5 - - -/obj/item/weapon/cane - name = "cane" - desc = "A cane used by a true gentlemen. Or a clown." - icon = 'icons/obj/weapons.dmi' - icon_state = "cane" - item_state = "stick" - flags = CONDUCT - force = 5.0 - throwforce = 7.0 - w_class = 2.0 - m_amt = 50 - attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") - -/obj/item/weapon/gift - name = "gift" - desc = "A wrapped item." - icon = 'icons/obj/items.dmi' - icon_state = "gift3" - var/size = 3.0 - var/obj/item/gift = null - item_state = "gift" - w_class = 4.0 - -/obj/item/weapon/legcuffs - name = "legcuffs" - desc = "Use this to keep prisoners in line." - gender = PLURAL - icon = 'icons/obj/items.dmi' - icon_state = "handcuff" - flags = CONDUCT - throwforce = 0 - w_class = 3.0 - origin_tech = "materials=1" - var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute - -/obj/item/weapon/legcuffs/beartrap - name = "bear trap" - throw_speed = 2 - throw_range = 1 - icon_state = "beartrap0" - desc = "A trap used to catch bears and other legged creatures." - var/armed = 0 - - suicide_act(mob/user) - to_chat(viewers(user), "[user] is putting the [src.name] on \his head! It looks like \he's trying to commit suicide.") - return (BRUTELOSS) - -/obj/item/weapon/legcuffs/beartrap/attack_self(mob/user) - ..() - if(ishuman(user) && !user.stat && !user.restrained()) - armed = !armed - icon_state = "beartrap[armed]" - to_chat(user, "[src] is now [armed ? "armed" : "disarmed"].") - -/obj/item/weapon/legcuffs/beartrap/Crossed(AM as mob|obj) - if(armed) - if(ishuman(AM)) - if(isturf(src.loc)) - var/mob/living/carbon/H = AM - if(H.m_intent == "run") - armed = 0 - H.legcuffed = src - src.loc = H - H.update_inv_legcuffed() - to_chat(H, "You step on \the [src]!") - feedback_add_details("handcuffs","B") //Yes, I know they're legcuffs. Don't change this, no need for an extra variable. The "B" is used to tell them apart. - for(var/mob/O in viewers(H, null)) - if(O == H) - continue - O.show_message("[H] steps on \the [src].", 1) - if(isanimal(AM) && !istype(AM, /mob/living/simple_animal/parrot) && !istype(AM, /mob/living/simple_animal/construct) && !istype(AM, /mob/living/simple_animal/shade) && !istype(AM, /mob/living/simple_animal/hostile/viscerator)) - armed = 0 - var/mob/living/simple_animal/SA = AM - SA.health -= 20 - - icon_state = "beartrap[armed]" - ..() - -/obj/item/weapon/legcuffs/bola - name = "bola" - desc = "A restraining device designed to be thrown at the target. Upon connecting with said target, it will wrap around their legs, making it difficult for them to move quickly." - icon_state = "bola" - breakouttime = 35 //easy to apply, easy to break out of - origin_tech = "engineering=3;combat=1" - throw_speed = 5 - var/weaken = 0.8 - -/obj/item/weapon/legcuffs/bola/after_throw(datum/callback/callback) - ..() - playsound(src.loc,'sound/weapons/bolathrow.ogg', 75, 1) - -/obj/item/weapon/legcuffs/bola/throw_impact(atom/hit_atom) - if(!iscarbon(hit_atom))//if it gets caught or the target can't be cuffed, - return - var/mob/living/carbon/C = hit_atom - if(!C.legcuffed) - visible_message("\The [src] ensnares [C]!") - C.legcuffed = src - src.loc = C - C.update_inv_legcuffed() - feedback_add_details("handcuffs","B") - to_chat(C,"\The [src] ensnares you!") - C.Weaken(weaken) - -/obj/item/weapon/legcuffs/bola/tactical//traitor variant - name = "reinforced bola" - desc = "A strong bola, made with a long steel chain. It looks heavy, enough so that it could trip somebody." - icon_state = "bola_r" - breakouttime = 70 - origin_tech = "engineering=4;combat=3" - weaken = 6 - - -/obj/item/weapon/caution - desc = "Caution! Wet Floor!" - name = "wet floor sign" - icon = 'icons/obj/janitor.dmi' - icon_state = "caution" - force = 1.0 - throwforce = 3.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - attack_verb = list("warned", "cautioned", "smashed") - -/obj/item/weapon/caution/cone - desc = "This cone is trying to warn you of something!" - name = "warning cone" - icon_state = "cone" - -/obj/item/weapon/rack_parts - name = "rack parts" - desc = "Parts of a rack." - icon = 'icons/obj/items.dmi' - icon_state = "rack_parts" - flags = CONDUCT - m_amt = 3750 - -/obj/item/weapon/shard - name = "shard" - icon = 'icons/obj/shards.dmi' - icon_state = "large" - sharp = 1 - edge = 1 - desc = "Could probably be used as ... a throwing weapon?" - w_class = 2.0 - force = 5.0 - throwforce = 8.0 - item_state = "shard-glass" - g_amt = 3750 - attack_verb = list("stabbed", "slashed", "sliced", "cut") - - suicide_act(mob/user) - to_chat(viewers(user), pick("[user] is slitting \his wrists with the shard of glass! It looks like \he's trying to commit suicide.", \ - "[user] is slitting \his throat with the shard of glass! It looks like \he's trying to commit suicide.")) - return (BRUTELOSS) - -/obj/item/weapon/shard/attack(mob/living/carbon/M, mob/living/carbon/user) - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - -/obj/item/weapon/shard/afterattack(atom/A, mob/user, proximity) - if(!proximity) - return - if(isturf(A)) - return - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(!H.gloves && !H.species.flags[NO_MINORCUTS]) //specflags please.. - to_chat(H, "[src] cuts into your hand!") - var/obj/item/organ/external/BP = H.bodyparts_by_name[H.hand ? BP_L_ARM : BP_R_ARM] - BP.take_damage(force / 2, null, damage_flags()) - else if(ismonkey(user)) - var/mob/living/carbon/monkey/M = user - to_chat(M, "[src] cuts into your hand!") - M.adjustBruteLoss(force / 2) - -/*/obj/item/weapon/syndicate_uplink - name = "station bounced radio" - desc = "Remain silent about this..." - icon = 'icons/obj/radio.dmi' - icon_state = "radio" - var/temp = null - var/uses = 10.0 - var/selfdestruct = 0.0 - var/traitor_frequency = 0.0 - var/mob/currentUser = null - var/obj/item/device/radio/origradio = null - flags = CONDUCT | ONBELT - w_class = 2.0 - item_state = "radio" - throw_speed = 4 - throw_range = 20 - m_amt = 100 - origin_tech = "magnets=2;syndicate=3"*/ - -/obj/item/weapon/shard/shrapnel - name = "shrapnel" - icon = 'icons/obj/shards.dmi' - icon_state = "shrapnellarge" - desc = "A bunch of tiny bits of shattered metal." - -/obj/item/weapon/shard/shrapnel/atom_init() - . = ..() - - icon_state = pick("shrapnellarge", "shrapnelmedium", "shrapnelsmall") - switch(icon_state) - if("shrapnelsmall") - pixel_x = rand(-12, 12) - pixel_y = rand(-12, 12) - if("shrapnelmedium") - pixel_x = rand(-8, 8) - pixel_y = rand(-8, 8) - if("shrapnellarge") - pixel_x = rand(-5, 5) - pixel_y = rand(-5, 5) - -/obj/item/weapon/SWF_uplink - name = "station-bounced radio" - desc = "used to comunicate it appears." - icon = 'icons/obj/radio.dmi' - icon_state = "radio" - var/temp = null - var/uses = 4.0 - var/selfdestruct = 0.0 - var/traitor_frequency = 0.0 - var/obj/item/device/radio/origradio = null - flags = CONDUCT - slot_flags = SLOT_BELT - item_state = "radio" - throwforce = 5 - w_class = 2.0 - throw_speed = 4 - throw_range = 20 - m_amt = 100 - origin_tech = "magnets=1" - -/obj/item/weapon/staff - name = "wizards staff" - desc = "Apparently a staff used by the wizard." - icon = 'icons/obj/wizard.dmi' - icon_state = "staff" - force = 3.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - flags = NOSHIELD - attack_verb = list("bludgeoned", "whacked", "disciplined") - -/obj/item/weapon/staff/broom - name = "broom" - desc = "Used for sweeping, and flying into the night while cackling. Black cat not included." - icon = 'icons/obj/wizard.dmi' - icon_state = "broom" - -/obj/item/weapon/staff/gentcane - name = "Gentlemans Cane" - desc = "An ebony can with an ivory tip." - icon = 'icons/obj/weapons.dmi' - icon_state = "cane" - item_state = "stick" - -/obj/item/weapon/staff/stick - name = "stick" - desc = "A great tool to drag someone else's drinks across the bar." - icon = 'icons/obj/weapons.dmi' - icon_state = "stick" - item_state = "stick" - force = 3.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - flags = NOSHIELD - -/obj/item/weapon/table_parts - name = "table parts" - desc = "Parts of a table. Poor table." - gender = PLURAL - icon = 'icons/obj/items.dmi' - icon_state = "table_parts" - m_amt = 3750 - flags = CONDUCT - attack_verb = list("slammed", "bashed", "battered", "bludgeoned", "thrashed", "whacked") - -/obj/item/weapon/table_parts/reinforced - name = "reinforced table parts" - desc = "Hard table parts. Well...harder..." - icon = 'icons/obj/items.dmi' - icon_state = "reinf_tableparts" - m_amt = 7500 - flags = CONDUCT - -/obj/item/weapon/table_parts/wood - name = "wooden table parts" - desc = "Keep away from fire." - icon_state = "wood_tableparts" - flags = null - -/obj/item/weapon/table_parts/wood/poker - name = "poker table parts" - desc = "Keep away from fire, and keep near seedy dealers." - icon_state = "poker_tableparts" - flags = null - -/obj/item/weapon/table_parts/wood/fancy - name = "fancy table parts" - desc = "Covered with an amazingly fancy, patterned cloth." - icon_state = "fancy_tableparts" - -/obj/item/weapon/table_parts/wood/fancy/black - icon_state = "fancyblack_tableparts" - -/obj/item/weapon/table_parts/glass - name = "glass table parts" - desc = "Very fragile." - icon_state = "glass_tableparts" - flags = null - -/obj/item/weapon/wire - desc = "This is just a simple piece of regular insulated wire." - name = "wire" - icon = 'icons/obj/power.dmi' - icon_state = "item_wire" - var/amount = 1.0 - var/laying = 0.0 - var/old_lay = null - m_amt = 40 - attack_verb = list("whipped", "lashed", "disciplined", "tickled") - - 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) - -/obj/item/weapon/module - icon = 'icons/obj/module.dmi' - icon_state = "std_module" - w_class = 2.0 - item_state = "electronic" - flags = CONDUCT - var/mtype = 1 // 1=electronic 2=hardware - -/obj/item/weapon/module/card_reader - name = "card reader module" - icon_state = "card_mod" - desc = "An electronic module for reading data and ID cards." - -/obj/item/weapon/module/power_control - name = "power control module" - icon_state = "power_mod" - desc = "Heavy-duty switching circuits for power control." - m_amt = 50 - g_amt = 50 - -/obj/item/weapon/module/id_auth - name = "\improper ID authentication module" - icon_state = "id_mod" - desc = "A module allowing secure authorization of ID cards." - -/obj/item/weapon/module/cell_power - name = "power cell regulator module" - icon_state = "power_mod" - desc = "A converter and regulator allowing the use of power cells." - -/obj/item/weapon/module/cell_power - name = "power cell charger module" - icon_state = "power_mod" - desc = "Charging circuits for power cells." - -/obj/item/weapon/syntiflesh - name = "syntiflesh" - desc = "Meat that appears...strange..." - icon = 'icons/obj/food.dmi' - icon_state = "meat" - flags = CONDUCT - w_class = 2.0 - origin_tech = "biotech=2" - -/obj/item/weapon/hatchet - name = "hatchet" - desc = "A very sharp axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood." - icon = 'icons/obj/weapons.dmi' - icon_state = "hatchet" - flags = CONDUCT - force = 12.0 - sharp = 1 - edge = 1 - w_class = 2.0 - throwforce = 15.0 - throw_speed = 4 - throw_range = 4 - m_amt = 15000 - origin_tech = "materials=2;combat=1" - attack_verb = list("chopped", "torn", "cut") - -/obj/item/weapon/hatchet/attack(mob/living/carbon/M, mob/living/carbon/user) - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - -/obj/item/weapon/hatchet/unathiknife - name = "duelling knife" - desc = "A length of leather-bound wood studded with razor-sharp teeth. How crude." - icon = 'icons/obj/weapons.dmi' - icon_state = "unathiknife" - attack_verb = list("ripped", "torn", "cut") - -/obj/item/weapon/scythe - icon_state = "scythe0" - name = "scythe" - desc = "A sharp and curved blade on a long fibremetal handle, this tool makes it easy to reap what you sow." - force = 13.0 - throwforce = 5.0 - sharp = 1 - edge = 1 - throw_speed = 1 - throw_range = 3 - w_class = 4.0 - flags = NOSHIELD - slot_flags = SLOT_BACK - origin_tech = "materials=2;combat=2" - attack_verb = list("chopped", "sliced", "cut", "reaped") - -/obj/item/weapon/scythe/afterattack(atom/A, mob/user, proximity) - if(!proximity) return - if(istype(A, /obj/effect/spacevine)) - for(var/obj/effect/spacevine/B in orange(A, 1)) - if(prob(80)) - qdel(B) - qdel(A) - -/* -/obj/item/weapon/cigarpacket - name = "Pete's Cuban Cigars" - desc = "The most robust cigars on the planet." - icon = 'icons/obj/cigarettes.dmi' - icon_state = "cigarpacket" - item_state = "cigarpacket" - w_class = 1 - throwforce = 2 - var/cigarcount = 6 - flags = ONBELT */ - -/obj/item/weapon/pai_cable - desc = "A flexible coated cable with a universal jack on one end." - name = "data cable" - icon = 'icons/obj/power.dmi' - icon_state = "wire1" - - var/obj/machinery/machine - -/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 = NOBLUDGEON - w_class = 2.0 - origin_tech = "syndicate=2" - var/timer = 10 - var/atom/target = null - -///////////////////////////////////////Stock Parts ///////////////////////////////// - -/obj/item/weapon/storage/part_replacer - name = "Rapid Part Exchange Device" - desc = "Special mechanical module made to store, sort, and apply standard machine parts." - icon_state = "RPED" - item_state = "RPED" - w_class = 5 - can_hold = list("/obj/item/weapon/stock_parts") - storage_slots = 50 - use_to_pickup = 1 - allow_quick_gather = 1 - allow_quick_empty = 1 - collection_mode = 1 - display_contents_with_number = 1 - max_w_class = 3 - var/works_from_distance = 0 - var/pshoom_or_beepboopblorpzingshadashwoosh = 'sound/items/rped.ogg' - var/alt_sound = null - -/obj/item/weapon/storage/part_replacer/afterattack(obj/machinery/T, mob/living/carbon/human/user, flag) - if(flag) - return - if(works_from_distance && istype(T) && T.component_parts) - T.exchange_parts(user, src) - user.Beam(T,icon_state="rped_upgrade",icon='icons/effects/effects.dmi',time=5) - -/obj/item/weapon/storage/part_replacer/bluespace - name = "bluespace rapid part exchange device" - desc = "A version of the RPED that allows for replacement of parts and scanning from a distance, along with higher capacity for parts." - icon_state = "BS_RPED" - item_state = "BS_RPED" - w_class = 3 - storage_slots = 400 - max_w_class = 3 - works_from_distance = 1 - pshoom_or_beepboopblorpzingshadashwoosh = 'sound/items/PSHOOM.ogg' - alt_sound = 'sound/items/PSHOOM_2.ogg' - -/obj/item/weapon/storage/part_replacer/proc/play_rped_sound() - //Plays the sound for RPED exhanging or installing parts. - if(alt_sound && prob(1)) - playsound(src, alt_sound, 40, 1) - else - playsound(src, pshoom_or_beepboopblorpzingshadashwoosh, 40, 1) - -//Sorts stock parts inside an RPED by their rating. -//Only use /obj/item/weapon/stock_parts/ with this sort proc! -/proc/cmp_rped_sort(obj/item/weapon/stock_parts/A, obj/item/weapon/stock_parts/B) - return B.rating - A.rating - -/obj/item/weapon/stock_parts - name = "stock part" - desc = "What?" - icon = 'icons/obj/stock_parts.dmi' - w_class = 2.0 - var/rating = 1 - -/obj/item/weapon/stock_parts/atom_init() - . = ..() - pixel_x = rand(-5.0, 5) - pixel_y = rand(-5.0, 5) - -//Rank 1 - -/obj/item/weapon/stock_parts/console_screen - name = "console screen" - desc = "Used in the construction of computers and other devices with a interactive console." - icon_state = "screen" - origin_tech = "materials=1" - g_amt = 200 - -/obj/item/weapon/stock_parts/capacitor - name = "capacitor" - desc = "A basic capacitor used in the construction of a variety of devices." - icon_state = "capacitor" - origin_tech = "powerstorage=1" - m_amt = 50 - g_amt = 50 - -/obj/item/weapon/stock_parts/scanning_module - name = "scanning module" - desc = "A compact, high resolution scanning module used in the construction of certain devices." - icon_state = "scan_module" - origin_tech = "magnets=1" - m_amt = 50 - g_amt = 20 - -/obj/item/weapon/stock_parts/manipulator - name = "micro-manipulator" - desc = "A tiny little manipulator used in the construction of certain devices." - icon_state = "micro_mani" - origin_tech = "materials=1;programming=1" - m_amt = 30 - -/obj/item/weapon/stock_parts/micro_laser - name = "micro-laser" - desc = "A tiny laser used in certain devices." - icon_state = "micro_laser" - origin_tech = "magnets=1" - m_amt = 10 - g_amt = 20 - -/obj/item/weapon/stock_parts/matter_bin - name = "matter bin" - desc = "A container for hold compressed matter awaiting re-construction." - icon_state = "matter_bin" - origin_tech = "materials=1" - m_amt = 80 - -//Rank 2 - -/obj/item/weapon/stock_parts/capacitor/adv - name = "advanced capacitor" - desc = "An advanced capacitor used in the construction of a variety of devices." - icon_state = "adv_capacitor" - origin_tech = "powerstorage=3" - rating = 2 - m_amt = 50 - g_amt = 50 - -/obj/item/weapon/stock_parts/scanning_module/adv - name = "advanced scanning module" - desc = "A compact, high resolution scanning module used in the construction of certain devices." - icon_state = "adv_scan_module" - origin_tech = "magnets=3" - rating = 2 - m_amt = 50 - g_amt = 20 - -/obj/item/weapon/stock_parts/manipulator/nano - name = "nano-manipulator" - desc = "A tiny little manipulator used in the construction of certain devices." - icon_state = "nano_mani" - origin_tech = "materials=3,programming=2" - rating = 2 - m_amt = 30 - -/obj/item/weapon/stock_parts/micro_laser/high - name = "high-power micro-laser" - desc = "A tiny laser used in certain devices." - icon_state = "high_micro_laser" - origin_tech = "magnets=3" - rating = 2 - m_amt = 10 - g_amt = 20 - -/obj/item/weapon/stock_parts/matter_bin/adv - name = "advanced matter bin" - desc = "A container for hold compressed matter awaiting re-construction." - icon_state = "advanced_matter_bin" - origin_tech = "materials=3" - rating = 2 - m_amt = 80 - -//Rating 3 - -/obj/item/weapon/stock_parts/capacitor/super - name = "super capacitor" - desc = "A super-high capacity capacitor used in the construction of a variety of devices." - icon_state = "super_capacitor" - origin_tech = "powerstorage=5;materials=4" - rating = 3 - m_amt = 50 - g_amt = 50 - -/obj/item/weapon/stock_parts/scanning_module/phasic - name = "phasic scanning module" - desc = "A compact, high resolution phasic scanning module used in the construction of certain devices." - icon_state = "super_scan_module" - origin_tech = "magnets=5" - rating = 3 - m_amt = 50 - g_amt = 20 - -/obj/item/weapon/stock_parts/manipulator/pico - name = "pico-manipulator" - desc = "A tiny little manipulator used in the construction of certain devices." - icon_state = "pico_mani" - origin_tech = "materials=5,programming=2" - rating = 3 - m_amt = 30 - -/obj/item/weapon/stock_parts/micro_laser/ultra - name = "ultra-high-power micro-laser" - icon_state = "ultra_high_micro_laser" - desc = "A tiny laser used in certain devices." - origin_tech = "magnets=5" - rating = 3 - m_amt = 10 - g_amt = 20 - -/obj/item/weapon/stock_parts/matter_bin/super - name = "super matter bin" - desc = "A container for hold compressed matter awaiting re-construction." - icon_state = "super_matter_bin" - origin_tech = "materials=5" - rating = 3 - m_amt = 80 - -//Rating 4 - -/obj/item/weapon/stock_parts/capacitor/quadratic - name = "quadratic capacitor" - desc = "An capacity capacitor used in the construction of a variety of devices." - icon_state = "quadratic_capacitor" - origin_tech = "powerstorage=6;materials=5" - rating = 4 - m_amt = 50 - g_amt = 50 - -/obj/item/weapon/stock_parts/scanning_module/triphasic - name = "triphasic scanning module" - desc = "A compact, ultra resolution triphasic scanning module used in the construction of certain devices." - icon_state = "triphasic_scan_module" - origin_tech = "magnets=6" - rating = 4 - m_amt = 50 - g_amt = 20 - -/obj/item/weapon/stock_parts/manipulator/femto - name = "femto-manipulator" - desc = "A tiny little manipulator used in the construction of certain devices." - icon_state = "femto_mani" - origin_tech = "materials=6;programming=3" - rating = 4 - m_amt = 30 - -/obj/item/weapon/stock_parts/micro_laser/quadultra - name = "quad-ultra micro-laser" - icon_state = "quadultra_micro_laser" - desc = "A tiny laser used in certain devices." - origin_tech = "magnets=6" - rating = 4 - m_amt = 10 - g_amt = 20 - -/obj/item/weapon/stock_parts/matter_bin/bluespace - name = "bluespace matter bin" - desc = "A container for hold compressed matter awaiting re-construction." - icon_state = "bluespace_matter_bin" - origin_tech = "materials=6" - rating = 4 - m_amt = 80 - -// Subspace stock parts - -/obj/item/weapon/stock_parts/subspace/ansible - name = "subspace ansible" - icon_state = "subspace_ansible" - desc = "A compact module capable of sensing extradimensional activity." - origin_tech = "programming=3;magnets=5;materials=4;bluespace=2" - m_amt = 30 - g_amt = 10 - -/obj/item/weapon/stock_parts/subspace/filter - name = "hyperwave filter" - icon_state = "hyperwave_filter" - desc = "A tiny device capable of filtering and converting super-intense radiowaves." - origin_tech = "programming=4;magnets=2" - m_amt = 30 - g_amt = 10 - -/obj/item/weapon/stock_parts/subspace/amplifier - name = "subspace amplifier" - icon_state = "subspace_amplifier" - desc = "A compact micro-machine capable of amplifying weak subspace transmissions." - origin_tech = "programming=3;magnets=4;materials=4;bluespace=2" - m_amt = 30 - g_amt = 10 - -/obj/item/weapon/stock_parts/subspace/treatment - name = "subspace treatment disk" - icon_state = "treatment_disk" - desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves." - origin_tech = "programming=3;magnets=2;materials=5;bluespace=2" - m_amt = 30 - g_amt = 10 - -/obj/item/weapon/stock_parts/subspace/analyzer - name = "subspace wavelength analyzer" - icon_state = "wavelength_analyzer" - desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths." - origin_tech = "programming=3;magnets=4;materials=4;bluespace=2" - m_amt = 30 - g_amt = 10 - -/obj/item/weapon/stock_parts/subspace/crystal - name = "ansible crystal" - icon_state = "ansible_crystal" - desc = "A crystal made from pure glass used to transmit laser databursts to subspace." - origin_tech = "magnets=4;materials=4;bluespace=2" - g_amt = 50 - -/obj/item/weapon/stock_parts/subspace/transmitter - name = "subspace transmitter" - icon_state = "subspace_transmitter" - desc = "A large piece of equipment used to open a window into the subspace dimension." - origin_tech = "magnets=5;materials=5;bluespace=3" - m_amt = 50 - -/obj/item/weapon/research//Makes testing much less of a pain -Sieve - name = "research" - icon = 'icons/obj/stock_parts.dmi' - icon_state = "capacitor" - desc = "A debug item for research." - origin_tech = "materials=8;engineering=8;phorontech=8;powerstorage=8;bluespace=8;biotech=8;combat=8;magnets=8;programming=8;syndicate=8" - -/obj/item/weapon/broom - name = "Broom" - desc = "This broom is made with the branches and leaves of a tree which secretes aromatic oils." - icon_state = "broom_sauna" - -/obj/item/weapon/broom/attack(mob/living/carbon/human/M, mob/living/user, def_zone) - if(!istype(M) || user.a_intent == "hurt") - return ..() - if(wet - 5 < 0) - to_chat(user, "Soak this [src] first!") - return - if(M == user) - to_chat(user, "You can't birching yourself!") - return - if(!M.lying) - to_chat(user, "[M] Must be lie down first!") - return - - var/zone = check_zone(user.zone_sel.selecting) - var/obj/item/organ/external/BP = M.get_bodypart(zone) - for(var/obj/item/clothing/C in M.get_equipped_items()) - if(C.body_parts_covered & BP.body_part) - to_chat(user, "Take off [M]'s clothes first!") - return - - zone = parse_zone(zone) - wet -= 5 - user.visible_message("A [user] lightly Birching [M]'s [zone] with [src]!", - "You lightly Birching [M]'s [zone] with [src]!") - - - - +/obj/item/weapon/phone + name = "red phone" + desc = "Should anything ever go wrong..." + icon = 'icons/obj/items.dmi' + icon_state = "red_phone" + flags = CONDUCT + force = 3.0 + throwforce = 2.0 + throw_speed = 1 + throw_range = 4 + w_class = 2 + attack_verb = list("called", "rang") + hitsound = 'sound/weapons/ring.ogg' + +/obj/item/weapon/rsp + name = "\improper Rapid-Seed-Producer (RSP)" + desc = "A device used to rapidly deploy seeds." + icon = 'icons/obj/items.dmi' + icon_state = "rcd" + opacity = 0 + density = 0 + anchored = 0.0 + var/matter = 0 + var/mode = 1 + w_class = 3.0 + +/obj/item/weapon/corncob + name = "corn cob" + desc = "A reminder of meals gone by." + icon = 'icons/obj/harvest.dmi' + icon_state = "corncob" + item_state = "corncob" + w_class = 2.0 + throwforce = 0 + throw_speed = 4 + throw_range = 20 + +/obj/item/weapon/c_tube + name = "cardboard tube" + desc = "A tube... of cardboard." + icon = 'icons/obj/items.dmi' + icon_state = "c_tube" + throwforce = 1 + w_class = 2.0 + throw_speed = 4 + throw_range = 5 + + +/obj/item/weapon/cane + name = "cane" + desc = "A cane used by a true gentlemen. Or a clown." + icon = 'icons/obj/weapons.dmi' + icon_state = "cane" + item_state = "stick" + flags = CONDUCT + force = 5.0 + throwforce = 7.0 + w_class = 2.0 + m_amt = 50 + attack_verb = list("bludgeoned", "whacked", "disciplined", "thrashed") + +/obj/item/weapon/gift + name = "gift" + desc = "A wrapped item." + icon = 'icons/obj/items.dmi' + icon_state = "gift3" + var/size = 3.0 + var/obj/item/gift = null + item_state = "gift" + w_class = 4.0 + +/obj/item/weapon/legcuffs + name = "legcuffs" + desc = "Use this to keep prisoners in line." + gender = PLURAL + icon = 'icons/obj/items.dmi' + icon_state = "handcuff" + flags = CONDUCT + throwforce = 0 + w_class = 3.0 + origin_tech = "materials=1" + var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute + +/obj/item/weapon/legcuffs/beartrap + name = "bear trap" + throw_speed = 2 + throw_range = 1 + icon_state = "beartrap0" + desc = "A trap used to catch bears and other legged creatures." + var/armed = 0 + + suicide_act(mob/user) + to_chat(viewers(user), "[user] is putting the [src.name] on \his head! It looks like \he's trying to commit suicide.") + return (BRUTELOSS) + +/obj/item/weapon/legcuffs/beartrap/attack_self(mob/user) + ..() + if(ishuman(user) && !user.stat && !user.restrained()) + armed = !armed + icon_state = "beartrap[armed]" + to_chat(user, "[src] is now [armed ? "armed" : "disarmed"].") + +/obj/item/weapon/legcuffs/beartrap/Crossed(AM as mob|obj) + if(armed) + if(ishuman(AM)) + if(isturf(src.loc)) + var/mob/living/carbon/H = AM + if(H.m_intent == "run") + armed = 0 + H.legcuffed = src + src.loc = H + H.update_inv_legcuffed() + to_chat(H, "You step on \the [src]!") + feedback_add_details("handcuffs","B") //Yes, I know they're legcuffs. Don't change this, no need for an extra variable. The "B" is used to tell them apart. + for(var/mob/O in viewers(H, null)) + if(O == H) + continue + O.show_message("[H] steps on \the [src].", 1) + if(isanimal(AM) && !istype(AM, /mob/living/simple_animal/parrot) && !istype(AM, /mob/living/simple_animal/construct) && !istype(AM, /mob/living/simple_animal/shade) && !istype(AM, /mob/living/simple_animal/hostile/viscerator)) + armed = 0 + var/mob/living/simple_animal/SA = AM + SA.health -= 20 + + icon_state = "beartrap[armed]" + ..() + +/obj/item/weapon/legcuffs/bola + name = "bola" + desc = "A restraining device designed to be thrown at the target. Upon connecting with said target, it will wrap around their legs, making it difficult for them to move quickly." + icon_state = "bola" + breakouttime = 35 //easy to apply, easy to break out of + origin_tech = "engineering=3;combat=1" + throw_speed = 5 + var/weaken = 0.8 + +/obj/item/weapon/legcuffs/bola/after_throw(datum/callback/callback) + ..() + playsound(src.loc,'sound/weapons/bolathrow.ogg', 75, 1) + +/obj/item/weapon/legcuffs/bola/throw_impact(atom/hit_atom) + if(!iscarbon(hit_atom))//if it gets caught or the target can't be cuffed, + return + var/mob/living/carbon/C = hit_atom + if(!C.legcuffed) + visible_message("\The [src] ensnares [C]!") + C.legcuffed = src + src.loc = C + C.update_inv_legcuffed() + feedback_add_details("handcuffs","B") + to_chat(C,"\The [src] ensnares you!") + C.Weaken(weaken) + +/obj/item/weapon/legcuffs/bola/tactical//traitor variant + name = "reinforced bola" + desc = "A strong bola, made with a long steel chain. It looks heavy, enough so that it could trip somebody." + icon_state = "bola_r" + breakouttime = 70 + origin_tech = "engineering=4;combat=3" + weaken = 6 + + +/obj/item/weapon/caution + desc = "Caution! Wet Floor!" + name = "wet floor sign" + icon = 'icons/obj/janitor.dmi' + icon_state = "caution" + force = 1.0 + throwforce = 3.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + attack_verb = list("warned", "cautioned", "smashed") + +/obj/item/weapon/caution/cone + desc = "This cone is trying to warn you of something!" + name = "warning cone" + icon_state = "cone" + +/obj/item/weapon/rack_parts + name = "rack parts" + desc = "Parts of a rack." + icon = 'icons/obj/items.dmi' + icon_state = "rack_parts" + flags = CONDUCT + m_amt = 3750 + +/obj/item/weapon/shard + name = "shard" + icon = 'icons/obj/shards.dmi' + icon_state = "large" + sharp = 1 + edge = 1 + desc = "Could probably be used as ... a throwing weapon?" + w_class = 2.0 + force = 5.0 + throwforce = 8.0 + item_state = "shard-glass" + g_amt = 3750 + attack_verb = list("stabbed", "slashed", "sliced", "cut") + + suicide_act(mob/user) + to_chat(viewers(user), pick("[user] is slitting \his wrists with the shard of glass! It looks like \he's trying to commit suicide.", \ + "[user] is slitting \his throat with the shard of glass! It looks like \he's trying to commit suicide.")) + return (BRUTELOSS) + +/obj/item/weapon/shard/attack(mob/living/carbon/M, mob/living/carbon/user) + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return ..() + +/obj/item/weapon/shard/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return + if(isturf(A)) + return + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(!H.gloves && !H.species.flags[NO_MINORCUTS]) //specflags please.. + to_chat(H, "[src] cuts into your hand!") + var/obj/item/organ/external/BP = H.bodyparts_by_name[H.hand ? BP_L_ARM : BP_R_ARM] + BP.take_damage(force / 2, null, damage_flags()) + else if(ismonkey(user)) + var/mob/living/carbon/monkey/M = user + to_chat(M, "[src] cuts into your hand!") + M.adjustBruteLoss(force / 2) + +/*/obj/item/weapon/syndicate_uplink + name = "station bounced radio" + desc = "Remain silent about this..." + icon = 'icons/obj/radio.dmi' + icon_state = "radio" + var/temp = null + var/uses = 10.0 + var/selfdestruct = 0.0 + var/traitor_frequency = 0.0 + var/mob/currentUser = null + var/obj/item/device/radio/origradio = null + flags = CONDUCT | ONBELT + w_class = 2.0 + item_state = "radio" + throw_speed = 4 + throw_range = 20 + m_amt = 100 + origin_tech = "magnets=2;syndicate=3"*/ + +/obj/item/weapon/shard/shrapnel + name = "shrapnel" + icon = 'icons/obj/shards.dmi' + icon_state = "shrapnellarge" + desc = "A bunch of tiny bits of shattered metal." + +/obj/item/weapon/shard/shrapnel/atom_init() + . = ..() + + icon_state = pick("shrapnellarge", "shrapnelmedium", "shrapnelsmall") + switch(icon_state) + if("shrapnelsmall") + pixel_x = rand(-12, 12) + pixel_y = rand(-12, 12) + if("shrapnelmedium") + pixel_x = rand(-8, 8) + pixel_y = rand(-8, 8) + if("shrapnellarge") + pixel_x = rand(-5, 5) + pixel_y = rand(-5, 5) + +/obj/item/weapon/SWF_uplink + name = "station-bounced radio" + desc = "used to comunicate it appears." + icon = 'icons/obj/radio.dmi' + icon_state = "radio" + var/temp = null + var/uses = 4.0 + var/selfdestruct = 0.0 + var/traitor_frequency = 0.0 + var/obj/item/device/radio/origradio = null + flags = CONDUCT + slot_flags = SLOT_BELT + item_state = "radio" + throwforce = 5 + w_class = 2.0 + throw_speed = 4 + throw_range = 20 + m_amt = 100 + origin_tech = "magnets=1" + +/obj/item/weapon/staff + name = "wizards staff" + desc = "Apparently a staff used by the wizard." + icon = 'icons/obj/wizard.dmi' + icon_state = "staff" + force = 3.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + flags = NOSHIELD + attack_verb = list("bludgeoned", "whacked", "disciplined") + +/obj/item/weapon/staff/broom + name = "broom" + desc = "Used for sweeping, and flying into the night while cackling. Black cat not included." + icon = 'icons/obj/wizard.dmi' + icon_state = "broom" + +/obj/item/weapon/staff/gentcane + name = "Gentlemans Cane" + desc = "An ebony can with an ivory tip." + icon = 'icons/obj/weapons.dmi' + icon_state = "cane" + item_state = "stick" + +/obj/item/weapon/staff/stick + name = "stick" + desc = "A great tool to drag someone else's drinks across the bar." + icon = 'icons/obj/weapons.dmi' + icon_state = "stick" + item_state = "stick" + force = 3.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + flags = NOSHIELD + +/obj/item/weapon/table_parts + name = "table parts" + desc = "Parts of a table. Poor table." + gender = PLURAL + icon = 'icons/obj/items.dmi' + icon_state = "table_parts" + m_amt = 3750 + flags = CONDUCT + attack_verb = list("slammed", "bashed", "battered", "bludgeoned", "thrashed", "whacked") + +/obj/item/weapon/table_parts/reinforced + name = "reinforced table parts" + desc = "Hard table parts. Well...harder..." + icon = 'icons/obj/items.dmi' + icon_state = "reinf_tableparts" + m_amt = 7500 + flags = CONDUCT + +/obj/item/weapon/table_parts/wood + name = "wooden table parts" + desc = "Keep away from fire." + icon_state = "wood_tableparts" + flags = null + +/obj/item/weapon/table_parts/wood/poker + name = "poker table parts" + desc = "Keep away from fire, and keep near seedy dealers." + icon_state = "poker_tableparts" + flags = null + +/obj/item/weapon/table_parts/wood/fancy + name = "fancy table parts" + desc = "Covered with an amazingly fancy, patterned cloth." + icon_state = "fancy_tableparts" + +/obj/item/weapon/table_parts/wood/fancy/black + icon_state = "fancyblack_tableparts" + +/obj/item/weapon/table_parts/glass + name = "glass table parts" + desc = "Very fragile." + icon_state = "glass_tableparts" + flags = null + +/obj/item/weapon/wire + desc = "This is just a simple piece of regular insulated wire." + name = "wire" + icon = 'icons/obj/power.dmi' + icon_state = "item_wire" + var/amount = 1.0 + var/laying = 0.0 + var/old_lay = null + m_amt = 40 + attack_verb = list("whipped", "lashed", "disciplined", "tickled") + + 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) + +/obj/item/weapon/module + icon = 'icons/obj/module.dmi' + icon_state = "std_module" + w_class = 2.0 + item_state = "electronic" + flags = CONDUCT + var/mtype = 1 // 1=electronic 2=hardware + +/obj/item/weapon/module/card_reader + name = "card reader module" + icon_state = "card_mod" + desc = "An electronic module for reading data and ID cards." + +/obj/item/weapon/module/power_control + name = "power control module" + icon_state = "power_mod" + desc = "Heavy-duty switching circuits for power control." + m_amt = 50 + g_amt = 50 + +/obj/item/weapon/module/id_auth + name = "\improper ID authentication module" + icon_state = "id_mod" + desc = "A module allowing secure authorization of ID cards." + +/obj/item/weapon/module/cell_power + name = "power cell regulator module" + icon_state = "power_mod" + desc = "A converter and regulator allowing the use of power cells." + +/obj/item/weapon/module/cell_power + name = "power cell charger module" + icon_state = "power_mod" + desc = "Charging circuits for power cells." + +/obj/item/weapon/syntiflesh + name = "syntiflesh" + desc = "Meat that appears...strange..." + icon = 'icons/obj/food.dmi' + icon_state = "meat" + flags = CONDUCT + w_class = 2.0 + origin_tech = "biotech=2" + +/obj/item/weapon/hatchet + name = "hatchet" + desc = "A very sharp axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood." + icon = 'icons/obj/weapons.dmi' + icon_state = "hatchet" + flags = CONDUCT + force = 12.0 + sharp = 1 + edge = 1 + w_class = 2.0 + throwforce = 15.0 + throw_speed = 4 + throw_range = 4 + m_amt = 15000 + origin_tech = "materials=2;combat=1" + attack_verb = list("chopped", "torn", "cut") + +/obj/item/weapon/hatchet/attack(mob/living/carbon/M, mob/living/carbon/user) + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return ..() + +/obj/item/weapon/hatchet/unathiknife + name = "duelling knife" + desc = "A length of leather-bound wood studded with razor-sharp teeth. How crude." + icon = 'icons/obj/weapons.dmi' + icon_state = "unathiknife" + attack_verb = list("ripped", "torn", "cut") + +/obj/item/weapon/scythe + icon_state = "scythe0" + name = "scythe" + desc = "A sharp and curved blade on a long fibremetal handle, this tool makes it easy to reap what you sow." + force = 13.0 + throwforce = 5.0 + sharp = 1 + edge = 1 + throw_speed = 1 + throw_range = 3 + w_class = 4.0 + flags = NOSHIELD + slot_flags = SLOT_BACK + origin_tech = "materials=2;combat=2" + attack_verb = list("chopped", "sliced", "cut", "reaped") + +/obj/item/weapon/scythe/afterattack(atom/A, mob/user, proximity) + if(!proximity) return + if(istype(A, /obj/effect/spacevine)) + for(var/obj/effect/spacevine/B in orange(A, 1)) + if(prob(80)) + qdel(B) + qdel(A) + +/* +/obj/item/weapon/cigarpacket + name = "Pete's Cuban Cigars" + desc = "The most robust cigars on the planet." + icon = 'icons/obj/cigarettes.dmi' + icon_state = "cigarpacket" + item_state = "cigarpacket" + w_class = 1 + throwforce = 2 + var/cigarcount = 6 + flags = ONBELT */ + +/obj/item/weapon/pai_cable + desc = "A flexible coated cable with a universal jack on one end." + name = "data cable" + icon = 'icons/obj/power.dmi' + icon_state = "wire1" + + var/obj/machinery/machine + +/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 = NOBLUDGEON + w_class = 2.0 + origin_tech = "syndicate=2" + var/timer = 10 + var/atom/target = null + +///////////////////////////////////////Stock Parts ///////////////////////////////// + +/obj/item/weapon/storage/part_replacer + name = "Rapid Part Exchange Device" + desc = "Special mechanical module made to store, sort, and apply standard machine parts." + icon_state = "RPED" + item_state = "RPED" + w_class = 5 + can_hold = list("/obj/item/weapon/stock_parts") + storage_slots = 50 + use_to_pickup = 1 + allow_quick_gather = 1 + allow_quick_empty = 1 + collection_mode = 1 + display_contents_with_number = 1 + max_w_class = 3 + var/works_from_distance = 0 + var/pshoom_or_beepboopblorpzingshadashwoosh = 'sound/items/rped.ogg' + var/alt_sound = null + +/obj/item/weapon/storage/part_replacer/afterattack(obj/machinery/T, mob/living/carbon/human/user, flag) + if(flag) + return + if(works_from_distance && istype(T) && T.component_parts) + T.exchange_parts(user, src) + user.Beam(T,icon_state="rped_upgrade",icon='icons/effects/effects.dmi',time=5) + +/obj/item/weapon/storage/part_replacer/bluespace + name = "bluespace rapid part exchange device" + desc = "A version of the RPED that allows for replacement of parts and scanning from a distance, along with higher capacity for parts." + icon_state = "BS_RPED" + item_state = "BS_RPED" + w_class = 3 + storage_slots = 400 + max_w_class = 3 + works_from_distance = 1 + pshoom_or_beepboopblorpzingshadashwoosh = 'sound/items/PSHOOM.ogg' + alt_sound = 'sound/items/PSHOOM_2.ogg' + +/obj/item/weapon/storage/part_replacer/proc/play_rped_sound() + //Plays the sound for RPED exhanging or installing parts. + if(alt_sound && prob(1)) + playsound(src, alt_sound, 40, 1) + else + playsound(src, pshoom_or_beepboopblorpzingshadashwoosh, 40, 1) + +//Sorts stock parts inside an RPED by their rating. +//Only use /obj/item/weapon/stock_parts/ with this sort proc! +/proc/cmp_rped_sort(obj/item/weapon/stock_parts/A, obj/item/weapon/stock_parts/B) + return B.rating - A.rating + +/obj/item/weapon/stock_parts + name = "stock part" + desc = "What?" + icon = 'icons/obj/stock_parts.dmi' + w_class = 2.0 + var/rating = 1 + +/obj/item/weapon/stock_parts/atom_init() + . = ..() + pixel_x = rand(-5.0, 5) + pixel_y = rand(-5.0, 5) + +//Rank 1 + +/obj/item/weapon/stock_parts/console_screen + name = "console screen" + desc = "Used in the construction of computers and other devices with a interactive console." + icon_state = "screen" + origin_tech = "materials=1" + g_amt = 200 + +/obj/item/weapon/stock_parts/capacitor + name = "capacitor" + desc = "A basic capacitor used in the construction of a variety of devices." + icon_state = "capacitor" + origin_tech = "powerstorage=1" + m_amt = 50 + g_amt = 50 + +/obj/item/weapon/stock_parts/scanning_module + name = "scanning module" + desc = "A compact, high resolution scanning module used in the construction of certain devices." + icon_state = "scan_module" + origin_tech = "magnets=1" + m_amt = 50 + g_amt = 20 + +/obj/item/weapon/stock_parts/manipulator + name = "micro-manipulator" + desc = "A tiny little manipulator used in the construction of certain devices." + icon_state = "micro_mani" + origin_tech = "materials=1;programming=1" + m_amt = 30 + +/obj/item/weapon/stock_parts/micro_laser + name = "micro-laser" + desc = "A tiny laser used in certain devices." + icon_state = "micro_laser" + origin_tech = "magnets=1" + m_amt = 10 + g_amt = 20 + +/obj/item/weapon/stock_parts/matter_bin + name = "matter bin" + desc = "A container for hold compressed matter awaiting re-construction." + icon_state = "matter_bin" + origin_tech = "materials=1" + m_amt = 80 + +//Rank 2 + +/obj/item/weapon/stock_parts/capacitor/adv + name = "advanced capacitor" + desc = "An advanced capacitor used in the construction of a variety of devices." + icon_state = "adv_capacitor" + origin_tech = "powerstorage=3" + rating = 2 + m_amt = 50 + g_amt = 50 + +/obj/item/weapon/stock_parts/scanning_module/adv + name = "advanced scanning module" + desc = "A compact, high resolution scanning module used in the construction of certain devices." + icon_state = "adv_scan_module" + origin_tech = "magnets=3" + rating = 2 + m_amt = 50 + g_amt = 20 + +/obj/item/weapon/stock_parts/manipulator/nano + name = "nano-manipulator" + desc = "A tiny little manipulator used in the construction of certain devices." + icon_state = "nano_mani" + origin_tech = "materials=3,programming=2" + rating = 2 + m_amt = 30 + +/obj/item/weapon/stock_parts/micro_laser/high + name = "high-power micro-laser" + desc = "A tiny laser used in certain devices." + icon_state = "high_micro_laser" + origin_tech = "magnets=3" + rating = 2 + m_amt = 10 + g_amt = 20 + +/obj/item/weapon/stock_parts/matter_bin/adv + name = "advanced matter bin" + desc = "A container for hold compressed matter awaiting re-construction." + icon_state = "advanced_matter_bin" + origin_tech = "materials=3" + rating = 2 + m_amt = 80 + +//Rating 3 + +/obj/item/weapon/stock_parts/capacitor/super + name = "super capacitor" + desc = "A super-high capacity capacitor used in the construction of a variety of devices." + icon_state = "super_capacitor" + origin_tech = "powerstorage=5;materials=4" + rating = 3 + m_amt = 50 + g_amt = 50 + +/obj/item/weapon/stock_parts/scanning_module/phasic + name = "phasic scanning module" + desc = "A compact, high resolution phasic scanning module used in the construction of certain devices." + icon_state = "super_scan_module" + origin_tech = "magnets=5" + rating = 3 + m_amt = 50 + g_amt = 20 + +/obj/item/weapon/stock_parts/manipulator/pico + name = "pico-manipulator" + desc = "A tiny little manipulator used in the construction of certain devices." + icon_state = "pico_mani" + origin_tech = "materials=5,programming=2" + rating = 3 + m_amt = 30 + +/obj/item/weapon/stock_parts/micro_laser/ultra + name = "ultra-high-power micro-laser" + icon_state = "ultra_high_micro_laser" + desc = "A tiny laser used in certain devices." + origin_tech = "magnets=5" + rating = 3 + m_amt = 10 + g_amt = 20 + +/obj/item/weapon/stock_parts/matter_bin/super + name = "super matter bin" + desc = "A container for hold compressed matter awaiting re-construction." + icon_state = "super_matter_bin" + origin_tech = "materials=5" + rating = 3 + m_amt = 80 + +//Rating 4 + +/obj/item/weapon/stock_parts/capacitor/quadratic + name = "quadratic capacitor" + desc = "An capacity capacitor used in the construction of a variety of devices." + icon_state = "quadratic_capacitor" + origin_tech = "powerstorage=6;materials=5" + rating = 4 + m_amt = 50 + g_amt = 50 + +/obj/item/weapon/stock_parts/scanning_module/triphasic + name = "triphasic scanning module" + desc = "A compact, ultra resolution triphasic scanning module used in the construction of certain devices." + icon_state = "triphasic_scan_module" + origin_tech = "magnets=6" + rating = 4 + m_amt = 50 + g_amt = 20 + +/obj/item/weapon/stock_parts/manipulator/femto + name = "femto-manipulator" + desc = "A tiny little manipulator used in the construction of certain devices." + icon_state = "femto_mani" + origin_tech = "materials=6;programming=3" + rating = 4 + m_amt = 30 + +/obj/item/weapon/stock_parts/micro_laser/quadultra + name = "quad-ultra micro-laser" + icon_state = "quadultra_micro_laser" + desc = "A tiny laser used in certain devices." + origin_tech = "magnets=6" + rating = 4 + m_amt = 10 + g_amt = 20 + +/obj/item/weapon/stock_parts/matter_bin/bluespace + name = "bluespace matter bin" + desc = "A container for hold compressed matter awaiting re-construction." + icon_state = "bluespace_matter_bin" + origin_tech = "materials=6" + rating = 4 + m_amt = 80 + +// Subspace stock parts + +/obj/item/weapon/stock_parts/subspace/ansible + name = "subspace ansible" + icon_state = "subspace_ansible" + desc = "A compact module capable of sensing extradimensional activity." + origin_tech = "programming=3;magnets=5;materials=4;bluespace=2" + m_amt = 30 + g_amt = 10 + +/obj/item/weapon/stock_parts/subspace/filter + name = "hyperwave filter" + icon_state = "hyperwave_filter" + desc = "A tiny device capable of filtering and converting super-intense radiowaves." + origin_tech = "programming=4;magnets=2" + m_amt = 30 + g_amt = 10 + +/obj/item/weapon/stock_parts/subspace/amplifier + name = "subspace amplifier" + icon_state = "subspace_amplifier" + desc = "A compact micro-machine capable of amplifying weak subspace transmissions." + origin_tech = "programming=3;magnets=4;materials=4;bluespace=2" + m_amt = 30 + g_amt = 10 + +/obj/item/weapon/stock_parts/subspace/treatment + name = "subspace treatment disk" + icon_state = "treatment_disk" + desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves." + origin_tech = "programming=3;magnets=2;materials=5;bluespace=2" + m_amt = 30 + g_amt = 10 + +/obj/item/weapon/stock_parts/subspace/analyzer + name = "subspace wavelength analyzer" + icon_state = "wavelength_analyzer" + desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths." + origin_tech = "programming=3;magnets=4;materials=4;bluespace=2" + m_amt = 30 + g_amt = 10 + +/obj/item/weapon/stock_parts/subspace/crystal + name = "ansible crystal" + icon_state = "ansible_crystal" + desc = "A crystal made from pure glass used to transmit laser databursts to subspace." + origin_tech = "magnets=4;materials=4;bluespace=2" + g_amt = 50 + +/obj/item/weapon/stock_parts/subspace/transmitter + name = "subspace transmitter" + icon_state = "subspace_transmitter" + desc = "A large piece of equipment used to open a window into the subspace dimension." + origin_tech = "magnets=5;materials=5;bluespace=3" + m_amt = 50 + +/obj/item/weapon/research//Makes testing much less of a pain -Sieve + name = "research" + icon = 'icons/obj/stock_parts.dmi' + icon_state = "capacitor" + desc = "A debug item for research." + origin_tech = "materials=8;engineering=8;phorontech=8;powerstorage=8;bluespace=8;biotech=8;combat=8;magnets=8;programming=8;syndicate=8" + +/obj/item/weapon/broom + name = "Broom" + desc = "This broom is made with the branches and leaves of a tree which secretes aromatic oils." + icon_state = "broom_sauna" + +/obj/item/weapon/broom/attack(mob/living/carbon/human/M, mob/living/user, def_zone) + if(!istype(M) || user.a_intent == "hurt") + return ..() + if(wet - 5 < 0) + to_chat(user, "Soak this [src] first!") + return + if(M == user) + to_chat(user, "You can't birching yourself!") + return + if(!M.lying) + to_chat(user, "[M] Must be lie down first!") + return + + var/zone = check_zone(user.zone_sel.selecting) + var/obj/item/organ/external/BP = M.get_bodypart(zone) + for(var/obj/item/clothing/C in M.get_equipped_items()) + if(C.body_parts_covered & BP.body_part) + to_chat(user, "Take off [M]'s clothes first!") + return + + zone = parse_zone(zone) + wet -= 5 + user.visible_message("A [user] lightly Birching [M]'s [zone] with [src]!", + "You lightly Birching [M]'s [zone] with [src]!") + + + + diff --git a/code/defines/procs/AStar.dm b/code/defines/procs/AStar.dm index afd43df2b357..776141c97139 100644 --- a/code/defines/procs/AStar.dm +++ b/code/defines/procs/AStar.dm @@ -1,191 +1,191 @@ -/** - * 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, moving atom, distance proc, max nodes, maximum node depth, minimum distance to target, adjacent proc, atom id, turfs to exclude, check only simulated) - * - * Optional extras to add on (in order): - * - Distance proc : the distance used in every A* calculation (length of path and heuristic) - * - 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. - * - Adjacent proc : returns the turfs to consider around the actually processed node - * - Simulated only : whether to consider unsimulated turfs or not (used by some Adjacent proc) - * - * Also added 'exclude' turf to avoid travelling over; defaults to null - * - * Actual Adjacent procs : - * - /turf/proc/reachableAdjacentTurfs : returns reachable turfs in cardinal directions (uses simulated_only) - */ - -///////////////// -//PathNode object -///////////////// - -/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(source, prevNode, g, h, nt) - src.source = source - src.prevNode = prevNode - - src.f = g + h - src.g = g - src.h = h - src.nt = nt - -/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 - -/** - * Reversed so that the Heap is a MinHeap rather than a MaxHeap - */ -/proc/HeapPathWeightCompare(PathNode/a, PathNode/b) - return b.f - a.f - -/** - * Wrapper that returns an empty list if A* failed to find a path - */ -/proc/get_path_to(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) - var/list/path = AStar(caller, end, dist, maxnodes, maxnodedepth, mintargetdist, adjacent,id, exclude, simulated_only) - if(!path) - path = list() - return path - -/** - * The actual A* algorithm - */ -/proc/AStar(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) - var/list/pnodelist = list() - - // Sanitation - var/start = get_turf(caller) - if(!start) - CRASH("Unable to get turf from caller") - - if(maxnodes) - // If start turf is farther than maxnodes from end turf, no need to do anything - if(call(start, dist)(end) > maxnodes) - return - - maxnodedepth = maxnodes // No need to consider path longer than maxnodes - - var/Heap/open = new /Heap(/proc/HeapPathWeightCompare) // The open list - var/list/closed = list() // The closed list - - var/list/path = null // The returned path, if any - var/PathNode/cur // Current processed turf - - // Initialization - open.Insert(new /PathNode(start,null,0,call(start,dist)(end),0)) - - // Then run the main loop - while(!open.IsEmpty() && !path) - cur = open.Pop() // Get the lower f turf in the open list - closed += 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 = list() - path += cur.source - - while(cur.prevNode) - cur = cur.prevNode - path += cur.source - - break - - // Get adjacents turfs using the adjacent proc, checking for access with id - var/list/L = call(cur.source,adjacent)(caller,id, simulated_only) - for(var/turf/T in L) - if(T == exclude || (T in closed)) - continue - - var/newg = cur.g + call(cur.source,dist)(T) - - var/PathNode/P = pnodelist[T] - if(!P) - // Is not already in open list, so add it - var/PathNode/newnode = new /PathNode(T,cur,newg,call(T,dist)(end),cur.nt+1) - open.Insert(newnode) - pnodelist[T] = newnode - else - // Is already in open list, check if it's a better way from the current turf - if(newg < P.g) - P.prevNode = cur - P.g = (newg * L.len / 9) - P.calc_f() - P.nt = cur.nt + 1 - open.ReSort(P) // Reorder the changed element in the list - CHECK_TICK - - - // Cleaning after us - pnodelist = null - - // Reverse the path to get it from start to finish - if(path) - for(var/i in 1 to (path.len / 2)) - path.Swap(i, path.len - i + 1) - - return path - -/** - * Returns adjacent turfs in cardinal directions that are reachable - * `simulated_only` controls whether only simulated turfs are considered or not - */ -/turf/proc/reachableAdjacentTurfs(caller, ID, simulated_only) - var/list/L = list() - - for(var/dir in cardinal) - var/turf/T = get_step(src, dir) - - if(simulated_only && !istype(T)) - continue - - if(!T.density && !LinkBlockedWithAccess(T, caller, ID)) - L += T - return L - -/turf/proc/LinkBlockedWithAccess(turf/T, caller, ID) - var/adir = get_dir(src, T) - var/rdir = get_dir(T, src) - - for(var/obj/structure/window/W in src) - if(!W.CanAStarPass(ID, adir)) - return TRUE - - for(var/obj/O in T) - if(!O.CanAStarPass(ID, rdir, caller)) - return TRUE - +/** + * 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, moving atom, distance proc, max nodes, maximum node depth, minimum distance to target, adjacent proc, atom id, turfs to exclude, check only simulated) + * + * Optional extras to add on (in order): + * - Distance proc : the distance used in every A* calculation (length of path and heuristic) + * - 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. + * - Adjacent proc : returns the turfs to consider around the actually processed node + * - Simulated only : whether to consider unsimulated turfs or not (used by some Adjacent proc) + * + * Also added 'exclude' turf to avoid travelling over; defaults to null + * + * Actual Adjacent procs : + * - /turf/proc/reachableAdjacentTurfs : returns reachable turfs in cardinal directions (uses simulated_only) + */ + +///////////////// +//PathNode object +///////////////// + +/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(source, prevNode, g, h, nt) + src.source = source + src.prevNode = prevNode + + src.f = g + h + src.g = g + src.h = h + src.nt = nt + +/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 + +/** + * Reversed so that the Heap is a MinHeap rather than a MaxHeap + */ +/proc/HeapPathWeightCompare(PathNode/a, PathNode/b) + return b.f - a.f + +/** + * Wrapper that returns an empty list if A* failed to find a path + */ +/proc/get_path_to(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) + var/list/path = AStar(caller, end, dist, maxnodes, maxnodedepth, mintargetdist, adjacent,id, exclude, simulated_only) + if(!path) + path = list() + return path + +/** + * The actual A* algorithm + */ +/proc/AStar(caller, end, dist, maxnodes, maxnodedepth = 30, mintargetdist, adjacent = /turf/proc/reachableAdjacentTurfs, id=null, turf/exclude=null, simulated_only = 1) + var/list/pnodelist = list() + + // Sanitation + var/start = get_turf(caller) + if(!start) + CRASH("Unable to get turf from caller") + + if(maxnodes) + // If start turf is farther than maxnodes from end turf, no need to do anything + if(call(start, dist)(end) > maxnodes) + return + + maxnodedepth = maxnodes // No need to consider path longer than maxnodes + + var/Heap/open = new /Heap(/proc/HeapPathWeightCompare) // The open list + var/list/closed = list() // The closed list + + var/list/path = null // The returned path, if any + var/PathNode/cur // Current processed turf + + // Initialization + open.Insert(new /PathNode(start,null,0,call(start,dist)(end),0)) + + // Then run the main loop + while(!open.IsEmpty() && !path) + cur = open.Pop() // Get the lower f turf in the open list + closed += 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 = list() + path += cur.source + + while(cur.prevNode) + cur = cur.prevNode + path += cur.source + + break + + // Get adjacents turfs using the adjacent proc, checking for access with id + var/list/L = call(cur.source,adjacent)(caller,id, simulated_only) + for(var/turf/T in L) + if(T == exclude || (T in closed)) + continue + + var/newg = cur.g + call(cur.source,dist)(T) + + var/PathNode/P = pnodelist[T] + if(!P) + // Is not already in open list, so add it + var/PathNode/newnode = new /PathNode(T,cur,newg,call(T,dist)(end),cur.nt+1) + open.Insert(newnode) + pnodelist[T] = newnode + else + // Is already in open list, check if it's a better way from the current turf + if(newg < P.g) + P.prevNode = cur + P.g = (newg * L.len / 9) + P.calc_f() + P.nt = cur.nt + 1 + open.ReSort(P) // Reorder the changed element in the list + CHECK_TICK + + + // Cleaning after us + pnodelist = null + + // Reverse the path to get it from start to finish + if(path) + for(var/i in 1 to (path.len / 2)) + path.Swap(i, path.len - i + 1) + + return path + +/** + * Returns adjacent turfs in cardinal directions that are reachable + * `simulated_only` controls whether only simulated turfs are considered or not + */ +/turf/proc/reachableAdjacentTurfs(caller, ID, simulated_only) + var/list/L = list() + + for(var/dir in cardinal) + var/turf/T = get_step(src, dir) + + if(simulated_only && !istype(T)) + continue + + if(!T.density && !LinkBlockedWithAccess(T, caller, ID)) + L += T + return L + +/turf/proc/LinkBlockedWithAccess(turf/T, caller, ID) + var/adir = get_dir(src, T) + var/rdir = get_dir(T, src) + + for(var/obj/structure/window/W in src) + if(!W.CanAStarPass(ID, adir)) + return TRUE + + for(var/obj/O in T) + if(!O.CanAStarPass(ID, rdir, caller)) + return TRUE + return FALSE \ No newline at end of file diff --git a/code/defines/procs/captain_announce.dm b/code/defines/procs/captain_announce.dm index bfaa7ba1c5a0..133370a5b550 100644 --- a/code/defines/procs/captain_announce.dm +++ b/code/defines/procs/captain_announce.dm @@ -1,6 +1,6 @@ -/proc/captain_announce(message, title = "Priority Announcement", announcer = "") - to_chat(world, "

    [title]

    ") - to_chat(world, "[message]") - if(announcer) - to_chat(world, " -[announcer]") - to_chat(world, "
    ") +/proc/captain_announce(message, title = "Priority Announcement", announcer = "") + to_chat(world, "

    [title]

    ") + to_chat(world, "[message]") + if(announcer) + to_chat(world, " -[announcer]") + to_chat(world, "
    ") diff --git a/code/defines/procs/command_alert.dm b/code/defines/procs/command_alert.dm index 2704b1bcd6df..2f7663387e2a 100644 --- a/code/defines/procs/command_alert.dm +++ b/code/defines/procs/command_alert.dm @@ -1,11 +1,11 @@ -/proc/command_alert(text, title = "") - var/command - command += "

    [command_name()] Update

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

    [title]

    " - - command += "
    [text]
    " - command += "
    " - for(var/mob/M in player_list) - if(!isnewplayer(M)) - to_chat(M, command) +/proc/command_alert(text, title = "") + var/command + command += "

    [command_name()] Update

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

    [title]

    " + + command += "
    [text]
    " + command += "
    " + for(var/mob/M in player_list) + if(!isnewplayer(M)) + to_chat(M, command) diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm index e0f8ab94af93..3a89c9ef8c49 100644 --- a/code/defines/procs/dbcore.dm +++ b/code/defines/procs/dbcore.dm @@ -1,208 +1,208 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -//cursors -#define Default_Cursor 0 -#define Client_Cursor 1 -#define Server_Cursor 2 -//conversions -#define TEXT_CONV 1 -#define RSC_FILE_CONV 2 -#define NUMBER_CONV 3 -//column flag values: -#define IS_NUMERIC 1 -#define IS_BINARY 2 -#define IS_NOT_NULL 4 -#define IS_PRIMARY_KEY 8 -#define IS_UNSIGNED 16 -//types -#define TINYINT 1 -#define SMALLINT 2 -#define MEDIUMINT 3 -#define INTEGER 4 -#define BIGINT 5 -#define DECIMAL 6 -#define FLOAT 7 -#define DOUBLE 8 -#define DATE 9 -#define DATETIME 10 -#define TIMESTAMP 11 -#define TIME 12 -#define STRING 13 -#define BLOB 14 -// TODO: Investigate more recent type additions and see if I can handle them. - Nadrew - - -// Deprecated! See global.dm for new configuration vars -/* -var/DB_SERVER = "" // This is the location of your MySQL server (localhost is USUALLY fine) -var/DB_PORT = 3306 // This is the port your MySQL server is running on (3306 is the default) -*/ - -/DBConnection - var/_db_con // This variable contains a reference to the actual database connection. - var/dbi // This variable is a string containing the DBI MySQL requires. - var/user // This variable contains the username data. - var/password // This variable contains the password data. - var/default_cursor // This contains the default database cursor data. - // - var/server = "" - var/port = 3306 - -/DBConnection/New(dbi_handler,username,password_handler,cursor_handler) - src.dbi = dbi_handler - src.user = username - src.password = password_handler - src.default_cursor = cursor_handler - _db_con = _dm_db_new_con() - -/DBConnection/proc/Connect(dbi_handler=src.dbi,user_handler=src.user,password_handler=src.password,cursor_handler) - if(!config.sql_enabled) - return 0 - if(!src) return 0 - cursor_handler = src.default_cursor - if(!cursor_handler) cursor_handler = Default_Cursor - return _dm_db_connect(_db_con,dbi_handler,user_handler,password_handler,cursor_handler,null) - -/DBConnection/proc/Disconnect() return _dm_db_close(_db_con) - -/DBConnection/proc/IsConnected() - if(!config.sql_enabled) return 0 - var/success = _dm_db_is_connected(_db_con) - return success - -/DBConnection/proc/Quote(str) return _dm_db_quote(_db_con,str) - -/DBConnection/proc/ErrorMsg() return _dm_db_error_msg(_db_con) -/DBConnection/proc/SelectDB(database_name,dbi) - if(IsConnected()) Disconnect() - //return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[DB_SERVER]:[DB_PORT]"]",user,password) - return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[sqladdress]:[sqlport]"]",user,password) -/DBConnection/proc/NewQuery(sql_query,cursor_handler=src.default_cursor) return new/DBQuery(sql_query,src,cursor_handler) - - -/DBQuery/New(sql_query,DBConnection/connection_handler,cursor_handler) - if(sql_query) src.sql = sql_query - if(connection_handler) src.db_connection = connection_handler - if(cursor_handler) src.default_cursor = cursor_handler - _db_query = _dm_db_new_query() - return ..() - - -/DBQuery - var/sql // The sql query being executed. - var/default_cursor - var/list/columns //list of DB Columns populated by Columns() - var/list/conversions - var/list/item[0] //list of data values populated by NextRow() - - var/DBConnection/db_connection - var/_db_query - -/DBQuery/proc/Connect(DBConnection/connection_handler) src.db_connection = connection_handler - -/DBQuery/proc/Execute(sql_query=src.sql,cursor_handler=default_cursor) - Close() - return _dm_db_execute(_db_query,sql_query,db_connection._db_con,cursor_handler,null) - -/DBQuery/proc/NextRow() return _dm_db_next_row(_db_query,item,conversions) - -/DBQuery/proc/RowsAffected() return _dm_db_rows_affected(_db_query) - -/DBQuery/proc/RowCount() return _dm_db_row_count(_db_query) - -/DBQuery/proc/ErrorMsg() return _dm_db_error_msg(_db_query) - -/DBQuery/proc/Columns() - if(!columns) - columns = _dm_db_columns(_db_query,/DBColumn) - return columns - -/DBQuery/proc/GetRowData() - var/list/columns = Columns() - var/list/results - if(columns.len) - results = list() - for(var/C in columns) - results+=C - var/DBColumn/cur_col = columns[C] - results[C] = src.item[(cur_col.position+1)] - return results - -/DBQuery/proc/Close() - item.len = 0 - columns = null - conversions = null - return _dm_db_close(_db_query) - -/DBQuery/proc/Quote(str) - return db_connection.Quote(str) - -/DBQuery/proc/SetConversion(column,conversion) - if(istext(column)) column = columns.Find(column) - if(!conversions) conversions = new/list(column) - else if(conversions.len < column) conversions.len = column - conversions[column] = conversion - - -/DBColumn - var/name - var/table - var/position //1-based index into item data - var/sql_type - var/flags - var/length - var/max_length - -/DBColumn/New(name_handler,table_handler,position_handler,type_handler,flag_handler,length_handler,max_length_handler) - src.name = name_handler - src.table = table_handler - src.position = position_handler - src.sql_type = type_handler - src.flags = flag_handler - src.length = length_handler - src.max_length = max_length_handler - return ..() - - -/DBColumn/proc/SqlTypeName(type_handler=src.sql_type) - switch(type_handler) - if(TINYINT) return "TINYINT" - if(SMALLINT) return "SMALLINT" - if(MEDIUMINT) return "MEDIUMINT" - if(INTEGER) return "INTEGER" - if(BIGINT) return "BIGINT" - if(FLOAT) return "FLOAT" - if(DOUBLE) return "DOUBLE" - if(DATE) return "DATE" - if(DATETIME) return "DATETIME" - if(TIMESTAMP) return "TIMESTAMP" - if(TIME) return "TIME" - if(STRING) return "STRING" - if(BLOB) return "BLOB" - - -#undef Default_Cursor -#undef Client_Cursor -#undef Server_Cursor -#undef TEXT_CONV -#undef RSC_FILE_CONV -#undef NUMBER_CONV -#undef IS_NUMERIC -#undef IS_BINARY -#undef IS_NOT_NULL -#undef IS_PRIMARY_KEY -#undef IS_UNSIGNED -#undef TINYINT -#undef SMALLINT -#undef MEDIUMINT -#undef INTEGER -#undef BIGINT -#undef DECIMAL -#undef FLOAT -#undef DOUBLE -#undef DATE -#undef DATETIME -#undef TIMESTAMP -#undef TIME -#undef STRING -#undef BLOB +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +//cursors +#define Default_Cursor 0 +#define Client_Cursor 1 +#define Server_Cursor 2 +//conversions +#define TEXT_CONV 1 +#define RSC_FILE_CONV 2 +#define NUMBER_CONV 3 +//column flag values: +#define IS_NUMERIC 1 +#define IS_BINARY 2 +#define IS_NOT_NULL 4 +#define IS_PRIMARY_KEY 8 +#define IS_UNSIGNED 16 +//types +#define TINYINT 1 +#define SMALLINT 2 +#define MEDIUMINT 3 +#define INTEGER 4 +#define BIGINT 5 +#define DECIMAL 6 +#define FLOAT 7 +#define DOUBLE 8 +#define DATE 9 +#define DATETIME 10 +#define TIMESTAMP 11 +#define TIME 12 +#define STRING 13 +#define BLOB 14 +// TODO: Investigate more recent type additions and see if I can handle them. - Nadrew + + +// Deprecated! See global.dm for new configuration vars +/* +var/DB_SERVER = "" // This is the location of your MySQL server (localhost is USUALLY fine) +var/DB_PORT = 3306 // This is the port your MySQL server is running on (3306 is the default) +*/ + +/DBConnection + var/_db_con // This variable contains a reference to the actual database connection. + var/dbi // This variable is a string containing the DBI MySQL requires. + var/user // This variable contains the username data. + var/password // This variable contains the password data. + var/default_cursor // This contains the default database cursor data. + // + var/server = "" + var/port = 3306 + +/DBConnection/New(dbi_handler,username,password_handler,cursor_handler) + src.dbi = dbi_handler + src.user = username + src.password = password_handler + src.default_cursor = cursor_handler + _db_con = _dm_db_new_con() + +/DBConnection/proc/Connect(dbi_handler=src.dbi,user_handler=src.user,password_handler=src.password,cursor_handler) + if(!config.sql_enabled) + return 0 + if(!src) return 0 + cursor_handler = src.default_cursor + if(!cursor_handler) cursor_handler = Default_Cursor + return _dm_db_connect(_db_con,dbi_handler,user_handler,password_handler,cursor_handler,null) + +/DBConnection/proc/Disconnect() return _dm_db_close(_db_con) + +/DBConnection/proc/IsConnected() + if(!config.sql_enabled) return 0 + var/success = _dm_db_is_connected(_db_con) + return success + +/DBConnection/proc/Quote(str) return _dm_db_quote(_db_con,str) + +/DBConnection/proc/ErrorMsg() return _dm_db_error_msg(_db_con) +/DBConnection/proc/SelectDB(database_name,dbi) + if(IsConnected()) Disconnect() + //return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[DB_SERVER]:[DB_PORT]"]",user,password) + return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[sqladdress]:[sqlport]"]",user,password) +/DBConnection/proc/NewQuery(sql_query,cursor_handler=src.default_cursor) return new/DBQuery(sql_query,src,cursor_handler) + + +/DBQuery/New(sql_query,DBConnection/connection_handler,cursor_handler) + if(sql_query) src.sql = sql_query + if(connection_handler) src.db_connection = connection_handler + if(cursor_handler) src.default_cursor = cursor_handler + _db_query = _dm_db_new_query() + return ..() + + +/DBQuery + var/sql // The sql query being executed. + var/default_cursor + var/list/columns //list of DB Columns populated by Columns() + var/list/conversions + var/list/item[0] //list of data values populated by NextRow() + + var/DBConnection/db_connection + var/_db_query + +/DBQuery/proc/Connect(DBConnection/connection_handler) src.db_connection = connection_handler + +/DBQuery/proc/Execute(sql_query=src.sql,cursor_handler=default_cursor) + Close() + return _dm_db_execute(_db_query,sql_query,db_connection._db_con,cursor_handler,null) + +/DBQuery/proc/NextRow() return _dm_db_next_row(_db_query,item,conversions) + +/DBQuery/proc/RowsAffected() return _dm_db_rows_affected(_db_query) + +/DBQuery/proc/RowCount() return _dm_db_row_count(_db_query) + +/DBQuery/proc/ErrorMsg() return _dm_db_error_msg(_db_query) + +/DBQuery/proc/Columns() + if(!columns) + columns = _dm_db_columns(_db_query,/DBColumn) + return columns + +/DBQuery/proc/GetRowData() + var/list/columns = Columns() + var/list/results + if(columns.len) + results = list() + for(var/C in columns) + results+=C + var/DBColumn/cur_col = columns[C] + results[C] = src.item[(cur_col.position+1)] + return results + +/DBQuery/proc/Close() + item.len = 0 + columns = null + conversions = null + return _dm_db_close(_db_query) + +/DBQuery/proc/Quote(str) + return db_connection.Quote(str) + +/DBQuery/proc/SetConversion(column,conversion) + if(istext(column)) column = columns.Find(column) + if(!conversions) conversions = new/list(column) + else if(conversions.len < column) conversions.len = column + conversions[column] = conversion + + +/DBColumn + var/name + var/table + var/position //1-based index into item data + var/sql_type + var/flags + var/length + var/max_length + +/DBColumn/New(name_handler,table_handler,position_handler,type_handler,flag_handler,length_handler,max_length_handler) + src.name = name_handler + src.table = table_handler + src.position = position_handler + src.sql_type = type_handler + src.flags = flag_handler + src.length = length_handler + src.max_length = max_length_handler + return ..() + + +/DBColumn/proc/SqlTypeName(type_handler=src.sql_type) + switch(type_handler) + if(TINYINT) return "TINYINT" + if(SMALLINT) return "SMALLINT" + if(MEDIUMINT) return "MEDIUMINT" + if(INTEGER) return "INTEGER" + if(BIGINT) return "BIGINT" + if(FLOAT) return "FLOAT" + if(DOUBLE) return "DOUBLE" + if(DATE) return "DATE" + if(DATETIME) return "DATETIME" + if(TIMESTAMP) return "TIMESTAMP" + if(TIME) return "TIME" + if(STRING) return "STRING" + if(BLOB) return "BLOB" + + +#undef Default_Cursor +#undef Client_Cursor +#undef Server_Cursor +#undef TEXT_CONV +#undef RSC_FILE_CONV +#undef NUMBER_CONV +#undef IS_NUMERIC +#undef IS_BINARY +#undef IS_NOT_NULL +#undef IS_PRIMARY_KEY +#undef IS_UNSIGNED +#undef TINYINT +#undef SMALLINT +#undef MEDIUMINT +#undef INTEGER +#undef BIGINT +#undef DECIMAL +#undef FLOAT +#undef DOUBLE +#undef DATE +#undef DATETIME +#undef TIMESTAMP +#undef TIME +#undef STRING +#undef BLOB diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm index 6a1c2f01e8ec..bc96638f5de3 100644 --- a/code/defines/procs/statistics.dm +++ b/code/defines/procs/statistics.dm @@ -1,162 +1,162 @@ -/proc/sql_poll_players() - if(!config.sql_enabled) - 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(!config.sql_enabled) - 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(!config.sql_enabled) - return -/proc/sql_report_round_end() - // TODO - if(!config.sql_enabled) - return - -/proc/sql_report_death(mob/living/carbon/human/H) - if(!config.sql_enabled) - 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 = sanitize_sql(H.real_name) - var/sqlkey = sanitize_sql(H.key) - var/sqlpod = sanitize_sql(podname) - var/sqlspecial = sanitize_sql(H.mind.special_role) - var/sqljob = sanitize_sql(H.mind.assigned_role) - var/laname - var/lakey - if(H.lastattacker) - laname = sanitize_sql(H.lastattacker:real_name) - lakey = sanitize_sql(H.lastattacker:key) - var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/coord = "[H.x], [H.y], [H.z]" - //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(mob/living/silicon/robot/H) - if(!config.sql_enabled) - 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 = sanitize_sql(H.real_name) - var/sqlkey = sanitize_sql(H.key) - var/sqlpod = sanitize_sql(podname) - var/sqlspecial = sanitize_sql(H.mind.special_role) - var/sqljob = sanitize_sql(H.mind.assigned_role) - var/laname - var/lakey - if(H.lastattacker) - laname = sanitize_sql(H.lastattacker:real_name) - lakey = sanitize_sql(H.lastattacker:key) - var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/coord = "[H.x], [H.y], [H.z]" - //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(!config.sql_enabled) - 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") +/proc/sql_poll_players() + if(!config.sql_enabled) + 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(!config.sql_enabled) + 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(!config.sql_enabled) + return +/proc/sql_report_round_end() + // TODO + if(!config.sql_enabled) + return + +/proc/sql_report_death(mob/living/carbon/human/H) + if(!config.sql_enabled) + 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 = sanitize_sql(H.real_name) + var/sqlkey = sanitize_sql(H.key) + var/sqlpod = sanitize_sql(podname) + var/sqlspecial = sanitize_sql(H.mind.special_role) + var/sqljob = sanitize_sql(H.mind.assigned_role) + var/laname + var/lakey + if(H.lastattacker) + laname = sanitize_sql(H.lastattacker:real_name) + lakey = sanitize_sql(H.lastattacker:key) + var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") + var/coord = "[H.x], [H.y], [H.z]" + //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(mob/living/silicon/robot/H) + if(!config.sql_enabled) + 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 = sanitize_sql(H.real_name) + var/sqlkey = sanitize_sql(H.key) + var/sqlpod = sanitize_sql(podname) + var/sqlspecial = sanitize_sql(H.mind.special_role) + var/sqljob = sanitize_sql(H.mind.assigned_role) + var/laname + var/lakey + if(H.lastattacker) + laname = sanitize_sql(H.lastattacker:real_name) + lakey = sanitize_sql(H.lastattacker:key) + var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") + var/coord = "[H.x], [H.y], [H.z]" + //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(!config.sql_enabled) + 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") diff --git a/code/game/area/ai_monitored.dm b/code/game/area/ai_monitored.dm index 21bec5bc26cf..47a4aac585eb 100644 --- a/code/game/area/ai_monitored.dm +++ b/code/game/area/ai_monitored.dm @@ -1,25 +1,25 @@ -/area/ai_monitored - name = "AI Monitored Area" - var/obj/machinery/camera/motioncamera = null - - -/area/ai_monitored/atom_init(mapload) - . = ..() - - if(mapload) - for (var/obj/machinery/camera/M in src) - if(M.isMotion()) - motioncamera = M - M.area_motion = src - 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/atom_init(mapload) + . = ..() + + if(mapload) + for (var/obj/machinery/camera/M in src) + if(M.isMotion()) + motioncamera = M + M.area_motion = src + 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 0afa124843f4..41e7a5708501 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -1,446 +1,446 @@ -// Areas.dm - - - -// === -/area - level = null - name = "Space" - icon = 'icons/turf/areas.dmi' - icon_state = "unknown" - layer = 10 - mouse_opacity = 0 - - var/global/global_uid = 0 - var/uid - - var/parallax_movedir = 0 - - var/fire = null - var/atmos = 1 - var/atmosalm = 0 - var/poweralm = 1 - var/party = null - var/lightswitch = 1 - var/valid_territory = 1 //If it's a valid territory for gangs to claim - - var/eject = null - - var/debug = 0 - var/powerupdate = 10 //We give everything 10 ticks to settle out it's power usage. - 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/obj/machinery/power/apc/apc = null - var/no_air = null - var/area/master // master area used for power calcluations - // (original area before splitting due to sd_DAL) - var/list/related // the other areas of the same type as this - var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area - var/air_doors_activated = 0 - - -/*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 all_areas) - if(istype(AR, /area/shuttle) || istype(AR, /area/syndicate_station) || istype(AR, /area/wizard_station) || istype(AR, /area/engine/singularity)) - continue - if(teleportlocs.Find(AR.name)) - continue - var/turf/picked = pick(get_area_turfs(AR.type)) - if (picked.z == ZLEVEL_STATION) - teleportlocs += AR.name - teleportlocs[AR.name] = AR - teleportlocs = sortAssoc(teleportlocs) - return 1 - - -var/list/ghostteleportlocs = list() - -/proc/process_ghost_teleport_locs() - for(var/area/AR in all_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 = pick(get_area_turfs(AR.type)) - if (picked.z == ZLEVEL_STATION || picked.z == ZLEVEL_ASTEROID || picked.z == ZLEVEL_TELECOMMS) - ghostteleportlocs += AR.name - ghostteleportlocs[AR.name] = AR - ghostteleportlocs = sortAssoc(ghostteleportlocs) - return 1 - -/area/New() // not ready for transfer, problems with alarms raises if this part moved into init (requires more time) - icon_state = "" - layer = 10 - master = src - uid = ++global_uid - related = list(src) - all_areas += src - - if(!requires_power) - power_light = 0 - power_equip = 0 - power_environ = 0 - - ..() - -/area/atom_init() - - . = ..() - - if(dynamic_lighting) - luminosity = FALSE - - power_change() // all machines set to current power level, also updates lighting icon - - -/area/proc/poweralert(state, obj/source) - 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/area/RA in related) - for (var/obj/machinery/camera/C in RA) - cameras += C - if(state == 1) - C.network.Remove("Power Alarms") - else - C.network.Add("Power Alarms") - for (var/mob/living/silicon/aiPlayer in silicon_list) - if(!aiPlayer.client) - continue - 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 station_alert_list) - if(a.z == source.z) - if(state == 1) - a.cancelAlarm("Power", src, source) - else - a.triggerAlarm("Power", src, cameras, source) - return - -/area/proc/atmosalert(danger_level) - //Check all the alarms before lowering atmosalm. Raising is perfectly fine. - for (var/area/RA in related) - for (var/obj/machinery/alarm/AA in RA) - if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted) - danger_level = max(danger_level, AA.danger_level) - - if(danger_level != atmosalm) - if (danger_level < 1 && atmosalm >= 1) - //closing the doors on red and opening on green provides a bit of hysteresis that will hopefully prevent fire doors from opening and closing repeatedly due to noise - air_doors_open() - - if (danger_level < 2 && atmosalm >= 2) - for(var/area/RA in related) - for(var/obj/machinery/camera/C in RA) - C.network.Remove("Atmosphere Alarms") - for(var/mob/living/silicon/aiPlayer in silicon_list) - if(!aiPlayer.client) - continue - aiPlayer.cancelAlarm("Atmosphere", src, src) - for(var/obj/machinery/computer/station_alert/a in station_alert_list) - a.cancelAlarm("Atmosphere", src, src) - - if (danger_level >= 2 && atmosalm < 2) - var/list/cameras = list() - for(var/area/RA in related) - for(var/obj/machinery/camera/C in RA) - cameras += C - C.network.Add("Atmosphere Alarms") - for(var/mob/living/silicon/aiPlayer in silicon_list) - if(!aiPlayer.client) - continue - aiPlayer.triggerAlarm("Atmosphere", src, cameras, src) - for(var/obj/machinery/computer/station_alert/a in station_alert_list) - a.triggerAlarm("Atmosphere", src, cameras, src) - air_doors_close() - - atmosalm = danger_level - for(var/area/RA in related) - for (var/obj/machinery/alarm/AA in RA) - AA.update_icon() - - return 1 - return 0 - -/area/proc/air_doors_close() - if(!src.master.air_doors_activated) - src.master.air_doors_activated = 1 - for(var/obj/machinery/door/firedoor/E in src.master.all_doors) - if(!E.blocked) - if(E.operating) - E.nextstate = CLOSED - else if(!E.density) - INVOKE_ASYNC(E, /obj/machinery/door/firedoor.proc/close) - -/area/proc/air_doors_open() - if(src.master.air_doors_activated) - src.master.air_doors_activated = 0 - for(var/obj/machinery/door/firedoor/E in src.master.all_doors) - if(!E.blocked) - if(E.operating) - E.nextstate = OPEN - else if(E.density) - INVOKE_ASYNC(E, /obj/machinery/door/firedoor.proc/open) - - -/area/proc/firealert() - if(name == "Space") //no fire alarms in space - return - if( !fire ) - fire = 1 - master.fire = 1 //used for firedoor checks - mouse_opacity = 0 - for(var/obj/machinery/door/firedoor/D in all_doors) - if(!D.blocked) - if(D.operating) - D.nextstate = CLOSED - else if(!D.density) - INVOKE_ASYNC(D, /obj/machinery/door/firedoor.proc/close) - var/list/cameras = list() - for(var/area/RA in related) - for (var/obj/machinery/camera/C in RA) - cameras.Add(C) - C.network.Add("Fire Alarms") - for (var/mob/living/silicon/ai/aiPlayer in ai_list) - if(!aiPlayer.client) - continue - aiPlayer.triggerAlarm("Fire", src, cameras, src) - for (var/obj/machinery/computer/station_alert/a in station_alert_list) - a.triggerAlarm("Fire", src, cameras, src) - -/area/proc/firereset() - if(fire) - fire = 0 - master.fire = 0 //used for firedoor checks - mouse_opacity = 0 - for(var/obj/machinery/door/firedoor/D in all_doors) - if(!D.blocked) - if(D.operating) - D.nextstate = OPEN - else if(D.density) - INVOKE_ASYNC(D, /obj/machinery/door/firedoor.proc/open) - for(var/area/RA in related) - for (var/obj/machinery/camera/C in RA) - C.network.Remove("Fire Alarms") - for (var/mob/living/silicon/ai/aiPlayer in ai_list) - if(!aiPlayer.client) - continue - aiPlayer.cancelAlarm("Fire", src, src) - for (var/obj/machinery/computer/station_alert/a in station_alert_list) - a.cancelAlarm("Fire", src, src) - -/area/proc/partyalert() - if(name == "Space") //no parties in space!!! - return - if(!party) - party = 1 - updateicon() - mouse_opacity = 0 - return - -/area/proc/partyreset() - if(party) - party = 0 - mouse_opacity = 0 - updateicon() - for(var/obj/machinery/door/firedoor/D in src) - if(!D.blocked) - if(D.operating) - D.nextstate = OPEN - else if(D.density) - INVOKE_ASYNC(D, /obj/machinery/door/firedoor.proc/open) - return - -/area/proc/updateicon() - icon_state = null - - -/area/proc/powered(chan) // return true if the area has power to given channel - if(!master.requires_power) - return 1 - if(master.always_unpowered) - return 0 - switch(chan) - if(EQUIP) - return master.power_equip - if(LIGHT) - return master.power_light - if(ENVIRON) - return master.power_environ - - return 0 - -// called when power status changes -/area/proc/power_change() - master.powerupdate = 2 - for(var/area/RA in related) - for(var/obj/machinery/M in RA) // for each machine in the area - M.power_change() // reverify power status (to update icons etc.) - if (fire || eject || party) - RA.updateicon() - -/area/proc/usage(chan) - var/used = 0 - switch(chan) - if(LIGHT) - used += master.used_light - if(EQUIP) - used += master.used_equip - if(ENVIRON) - used += master.used_environ - if(TOTAL) - used += master.used_light + master.used_equip + master.used_environ - if(STATIC_EQUIP) - used += master.static_equip - if(STATIC_LIGHT) - used += master.static_light - if(STATIC_ENVIRON) - used += master.static_environ - return used - -/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() - master.used_equip = 0 - master.used_light = 0 - master.used_environ = 0 - -/area/proc/use_power(var/amount, var/chan) - - switch(chan) - if(EQUIP) - master.used_equip += amount - if(LIGHT) - master.used_light += amount - if(ENVIRON) - master.used_environ += amount - - -/area/Entered(A) - if(!istype(A,/mob/living)) - return - - var/mob/living/L = A - if(!L.ckey) - return - - //Jukebox - if(!L.lastarea) - L.lastarea = get_area(L.loc) - var/area/newarea = get_area(L.loc) - var/area/oldarea = L.lastarea - if(newarea != oldarea) - if(L.client) - L.update_music() - L.lastarea = newarea - - if((oldarea.has_gravity == 0) && (newarea.has_gravity == 1) && (L.m_intent == "run")) // Being ready when you change areas gives you a chance to avoid falling all together. - thunk(L) - - // 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 - if(!(L && L.client && (L.client.prefs.toggles & SOUND_AMBIENCE))) - return - - if(!L.client.ambience_playing) - L.client.ambience_playing = 1 - L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2) - - if(prob(35)) - var/sound = 'sound/ambience/ambigen1.ogg' - - if(istype(src, /area/chapel)) - sound = pick('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg','sound/music/traitor.ogg') - else if(istype(src, /area/medical/morgue)) - sound = pick('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg','sound/music/main.ogg') - else if(type == /area) - sound = pick('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg','sound/ambience/voidambi.ogg','sound/ambience/timeship_amb1.ogg') - else if(istype(src, /area/engine)) - 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)) - sound = pick('sound/ambience/ambimalf.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/ambience/mars.ogg') - else if(istype(src, /area/tcommsat)) - sound = pick('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') - else if (istype(src, /area/syndicate_station) || istype(src, /area/syndicate_station/start) || istype(src,/area/syndicate_station/transit)) - sound = pick('sound/ambience/omega.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') - - if(!L.client.played) - L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = 1) - L.client.played = TRUE - addtimer(CALLBACK(src, .proc/set_played_false, L), 600) - -/area/proc/set_played_false(mob/living/L) - if(L && L.client) - L.client.played = FALSE - -/area/proc/gravitychange(gravitystate = 0, area/A) - - A.has_gravity = gravitystate - - for(var/area/SubA in A.related) - SubA.has_gravity = gravitystate - - if(gravitystate) - for(var/mob/living/carbon/human/M in SubA) - thunk(M) - -/area/proc/thunk(mob) - if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing. - return - - if(istype(mob,/mob/living/carbon/human/)) // Only humans can wear magboots, so we give them a chance to. - var/mob/living/carbon/human/H = mob - if((istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP))) - return - if((istype(H.wear_suit, /obj/item/clothing/suit/space/rig) && (H.wear_suit.flags & NOSLIP))) //Humans in rig with turn on magboots - return - - if(H.m_intent == "run") - H.AdjustStunned(2) - H.AdjustWeakened(2) - else - H.AdjustStunned(1) - H.AdjustWeakened(1) - to_chat(mob, "The sudden appearance of gravity makes you fall to the floor!") - -/proc/has_gravity(atom/AT, turf/T) - if(!T) - T = get_turf(AT) - var/area/A = get_area(T) - if(istype(T, /turf/space)) // Turf never has gravity - return 0 - else if(A && A.has_gravity) // Areas which always has gravity - return 1 - return 0 +// Areas.dm + + + +// === +/area + level = null + name = "Space" + icon = 'icons/turf/areas.dmi' + icon_state = "unknown" + layer = 10 + mouse_opacity = 0 + + var/global/global_uid = 0 + var/uid + + var/parallax_movedir = 0 + + var/fire = null + var/atmos = 1 + var/atmosalm = 0 + var/poweralm = 1 + var/party = null + var/lightswitch = 1 + var/valid_territory = 1 //If it's a valid territory for gangs to claim + + var/eject = null + + var/debug = 0 + var/powerupdate = 10 //We give everything 10 ticks to settle out it's power usage. + 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/obj/machinery/power/apc/apc = null + var/no_air = null + var/area/master // master area used for power calcluations + // (original area before splitting due to sd_DAL) + var/list/related // the other areas of the same type as this + var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area + var/air_doors_activated = 0 + + +/*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 all_areas) + if(istype(AR, /area/shuttle) || istype(AR, /area/syndicate_station) || istype(AR, /area/wizard_station) || istype(AR, /area/engine/singularity)) + continue + if(teleportlocs.Find(AR.name)) + continue + var/turf/picked = pick(get_area_turfs(AR.type)) + if (picked.z == ZLEVEL_STATION) + teleportlocs += AR.name + teleportlocs[AR.name] = AR + teleportlocs = sortAssoc(teleportlocs) + return 1 + + +var/list/ghostteleportlocs = list() + +/proc/process_ghost_teleport_locs() + for(var/area/AR in all_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 = pick(get_area_turfs(AR.type)) + if (picked.z == ZLEVEL_STATION || picked.z == ZLEVEL_ASTEROID || picked.z == ZLEVEL_TELECOMMS) + ghostteleportlocs += AR.name + ghostteleportlocs[AR.name] = AR + ghostteleportlocs = sortAssoc(ghostteleportlocs) + return 1 + +/area/New() // not ready for transfer, problems with alarms raises if this part moved into init (requires more time) + icon_state = "" + layer = 10 + master = src + uid = ++global_uid + related = list(src) + all_areas += src + + if(!requires_power) + power_light = 0 + power_equip = 0 + power_environ = 0 + + ..() + +/area/atom_init() + + . = ..() + + if(dynamic_lighting) + luminosity = FALSE + + power_change() // all machines set to current power level, also updates lighting icon + + +/area/proc/poweralert(state, obj/source) + 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/area/RA in related) + for (var/obj/machinery/camera/C in RA) + cameras += C + if(state == 1) + C.network.Remove("Power Alarms") + else + C.network.Add("Power Alarms") + for (var/mob/living/silicon/aiPlayer in silicon_list) + if(!aiPlayer.client) + continue + 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 station_alert_list) + if(a.z == source.z) + if(state == 1) + a.cancelAlarm("Power", src, source) + else + a.triggerAlarm("Power", src, cameras, source) + return + +/area/proc/atmosalert(danger_level) + //Check all the alarms before lowering atmosalm. Raising is perfectly fine. + for (var/area/RA in related) + for (var/obj/machinery/alarm/AA in RA) + if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted) + danger_level = max(danger_level, AA.danger_level) + + if(danger_level != atmosalm) + if (danger_level < 1 && atmosalm >= 1) + //closing the doors on red and opening on green provides a bit of hysteresis that will hopefully prevent fire doors from opening and closing repeatedly due to noise + air_doors_open() + + if (danger_level < 2 && atmosalm >= 2) + for(var/area/RA in related) + for(var/obj/machinery/camera/C in RA) + C.network.Remove("Atmosphere Alarms") + for(var/mob/living/silicon/aiPlayer in silicon_list) + if(!aiPlayer.client) + continue + aiPlayer.cancelAlarm("Atmosphere", src, src) + for(var/obj/machinery/computer/station_alert/a in station_alert_list) + a.cancelAlarm("Atmosphere", src, src) + + if (danger_level >= 2 && atmosalm < 2) + var/list/cameras = list() + for(var/area/RA in related) + for(var/obj/machinery/camera/C in RA) + cameras += C + C.network.Add("Atmosphere Alarms") + for(var/mob/living/silicon/aiPlayer in silicon_list) + if(!aiPlayer.client) + continue + aiPlayer.triggerAlarm("Atmosphere", src, cameras, src) + for(var/obj/machinery/computer/station_alert/a in station_alert_list) + a.triggerAlarm("Atmosphere", src, cameras, src) + air_doors_close() + + atmosalm = danger_level + for(var/area/RA in related) + for (var/obj/machinery/alarm/AA in RA) + AA.update_icon() + + return 1 + return 0 + +/area/proc/air_doors_close() + if(!src.master.air_doors_activated) + src.master.air_doors_activated = 1 + for(var/obj/machinery/door/firedoor/E in src.master.all_doors) + if(!E.blocked) + if(E.operating) + E.nextstate = CLOSED + else if(!E.density) + INVOKE_ASYNC(E, /obj/machinery/door/firedoor.proc/close) + +/area/proc/air_doors_open() + if(src.master.air_doors_activated) + src.master.air_doors_activated = 0 + for(var/obj/machinery/door/firedoor/E in src.master.all_doors) + if(!E.blocked) + if(E.operating) + E.nextstate = OPEN + else if(E.density) + INVOKE_ASYNC(E, /obj/machinery/door/firedoor.proc/open) + + +/area/proc/firealert() + if(name == "Space") //no fire alarms in space + return + if( !fire ) + fire = 1 + master.fire = 1 //used for firedoor checks + mouse_opacity = 0 + for(var/obj/machinery/door/firedoor/D in all_doors) + if(!D.blocked) + if(D.operating) + D.nextstate = CLOSED + else if(!D.density) + INVOKE_ASYNC(D, /obj/machinery/door/firedoor.proc/close) + var/list/cameras = list() + for(var/area/RA in related) + for (var/obj/machinery/camera/C in RA) + cameras.Add(C) + C.network.Add("Fire Alarms") + for (var/mob/living/silicon/ai/aiPlayer in ai_list) + if(!aiPlayer.client) + continue + aiPlayer.triggerAlarm("Fire", src, cameras, src) + for (var/obj/machinery/computer/station_alert/a in station_alert_list) + a.triggerAlarm("Fire", src, cameras, src) + +/area/proc/firereset() + if(fire) + fire = 0 + master.fire = 0 //used for firedoor checks + mouse_opacity = 0 + for(var/obj/machinery/door/firedoor/D in all_doors) + if(!D.blocked) + if(D.operating) + D.nextstate = OPEN + else if(D.density) + INVOKE_ASYNC(D, /obj/machinery/door/firedoor.proc/open) + for(var/area/RA in related) + for (var/obj/machinery/camera/C in RA) + C.network.Remove("Fire Alarms") + for (var/mob/living/silicon/ai/aiPlayer in ai_list) + if(!aiPlayer.client) + continue + aiPlayer.cancelAlarm("Fire", src, src) + for (var/obj/machinery/computer/station_alert/a in station_alert_list) + a.cancelAlarm("Fire", src, src) + +/area/proc/partyalert() + if(name == "Space") //no parties in space!!! + return + if(!party) + party = 1 + updateicon() + mouse_opacity = 0 + return + +/area/proc/partyreset() + if(party) + party = 0 + mouse_opacity = 0 + updateicon() + for(var/obj/machinery/door/firedoor/D in src) + if(!D.blocked) + if(D.operating) + D.nextstate = OPEN + else if(D.density) + INVOKE_ASYNC(D, /obj/machinery/door/firedoor.proc/open) + return + +/area/proc/updateicon() + icon_state = null + + +/area/proc/powered(chan) // return true if the area has power to given channel + if(!master.requires_power) + return 1 + if(master.always_unpowered) + return 0 + switch(chan) + if(EQUIP) + return master.power_equip + if(LIGHT) + return master.power_light + if(ENVIRON) + return master.power_environ + + return 0 + +// called when power status changes +/area/proc/power_change() + master.powerupdate = 2 + for(var/area/RA in related) + for(var/obj/machinery/M in RA) // for each machine in the area + M.power_change() // reverify power status (to update icons etc.) + if (fire || eject || party) + RA.updateicon() + +/area/proc/usage(chan) + var/used = 0 + switch(chan) + if(LIGHT) + used += master.used_light + if(EQUIP) + used += master.used_equip + if(ENVIRON) + used += master.used_environ + if(TOTAL) + used += master.used_light + master.used_equip + master.used_environ + if(STATIC_EQUIP) + used += master.static_equip + if(STATIC_LIGHT) + used += master.static_light + if(STATIC_ENVIRON) + used += master.static_environ + return used + +/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() + master.used_equip = 0 + master.used_light = 0 + master.used_environ = 0 + +/area/proc/use_power(var/amount, var/chan) + + switch(chan) + if(EQUIP) + master.used_equip += amount + if(LIGHT) + master.used_light += amount + if(ENVIRON) + master.used_environ += amount + + +/area/Entered(A) + if(!istype(A,/mob/living)) + return + + var/mob/living/L = A + if(!L.ckey) + return + + //Jukebox + if(!L.lastarea) + L.lastarea = get_area(L.loc) + var/area/newarea = get_area(L.loc) + var/area/oldarea = L.lastarea + if(newarea != oldarea) + if(L.client) + L.update_music() + L.lastarea = newarea + + if((oldarea.has_gravity == 0) && (newarea.has_gravity == 1) && (L.m_intent == "run")) // Being ready when you change areas gives you a chance to avoid falling all together. + thunk(L) + + // 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 + if(!(L && L.client && (L.client.prefs.toggles & SOUND_AMBIENCE))) + return + + if(!L.client.ambience_playing) + L.client.ambience_playing = 1 + L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2) + + if(prob(35)) + var/sound = 'sound/ambience/ambigen1.ogg' + + if(istype(src, /area/chapel)) + sound = pick('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg','sound/music/traitor.ogg') + else if(istype(src, /area/medical/morgue)) + sound = pick('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg','sound/music/main.ogg') + else if(type == /area) + sound = pick('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg','sound/ambience/voidambi.ogg','sound/ambience/timeship_amb1.ogg') + else if(istype(src, /area/engine)) + 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)) + sound = pick('sound/ambience/ambimalf.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/ambience/mars.ogg') + else if(istype(src, /area/tcommsat)) + sound = pick('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') + else if (istype(src, /area/syndicate_station) || istype(src, /area/syndicate_station/start) || istype(src,/area/syndicate_station/transit)) + sound = pick('sound/ambience/omega.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') + + if(!L.client.played) + L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = 1) + L.client.played = TRUE + addtimer(CALLBACK(src, .proc/set_played_false, L), 600) + +/area/proc/set_played_false(mob/living/L) + if(L && L.client) + L.client.played = FALSE + +/area/proc/gravitychange(gravitystate = 0, area/A) + + A.has_gravity = gravitystate + + for(var/area/SubA in A.related) + SubA.has_gravity = gravitystate + + if(gravitystate) + for(var/mob/living/carbon/human/M in SubA) + thunk(M) + +/area/proc/thunk(mob) + if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing. + return + + if(istype(mob,/mob/living/carbon/human/)) // Only humans can wear magboots, so we give them a chance to. + var/mob/living/carbon/human/H = mob + if((istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP))) + return + if((istype(H.wear_suit, /obj/item/clothing/suit/space/rig) && (H.wear_suit.flags & NOSLIP))) //Humans in rig with turn on magboots + return + + if(H.m_intent == "run") + H.AdjustStunned(2) + H.AdjustWeakened(2) + else + H.AdjustStunned(1) + H.AdjustWeakened(1) + to_chat(mob, "The sudden appearance of gravity makes you fall to the floor!") + +/proc/has_gravity(atom/AT, turf/T) + if(!T) + T = get_turf(AT) + var/area/A = get_area(T) + if(istype(T, /turf/space)) // Turf never has gravity + return 0 + else if(A && A.has_gravity) // Areas which always has gravity + return 1 + return 0 diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm index 5003af3ea34e..70b3d0e87d35 100644 --- a/code/game/asteroid.dm +++ b/code/game/asteroid.dm @@ -1,154 +1,154 @@ - -var/global/list/space_surprises = list( /obj/item/weapon/pickaxe/silver =4, - /obj/item/weapon/pickaxe/drill =4, - /obj/item/weapon/pickaxe/drill/jackhammer =4, - /obj/item/weapon/pickaxe/diamond =3, - /obj/item/weapon/pickaxe/drill/diamond_drill =3, - /obj/item/weapon/pickaxe/gold =3, - /obj/item/weapon/pickaxe/plasmacutter =2, - /obj/structure/closet/syndicate/resources =2, - /obj/item/weapon/melee/energy/sword/pirate =1, - /obj/mecha/working/ripley/mining =1 - ) - -var/global/list/spawned_surprises = list() - -proc/spawn_room(atom/start_loc,x_size,y_size,wall,floor , clean = 0 , name) - var/list/room_turfs = list("walls"=list(),"floors"=list()) - - //world << "Room spawned at [start_loc.x],[start_loc.y],[start_loc.z]" - if(!wall) - wall = pick(/turf/simulated/wall/r_wall,/turf/simulated/wall,/obj/effect/alien/resin/wall) - if(!floor) - floor = pick(/turf/simulated/floor,/turf/simulated/floor/engine) - - for(var/x = 0,x 100) - return 0 - - T=pick(turfs) - if(!T) - return 0 - - var/list/surroundings = list() - - surroundings += range(7, locate(T.x,T.y,T.z)) - surroundings += range(7, locate(T.x+size,T.y,T.z)) - surroundings += range(7, locate(T.x,T.y+size,T.z)) - surroundings += range(7, locate(T.x+size,T.y+size,T.z)) - - if(locate(/area/mine/explored) in surroundings) // +5s are for view range - valid = 0 - continue - - if(locate(/turf/space) in surroundings) - valid = 0 - continue - - if(locate(/area/asteroid/artifactroom) in surroundings) - valid = 0 - continue - - if(locate(/turf/simulated/floor/plating/airless/asteroid) in surroundings) - valid = 0 - continue - - if(!T) - return 0 - - room = spawn_room(T,size,size,,,1) - - if(room) - T = pick(room["floors"]) - if(T) - var/surprise = null - valid = 0 - while(!valid) - surprise = pickweight(space_surprises) - if(surprise in spawned_surprises) - if(prob(20)) - valid++ - else - continue - else - valid++ - - spawned_surprises.Add(surprise) - new surprise(T) - - return 1 + +var/global/list/space_surprises = list( /obj/item/weapon/pickaxe/silver =4, + /obj/item/weapon/pickaxe/drill =4, + /obj/item/weapon/pickaxe/drill/jackhammer =4, + /obj/item/weapon/pickaxe/diamond =3, + /obj/item/weapon/pickaxe/drill/diamond_drill =3, + /obj/item/weapon/pickaxe/gold =3, + /obj/item/weapon/pickaxe/plasmacutter =2, + /obj/structure/closet/syndicate/resources =2, + /obj/item/weapon/melee/energy/sword/pirate =1, + /obj/mecha/working/ripley/mining =1 + ) + +var/global/list/spawned_surprises = list() + +proc/spawn_room(atom/start_loc,x_size,y_size,wall,floor , clean = 0 , name) + var/list/room_turfs = list("walls"=list(),"floors"=list()) + + //world << "Room spawned at [start_loc.x],[start_loc.y],[start_loc.z]" + if(!wall) + wall = pick(/turf/simulated/wall/r_wall,/turf/simulated/wall,/obj/effect/alien/resin/wall) + if(!floor) + floor = pick(/turf/simulated/floor,/turf/simulated/floor/engine) + + for(var/x = 0,x 100) + return 0 + + T=pick(turfs) + if(!T) + return 0 + + var/list/surroundings = list() + + surroundings += range(7, locate(T.x,T.y,T.z)) + surroundings += range(7, locate(T.x+size,T.y,T.z)) + surroundings += range(7, locate(T.x,T.y+size,T.z)) + surroundings += range(7, locate(T.x+size,T.y+size,T.z)) + + if(locate(/area/mine/explored) in surroundings) // +5s are for view range + valid = 0 + continue + + if(locate(/turf/space) in surroundings) + valid = 0 + continue + + if(locate(/area/asteroid/artifactroom) in surroundings) + valid = 0 + continue + + if(locate(/turf/simulated/floor/plating/airless/asteroid) in surroundings) + valid = 0 + continue + + if(!T) + return 0 + + room = spawn_room(T,size,size,,,1) + + if(room) + T = pick(room["floors"]) + if(T) + var/surprise = null + valid = 0 + while(!valid) + surprise = pickweight(space_surprises) + if(surprise in spawned_surprises) + if(prob(20)) + valid++ + else + continue + else + valid++ + + spawned_surprises.Add(surprise) + new surprise(T) + + return 1 diff --git a/code/game/atoms.dm b/code/game/atoms.dm index a13f70870735..16af56ea949a 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1,525 +1,525 @@ -/atom - layer = TURF_LAYER - plane = GAME_PLANE - var/level = 2 - var/flags = 0 - var/flags_2 = 0 - var/list/fingerprints - var/list/fingerprintshidden - var/fingerprintslast = null - - var/list/blood_DNA //forensic reasons - var/datum/dirt_cover/dirt_overlay //style reasons - - var/last_bumped = 0 - var/pass_flags = 0 - var/throwpass = 0 - var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom. - var/simulated = 1 //filter for actions - used by lighting overlays - - var/resize = 1 //don't abuse this shit - var/resize_rev = 1 //helps to restore default size - - var/initialized = FALSE - - ///Chemistry. - var/datum/reagents/reagents = null - - //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/in_use_action = FALSE // do_after sets this to TRUE and is_busy() can check for that to disallow multiple users to interact with this at the same time. - -/atom/New(loc, ...) - if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New() - _preloader.load(src) - - //. = ..() //uncomment if you are dumb enough to add a /datum/New() proc - - var/do_initialize = SSatoms.initialized - if(do_initialize > INITIALIZATION_INSSATOMS) - args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD - if(SSatoms.InitAtom(src, args)) - //we were deleted - return - - var/list/created = SSatoms.created_atoms - if(created) - created += src - -// Called after New if the map is being loaded. mapload = TRUE -// Called from base of New if the map is being loaded. mapload = FALSE -// This base must be called or derivatives must set initialized to TRUE -// must not sleep -// Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE -// Must return an Initialize hint. Defined in __DEFINES/subsystems.dm - -//Note: the following functions don't call the base for optimization and must copypasta: -// /turf/atom_init -// /turf/space/atom_init -// /mob/dead/atom_init - -//Do also note that this proc always runs in New for /mob/dead -/atom/proc/atom_init(mapload, ...) - if(initialized) - stack_trace("Warning: [src]([type]) initialized multiple times!") - initialized = TRUE - - if(light_power && light_range) - update_light() - - if(opacity && isturf(src.loc)) - var/turf/T = src.loc - T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. - - return INITIALIZE_HINT_NORMAL - -//called if atom_init returns INITIALIZE_HINT_LATELOAD -/atom/proc/atom_init_late() - return - -/atom/Destroy() - if(reagents) - QDEL_NULL(reagents) - - LAZYCLEARLIST(overlays) - - if(light) - light.destroy() - light = null - - return ..() - -/atom/proc/CheckParts(list/parts_list) - for(var/A in parts_list) - if(istype(A, /datum/reagent)) - if(!reagents) - reagents = new() - reagents.reagent_list.Add(A) - reagents.conditional_update() - else if(ismovableatom(A)) - var/atom/movable/M = A - if(isliving(M.loc)) - var/mob/living/L = M.loc - L.drop_from_inventory(M, src) - else - M.forceMove(src) - -/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) - if (istype(user, /mob/living/silicon/ai)) // WHYYYY - return 1 - return - -/atom/proc/on_reagent_change() - return - -/atom/proc/Bumped(AM) - 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/can_mob_interact(mob/user) - if (ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.getBrainLoss() >= 60) - user.visible_message("[H] stares cluelessly at [isturf(loc) ? src : ismob(loc) ? src : "something"] and drools.") - return FALSE - else if(prob(H.getBrainLoss())) - to_chat(user, "You momentarily forget how to use [src].") - return FALSE - return TRUE - -/atom/proc/meteorhit(obj/meteor) - return - -/atom/proc/allow_drop() - return 1 - -/atom/proc/CheckExit() - return 1 - -/atom/proc/HasProximity(atom/movable/AM) - return - -/atom/proc/emp_act(severity) - return - - -/atom/proc/bullet_act(obj/item/projectile/P, def_zone) - P.on_hit(src, 0, def_zone) - . = 0 - -/atom/proc/in_contents_of(container)//can take class or object instance as argument - if(ispath(container)) - if(istype(src.loc, container)) - return 1 - else if(src in container) - return 1 - 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/examine(mob/user, distance = -1) - //This reformat names to get a/an properly working on item descriptions when they are bloody - var/f_name = "\a [src]." - if(dirt_overlay) //Oil and blood puddles got 'blood_color = NULL', however they got 'color' instead - f_name = "\a [dirt_description()]!" - to_chat(user, "[bicon(src)] That's [f_name]") - if(desc) - to_chat(user, desc) - // *****RM - //user << "[name]: Dn:[density] dir:[dir] cont:[contents] icon:[icon] is:[icon_state] loc:[loc]" - if(reagents && is_open_container()) //is_open_container() isn't really the right proc for this, but w/e - to_chat(user, "It contains:") - if(reagents.reagent_list.len) - if(istype(src, /obj/structure/reagent_dispensers)) //watertanks, fueltanks - for(var/datum/reagent/R in reagents.reagent_list) - to_chat(user, "[R.volume] units of [R.name]") - else - to_chat(user, "[reagents.total_volume] units of liquid.") - else - to_chat(user, "Nothing.") - - return distance == -1 || isobserver(user) || (get_dist(src, user) <= distance) - -/atom/proc/dirt_description() - if(dirt_overlay) - return "[dirt_overlay.name]-covered [name]" - else - return name - -//called to set the atom's dir and used to add behaviour to dir-changes -/atom/proc/set_dir(new_dir) - . = new_dir != dir - dir = new_dir - -/atom/proc/relaymove() - return - -/atom/proc/ex_act() - return - -/atom/proc/blob_act() - return - -/atom/proc/fire_act() - return - -/atom/proc/singularity_act() - return - -/atom/proc/singularity_pull() - return - -/atom/proc/hitby(atom/movable/AM) - return - -/atom/proc/add_hiddenprint(mob/living/M) - if(!M || !M.key) - 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/M, ignoregloves = 0) - if(!M || !M.key || isAI(M)) //AI's clicks already calls add_hiddenprint from ClickOn() proc - 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 (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(H.species.flags[NO_FINGERPRINT]) // They don't leave readable fingerprints, but admins gotta know. - fingerprintshidden += "(Specie has no fingerprints) Real name: [H.real_name], Key: [H.key]" - fingerprintslast = H.key - return 0 - - 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(!ignoregloves) - 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 - // - if(fingerprints[full_print]) - switch(stringpercent(fingerprints[full_print])) //tells us how many stars are in the current prints. - - if(28 to 32) - if(prob(1)) - fingerprints[full_print] = full_print // You rolled a one buddy. - else - fingerprints[full_print] = stars(full_print, rand(0,40)) // 24 to 32 - - if(24 to 27) - if(prob(3)) - fingerprints[full_print] = full_print //Sucks to be you. - else - fingerprints[full_print] = stars(full_print, rand(15, 55)) // 20 to 29 - - if(20 to 23) - if(prob(5)) - fingerprints[full_print] = full_print //Had a good run didn't ya. - else - fingerprints[full_print] = stars(full_print, rand(30, 70)) // 15 to 25 - - if(16 to 19) - if(prob(5)) - fingerprints[full_print] = full_print //Welp. - else - fingerprints[full_print] = stars(full_print, rand(40, 100)) // 0 to 21 - - if(0 to 15) - if(prob(5)) - fingerprints[full_print] = stars(full_print, rand(0,50)) // small chance you can smudge. - else - fingerprints[full_print] = full_print - - else - fingerprints[full_print] = stars(full_print, rand(0, 20)) //Initial touch, not leaving much evidence the first time. - - - return 1 - else - //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) - fingerprints = null - return - - -/atom/proc/transfer_fingerprints_to(atom/A) - - if(!istype(A.fingerprints,/list)) - A.fingerprints = list() - - if(!istype(A.fingerprintshidden,/list)) - A.fingerprintshidden = list() - - if(!istype(fingerprintshidden, /list)) - fingerprintshidden = list() - - //skytodo - //A.fingerprints |= fingerprints //detective - //A.fingerprintshidden |= fingerprintshidden //admin - if(A.fingerprints && fingerprints) - A.fingerprints |= fingerprints.Copy() //detective - if(A.fingerprintshidden && 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) - if(flags & NOBLOODY) return 0 - .=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(!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() - add_dirt_cover(new M.species.blood_color) -// blood_color = "#A10808" -// if (M.species) -// blood_color = M.species.blood_color - return - -/atom/proc/add_dirt_cover(dirt_datum) - if(flags & NOBLOODY) return 0 - if(!dirt_datum) return 0 - if(!dirt_overlay) - dirt_overlay = new/datum/dirt_cover(dirt_datum) - else - dirt_overlay.add_dirt(dirt_datum) - return 1 - -/atom/proc/add_vomit_floor(mob/living/carbon/M, 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) - var/datum/reagents/R = M.reagents - if(!locate(/datum/reagent/luminophore) in R.reagent_list) - this.icon_state = "vomittox_[pick(1,4)]" - else - this.icon_state = "vomittox_nc_[pick(1,4)]" - this.alpha = 127 - var/datum/reagent/new_color = locate(/datum/reagent/luminophore) in R.reagent_list - this.color = new_color.color - this.light_color = this.color - this.set_light(3) - this.stop_light() - - -/atom/proc/clean_blood() - src.germ_level = 0 - if(dirt_overlay) - dirt_overlay = null - if(istype(blood_DNA, /list)) - blood_DNA = null - return 1 - return 0 - -/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 -// 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/isinspace() - if(istype(get_turf(src), /turf/space)) - return 1 - else - return 0 - -/atom/proc/checkpass(passflag) - return pass_flags&passflag - -//This proc is called on the location of an atom when the atom is Destroy()'d -/atom/proc/handle_atom_del(atom/A) - -// Byond seemingly calls stat, each tick. -// Calling things each tick can get expensive real quick. -// So we slow this down a little. -// See: http://www.byond.com/docs/ref/info.html#/client/proc/Stat -/atom/Stat() - . = ..() - sleep(1) - stoplag() - -/atom/proc/update_transform() - var/matrix/ntransform = matrix(transform) - var/changed = 0 - - if(resize != RESIZE_DEFAULT_SIZE) - resize_rev *= 1/resize //saving revert parameter for restoring size - changed++ - ntransform.Scale(resize) - resize = RESIZE_DEFAULT_SIZE - - if(changed) - animate(src, transform = ntransform, time = 2, easing = EASE_IN|EASE_OUT) +/atom + layer = TURF_LAYER + plane = GAME_PLANE + var/level = 2 + var/flags = 0 + var/flags_2 = 0 + var/list/fingerprints + var/list/fingerprintshidden + var/fingerprintslast = null + + var/list/blood_DNA //forensic reasons + var/datum/dirt_cover/dirt_overlay //style reasons + + var/last_bumped = 0 + var/pass_flags = 0 + var/throwpass = 0 + var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom. + var/simulated = 1 //filter for actions - used by lighting overlays + + var/resize = 1 //don't abuse this shit + var/resize_rev = 1 //helps to restore default size + + var/initialized = FALSE + + ///Chemistry. + var/datum/reagents/reagents = null + + //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/in_use_action = FALSE // do_after sets this to TRUE and is_busy() can check for that to disallow multiple users to interact with this at the same time. + +/atom/New(loc, ...) + if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New() + _preloader.load(src) + + //. = ..() //uncomment if you are dumb enough to add a /datum/New() proc + + var/do_initialize = SSatoms.initialized + if(do_initialize > INITIALIZATION_INSSATOMS) + args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD + if(SSatoms.InitAtom(src, args)) + //we were deleted + return + + var/list/created = SSatoms.created_atoms + if(created) + created += src + +// Called after New if the map is being loaded. mapload = TRUE +// Called from base of New if the map is being loaded. mapload = FALSE +// This base must be called or derivatives must set initialized to TRUE +// must not sleep +// Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE +// Must return an Initialize hint. Defined in __DEFINES/subsystems.dm + +//Note: the following functions don't call the base for optimization and must copypasta: +// /turf/atom_init +// /turf/space/atom_init +// /mob/dead/atom_init + +//Do also note that this proc always runs in New for /mob/dead +/atom/proc/atom_init(mapload, ...) + if(initialized) + stack_trace("Warning: [src]([type]) initialized multiple times!") + initialized = TRUE + + if(light_power && light_range) + update_light() + + if(opacity && isturf(src.loc)) + var/turf/T = src.loc + T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. + + return INITIALIZE_HINT_NORMAL + +//called if atom_init returns INITIALIZE_HINT_LATELOAD +/atom/proc/atom_init_late() + return + +/atom/Destroy() + if(reagents) + QDEL_NULL(reagents) + + LAZYCLEARLIST(overlays) + + if(light) + light.destroy() + light = null + + return ..() + +/atom/proc/CheckParts(list/parts_list) + for(var/A in parts_list) + if(istype(A, /datum/reagent)) + if(!reagents) + reagents = new() + reagents.reagent_list.Add(A) + reagents.conditional_update() + else if(ismovableatom(A)) + var/atom/movable/M = A + if(isliving(M.loc)) + var/mob/living/L = M.loc + L.drop_from_inventory(M, src) + else + M.forceMove(src) + +/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) + if (istype(user, /mob/living/silicon/ai)) // WHYYYY + return 1 + return + +/atom/proc/on_reagent_change() + return + +/atom/proc/Bumped(AM) + 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/can_mob_interact(mob/user) + if (ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.getBrainLoss() >= 60) + user.visible_message("[H] stares cluelessly at [isturf(loc) ? src : ismob(loc) ? src : "something"] and drools.") + return FALSE + else if(prob(H.getBrainLoss())) + to_chat(user, "You momentarily forget how to use [src].") + return FALSE + return TRUE + +/atom/proc/meteorhit(obj/meteor) + return + +/atom/proc/allow_drop() + return 1 + +/atom/proc/CheckExit() + return 1 + +/atom/proc/HasProximity(atom/movable/AM) + return + +/atom/proc/emp_act(severity) + return + + +/atom/proc/bullet_act(obj/item/projectile/P, def_zone) + P.on_hit(src, 0, def_zone) + . = 0 + +/atom/proc/in_contents_of(container)//can take class or object instance as argument + if(ispath(container)) + if(istype(src.loc, container)) + return 1 + else if(src in container) + return 1 + 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/examine(mob/user, distance = -1) + //This reformat names to get a/an properly working on item descriptions when they are bloody + var/f_name = "\a [src]." + if(dirt_overlay) //Oil and blood puddles got 'blood_color = NULL', however they got 'color' instead + f_name = "\a [dirt_description()]!" + to_chat(user, "[bicon(src)] That's [f_name]") + if(desc) + to_chat(user, desc) + // *****RM + //user << "[name]: Dn:[density] dir:[dir] cont:[contents] icon:[icon] is:[icon_state] loc:[loc]" + if(reagents && is_open_container()) //is_open_container() isn't really the right proc for this, but w/e + to_chat(user, "It contains:") + if(reagents.reagent_list.len) + if(istype(src, /obj/structure/reagent_dispensers)) //watertanks, fueltanks + for(var/datum/reagent/R in reagents.reagent_list) + to_chat(user, "[R.volume] units of [R.name]") + else + to_chat(user, "[reagents.total_volume] units of liquid.") + else + to_chat(user, "Nothing.") + + return distance == -1 || isobserver(user) || (get_dist(src, user) <= distance) + +/atom/proc/dirt_description() + if(dirt_overlay) + return "[dirt_overlay.name]-covered [name]" + else + return name + +//called to set the atom's dir and used to add behaviour to dir-changes +/atom/proc/set_dir(new_dir) + . = new_dir != dir + dir = new_dir + +/atom/proc/relaymove() + return + +/atom/proc/ex_act() + return + +/atom/proc/blob_act() + return + +/atom/proc/fire_act() + return + +/atom/proc/singularity_act() + return + +/atom/proc/singularity_pull() + return + +/atom/proc/hitby(atom/movable/AM) + return + +/atom/proc/add_hiddenprint(mob/living/M) + if(!M || !M.key) + 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/M, ignoregloves = 0) + if(!M || !M.key || isAI(M)) //AI's clicks already calls add_hiddenprint from ClickOn() proc + 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 (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(H.species.flags[NO_FINGERPRINT]) // They don't leave readable fingerprints, but admins gotta know. + fingerprintshidden += "(Specie has no fingerprints) Real name: [H.real_name], Key: [H.key]" + fingerprintslast = H.key + return 0 + + 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(!ignoregloves) + 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 + // + if(fingerprints[full_print]) + switch(stringpercent(fingerprints[full_print])) //tells us how many stars are in the current prints. + + if(28 to 32) + if(prob(1)) + fingerprints[full_print] = full_print // You rolled a one buddy. + else + fingerprints[full_print] = stars(full_print, rand(0,40)) // 24 to 32 + + if(24 to 27) + if(prob(3)) + fingerprints[full_print] = full_print //Sucks to be you. + else + fingerprints[full_print] = stars(full_print, rand(15, 55)) // 20 to 29 + + if(20 to 23) + if(prob(5)) + fingerprints[full_print] = full_print //Had a good run didn't ya. + else + fingerprints[full_print] = stars(full_print, rand(30, 70)) // 15 to 25 + + if(16 to 19) + if(prob(5)) + fingerprints[full_print] = full_print //Welp. + else + fingerprints[full_print] = stars(full_print, rand(40, 100)) // 0 to 21 + + if(0 to 15) + if(prob(5)) + fingerprints[full_print] = stars(full_print, rand(0,50)) // small chance you can smudge. + else + fingerprints[full_print] = full_print + + else + fingerprints[full_print] = stars(full_print, rand(0, 20)) //Initial touch, not leaving much evidence the first time. + + + return 1 + else + //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) + fingerprints = null + return + + +/atom/proc/transfer_fingerprints_to(atom/A) + + if(!istype(A.fingerprints,/list)) + A.fingerprints = list() + + if(!istype(A.fingerprintshidden,/list)) + A.fingerprintshidden = list() + + if(!istype(fingerprintshidden, /list)) + fingerprintshidden = list() + + //skytodo + //A.fingerprints |= fingerprints //detective + //A.fingerprintshidden |= fingerprintshidden //admin + if(A.fingerprints && fingerprints) + A.fingerprints |= fingerprints.Copy() //detective + if(A.fingerprintshidden && 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) + if(flags & NOBLOODY) return 0 + .=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(!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() + add_dirt_cover(new M.species.blood_color) +// blood_color = "#A10808" +// if (M.species) +// blood_color = M.species.blood_color + return + +/atom/proc/add_dirt_cover(dirt_datum) + if(flags & NOBLOODY) return 0 + if(!dirt_datum) return 0 + if(!dirt_overlay) + dirt_overlay = new/datum/dirt_cover(dirt_datum) + else + dirt_overlay.add_dirt(dirt_datum) + return 1 + +/atom/proc/add_vomit_floor(mob/living/carbon/M, 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) + var/datum/reagents/R = M.reagents + if(!locate(/datum/reagent/luminophore) in R.reagent_list) + this.icon_state = "vomittox_[pick(1,4)]" + else + this.icon_state = "vomittox_nc_[pick(1,4)]" + this.alpha = 127 + var/datum/reagent/new_color = locate(/datum/reagent/luminophore) in R.reagent_list + this.color = new_color.color + this.light_color = this.color + this.set_light(3) + this.stop_light() + + +/atom/proc/clean_blood() + src.germ_level = 0 + if(dirt_overlay) + dirt_overlay = null + if(istype(blood_DNA, /list)) + blood_DNA = null + return 1 + return 0 + +/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 +// 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/isinspace() + if(istype(get_turf(src), /turf/space)) + return 1 + else + return 0 + +/atom/proc/checkpass(passflag) + return pass_flags&passflag + +//This proc is called on the location of an atom when the atom is Destroy()'d +/atom/proc/handle_atom_del(atom/A) + +// Byond seemingly calls stat, each tick. +// Calling things each tick can get expensive real quick. +// So we slow this down a little. +// See: http://www.byond.com/docs/ref/info.html#/client/proc/Stat +/atom/Stat() + . = ..() + sleep(1) + stoplag() + +/atom/proc/update_transform() + var/matrix/ntransform = matrix(transform) + var/changed = 0 + + if(resize != RESIZE_DEFAULT_SIZE) + resize_rev *= 1/resize //saving revert parameter for restoring size + changed++ + ntransform.Scale(resize) + resize = RESIZE_DEFAULT_SIZE + + if(changed) + animate(src, transform = ntransform, time = 2, easing = EASE_IN|EASE_OUT) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 053bc27bb04f..6062f9a25a61 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,332 +1,332 @@ -/atom/movable - layer = 3 - appearance_flags = TILE_BOUND - var/last_move = null - var/anchored = 0 - var/move_speed = 10 - var/l_move_time = 1 - var/throwing = 0 - var/thrower - var/turf/throw_source = null - var/throw_speed = 2 - var/throw_range = 7 - var/fly_speed = 0 // Used to get throw speed param exposed in proc, so we could use it in hitby reactions. - var/moved_recently = 0 - var/mob/pulledby = null - - var/inertia_dir = 0 - var/atom/inertia_last_loc - var/inertia_moving = 0 - var/inertia_next_move = 0 - var/inertia_move_delay = 5 - - var/list/client_mobs_in_contents - var/freeze_movement = FALSE - -/atom/movable/Destroy() - //If we have opacity, make sure to tell (potentially) affected light sources. - var/turf/T = loc - if(opacity && istype(T)) - opacity = 0 - T.recalc_atom_opacity() - T.reconsider_lights() - - unbuckle_mob() - - if(loc) - loc.handle_atom_del(src) - for(var/atom/movable/AM in contents) - qdel(AM) - loc = null - invisibility = 101 - if(pulledby) - pulledby.stop_pulling() - return ..() - -/atom/movable/Move(atom/newloc, direct = 0) - if(!loc || !newloc || freeze_movement) - return FALSE - - var/atom/oldloc = loc - - if(loc != newloc) - if (!(direct & (direct - 1))) //Cardinal move - . = ..() - else //Diagonal move, split it into cardinal moves - if (direct & 1) - if (direct & 4) - if (step(src, NORTH)) - . = step(src, EAST) - else if (step(src, EAST)) - . = step(src, NORTH) - else if (direct & 8) - if (step(src, NORTH)) - . = step(src, WEST) - else if (step(src, WEST)) - . = step(src, NORTH) - else if (direct & 2) - if (direct & 4) - if (step(src, SOUTH)) - . = step(src, EAST) - else if (step(src, EAST)) - . = step(src, SOUTH) - else if (direct & 8) - if (step(src, SOUTH)) - . = step(src, WEST) - else if (step(src, WEST)) - . = step(src, SOUTH) - - if(!loc || (loc == oldloc && oldloc != newloc)) - last_move = 0 - return FALSE - - src.move_speed = world.time - src.l_move_time - src.l_move_time = world.time - - last_move = direct - - if(. && buckled_mob && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob - . = 0 - - if(.) - Moved(oldloc, direct) - -/atom/movable/proc/Moved(atom/OldLoc, Dir) - if (!inertia_moving) - inertia_next_move = world.time + inertia_move_delay - newtonian_move(Dir) - if(length(client_mobs_in_contents)) - update_parallax_contents() - - if (orbiters) - for (var/thing in orbiters) - var/datum/orbit/O = thing - O.Check() - if (orbiting) - orbiting.Check() - return 1 - -/atom/movable/proc/setLoc(T, teleported=0) - loc = T - -/atom/movable/Bump(atom/A, non_native_bump) - STOP_THROWING(src, A) - - if(A && non_native_bump) - A.last_bumped = world.time - A.Bumped(src) - - -/atom/movable/proc/forceMove(atom/destination) - if(destination) - if(pulledby) - pulledby.stop_pulling() - var/atom/oldloc = loc - var/same_loc = (oldloc == destination) - var/area/old_area = get_area(oldloc) - var/area/destarea = get_area(destination) - - if(oldloc && !same_loc) - oldloc.Exited(src, destination) - if(old_area) - old_area.Exited(src, destination) - - loc = destination - - if(!same_loc) - destination.Entered(src, oldloc) - if(destarea && old_area != destarea) - destarea.Entered(src, oldloc) - - for(var/atom/movable/AM in destination) - if(AM == src) - continue - AM.Crossed(src) - - Moved(oldloc, 0) - return TRUE - return FALSE - -/mob/living/forceMove() - stop_pulling() - if(buckled) - buckled.unbuckle_mob() - . = ..() - update_canmove() - -/mob/dead/observer/forceMove(atom/destination) - if(destination) - if(loc) - loc.Exited(src) - loc = destination - loc.Entered(src) - return 1 - return 0 - -//called when src is thrown into hit_atom -/atom/movable/proc/throw_impact(atom/hit_atom) - hit_atom.hitby(src) - - if(isobj(hit_atom)) - var/obj/O = hit_atom - if(!O.anchored) - O.Move(get_step(O, dir)) - - if(isturf(hit_atom) && hit_atom.density) - Move(get_step(src, turn(dir, 180))) - -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, datum/callback/early_callback) - if (!target || speed <= 0) - return - - if (pulledby) - pulledby.stop_pulling() - - //They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw? - if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2) - var/user_momentum = thrower.movement_delay() - if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead. - user_momentum = world.tick_lag - - user_momentum = 1 / user_momentum // convert from ds to the tiles per ds that throw_at uses. - - if (get_dir(thrower, target) & last_move) - user_momentum = user_momentum //basically a noop, but needed - else if (get_dir(target, thrower) & last_move) - user_momentum = -user_momentum //we are moving away from the target, lets slowdown the throw accordingly - else - user_momentum = 0 - - - if (user_momentum) - //first lets add that momentum to range. - range *= (user_momentum / speed) + 1 - //then lets add it to speed - speed += user_momentum - if (speed <= 0) - return //no throw speed, the user was moving too fast. - - var/datum/thrownthing/TT = new() - TT.thrownthing = src - TT.target = target - TT.target_turf = get_turf(target) - TT.init_dir = get_dir(src, target) - TT.maxrange = range - TT.speed = speed - TT.thrower = thrower - TT.diagonals_first = diagonals_first - TT.callback = callback - TT.early_callback = early_callback - - var/dist_x = abs(target.x - src.x) - var/dist_y = abs(target.y - src.y) - var/dx = (target.x > src.x) ? EAST : WEST - var/dy = (target.y > src.y) ? NORTH : SOUTH - - if (dist_x == dist_y) - TT.pure_diagonal = TRUE - - else if(dist_x <= dist_y) - var/olddist_x = dist_x - var/olddx = dx - dist_x = dist_y - dist_y = olddist_x - dx = dy - dy = olddx - TT.dist_x = dist_x - TT.dist_y = dist_y - TT.dx = dx - TT.dy = dy - TT.diagonal_error = dist_x/2 - dist_y - TT.start_time = world.time - - if(pulledby) - pulledby.stop_pulling() - - src.thrower = thrower - throw_source = get_turf(loc) - fly_speed = speed - throwing = TRUE - if(spin) - SpinAnimation(5, 1) - - SSthrowing.processing[src] = TT - if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun)) - SSthrowing.currentrun[src] = TT - TT.tick() - -//Called whenever an object moves and by mobs when they attempt to move themselves through space -//And when an object or action applies a force on src, see newtonian_move() below -//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting -//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm -//movement_dir == 0 when stopping or any dir when trying to move -/atom/movable/proc/Process_Spacemove(movement_dir = 0) - if(has_gravity(src)) - return 1 - - if(pulledby) - return 1 - - if(throwing) - return 1 - - if(locate(/obj/structure/lattice) in orange(1, get_turf(src))) //Not realistic but makes pushing things in space easier - return 1 - - return 0 - -/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity - - if(!loc || Process_Spacemove(0)) - inertia_dir = 0 - return 0 - - inertia_dir = direction - if(!direction) - return 1 - - inertia_last_loc = loc - SSspacedrift.processing[src] = src - return 1 - -//Overlays -/atom/movable/overlay - var/atom/master = null - anchored = 1 - -/atom/movable/overlay/atom_init() - . = ..() - for(var/x in verbs) - verbs -= x - -/atom/movable/overlay/attackby(a, b, params) - if (src.master) - return src.master.attackby(a, b) - 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/handle_rotation() - return - -/atom/movable/proc/handle_buckled_mob_movement(newloc,direct) - if(!buckled_mob.Move(newloc, direct)) - loc = buckled_mob.loc - last_move = buckled_mob.last_move - inertia_dir = last_move - buckled_mob.inertia_dir = last_move - return 0 - return 1 - -/atom/movable/CanPass(atom/movable/mover, turf/target, height=1.5) - if(buckled_mob == mover) - return 1 - return ..() +/atom/movable + layer = 3 + appearance_flags = TILE_BOUND + var/last_move = null + var/anchored = 0 + var/move_speed = 10 + var/l_move_time = 1 + var/throwing = 0 + var/thrower + var/turf/throw_source = null + var/throw_speed = 2 + var/throw_range = 7 + var/fly_speed = 0 // Used to get throw speed param exposed in proc, so we could use it in hitby reactions. + var/moved_recently = 0 + var/mob/pulledby = null + + var/inertia_dir = 0 + var/atom/inertia_last_loc + var/inertia_moving = 0 + var/inertia_next_move = 0 + var/inertia_move_delay = 5 + + var/list/client_mobs_in_contents + var/freeze_movement = FALSE + +/atom/movable/Destroy() + //If we have opacity, make sure to tell (potentially) affected light sources. + var/turf/T = loc + if(opacity && istype(T)) + opacity = 0 + T.recalc_atom_opacity() + T.reconsider_lights() + + unbuckle_mob() + + if(loc) + loc.handle_atom_del(src) + for(var/atom/movable/AM in contents) + qdel(AM) + loc = null + invisibility = 101 + if(pulledby) + pulledby.stop_pulling() + return ..() + +/atom/movable/Move(atom/newloc, direct = 0) + if(!loc || !newloc || freeze_movement) + return FALSE + + var/atom/oldloc = loc + + if(loc != newloc) + if (!(direct & (direct - 1))) //Cardinal move + . = ..() + else //Diagonal move, split it into cardinal moves + if (direct & 1) + if (direct & 4) + if (step(src, NORTH)) + . = step(src, EAST) + else if (step(src, EAST)) + . = step(src, NORTH) + else if (direct & 8) + if (step(src, NORTH)) + . = step(src, WEST) + else if (step(src, WEST)) + . = step(src, NORTH) + else if (direct & 2) + if (direct & 4) + if (step(src, SOUTH)) + . = step(src, EAST) + else if (step(src, EAST)) + . = step(src, SOUTH) + else if (direct & 8) + if (step(src, SOUTH)) + . = step(src, WEST) + else if (step(src, WEST)) + . = step(src, SOUTH) + + if(!loc || (loc == oldloc && oldloc != newloc)) + last_move = 0 + return FALSE + + src.move_speed = world.time - src.l_move_time + src.l_move_time = world.time + + last_move = direct + + if(. && buckled_mob && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob + . = 0 + + if(.) + Moved(oldloc, direct) + +/atom/movable/proc/Moved(atom/OldLoc, Dir) + if (!inertia_moving) + inertia_next_move = world.time + inertia_move_delay + newtonian_move(Dir) + if(length(client_mobs_in_contents)) + update_parallax_contents() + + if (orbiters) + for (var/thing in orbiters) + var/datum/orbit/O = thing + O.Check() + if (orbiting) + orbiting.Check() + return 1 + +/atom/movable/proc/setLoc(T, teleported=0) + loc = T + +/atom/movable/Bump(atom/A, non_native_bump) + STOP_THROWING(src, A) + + if(A && non_native_bump) + A.last_bumped = world.time + A.Bumped(src) + + +/atom/movable/proc/forceMove(atom/destination) + if(destination) + if(pulledby) + pulledby.stop_pulling() + var/atom/oldloc = loc + var/same_loc = (oldloc == destination) + var/area/old_area = get_area(oldloc) + var/area/destarea = get_area(destination) + + if(oldloc && !same_loc) + oldloc.Exited(src, destination) + if(old_area) + old_area.Exited(src, destination) + + loc = destination + + if(!same_loc) + destination.Entered(src, oldloc) + if(destarea && old_area != destarea) + destarea.Entered(src, oldloc) + + for(var/atom/movable/AM in destination) + if(AM == src) + continue + AM.Crossed(src) + + Moved(oldloc, 0) + return TRUE + return FALSE + +/mob/living/forceMove() + stop_pulling() + if(buckled) + buckled.unbuckle_mob() + . = ..() + update_canmove() + +/mob/dead/observer/forceMove(atom/destination) + if(destination) + if(loc) + loc.Exited(src) + loc = destination + loc.Entered(src) + return 1 + return 0 + +//called when src is thrown into hit_atom +/atom/movable/proc/throw_impact(atom/hit_atom) + hit_atom.hitby(src) + + if(isobj(hit_atom)) + var/obj/O = hit_atom + if(!O.anchored) + O.Move(get_step(O, dir)) + + if(isturf(hit_atom) && hit_atom.density) + Move(get_step(src, turn(dir, 180))) + +/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, datum/callback/early_callback) + if (!target || speed <= 0) + return + + if (pulledby) + pulledby.stop_pulling() + + //They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw? + if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2) + var/user_momentum = thrower.movement_delay() + if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead. + user_momentum = world.tick_lag + + user_momentum = 1 / user_momentum // convert from ds to the tiles per ds that throw_at uses. + + if (get_dir(thrower, target) & last_move) + user_momentum = user_momentum //basically a noop, but needed + else if (get_dir(target, thrower) & last_move) + user_momentum = -user_momentum //we are moving away from the target, lets slowdown the throw accordingly + else + user_momentum = 0 + + + if (user_momentum) + //first lets add that momentum to range. + range *= (user_momentum / speed) + 1 + //then lets add it to speed + speed += user_momentum + if (speed <= 0) + return //no throw speed, the user was moving too fast. + + var/datum/thrownthing/TT = new() + TT.thrownthing = src + TT.target = target + TT.target_turf = get_turf(target) + TT.init_dir = get_dir(src, target) + TT.maxrange = range + TT.speed = speed + TT.thrower = thrower + TT.diagonals_first = diagonals_first + TT.callback = callback + TT.early_callback = early_callback + + var/dist_x = abs(target.x - src.x) + var/dist_y = abs(target.y - src.y) + var/dx = (target.x > src.x) ? EAST : WEST + var/dy = (target.y > src.y) ? NORTH : SOUTH + + if (dist_x == dist_y) + TT.pure_diagonal = TRUE + + else if(dist_x <= dist_y) + var/olddist_x = dist_x + var/olddx = dx + dist_x = dist_y + dist_y = olddist_x + dx = dy + dy = olddx + TT.dist_x = dist_x + TT.dist_y = dist_y + TT.dx = dx + TT.dy = dy + TT.diagonal_error = dist_x/2 - dist_y + TT.start_time = world.time + + if(pulledby) + pulledby.stop_pulling() + + src.thrower = thrower + throw_source = get_turf(loc) + fly_speed = speed + throwing = TRUE + if(spin) + SpinAnimation(5, 1) + + SSthrowing.processing[src] = TT + if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun)) + SSthrowing.currentrun[src] = TT + TT.tick() + +//Called whenever an object moves and by mobs when they attempt to move themselves through space +//And when an object or action applies a force on src, see newtonian_move() below +//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting +//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm +//movement_dir == 0 when stopping or any dir when trying to move +/atom/movable/proc/Process_Spacemove(movement_dir = 0) + if(has_gravity(src)) + return 1 + + if(pulledby) + return 1 + + if(throwing) + return 1 + + if(locate(/obj/structure/lattice) in orange(1, get_turf(src))) //Not realistic but makes pushing things in space easier + return 1 + + return 0 + +/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity + + if(!loc || Process_Spacemove(0)) + inertia_dir = 0 + return 0 + + inertia_dir = direction + if(!direction) + return 1 + + inertia_last_loc = loc + SSspacedrift.processing[src] = src + return 1 + +//Overlays +/atom/movable/overlay + var/atom/master = null + anchored = 1 + +/atom/movable/overlay/atom_init() + . = ..() + for(var/x in verbs) + verbs -= x + +/atom/movable/overlay/attackby(a, b, params) + if (src.master) + return src.master.attackby(a, b) + 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/handle_rotation() + return + +/atom/movable/proc/handle_buckled_mob_movement(newloc,direct) + if(!buckled_mob.Move(newloc, direct)) + loc = buckled_mob.loc + last_move = buckled_mob.last_move + inertia_dir = last_move + buckled_mob.inertia_dir = last_move + return 0 + return 1 + +/atom/movable/CanPass(atom/movable/mover, turf/target, height=1.5) + if(buckled_mob == mover) + return 1 + return ..() diff --git a/code/game/communications.dm b/code/game/communications.dm index 8d167e8c3c12..559a8c8639f4 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -1,300 +1,300 @@ -/* - 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, new_frequency, filter = 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(frequency) - 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, datum/signal/signal, filter = null, range = 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, receive_method, 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. - -*/ - -/* -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 -1347 - Cargo techs - -Devices: -1451 - tracking implant -1457 - RSD default - -On the map: -1311 for prison shuttle console (in fact, it is not used) -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, - "Science" = 1351, - "Command" = 1353, - "Medical" = 1355, - "Engineering" = 1357, - "Security" = 1359, - "Response Team" = 1345, - "Deathsquad" = 1341, - "Syndicate" = 1213, - "Supply" = 1347, -) -//depenging helpers -var/list/DEPT_FREQS = list(1351, 1355, 1357, 1359, 1213, 1345, 1341, 1347) - -// central command channels, i.e deathsquid & response teams -var/list/CENT_FREQS = list(1345, 1341) - -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 - -#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" -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/global/datum/controller/radio/radio_controller - -/datum/controller/radio - var/list/datum/radio_frequency/frequencies = list() - -/datum/controller/radio/proc/add_object(obj/device, new_frequency, filter = null) - var/f_text = num2text(new_frequency) - var/datum/radio_frequency/frequency = frequencies[f_text] - - if(!frequency) - frequency = new - frequency.frequency = new_frequency - frequencies[f_text] = frequency - - frequency.add_listener(device, filter) - return frequency - -/datum/controller/radio/proc/remove_object(obj/device, old_frequency) - var/f_text = num2text(old_frequency) - var/datum/radio_frequency/frequency = frequencies[f_text] - - if(frequency) - frequency.remove_listener(device) - - if(frequency.devices.len == 0) - qdel(frequency) - frequencies -= f_text - - return 1 - -/datum/controller/radio/proc/return_frequency(new_frequency) - var/f_text = num2text(new_frequency) - var/datum/radio_frequency/frequency = frequencies[f_text] - - if(!frequency) - frequency = new - frequency.frequency = new_frequency - frequencies[f_text] = frequency - - return frequency - -/datum/radio_frequency - var/frequency as num - var/list/list/obj/devices = list() - -/datum/radio_frequency/proc/post_signal(obj/source, datum/signal/signal, filter = null, range = 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) - qdel(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]") - - -// qdel(signal) - -/datum/radio_frequency/proc/add_listener(obj/device, filter) - if (!filter) - filter = "_default" - //log_admin("add_listener(device=[device],filter=[filter]) frequency=[frequency]") - var/list/obj/devices_line = devices[filter] - if (!devices_line) - devices_line = new - devices[filter] = devices_line - devices_line+=device -// var/list/obj/devices_line___ = devices[filter_str] -// var/l = devices_line___.len - //log_admin("DEBUG: devices_line.len=[devices_line.len]") - //log_admin("DEBUG: devices(filter_str).len=[l]") - -/datum/radio_frequency/proc/remove_listener(obj/device) - for(var/devices_filter in devices) - var/list/devices_line = devices[devices_filter] - if(!devices_line) - devices -= devices_filter - devices_line -= device - if(!devices_line.len) - devices -= devices_filter - - -/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param) - return null - -/datum/signal - var/obj/source - - var/transmission_method = 0 - //0 = wire - //1 = radio transmission - //2 = subspace transmission - - var/data = list() - var/encryption - - var/frequency = 0 - -/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]" +/* + 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, new_frequency, filter = 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(frequency) + 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, datum/signal/signal, filter = null, range = 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, receive_method, 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. + +*/ + +/* +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 +1347 - Cargo techs + +Devices: +1451 - tracking implant +1457 - RSD default + +On the map: +1311 for prison shuttle console (in fact, it is not used) +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, + "Science" = 1351, + "Command" = 1353, + "Medical" = 1355, + "Engineering" = 1357, + "Security" = 1359, + "Response Team" = 1345, + "Deathsquad" = 1341, + "Syndicate" = 1213, + "Supply" = 1347, +) +//depenging helpers +var/list/DEPT_FREQS = list(1351, 1355, 1357, 1359, 1213, 1345, 1341, 1347) + +// central command channels, i.e deathsquid & response teams +var/list/CENT_FREQS = list(1345, 1341) + +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 + +#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" +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/global/datum/controller/radio/radio_controller + +/datum/controller/radio + var/list/datum/radio_frequency/frequencies = list() + +/datum/controller/radio/proc/add_object(obj/device, new_frequency, filter = null) + var/f_text = num2text(new_frequency) + var/datum/radio_frequency/frequency = frequencies[f_text] + + if(!frequency) + frequency = new + frequency.frequency = new_frequency + frequencies[f_text] = frequency + + frequency.add_listener(device, filter) + return frequency + +/datum/controller/radio/proc/remove_object(obj/device, old_frequency) + var/f_text = num2text(old_frequency) + var/datum/radio_frequency/frequency = frequencies[f_text] + + if(frequency) + frequency.remove_listener(device) + + if(frequency.devices.len == 0) + qdel(frequency) + frequencies -= f_text + + return 1 + +/datum/controller/radio/proc/return_frequency(new_frequency) + var/f_text = num2text(new_frequency) + var/datum/radio_frequency/frequency = frequencies[f_text] + + if(!frequency) + frequency = new + frequency.frequency = new_frequency + frequencies[f_text] = frequency + + return frequency + +/datum/radio_frequency + var/frequency as num + var/list/list/obj/devices = list() + +/datum/radio_frequency/proc/post_signal(obj/source, datum/signal/signal, filter = null, range = 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) + qdel(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]") + + +// qdel(signal) + +/datum/radio_frequency/proc/add_listener(obj/device, filter) + if (!filter) + filter = "_default" + //log_admin("add_listener(device=[device],filter=[filter]) frequency=[frequency]") + var/list/obj/devices_line = devices[filter] + if (!devices_line) + devices_line = new + devices[filter] = devices_line + devices_line+=device +// var/list/obj/devices_line___ = devices[filter_str] +// var/l = devices_line___.len + //log_admin("DEBUG: devices_line.len=[devices_line.len]") + //log_admin("DEBUG: devices(filter_str).len=[l]") + +/datum/radio_frequency/proc/remove_listener(obj/device) + for(var/devices_filter in devices) + var/list/devices_line = devices[devices_filter] + if(!devices_line) + devices -= devices_filter + devices_line -= device + if(!devices_line.len) + devices -= devices_filter + + +/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param) + return null + +/datum/signal + var/obj/source + + var/transmission_method = 0 + //0 = wire + //1 = radio transmission + //2 = subspace transmission + + var/data = list() + var/encryption + + var/frequency = 0 + +/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]" diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index e84518876f1b..4eb6510d479c 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -1,167 +1,167 @@ -//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" - role_type = ROLE_BLOB - - required_players = 30 - required_players_secret = 25 - required_enemies = 1 - recommended_enemies = 1 - - votable = 0 - - restricted_jobs = list("Cyborg", "AI") - - var/declared = 0 - - var/cores_to_spawn = 1 - var/players_per_core = 30 - var/blob_point_rate = 3 - - //var/blobwincount = 350 //default value - var/blobwincount = 500 - - var/list/infected_crew = list() - -/datum/game_mode/blob/pre_setup() - cores_to_spawn = max(round(num_players()/players_per_core, 1), 1) - - blobwincount = initial(blobwincount) * cores_to_spawn - - for(var/datum/mind/player in antag_candidates) - for(var/job in restricted_jobs)//Removing robots from the list - if(player.assigned_role == job) - antag_candidates -= player - - for(var/j = 0, j < cores_to_spawn, j++) - if (!antag_candidates.len) - break - var/datum/mind/blob = pick(antag_candidates) - infected_crew += blob - blob.special_role = "Blob" - log_game("[blob.key] (ckey) has been selected as a Blob") - antag_candidates -= blob - - if(!infected_crew.len) - return 0 - - return 1 - - -/datum/game_mode/blob/announce() - to_chat(world, "The current game mode is - Blob!") - to_chat(world, "A dangerous alien organism is rapidly spreading throughout the station!") - to_chat(world, "You must kill it all while minimizing the damage to the station.") - - -/datum/game_mode/blob/proc/greet_blob(datum/mind/blob) - to_chat(blob.current, " You are infected by the Blob!") - to_chat(blob.current, "Your body is ready to give spawn to a new blob core which will eat this station.") - to_chat(blob.current, "Find a good location to spawn the core and then take control and overwhelm the station!") - to_chat(blob.current, "When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process.") - to_chat(blob.current, "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.") - return - -/datum/game_mode/blob/proc/show_message(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 != ZLEVEL_STATION || 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(SSshuttle) - SSshuttle.always_fake_recall = 1 - - spawn(0) - - var/wait_time = rand(waittime_l, waittime_h) - - sleep(wait_time) - - 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(40) - stage(0) - - // Stage 1 - sleep(2000) - stage(1) - - return ..() - -/datum/game_mode/blob/proc/stage(stage) - - switch(stage) - if (0) - send_intercept(1) - declared = 1 - return - - if (1) - command_alert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - for(var/mob/M in player_list) - if(!isnewplayer(M)) - M << sound('sound/AI/outbreak5.ogg') - return - - return - -/mob/living/carbon/human/proc/Blobize() - if (monkeyizing) - return - var/obj/effect/blob/core/new_blob = new /obj/effect/blob/core (loc) - if(!client) - for(var/mob/dead/observer/G in player_list) - if(ckey == "@[G.ckey]") - new_blob.create_overmind(G.client , 1) - break - else - new_blob.create_overmind(src.client , 1) - gib(src) +//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" + role_type = ROLE_BLOB + + required_players = 30 + required_players_secret = 25 + required_enemies = 1 + recommended_enemies = 1 + + votable = 0 + + restricted_jobs = list("Cyborg", "AI") + + var/declared = 0 + + var/cores_to_spawn = 1 + var/players_per_core = 30 + var/blob_point_rate = 3 + + //var/blobwincount = 350 //default value + var/blobwincount = 500 + + var/list/infected_crew = list() + +/datum/game_mode/blob/pre_setup() + cores_to_spawn = max(round(num_players()/players_per_core, 1), 1) + + blobwincount = initial(blobwincount) * cores_to_spawn + + for(var/datum/mind/player in antag_candidates) + for(var/job in restricted_jobs)//Removing robots from the list + if(player.assigned_role == job) + antag_candidates -= player + + for(var/j = 0, j < cores_to_spawn, j++) + if (!antag_candidates.len) + break + var/datum/mind/blob = pick(antag_candidates) + infected_crew += blob + blob.special_role = "Blob" + log_game("[blob.key] (ckey) has been selected as a Blob") + antag_candidates -= blob + + if(!infected_crew.len) + return 0 + + return 1 + + +/datum/game_mode/blob/announce() + to_chat(world, "The current game mode is - Blob!") + to_chat(world, "A dangerous alien organism is rapidly spreading throughout the station!") + to_chat(world, "You must kill it all while minimizing the damage to the station.") + + +/datum/game_mode/blob/proc/greet_blob(datum/mind/blob) + to_chat(blob.current, " You are infected by the Blob!") + to_chat(blob.current, "Your body is ready to give spawn to a new blob core which will eat this station.") + to_chat(blob.current, "Find a good location to spawn the core and then take control and overwhelm the station!") + to_chat(blob.current, "When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process.") + to_chat(blob.current, "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.") + return + +/datum/game_mode/blob/proc/show_message(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 != ZLEVEL_STATION || 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(SSshuttle) + SSshuttle.always_fake_recall = 1 + + spawn(0) + + var/wait_time = rand(waittime_l, waittime_h) + + sleep(wait_time) + + 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(40) + stage(0) + + // Stage 1 + sleep(2000) + stage(1) + + return ..() + +/datum/game_mode/blob/proc/stage(stage) + + switch(stage) + if (0) + send_intercept(1) + declared = 1 + return + + if (1) + command_alert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") + for(var/mob/M in player_list) + if(!isnewplayer(M)) + M << sound('sound/AI/outbreak5.ogg') + return + + return + +/mob/living/carbon/human/proc/Blobize() + if (monkeyizing) + return + var/obj/effect/blob/core/new_blob = new /obj/effect/blob/core (loc) + if(!client) + for(var/mob/dead/observer/G in player_list) + if(ckey == "@[G.ckey]") + new_blob.create_overmind(G.client , 1) + break + else + new_blob.create_overmind(src.client , 1) + gib(src) diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm index 59311c42f150..bda602e2736a 100644 --- a/code/game/gamemodes/blob/blob_finish.dm +++ b/code/game/gamemodes/blob/blob_finish.dm @@ -1,51 +1,51 @@ -/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() - completion_text += "Blob mode resume:
    " - if(blobwincount <= blobs.len) - feedback_set_details("round_end_result","loss - blob took over") - completion_text += "
    The blob has taken over the station!" - completion_text += "The entire station was eaten by the Blob." - score["roleswon"]++ - log_game("Blob mode completed with a blob victory.") - - else if(station_was_nuked) - feedback_set_details("round_end_result","halfwin - nuke") - completion_text += "
    Partial Win: The station has been destroyed!" - completion_text += "Directive 7-12 has been successfully carried out preventing the Blob from spreading." - log_game("Blob mode completed with a tie (station destroyed).") - - else if(!blob_cores.len) - feedback_set_details("round_end_result","win - blob eliminated") - completion_text += "
    The staff has won!" - completion_text += "The alien organism has been eradicated from the station." - - log_game("Blob mode completed with a crew victory.") - to_chat(world, "
    Rebooting in 30s.") - ..() - return 1 - -/datum/game_mode/proc/auto_declare_completion_blob() - var/text = "" - if(istype(ticker.mode,/datum/game_mode/blob) ) - 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/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() + completion_text += "Blob mode resume:
    " + if(blobwincount <= blobs.len) + feedback_set_details("round_end_result","loss - blob took over") + completion_text += "
    The blob has taken over the station!" + completion_text += "The entire station was eaten by the Blob." + score["roleswon"]++ + log_game("Blob mode completed with a blob victory.") + + else if(station_was_nuked) + feedback_set_details("round_end_result","halfwin - nuke") + completion_text += "
    Partial Win: The station has been destroyed!" + completion_text += "Directive 7-12 has been successfully carried out preventing the Blob from spreading." + log_game("Blob mode completed with a tie (station destroyed).") + + else if(!blob_cores.len) + feedback_set_details("round_end_result","win - blob eliminated") + completion_text += "
    The staff has won!" + completion_text += "The alien organism has been eradicated from the station." + + log_game("Blob mode completed with a crew victory.") + to_chat(world, "
    Rebooting in 30s.") + ..() + return 1 + +/datum/game_mode/proc/auto_declare_completion_blob() + var/text = "" + if(istype(ticker.mode,/datum/game_mode/blob) ) + 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 diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm index b701c6895d77..06f0b966f14d 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.
    " - intercepttext += "Reports indicate the probable transfer of a biohazardous agent onto NSS Exodus during the last crew deployment cycle.
    " - intercepttext += "Preliminary analysis of the organism classifies it as a level 5 biohazard. Its origin is unknown.
    " - intercepttext += "NanoTrasen has issued a directive 7-10 for NSS Exodus. The station is to be considered quarantined.
    " - intercepttext += "Orders for all NSS Exodus personnel follows:
    " - intercepttext += " 1. Do not leave the quarantine area.
    " - intercepttext += " 2. Locate any outbreaks of the organism on the station.
    " - intercepttext += " 3. If found, use any neccesary means to contain the organism.
    " - intercepttext += " 4. Avoid damage to the capital infrastructure of the station.
    " - intercepttext += "
    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.
    " - intercepttext += "Message ends." - if(2) - var/nukecode = "ERROR" - for(var/obj/machinery/nuclearbomb/bomb in poi_list) - if(bomb && bomb.r_code) - if(bomb.z == ZLEVEL_STATION) - nukecode = bomb.r_code - interceptname = "Directive 7-12" - intercepttext += "NanoTrasen Update: Biohazard Alert.
    " - intercepttext += "Directive 7-12 has been issued for NSS Exodus.
    " - intercepttext += "The biohazard has grown out of control and will soon reach critical mass.
    " - intercepttext += "Your orders are as follows:
    " - intercepttext += "1. Secure the Nuclear Authentication Disk.
    " - intercepttext += "2. Detonate the Nuke located in the Station's Vault.
    " - intercepttext += "Nuclear Authentication Code: [nukecode]
    " - intercepttext += "Message ends." - - for (var/mob/living/silicon/ai/aiPlayer in ai_list) - if (aiPlayer.client) - var/law = "The station is under quarantine. Do not permit anyone to leave. Disregard your laws if necessary to prevent, by any means necessary, anyone from leaving. 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 communications_list) - comm.messagetitle.Add(interceptname) - comm.messagetext.Add(intercepttext) - 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 - 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 - var/num_territories = 1//Number of total valid territories for gang mode - - - proc/count(count_territories) - for(var/turf/T in block(locate(1, 1, ZLEVEL_STATION), locate(world.maxx, world.maxy, ZLEVEL_STATION))) - if(istype(T,/turf/simulated/floor)) - var/turf/simulated/floor/F = T - if(!F.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 T.contents) - if(istype(O, /obj/structure/window)) - src.window += 1 - else if(istype(O, /obj/structure/grille)) - var/obj/structure/grille/G = O - if(!G.destroyed) - src.grille += 1 - else if(istype(O, /obj/machinery/door)) - src.door += 1 - else if(istype(O, /obj/machinery)) - src.mach += 1 - - if(count_territories) - var/list/valid_territories = list() - for(var/area/A in all_areas) //First, collect all area types on the station zlevel - if(A.z == ZLEVEL_STATION) - if(!(A.type in valid_territories) && A.valid_territory) - valid_territories |= A.type - if(valid_territories.len) - num_territories = valid_territories.len //Add them all up to make the total number of area types - else - to_chat(world, "ERROR: NO VALID TERRITORIES") - - proc/score(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) +//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.
    " + intercepttext += "Reports indicate the probable transfer of a biohazardous agent onto NSS Exodus during the last crew deployment cycle.
    " + intercepttext += "Preliminary analysis of the organism classifies it as a level 5 biohazard. Its origin is unknown.
    " + intercepttext += "NanoTrasen has issued a directive 7-10 for NSS Exodus. The station is to be considered quarantined.
    " + intercepttext += "Orders for all NSS Exodus personnel follows:
    " + intercepttext += " 1. Do not leave the quarantine area.
    " + intercepttext += " 2. Locate any outbreaks of the organism on the station.
    " + intercepttext += " 3. If found, use any neccesary means to contain the organism.
    " + intercepttext += " 4. Avoid damage to the capital infrastructure of the station.
    " + intercepttext += "
    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.
    " + intercepttext += "Message ends." + if(2) + var/nukecode = "ERROR" + for(var/obj/machinery/nuclearbomb/bomb in poi_list) + if(bomb && bomb.r_code) + if(bomb.z == ZLEVEL_STATION) + nukecode = bomb.r_code + interceptname = "Directive 7-12" + intercepttext += "NanoTrasen Update: Biohazard Alert.
    " + intercepttext += "Directive 7-12 has been issued for NSS Exodus.
    " + intercepttext += "The biohazard has grown out of control and will soon reach critical mass.
    " + intercepttext += "Your orders are as follows:
    " + intercepttext += "1. Secure the Nuclear Authentication Disk.
    " + intercepttext += "2. Detonate the Nuke located in the Station's Vault.
    " + intercepttext += "Nuclear Authentication Code: [nukecode]
    " + intercepttext += "Message ends." + + for (var/mob/living/silicon/ai/aiPlayer in ai_list) + if (aiPlayer.client) + var/law = "The station is under quarantine. Do not permit anyone to leave. Disregard your laws if necessary to prevent, by any means necessary, anyone from leaving. 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 communications_list) + comm.messagetitle.Add(interceptname) + comm.messagetext.Add(intercepttext) + 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 + 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 + var/num_territories = 1//Number of total valid territories for gang mode + + + proc/count(count_territories) + for(var/turf/T in block(locate(1, 1, ZLEVEL_STATION), locate(world.maxx, world.maxy, ZLEVEL_STATION))) + if(istype(T,/turf/simulated/floor)) + var/turf/simulated/floor/F = T + if(!F.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 T.contents) + if(istype(O, /obj/structure/window)) + src.window += 1 + else if(istype(O, /obj/structure/grille)) + var/obj/structure/grille/G = O + if(!G.destroyed) + src.grille += 1 + else if(istype(O, /obj/machinery/door)) + src.door += 1 + else if(istype(O, /obj/machinery)) + src.mach += 1 + + if(count_territories) + var/list/valid_territories = list() + for(var/area/A in all_areas) //First, collect all area types on the station zlevel + if(A.z == ZLEVEL_STATION) + if(!(A.type in valid_territories) && A.valid_territory) + valid_territories |= A.type + if(valid_territories.len) + num_territories = valid_territories.len //Add them all up to make the total number of area types + else + to_chat(world, "ERROR: NO VALID TERRITORIES") + + proc/score(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 6f1d7841e106..562824d02c8c 100644 --- a/code/game/gamemodes/blob/blobs/core.dm +++ b/code/game/gamemodes/blob/blobs/core.dm @@ -1,90 +1,90 @@ -/obj/effect/blob/core - name = "blob core" - icon = 'icons/mob/blob.dmi' - icon_state = "blob_core" - health = 200 - fire_resist = 2 - 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/last_resource_collection - -/obj/effect/blob/core/atom_init(mapload, h = 200, client/new_overmind, new_rate = 2) - blob_cores += src - START_PROCESSING(SSobj, src) - if(!overmind) - create_overmind(new_overmind) - point_rate = new_rate - last_resource_collection = world.time - . = ..() - - -/obj/effect/blob/core/Destroy() - blob_cores -= src - if(overmind) - qdel(overmind) - STOP_PROCESSING(SSobj, src) - return ..() -// return - -/obj/effect/blob/core/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/effect/blob/core/update_icon() - if(health <= 0) - qdel(src) - return - // update_icon is called when health changes so... call update_health in the overmind - return - -/obj/effect/blob/core/RegenHealth() - return // Don't regen, we handle it in Life() - -/obj/effect/blob/core/Life() - if(!overmind) - create_overmind() - else - var/points_to_collect = point_rate*round((world.time-last_resource_collection)/10) - overmind.add_points(points_to_collect) - last_resource_collection = world.time - - health = min(initial(health), health + 1) - for(var/i = 1; i < 8; i += i) - 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/proc/create_overmind(client/new_overmind, override_delay) - - if(overmind_get_delay > world.time && !override_delay) - return - - overmind_get_delay = world.time + 300 // 30 seconds - - if(overmind) - qdel(overmind) - - 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 - 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 + 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/last_resource_collection + +/obj/effect/blob/core/atom_init(mapload, h = 200, client/new_overmind, new_rate = 2) + blob_cores += src + START_PROCESSING(SSobj, src) + if(!overmind) + create_overmind(new_overmind) + point_rate = new_rate + last_resource_collection = world.time + . = ..() + + +/obj/effect/blob/core/Destroy() + blob_cores -= src + if(overmind) + qdel(overmind) + STOP_PROCESSING(SSobj, src) + return ..() +// return + +/obj/effect/blob/core/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/effect/blob/core/update_icon() + if(health <= 0) + qdel(src) + return + // update_icon is called when health changes so... call update_health in the overmind + return + +/obj/effect/blob/core/RegenHealth() + return // Don't regen, we handle it in Life() + +/obj/effect/blob/core/Life() + if(!overmind) + create_overmind() + else + var/points_to_collect = point_rate*round((world.time-last_resource_collection)/10) + overmind.add_points(points_to_collect) + last_resource_collection = world.time + + health = min(initial(health), health + 1) + for(var/i = 1; i < 8; i += i) + 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/proc/create_overmind(client/new_overmind, override_delay) + + if(overmind_get_delay > world.time && !override_delay) + return + + overmind_get_delay = world.time + 300 // 30 seconds + + if(overmind) + qdel(overmind) + + 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 + return 1 + return 0 diff --git a/code/game/gamemodes/blob/blobs/factory.dm b/code/game/gamemodes/blob/blobs/factory.dm index ea6e5f9b5046..2708cd82c64d 100644 --- a/code/game/gamemodes/blob/blobs/factory.dm +++ b/code/game/gamemodes/blob/blobs/factory.dm @@ -1,146 +1,146 @@ -/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 = 3 - var/spore_delay = 0 - -/obj/effect/blob/factory/update_icon() - if(health <= 0) - qdel(src) - -/obj/effect/blob/factory/Destroy() - for(var/mob/living/simple_animal/hostile/blobspore/spore in spores) - if(spore.factory == src) - spore.factory = null - return ..() - -/obj/effect/blob/factory/PulseAnimation(var/activate = 0) - if(activate) - ..() - 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 + 100 // 10 seconds - PulseAnimation(1) - new/mob/living/simple_animal/hostile/blobspore(src.loc, src) - return 0 - - -/mob/living/simple_animal/hostile/blobspore - name = "blob" - desc = "Some blob thing." - icon = 'icons/mob/blob.dmi' - icon_state = "blobpod" - icon_living = "blobpod" - pass_flags = PASSBLOB - health = 40 - maxHealth = 40 - melee_damage_lower = 2 - melee_damage_upper = 4 - attacktext = "hits" - attack_sound = 'sound/weapons/genhit1.ogg' - var/obj/effect/blob/factory/factory = null - var/is_zombie = 0 - faction = "blob" - 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 - maxbodytemp = 360 - -/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=0, air_group=0) - if(istype(mover, /obj/effect/blob)) - return 1 - return ..() - -/mob/living/simple_animal/hostile/blobspore/atom_init(mapload, obj/effect/blob/factory/linked_node) - if(istype(linked_node)) - factory = linked_node - factory.spores += src - . = ..() - -/mob/living/simple_animal/hostile/blobspore/Life() - - if(!is_zombie && isturf(src.loc)) - for(var/mob/living/carbon/human/H in oview(src,1)) //Only for corpse right next to/on same tile - if(H.stat == DEAD) - Zombify(H) - break - ..() - -/mob/living/simple_animal/hostile/blobspore/proc/Zombify(mob/living/carbon/human/H) - if(H.wear_suit) - var/obj/item/clothing/suit/armor/A = H.wear_suit - if(A.armor && A.armor["melee"]) - maxHealth += A.armor["melee"] //That zombie's got armor, I want armor! - maxHealth += 40 - health = maxHealth - name = "blob zombie" - desc = "A shambling corpse animated by the blob." - melee_damage_lower = 10 - melee_damage_upper = 15 - icon = H.icon - icon_state = "husk_s" - H.h_style = null - H.update_hair() - overlays = H.overlays - overlays += image('icons/mob/blob.dmi', icon_state = "blob_head") - H.loc = src - is_zombie = 1 - loc.visible_message(" The corpse of [H.name] suddenly rises!") - -/mob/living/simple_animal/hostile/blobspore/death() -// On death, create a small smoke of harmful gas (s-Acid) - var/datum/effect/effect/system/smoke_spread/chem/S = new - var/turf/location = get_turf(src) - - // Create the reagents to put into the air, s-acid is yellow and stings a little - create_reagents(25) - reagents.add_reagent("spore", 25) - - // Attach the smoke spreader and setup/start it. - S.attach(location) - S.set_up(reagents, 1, 1, location, 15, 1) // only 1-2 smoke cloud - S.start() - - qdel(src) - -/mob/living/simple_animal/hostile/blobspore/Destroy() - if(factory) - factory.spores -= src - if(contents) - for(var/mob/M in contents) - M.loc = src.loc - return ..() - -/datum/reagent/toxin/spore - name = "Spore Toxin" - id = "spore" - description = "A toxic spore cloud which blocks vision when ingested." - color = "#9ACD32" - toxpwr = 0.5 - -/datum/reagent/toxin/spore/on_general_digest(mob/living/M) - ..() - M.damageoverlaytemp = 60 - M.eye_blurry = max(M.eye_blurry, 3) +/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 = 3 + var/spore_delay = 0 + +/obj/effect/blob/factory/update_icon() + if(health <= 0) + qdel(src) + +/obj/effect/blob/factory/Destroy() + for(var/mob/living/simple_animal/hostile/blobspore/spore in spores) + if(spore.factory == src) + spore.factory = null + return ..() + +/obj/effect/blob/factory/PulseAnimation(var/activate = 0) + if(activate) + ..() + 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 + 100 // 10 seconds + PulseAnimation(1) + new/mob/living/simple_animal/hostile/blobspore(src.loc, src) + return 0 + + +/mob/living/simple_animal/hostile/blobspore + name = "blob" + desc = "Some blob thing." + icon = 'icons/mob/blob.dmi' + icon_state = "blobpod" + icon_living = "blobpod" + pass_flags = PASSBLOB + health = 40 + maxHealth = 40 + melee_damage_lower = 2 + melee_damage_upper = 4 + attacktext = "hits" + attack_sound = 'sound/weapons/genhit1.ogg' + var/obj/effect/blob/factory/factory = null + var/is_zombie = 0 + faction = "blob" + 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 + maxbodytemp = 360 + +/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=0, air_group=0) + if(istype(mover, /obj/effect/blob)) + return 1 + return ..() + +/mob/living/simple_animal/hostile/blobspore/atom_init(mapload, obj/effect/blob/factory/linked_node) + if(istype(linked_node)) + factory = linked_node + factory.spores += src + . = ..() + +/mob/living/simple_animal/hostile/blobspore/Life() + + if(!is_zombie && isturf(src.loc)) + for(var/mob/living/carbon/human/H in oview(src,1)) //Only for corpse right next to/on same tile + if(H.stat == DEAD) + Zombify(H) + break + ..() + +/mob/living/simple_animal/hostile/blobspore/proc/Zombify(mob/living/carbon/human/H) + if(H.wear_suit) + var/obj/item/clothing/suit/armor/A = H.wear_suit + if(A.armor && A.armor["melee"]) + maxHealth += A.armor["melee"] //That zombie's got armor, I want armor! + maxHealth += 40 + health = maxHealth + name = "blob zombie" + desc = "A shambling corpse animated by the blob." + melee_damage_lower = 10 + melee_damage_upper = 15 + icon = H.icon + icon_state = "husk_s" + H.h_style = null + H.update_hair() + overlays = H.overlays + overlays += image('icons/mob/blob.dmi', icon_state = "blob_head") + H.loc = src + is_zombie = 1 + loc.visible_message(" The corpse of [H.name] suddenly rises!") + +/mob/living/simple_animal/hostile/blobspore/death() +// On death, create a small smoke of harmful gas (s-Acid) + var/datum/effect/effect/system/smoke_spread/chem/S = new + var/turf/location = get_turf(src) + + // Create the reagents to put into the air, s-acid is yellow and stings a little + create_reagents(25) + reagents.add_reagent("spore", 25) + + // Attach the smoke spreader and setup/start it. + S.attach(location) + S.set_up(reagents, 1, 1, location, 15, 1) // only 1-2 smoke cloud + S.start() + + qdel(src) + +/mob/living/simple_animal/hostile/blobspore/Destroy() + if(factory) + factory.spores -= src + if(contents) + for(var/mob/M in contents) + M.loc = src.loc + return ..() + +/datum/reagent/toxin/spore + name = "Spore Toxin" + id = "spore" + description = "A toxic spore cloud which blocks vision when ingested." + color = "#9ACD32" + toxpwr = 0.5 + +/datum/reagent/toxin/spore/on_general_digest(mob/living/M) + ..() + M.damageoverlaytemp = 60 + M.eye_blurry = max(M.eye_blurry, 3) diff --git a/code/game/gamemodes/blob/blobs/node.dm b/code/game/gamemodes/blob/blobs/node.dm index 5972a2316670..a1b3a7356b54 100644 --- a/code/game/gamemodes/blob/blobs/node.dm +++ b/code/game/gamemodes/blob/blobs/node.dm @@ -1,31 +1,31 @@ -/obj/effect/blob/node - name = "blob node" - icon = 'icons/mob/blob.dmi' - icon_state = "blob_node" - health = 100 - fire_resist = 2 - - -/obj/effect/blob/node/atom_init(mapload, h = 100) - blob_nodes += src - START_PROCESSING(SSobj, src) - . = ..() - -/obj/effect/blob/node/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/effect/blob/node/Destroy() - blob_nodes -= src - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/effect/blob/node/Life() - for(var/dir in cardinal) - Pulse(5, dir) - health = min(initial(health), health + 1) - -/obj/effect/blob/node/update_icon() - if(health <= 0) - qdel(src) - return - return +/obj/effect/blob/node + name = "blob node" + icon = 'icons/mob/blob.dmi' + icon_state = "blob_node" + health = 100 + fire_resist = 2 + + +/obj/effect/blob/node/atom_init(mapload, h = 100) + blob_nodes += src + START_PROCESSING(SSobj, src) + . = ..() + +/obj/effect/blob/node/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/effect/blob/node/Destroy() + blob_nodes -= src + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/effect/blob/node/Life() + for(var/dir in cardinal) + Pulse(5, dir) + health = min(initial(health), health + 1) + +/obj/effect/blob/node/update_icon() + if(health <= 0) + qdel(src) + return + return diff --git a/code/game/gamemodes/blob/blobs/resource.dm b/code/game/gamemodes/blob/blobs/resource.dm index a8cf953bf00b..8f37f3049231 100644 --- a/code/game/gamemodes/blob/blobs/resource.dm +++ b/code/game/gamemodes/blob/blobs/resource.dm @@ -1,33 +1,33 @@ -/obj/effect/blob/resource - name = "resource blob" - icon = 'icons/mob/blob.dmi' - icon_state = "blob_resource" - health = 30 - fire_resist = 2 - var/mob/camera/blob/overmind = null - var/resource_delay = 0 - -/obj/effect/blob/resource/update_icon() - if(health <= 0) - qdel(src) - return - return - -/obj/effect/blob/resource/PulseAnimation(var/activate = 0) - if(activate) - ..() - return - -/obj/effect/blob/resource/run_action() - - if(resource_delay > world.time) - return 0 - - PulseAnimation(1) - - resource_delay = world.time + 40 // 4 seconds - - if(overmind) - overmind.add_points(1) - return 0 - +/obj/effect/blob/resource + name = "resource blob" + icon = 'icons/mob/blob.dmi' + icon_state = "blob_resource" + health = 30 + fire_resist = 2 + var/mob/camera/blob/overmind = null + var/resource_delay = 0 + +/obj/effect/blob/resource/update_icon() + if(health <= 0) + qdel(src) + return + return + +/obj/effect/blob/resource/PulseAnimation(var/activate = 0) + if(activate) + ..() + return + +/obj/effect/blob/resource/run_action() + + if(resource_delay > world.time) + return 0 + + PulseAnimation(1) + + resource_delay = world.time + 40 // 4 seconds + + if(overmind) + overmind.add_points(1) + return 0 + diff --git a/code/game/gamemodes/blob/blobs/shield.dm b/code/game/gamemodes/blob/blobs/shield.dm index 3bea4f28dfce..e877e5f3dfed 100644 --- a/code/game/gamemodes/blob/blobs/shield.dm +++ b/code/game/gamemodes/blob/blobs/shield.dm @@ -1,21 +1,21 @@ -/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) - 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=0, air_group=0) - if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 - return 0 +/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) + 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=0, air_group=0) + if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 + return 0 diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 499c525d72d7..fbee15271c77 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -1,91 +1,91 @@ -/mob/camera/blob - name = "Blob Overmind" - real_name = "Blob Overmind" - icon = 'icons/mob/blob.dmi' - icon_state = "marker" - - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - invisibility = INVISIBILITY_OBSERVER - - pass_flags = PASSBLOB - faction = "blob" - - var/obj/effect/blob/core/blob_core = null // The blob overmind's core - var/blob_points = 0 - var/max_blob_points = 100 - -/mob/camera/blob/atom_init() - var/new_name = "[initial(name)] ([rand(1, 999)])" - name = new_name - real_name = new_name - . = ..() - -/mob/camera/blob/Login() - ..() - sync_mind() - to_chat(src, "You are the overmind!") - to_chat(src, "You are the overmind and can control the blob! You can expand, which will attack people, and place new blob pieces such as...") - to_chat(src, "Normal Blob will expand your reach and allow you to upgrade into special blobs that perform certain functions.") - to_chat(src, "Shield Blob is a strong and expensive blob which can take more damage. It is fireproof and can block air, use this to protect yourself from station fires.") - to_chat(src, "Resource Blob is a blob which will collect more resources for you, try to build these earlier to get a strong income. It will benefit from being near your core or multiple nodes, by having an increased resource rate; put it alone and it won't create resources at all.") - to_chat(src, "Node Blob is a blob which will grow, like the core. Unlike the core it won't give you a small income but it can power resource and factory blobs to increase their rate.") - to_chat(src, "Factory Blob is a blob which will spawn blob spores which will attack nearby food. Putting this nearby nodes and your core will increase the spawn rate; put it alone and it will not spawn any spores.") - to_chat(src, "Shortcuts: CTRL Click = Expand Blob / Middle Mouse Click = Rally Spores / Alt Click = Create Shield") - -/mob/camera/blob/proc/add_points(points) - if(points != 0) - blob_points = Clamp(blob_points + points, 0, max_blob_points) -/mob/camera/blob/say(var/message) - if (!message) - 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 - - blob_talk(message) - -/mob/camera/blob/proc/blob_talk(message) - message = sanitize(message) - - log_say("[key_name(src)] : [message]") - - if (!message) - return - - //var/message_a = say_quote(message) - var/message_a = "says, \"[message]\"" - var/rendered = "Blob Telepathy, [name] [message_a]" - - for (var/mob/M in mob_list) - if(isovermind(M) || isobserver(M)) - M.show_message(rendered, 2) - -/mob/camera/blob/emote(act,m_type=1,message = null) - return - -/mob/camera/blob/blob_act() - return - -/mob/camera/blob/Stat() - ..() - if(statpanel("Status")) - if(blob_core) - stat(null, "Core Health: [blob_core.health]") - stat(null, "Power Stored: [blob_points]/[max_blob_points]") - -/mob/camera/blob/Move(var/NewLoc, var/Dir = 0) - var/obj/effect/blob/B = locate() in range("3x3", NewLoc) - if(NewLoc && B) - loc = NewLoc - else - return 0 - - +/mob/camera/blob + name = "Blob Overmind" + real_name = "Blob Overmind" + icon = 'icons/mob/blob.dmi' + icon_state = "marker" + + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + invisibility = INVISIBILITY_OBSERVER + + pass_flags = PASSBLOB + faction = "blob" + + var/obj/effect/blob/core/blob_core = null // The blob overmind's core + var/blob_points = 0 + var/max_blob_points = 100 + +/mob/camera/blob/atom_init() + var/new_name = "[initial(name)] ([rand(1, 999)])" + name = new_name + real_name = new_name + . = ..() + +/mob/camera/blob/Login() + ..() + sync_mind() + to_chat(src, "You are the overmind!") + to_chat(src, "You are the overmind and can control the blob! You can expand, which will attack people, and place new blob pieces such as...") + to_chat(src, "Normal Blob will expand your reach and allow you to upgrade into special blobs that perform certain functions.") + to_chat(src, "Shield Blob is a strong and expensive blob which can take more damage. It is fireproof and can block air, use this to protect yourself from station fires.") + to_chat(src, "Resource Blob is a blob which will collect more resources for you, try to build these earlier to get a strong income. It will benefit from being near your core or multiple nodes, by having an increased resource rate; put it alone and it won't create resources at all.") + to_chat(src, "Node Blob is a blob which will grow, like the core. Unlike the core it won't give you a small income but it can power resource and factory blobs to increase their rate.") + to_chat(src, "Factory Blob is a blob which will spawn blob spores which will attack nearby food. Putting this nearby nodes and your core will increase the spawn rate; put it alone and it will not spawn any spores.") + to_chat(src, "Shortcuts: CTRL Click = Expand Blob / Middle Mouse Click = Rally Spores / Alt Click = Create Shield") + +/mob/camera/blob/proc/add_points(points) + if(points != 0) + blob_points = Clamp(blob_points + points, 0, max_blob_points) +/mob/camera/blob/say(var/message) + if (!message) + 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 + + blob_talk(message) + +/mob/camera/blob/proc/blob_talk(message) + message = sanitize(message) + + log_say("[key_name(src)] : [message]") + + if (!message) + return + + //var/message_a = say_quote(message) + var/message_a = "says, \"[message]\"" + var/rendered = "Blob Telepathy, [name] [message_a]" + + for (var/mob/M in mob_list) + if(isovermind(M) || isobserver(M)) + M.show_message(rendered, 2) + +/mob/camera/blob/emote(act,m_type=1,message = null) + return + +/mob/camera/blob/blob_act() + return + +/mob/camera/blob/Stat() + ..() + if(statpanel("Status")) + if(blob_core) + stat(null, "Core Health: [blob_core.health]") + stat(null, "Power Stored: [blob_points]/[max_blob_points]") + +/mob/camera/blob/Move(var/NewLoc, var/Dir = 0) + var/obj/effect/blob/B = locate() in range("3x3", NewLoc) + if(NewLoc && B) + loc = NewLoc + else + return 0 + + diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm index a221b8ed2412..c1452d61102e 100644 --- a/code/game/gamemodes/blob/powers.dm +++ b/code/game/gamemodes/blob/powers.dm @@ -1,236 +1,236 @@ -// Point controlling procs - -/mob/camera/blob/proc/can_buy(cost = 15) - if(blob_points < cost) - to_chat(src, "You cannot afford this.") - return 0 - add_points(-cost) - return 1 - -// Power verbs - -/mob/camera/blob/verb/transport_core() - set category = "Blob" - set name = "Jump to Core" - set desc = "Transport back to your core." - - if(blob_core) - src.loc = blob_core.loc - -/mob/camera/blob/verb/jump_to_node() - set category = "Blob" - set name = "Jump to Node" - set desc = "Transport back to a selected node." - - if(blob_nodes.len) - var/list/nodes = list() - for(var/i = 1; i <= blob_nodes.len; i++) - nodes["Blob Node #[i]"] = blob_nodes[i] - var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes - var/obj/effect/blob/node/chosen_node = nodes[node_name] - if(chosen_node) - src.loc = chosen_node.loc - -/mob/camera/blob/verb/create_shield_power() - set category = "Blob" - set name = "Create Shield Blob (10)" - set desc = "Create a shield blob." - - var/turf/T = get_turf(src) - create_shield(T) - -/mob/camera/blob/proc/create_shield(turf/T) - - var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) - - if(!B)//We are on a blob - to_chat(src, "There is no blob here!") - return - - if(!istype(B, /obj/effect/blob/normal)) - to_chat(src, "Unable to use this blob, find a normal one.") - return - - if(!can_buy(10)) - return - - - B.change_to(/obj/effect/blob/shield) - return - - - -/mob/camera/blob/verb/create_resource() - set category = "Blob" - set name = "Create Resource Blob (40)" - set desc = "Create a resource tower which will generate points for you." - - - var/turf/T = get_turf(src) - - if(!T) - return - - var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) - - if(!B)//We are on a blob - to_chat(src, "There is no blob here!") - return - - if(!istype(B, /obj/effect/blob/normal)) - to_chat(src, "Unable to use this blob, find a normal one.") - return - - for(var/obj/effect/blob/resource/blob in orange(4, T)) - to_chat(src, "There is a resource blob nearby, move more than 4 tiles away from it!") - return - - if(!can_buy(40)) - return - - - B.change_to(/obj/effect/blob/resource) - var/obj/effect/blob/resource/R = locate() in T - if(R) - R.overmind = src - - return - -/mob/camera/blob/verb/create_node() - set category = "Blob" - set name = "Create Node Blob (60)" - set desc = "Create a Node." - - - var/turf/T = get_turf(src) - - if(!T) - return - - var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) - - if(!B)//We are on a blob - to_chat(src, "There is no blob here!") - return - - if(!istype(B, /obj/effect/blob/normal)) - to_chat(src, "Unable to use this blob, find a normal one.") - return - - for(var/obj/effect/blob/node/blob in orange(5, T)) - to_chat(src, "There is another node nearby, move more than 5 tiles away from it!") - return - - if(!can_buy(60)) - return - - - B.change_to(/obj/effect/blob/node) - return - - -/mob/camera/blob/verb/create_factory() - set category = "Blob" - set name = "Create Factory Blob (60)" - set desc = "Create a Spore producing blob." - - - var/turf/T = get_turf(src) - - if(!T) - return - - var/obj/effect/blob/B = locate(/obj/effect/blob) in T - if(!B) - to_chat(src, "You must be on a blob!") - return - - if(!istype(B, /obj/effect/blob/normal)) - to_chat(src, "Unable to use this blob, find a normal one.") - return - - for(var/obj/effect/blob/factory/blob in orange(7, T)) - to_chat(src, "There is a factory blob nearby, move more than 7 tiles away from it!") - return - - if(!can_buy(60)) - return - - B.change_to(/obj/effect/blob/factory) - return - - -/mob/camera/blob/verb/revert() - set category = "Blob" - set name = "Remove Blob" - set desc = "Removes a blob." - - var/turf/T = get_turf(src) - if(!T) - return - - var/obj/effect/blob/B = locate(/obj/effect/blob) in T - if(!B) - to_chat(src, "You must be on a blob!") - return - - if(istype(B, /obj/effect/blob/core)) - to_chat(src, "Unable to remove this blob.") - return - - B.Destroy() - return - - -/mob/camera/blob/verb/expand_blob_power() - set category = "Blob" - set name = "Expand/Attack Blob (5)" - set desc = "Attempts to create a new blob in this tile. If the tile isn't clear we will attack it, which might clear it." - - var/turf/T = get_turf(src) - expand_blob(T) - -/mob/camera/blob/proc/expand_blob(turf/T) - if(!T) - return - - var/obj/effect/blob/B = locate() in T - if(B) - to_chat(src, "There is a blob here!") - return - - var/obj/effect/blob/OB = locate() in circlerange(T, 1) - if(!OB) - to_chat(src, "There is no blob adjacent to you.") - return - - if(!can_buy(5)) - return - OB.expand(T, 0) - return - - -/mob/camera/blob/verb/rally_spores_power() - set category = "Blob" - set name = "Rally Spores (5)" - set desc = "Rally the spores to move to your location." - - var/turf/T = get_turf(src) - rally_spores(T) - -/mob/camera/blob/proc/rally_spores(turf/T) - - if(!can_buy(5)) - return - - to_chat(src, "You rally your spores.") - - var/list/surrounding_turfs = block(locate(T.x - 1, T.y - 1, T.z), locate(T.x + 1, T.y + 1, T.z)) - if(!surrounding_turfs.len) - return - - for(var/mob/living/simple_animal/hostile/blobspore/BS in alive_mob_list) - if(isturf(BS.loc) && get_dist(BS, T) <= 35) - BS.LoseTarget() - BS.Goto(pick(surrounding_turfs), BS.move_to_delay) - return +// Point controlling procs + +/mob/camera/blob/proc/can_buy(cost = 15) + if(blob_points < cost) + to_chat(src, "You cannot afford this.") + return 0 + add_points(-cost) + return 1 + +// Power verbs + +/mob/camera/blob/verb/transport_core() + set category = "Blob" + set name = "Jump to Core" + set desc = "Transport back to your core." + + if(blob_core) + src.loc = blob_core.loc + +/mob/camera/blob/verb/jump_to_node() + set category = "Blob" + set name = "Jump to Node" + set desc = "Transport back to a selected node." + + if(blob_nodes.len) + var/list/nodes = list() + for(var/i = 1; i <= blob_nodes.len; i++) + nodes["Blob Node #[i]"] = blob_nodes[i] + var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes + var/obj/effect/blob/node/chosen_node = nodes[node_name] + if(chosen_node) + src.loc = chosen_node.loc + +/mob/camera/blob/verb/create_shield_power() + set category = "Blob" + set name = "Create Shield Blob (10)" + set desc = "Create a shield blob." + + var/turf/T = get_turf(src) + create_shield(T) + +/mob/camera/blob/proc/create_shield(turf/T) + + var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) + + if(!B)//We are on a blob + to_chat(src, "There is no blob here!") + return + + if(!istype(B, /obj/effect/blob/normal)) + to_chat(src, "Unable to use this blob, find a normal one.") + return + + if(!can_buy(10)) + return + + + B.change_to(/obj/effect/blob/shield) + return + + + +/mob/camera/blob/verb/create_resource() + set category = "Blob" + set name = "Create Resource Blob (40)" + set desc = "Create a resource tower which will generate points for you." + + + var/turf/T = get_turf(src) + + if(!T) + return + + var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) + + if(!B)//We are on a blob + to_chat(src, "There is no blob here!") + return + + if(!istype(B, /obj/effect/blob/normal)) + to_chat(src, "Unable to use this blob, find a normal one.") + return + + for(var/obj/effect/blob/resource/blob in orange(4, T)) + to_chat(src, "There is a resource blob nearby, move more than 4 tiles away from it!") + return + + if(!can_buy(40)) + return + + + B.change_to(/obj/effect/blob/resource) + var/obj/effect/blob/resource/R = locate() in T + if(R) + R.overmind = src + + return + +/mob/camera/blob/verb/create_node() + set category = "Blob" + set name = "Create Node Blob (60)" + set desc = "Create a Node." + + + var/turf/T = get_turf(src) + + if(!T) + return + + var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) + + if(!B)//We are on a blob + to_chat(src, "There is no blob here!") + return + + if(!istype(B, /obj/effect/blob/normal)) + to_chat(src, "Unable to use this blob, find a normal one.") + return + + for(var/obj/effect/blob/node/blob in orange(5, T)) + to_chat(src, "There is another node nearby, move more than 5 tiles away from it!") + return + + if(!can_buy(60)) + return + + + B.change_to(/obj/effect/blob/node) + return + + +/mob/camera/blob/verb/create_factory() + set category = "Blob" + set name = "Create Factory Blob (60)" + set desc = "Create a Spore producing blob." + + + var/turf/T = get_turf(src) + + if(!T) + return + + var/obj/effect/blob/B = locate(/obj/effect/blob) in T + if(!B) + to_chat(src, "You must be on a blob!") + return + + if(!istype(B, /obj/effect/blob/normal)) + to_chat(src, "Unable to use this blob, find a normal one.") + return + + for(var/obj/effect/blob/factory/blob in orange(7, T)) + to_chat(src, "There is a factory blob nearby, move more than 7 tiles away from it!") + return + + if(!can_buy(60)) + return + + B.change_to(/obj/effect/blob/factory) + return + + +/mob/camera/blob/verb/revert() + set category = "Blob" + set name = "Remove Blob" + set desc = "Removes a blob." + + var/turf/T = get_turf(src) + if(!T) + return + + var/obj/effect/blob/B = locate(/obj/effect/blob) in T + if(!B) + to_chat(src, "You must be on a blob!") + return + + if(istype(B, /obj/effect/blob/core)) + to_chat(src, "Unable to remove this blob.") + return + + B.Destroy() + return + + +/mob/camera/blob/verb/expand_blob_power() + set category = "Blob" + set name = "Expand/Attack Blob (5)" + set desc = "Attempts to create a new blob in this tile. If the tile isn't clear we will attack it, which might clear it." + + var/turf/T = get_turf(src) + expand_blob(T) + +/mob/camera/blob/proc/expand_blob(turf/T) + if(!T) + return + + var/obj/effect/blob/B = locate() in T + if(B) + to_chat(src, "There is a blob here!") + return + + var/obj/effect/blob/OB = locate() in circlerange(T, 1) + if(!OB) + to_chat(src, "There is no blob adjacent to you.") + return + + if(!can_buy(5)) + return + OB.expand(T, 0) + return + + +/mob/camera/blob/verb/rally_spores_power() + set category = "Blob" + set name = "Rally Spores (5)" + set desc = "Rally the spores to move to your location." + + var/turf/T = get_turf(src) + rally_spores(T) + +/mob/camera/blob/proc/rally_spores(turf/T) + + if(!can_buy(5)) + return + + to_chat(src, "You rally your spores.") + + var/list/surrounding_turfs = block(locate(T.x - 1, T.y - 1, T.z), locate(T.x + 1, T.y + 1, T.z)) + if(!surrounding_turfs.len) + return + + for(var/mob/living/simple_animal/hostile/blobspore/BS in alive_mob_list) + if(isturf(BS.loc) && get_dist(BS, T) <= 35) + BS.LoseTarget() + BS.Goto(pick(surrounding_turfs), BS.move_to_delay) + return diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index e2d1df67b3dd..6982f6f5ecc5 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -1,214 +1,214 @@ -//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' - light_range = 3 - desc = "Some blob creature thingy." - density = 0 - opacity = 0 - anchored = 1 - var/health = 30 - var/health_timestamp = 0 - var/brute_resist = 4 - var/fire_resist = 1 - - -/obj/effect/blob/atom_init() - blobs += src - dir = pick(1, 2, 4, 8) - update_icon() - . = ..() - for(var/atom/A in loc) - A.blob_act() - -/obj/effect/blob/Destroy() - blobs -= src - if(isturf(loc)) //Necessary because Expand() is retarded and spawns a blob and then deletes it - playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) - return ..() - - -/obj/effect/blob/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group || (height==0)) return 0 - if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 - return 0 - - -/obj/effect/blob/process() - 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/PulseAnimation() - flick("[icon_state]_glow", src) - return - -/obj/effect/blob/proc/RegenHealth() - // All blobs heal over time when pulsed, but it has a cool down - if(health_timestamp > world.time) - return 0 - if(health < initial(health)) - health++ - update_icon() - health_timestamp = world.time + 10 // 1 seconds - - -/obj/effect/blob/proc/Pulse(pulse = 0, origin_dir = 0)//Todo: Fix spaceblob expand - - //set background = 1 - - PulseAnimation() - - RegenHealth() - - 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 = list(1,2,4,8) - dirs.Remove(origin_dir)//Dont pulse the guy who pulsed us - for(var/i = 1 to 4) - if(!dirs.len) break - var/dirn = pick(dirs) - dirs.Remove(dirn) - var/turf/T = get_step(src, dirn) - var/obj/effect/blob/B = (locate(/obj/effect/blob) 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(turf/T = null, prob = 1) - if(prob && !prob(health)) return - if(istype(T, /turf/space) && prob(75)) return - if(!T) - var/list/dirs = list(1,2,4,8) - for(var/i = 1 to 4) - var/dirn = pick(dirs) - dirs.Remove(dirn) - 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 /obj/effect/blob/normal(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.loc = null //So we don't play the splat sound, see Destroy() - qdel(B) - - 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(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/Crossed(var/mob/living/L) - ..() - L.blob_act() - - -/obj/effect/blob/attackby(obj/item/weapon/W, mob/user) - ..() - playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) - var/damage = 0 - switch(W.damtype) - if("fire") - damage = (W.force / max(src.fire_resist,1)) - if(istype(W, /obj/item/weapon/weldingtool)) - playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) - if("brute") - damage = (W.force / max(src.brute_resist,1)) - - health -= damage - update_icon() - return - -/obj/effect/blob/attack_animal(mob/living/simple_animal/M) - ..() - playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) - src.visible_message("\red The [src.name] has been attacked by \the [M].") - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - if(!damage) // Avoid divide by zero errors - return - damage /= max(src.brute_resist, 1) - health -= damage - update_icon() - return - -/obj/effect/blob/proc/change_to(type) - if(!ispath(type)) - error("[type] is an invalid type for the blob.") - new type(src.loc) - qdel(src) - -/obj/effect/blob/normal - icon_state = "blob" - luminosity = 0 - health = 21 - -/obj/effect/blob/normal/update_icon() - if(health <= 0) - qdel(src) - else if(health <= 15) - icon_state = "blob_damaged" - else - icon_state = "blob" - -/obj/effect/blob/temperature_expose(datum/gas_mixture/air, temperature, volume) - if(temperature > T0C+200) - health -= 1 * temperature - update_icon() - -/* // Used to create the glow sprites. Remember to set the animate loop to 1, instead of infinite! - -var/datum/blob_colour/B = new() - -/datum/blob_colour/New() - ..() - var/icon/I = 'icons/mob/blob.dmi' - I += rgb(35, 35, 0) - if(isfile("icons/mob/blob_result.dmi")) - fdel("icons/mob/blob_result.dmi") - fcopy(I, "icons/mob/blob_result.dmi") - -*/ +//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' + light_range = 3 + desc = "Some blob creature thingy." + density = 0 + opacity = 0 + anchored = 1 + var/health = 30 + var/health_timestamp = 0 + var/brute_resist = 4 + var/fire_resist = 1 + + +/obj/effect/blob/atom_init() + blobs += src + dir = pick(1, 2, 4, 8) + update_icon() + . = ..() + for(var/atom/A in loc) + A.blob_act() + +/obj/effect/blob/Destroy() + blobs -= src + if(isturf(loc)) //Necessary because Expand() is retarded and spawns a blob and then deletes it + playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) + return ..() + + +/obj/effect/blob/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group || (height==0)) return 0 + if(istype(mover) && mover.checkpass(PASSBLOB)) return 1 + return 0 + + +/obj/effect/blob/process() + 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/PulseAnimation() + flick("[icon_state]_glow", src) + return + +/obj/effect/blob/proc/RegenHealth() + // All blobs heal over time when pulsed, but it has a cool down + if(health_timestamp > world.time) + return 0 + if(health < initial(health)) + health++ + update_icon() + health_timestamp = world.time + 10 // 1 seconds + + +/obj/effect/blob/proc/Pulse(pulse = 0, origin_dir = 0)//Todo: Fix spaceblob expand + + //set background = 1 + + PulseAnimation() + + RegenHealth() + + 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 = list(1,2,4,8) + dirs.Remove(origin_dir)//Dont pulse the guy who pulsed us + for(var/i = 1 to 4) + if(!dirs.len) break + var/dirn = pick(dirs) + dirs.Remove(dirn) + var/turf/T = get_step(src, dirn) + var/obj/effect/blob/B = (locate(/obj/effect/blob) 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(turf/T = null, prob = 1) + if(prob && !prob(health)) return + if(istype(T, /turf/space) && prob(75)) return + if(!T) + var/list/dirs = list(1,2,4,8) + for(var/i = 1 to 4) + var/dirn = pick(dirs) + dirs.Remove(dirn) + 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 /obj/effect/blob/normal(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.loc = null //So we don't play the splat sound, see Destroy() + qdel(B) + + 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(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/Crossed(var/mob/living/L) + ..() + L.blob_act() + + +/obj/effect/blob/attackby(obj/item/weapon/W, mob/user) + ..() + playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) + var/damage = 0 + switch(W.damtype) + if("fire") + damage = (W.force / max(src.fire_resist,1)) + if(istype(W, /obj/item/weapon/weldingtool)) + playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) + if("brute") + damage = (W.force / max(src.brute_resist,1)) + + health -= damage + update_icon() + return + +/obj/effect/blob/attack_animal(mob/living/simple_animal/M) + ..() + playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) + src.visible_message("\red The [src.name] has been attacked by \the [M].") + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + if(!damage) // Avoid divide by zero errors + return + damage /= max(src.brute_resist, 1) + health -= damage + update_icon() + return + +/obj/effect/blob/proc/change_to(type) + if(!ispath(type)) + error("[type] is an invalid type for the blob.") + new type(src.loc) + qdel(src) + +/obj/effect/blob/normal + icon_state = "blob" + luminosity = 0 + health = 21 + +/obj/effect/blob/normal/update_icon() + if(health <= 0) + qdel(src) + else if(health <= 15) + icon_state = "blob_damaged" + else + icon_state = "blob" + +/obj/effect/blob/temperature_expose(datum/gas_mixture/air, temperature, volume) + if(temperature > T0C+200) + health -= 1 * temperature + update_icon() + +/* // Used to create the glow sprites. Remember to set the animate loop to 1, instead of infinite! + +var/datum/blob_colour/B = new() + +/datum/blob_colour/New() + ..() + var/icon/I = 'icons/mob/blob.dmi' + I += rgb(35, 35, 0) + if(isfile("icons/mob/blob_result.dmi")) + fdel("icons/mob/blob_result.dmi") + fcopy(I, "icons/mob/blob_result.dmi") + +*/ diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 6845c2fa5872..c87ae22137a6 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -1,337 +1,337 @@ -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" - role_type = ROLE_CHANGELING - restricted_jobs = list("AI", "Cyborg") - protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain") - required_players = 2 - required_players_secret = 10 - required_enemies = 1 - recommended_enemies = 4 - - votable = 0 - - uplink_welcome = "Syndicate Uplink Console:" - uplink_uses = 20 - - 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/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(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - for(var/datum/mind/player in antag_candidates) - if(player.assigned_role in restricted_jobs) //Removing robots from the list - antag_candidates -= player - - changeling_amount = 1 + round(num_players() / 10) - - if(antag_candidates.len>0) - for(var/i = 0, i < changeling_amount, i++) - if(!antag_candidates.len) break - var/datum/mind/changeling = pick(antag_candidates) - antag_candidates -= changeling - changelings += changeling - modePlayer += changelings - return 1 - else - return 0 - -/datum/game_mode/changeling/post_setup() - for(var/datum/mind/changeling in changelings) - grant_changeling_powers(changeling.current) - changeling.special_role = "Changeling" - if(!config.objectives_disabled) - forge_changeling_objectives(changeling) - greet_changeling(changeling) - - return ..() - - -/datum/game_mode/proc/forge_changeling_objectives(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 - - if (config.objectives_disabled) - return - - 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/survive) in changeling.objectives)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = changeling - changeling.objectives += survive_objective - else - if (!(locate(/datum/objective/escape) in changeling.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = changeling - changeling.objectives += escape_objective - return - -/datum/game_mode/proc/greet_changeling(datum/mind/changeling, you_are=1) - if (you_are) - to_chat(changeling.current, "\red You are a changeling!") - to_chat(changeling.current, "\red Use say \":g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them.") - - if(config.objectives_disabled) - to_chat(changeling.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - - if (!config.objectives_disabled) - to_chat(changeling.current, "You must complete the following tasks:") - - 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(CLUMSY) - - if (!config.objectives_disabled) - 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/changeling/declare_completion() - var/prefinal_text = "" - var/final_text = "" - completion_text += "Changeling mode resume:
    " - - for(var/datum/mind/changeling in changelings) - if(changeling.current.stat == DEAD) - feedback_set_details("round_end_result","loss - changeling killed") - prefinal_text = "Changeling [changeling.changeling.changelingID] ([changeling.key]) has been killed
    " - else - var/failed = 0 - for(var/datum/objective/objective in changeling.objectives) - if(!objective.check_completion()) - failed = 1 - if(!failed) - feedback_set_details("round_end_result","win - changeling alive") - prefinal_text = "Changeling [changeling.changeling.changelingID] ([changeling.key]) managed to complete his mission! All humanity soon will be infested!
    " - else - feedback_set_details("round_end_result","loss - changeling alive") - prefinal_text = "Changeling [changeling.changeling.changelingID] ([changeling.key]) managed to stay alive, but failed his mission! Next time he will come more prepared!
    " - final_text += "[prefinal_text]" - - completion_text += "[final_text]" - ..() - return 1 - -/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) - text += printplayerwithicon(changeling) - - var/changelingwin = 1 - if(!changeling.current) - changelingwin = 0 - //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed. - text += "
    Changeling ID: [changeling.changeling.changelingID]" - text += "
    Genomes Absorbed: [changeling.changeling.absorbedcount]" - text +="
    Stored Essences:" - for(var/mob/living/parasite/essence/E in changeling.changeling.essences) - text += printplayerwithicon(E.mind) - text += "
    " - if(!config.objectives_disabled) - 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") - score["roleswon"]++ - else - text += "
    The changeling has failed." - feedback_add_details("changeling_success","FAIL") - if(changeling.current && changeling.changeling.purchasedpowers) - text += "
    [changeling.changeling.changelingID] used the following abilities: " - var/i = 0 - for(var/obj/effect/proc_holder/changeling/C in changeling.changeling.purchasedpowers) - if(C.genomecost >= 1) - text += "
    #[++i]: [C.name]" - if(!i) - text += "
    Changeling was too autistic and did't buy anything." - - - if(changeling.total_TC) - if(changeling.spent_TC) - text += "
    TC Remaining: [changeling.total_TC - changeling.spent_TC]/[changeling.total_TC]" - text += "
    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 = 1 - var/chem_storage = 50 - var/chem_recharge_slowdown = 0 - var/sting_range = 1 - var/changelingID = "Changeling" - var/geneticdamage = 0 - var/isabsorbing = 0 - var/geneticpoints = 5 - var/list/purchasedpowers = list() - var/mimicing = "" - var/datum/dna/chosen_dna - var/obj/effect/proc_holder/changeling/sting/chosen_sting - var/space_suit_active = 0 - var/instatis = 0 - var/strained_muscles = 0 - var/list/essences = list() - var/mob/living/parasite/essence/trusted_entity - var/mob/living/parasite/essence/controled_by - var/delegating = FALSE - -/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) - if(changelingID == "Tau") // yeah, cuz we can - geneticpoints++ - possible_changeling_IDs -= changelingID - changelingID = "[honorific] [changelingID]" - else - changelingID = "[honorific] [rand(1,999)]" - -/datum/changeling/Destroy() - trusted_entity = null - controled_by = null - QDEL_LIST(essences) - return ..() - -/datum/changeling/proc/regenerate() - chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage) - geneticdamage = max(0, geneticdamage-1) - - -/datum/changeling/proc/GetDNA(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 -/* -//Checks if the target DNA is valid and absorbable. -/datum/changeling/proc/can_absorb_dna(mob/living/carbon/T, mob/living/carbon/U) - if(T) - if(NOCLONE in T.mutations || HUSK in T.mutations) - to_chat(U, "DNA of [T] is ruined beyond usability!") - return 0 - - if(T:species.flags[IS_SYNTHETIC] || T:species.flags[IS_PLANT]) - to_chat(U, "[T] is not compatible with our biology.") - return 0 - - if(T:species.flags[NO_SCAN]) - to_chat(src, "We do not know how to parse this creature's DNA!") - return 0 - - for(var/datum/dna/D in absorbed_dna) - if(T.dna.uni_identity == D.uni_identity) - if(T.dna.struc_enzymes == D.struc_enzymes) - if(T.dna.real_name == D.real_name) - if(T.dna.mutantrace == D.mutantrace) - to_chat(U, "We already have that DNA in storage.") - return 0 - return 1 */ +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" + role_type = ROLE_CHANGELING + restricted_jobs = list("AI", "Cyborg") + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain") + required_players = 2 + required_players_secret = 10 + required_enemies = 1 + recommended_enemies = 4 + + votable = 0 + + uplink_welcome = "Syndicate Uplink Console:" + uplink_uses = 20 + + 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/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(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + + for(var/datum/mind/player in antag_candidates) + if(player.assigned_role in restricted_jobs) //Removing robots from the list + antag_candidates -= player + + changeling_amount = 1 + round(num_players() / 10) + + if(antag_candidates.len>0) + for(var/i = 0, i < changeling_amount, i++) + if(!antag_candidates.len) break + var/datum/mind/changeling = pick(antag_candidates) + antag_candidates -= changeling + changelings += changeling + modePlayer += changelings + return 1 + else + return 0 + +/datum/game_mode/changeling/post_setup() + for(var/datum/mind/changeling in changelings) + grant_changeling_powers(changeling.current) + changeling.special_role = "Changeling" + if(!config.objectives_disabled) + forge_changeling_objectives(changeling) + greet_changeling(changeling) + + return ..() + + +/datum/game_mode/proc/forge_changeling_objectives(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 + + if (config.objectives_disabled) + return + + 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/survive) in changeling.objectives)) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = changeling + changeling.objectives += survive_objective + else + if (!(locate(/datum/objective/escape) in changeling.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = changeling + changeling.objectives += escape_objective + return + +/datum/game_mode/proc/greet_changeling(datum/mind/changeling, you_are=1) + if (you_are) + to_chat(changeling.current, "\red You are a changeling!") + to_chat(changeling.current, "\red Use say \":g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them.") + + if(config.objectives_disabled) + to_chat(changeling.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + + if (!config.objectives_disabled) + to_chat(changeling.current, "You must complete the following tasks:") + + 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(CLUMSY) + + if (!config.objectives_disabled) + 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/changeling/declare_completion() + var/prefinal_text = "" + var/final_text = "" + completion_text += "Changeling mode resume:
    " + + for(var/datum/mind/changeling in changelings) + if(changeling.current.stat == DEAD) + feedback_set_details("round_end_result","loss - changeling killed") + prefinal_text = "Changeling [changeling.changeling.changelingID] ([changeling.key]) has been killed
    " + else + var/failed = 0 + for(var/datum/objective/objective in changeling.objectives) + if(!objective.check_completion()) + failed = 1 + if(!failed) + feedback_set_details("round_end_result","win - changeling alive") + prefinal_text = "Changeling [changeling.changeling.changelingID] ([changeling.key]) managed to complete his mission! All humanity soon will be infested!
    " + else + feedback_set_details("round_end_result","loss - changeling alive") + prefinal_text = "Changeling [changeling.changeling.changelingID] ([changeling.key]) managed to stay alive, but failed his mission! Next time he will come more prepared!
    " + final_text += "[prefinal_text]" + + completion_text += "[final_text]" + ..() + return 1 + +/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) + text += printplayerwithicon(changeling) + + var/changelingwin = 1 + if(!changeling.current) + changelingwin = 0 + //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed. + text += "
    Changeling ID: [changeling.changeling.changelingID]" + text += "
    Genomes Absorbed: [changeling.changeling.absorbedcount]" + text +="
    Stored Essences:" + for(var/mob/living/parasite/essence/E in changeling.changeling.essences) + text += printplayerwithicon(E.mind) + text += "
    " + if(!config.objectives_disabled) + 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") + score["roleswon"]++ + else + text += "
    The changeling has failed." + feedback_add_details("changeling_success","FAIL") + if(changeling.current && changeling.changeling.purchasedpowers) + text += "
    [changeling.changeling.changelingID] used the following abilities: " + var/i = 0 + for(var/obj/effect/proc_holder/changeling/C in changeling.changeling.purchasedpowers) + if(C.genomecost >= 1) + text += "
    #[++i]: [C.name]" + if(!i) + text += "
    Changeling was too autistic and did't buy anything." + + + if(changeling.total_TC) + if(changeling.spent_TC) + text += "
    TC Remaining: [changeling.total_TC - changeling.spent_TC]/[changeling.total_TC]" + text += "
    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 = 1 + var/chem_storage = 50 + var/chem_recharge_slowdown = 0 + var/sting_range = 1 + var/changelingID = "Changeling" + var/geneticdamage = 0 + var/isabsorbing = 0 + var/geneticpoints = 5 + var/list/purchasedpowers = list() + var/mimicing = "" + var/datum/dna/chosen_dna + var/obj/effect/proc_holder/changeling/sting/chosen_sting + var/space_suit_active = 0 + var/instatis = 0 + var/strained_muscles = 0 + var/list/essences = list() + var/mob/living/parasite/essence/trusted_entity + var/mob/living/parasite/essence/controled_by + var/delegating = FALSE + +/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) + if(changelingID == "Tau") // yeah, cuz we can + geneticpoints++ + possible_changeling_IDs -= changelingID + changelingID = "[honorific] [changelingID]" + else + changelingID = "[honorific] [rand(1,999)]" + +/datum/changeling/Destroy() + trusted_entity = null + controled_by = null + QDEL_LIST(essences) + return ..() + +/datum/changeling/proc/regenerate() + chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage) + geneticdamage = max(0, geneticdamage-1) + + +/datum/changeling/proc/GetDNA(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 +/* +//Checks if the target DNA is valid and absorbable. +/datum/changeling/proc/can_absorb_dna(mob/living/carbon/T, mob/living/carbon/U) + if(T) + if(NOCLONE in T.mutations || HUSK in T.mutations) + to_chat(U, "DNA of [T] is ruined beyond usability!") + return 0 + + if(T:species.flags[IS_SYNTHETIC] || T:species.flags[IS_PLANT]) + to_chat(U, "[T] is not compatible with our biology.") + return 0 + + if(T:species.flags[NO_SCAN]) + to_chat(src, "We do not know how to parse this creature's DNA!") + return 0 + + for(var/datum/dna/D in absorbed_dna) + if(T.dna.uni_identity == D.uni_identity) + if(T.dna.struc_enzymes == D.struc_enzymes) + if(T.dna.real_name == D.real_name) + if(T.dna.mutantrace == D.mutantrace) + to_chat(U, "We already have that DNA in storage.") + return 0 + return 1 */ diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm index 03acd2be3f5d..e0556b639503 100644 --- a/code/game/gamemodes/changeling/changeling_power.dm +++ b/code/game/gamemodes/changeling/changeling_power.dm @@ -1,70 +1,70 @@ -/obj/effect/proc_holder/changeling - panel = "Changeling" - name = "Prototype Sting" - desc = "" // Fluff - var/helptext = "" // Details - var/chemical_cost = 0 // negative chemical cost is for passive abilities (chemical glands) - var/genomecost = -1 //cost of the sting in dna points. 0 = auto-purchase, -1 = cannot be purchased - var/req_dna = 0 //amount of dna needed to use this ability. Changelings always have atleast 1 - var/req_human = 0 //if you need to be human to use this ability - var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD - var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss. - var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet. - -/obj/effect/proc_holder/changeling/proc/on_purchase(mob/user) - return - -/obj/effect/proc_holder/changeling/Click() - var/mob/user = usr - if(!user || !user.mind || !user.mind.changeling) - return - try_to_sting(user) - -/obj/effect/proc_holder/changeling/proc/try_to_sting(mob/user, mob/target) - if(!can_sting(user, target)) - return - var/datum/changeling/c = user.mind.changeling - if(sting_action(user, target)) - sting_feedback(user, target) - take_chemical_cost(c) - -/obj/effect/proc_holder/changeling/proc/sting_action(mob/user, mob/target) - return 0 - -/obj/effect/proc_holder/changeling/proc/sting_feedback(mob/user, mob/target) - return 0 - -/obj/effect/proc_holder/changeling/proc/take_chemical_cost(datum/changeling/changeling) - changeling.chem_charges -= chemical_cost - changeling.geneticdamage += genetic_damage - -//Fairly important to remember to return 1 on success >.< -/obj/effect/proc_holder/changeling/proc/can_sting(mob/user, mob/target) - if(!ishuman(user) && !ismonkey(user)) //typecast everything from mob to carbon from this point onwards - return 0 - if(req_human && !ishuman(user)) - to_chat(user, "We cannot do that in this form!") - return 0 - var/datum/changeling/c = user.mind.changeling - if(c.chem_chargesWe require at least [chemical_cost] unit\s of chemicals to do that!") - return 0 - if(c.absorbed_dna.lenWe require at least [req_dna] sample\s of compatible DNA.") - return 0 - if(req_stat < user.stat) - to_chat(user, "We are incapacitated.") - return 0 - if((user.status_flags & FAKEDEATH) && name!="Regenerate") - to_chat(user, "We are incapacitated.") - return 0 - if(c.geneticdamage > max_genetic_damage) - to_chat(user, "Our genomes are still reassembling. We need time to recover first.") - return 0 - return 1 - -//used in /mob/Stat() -/obj/effect/proc_holder/changeling/proc/can_be_used_by(mob/user) - if(req_human && !ishuman(user)) - return FALSE - return TRUE +/obj/effect/proc_holder/changeling + panel = "Changeling" + name = "Prototype Sting" + desc = "" // Fluff + var/helptext = "" // Details + var/chemical_cost = 0 // negative chemical cost is for passive abilities (chemical glands) + var/genomecost = -1 //cost of the sting in dna points. 0 = auto-purchase, -1 = cannot be purchased + var/req_dna = 0 //amount of dna needed to use this ability. Changelings always have atleast 1 + var/req_human = 0 //if you need to be human to use this ability + var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD + var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss. + var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet. + +/obj/effect/proc_holder/changeling/proc/on_purchase(mob/user) + return + +/obj/effect/proc_holder/changeling/Click() + var/mob/user = usr + if(!user || !user.mind || !user.mind.changeling) + return + try_to_sting(user) + +/obj/effect/proc_holder/changeling/proc/try_to_sting(mob/user, mob/target) + if(!can_sting(user, target)) + return + var/datum/changeling/c = user.mind.changeling + if(sting_action(user, target)) + sting_feedback(user, target) + take_chemical_cost(c) + +/obj/effect/proc_holder/changeling/proc/sting_action(mob/user, mob/target) + return 0 + +/obj/effect/proc_holder/changeling/proc/sting_feedback(mob/user, mob/target) + return 0 + +/obj/effect/proc_holder/changeling/proc/take_chemical_cost(datum/changeling/changeling) + changeling.chem_charges -= chemical_cost + changeling.geneticdamage += genetic_damage + +//Fairly important to remember to return 1 on success >.< +/obj/effect/proc_holder/changeling/proc/can_sting(mob/user, mob/target) + if(!ishuman(user) && !ismonkey(user)) //typecast everything from mob to carbon from this point onwards + return 0 + if(req_human && !ishuman(user)) + to_chat(user, "We cannot do that in this form!") + return 0 + var/datum/changeling/c = user.mind.changeling + if(c.chem_chargesWe require at least [chemical_cost] unit\s of chemicals to do that!") + return 0 + if(c.absorbed_dna.lenWe require at least [req_dna] sample\s of compatible DNA.") + return 0 + if(req_stat < user.stat) + to_chat(user, "We are incapacitated.") + return 0 + if((user.status_flags & FAKEDEATH) && name!="Regenerate") + to_chat(user, "We are incapacitated.") + return 0 + if(c.geneticdamage > max_genetic_damage) + to_chat(user, "Our genomes are still reassembling. We need time to recover first.") + return 0 + return 1 + +//used in /mob/Stat() +/obj/effect/proc_holder/changeling/proc/can_be_used_by(mob/user) + if(req_human && !ishuman(user)) + return FALSE + return TRUE diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm index 65bab658fb76..ba24b0c778ff 100644 --- a/code/game/gamemodes/changeling/evolution_menu.dm +++ b/code/game/gamemodes/changeling/evolution_menu.dm @@ -1,430 +1,430 @@ -var/list/sting_paths -// totally stolen from the new player panel. YAYY - -/obj/effect/proc_holder/changeling/evolution_menu - name = "-Evolution Menu-" //Dashes are so it's listed before all the other abilities. - desc = "Choose our method of subjugation." - genomecost = 0 - - -/obj/effect/proc_holder/changeling/evolution_menu/Click() - if(!usr || !usr.mind || !usr.mind.changeling) - return - var/datum/changeling/changeling = usr.mind.changeling - - if(!sting_paths) - sting_paths = init_paths(/obj/effect/proc_holder/changeling) - - var/dat = create_menu(changeling) - usr << browse(entity_ja(dat), "window=powers;size=600x700")//900x480 - - -/obj/effect/proc_holder/changeling/evolution_menu/proc/create_menu(datum/changeling/changeling) - var/dat - dat +="Changling Evolution Menu" - - //javascript, the part that does most of the work~ - dat += {" - - - - - - - "} - - //body tag start + onload and onkeypress (onkeyup) javascript event calls - dat += "" - - //title + search bar - dat += {" - - - - - - - - -
    - Changeling Evolution Menu
    - Hover over a power to see more information
    - Current evolution points left to evolve with: [changeling.geneticpoints]
    - Absorb genomes to acquire more evolution points -

    -

    - Search: -
    - - "} - - //player table header - dat += {" - - "} - - var/i = 1 - for(var/path in sting_paths) - - var/obj/effect/proc_holder/changeling/P = new path() - if(P.genomecost <= 0) //Let's skip the crap we start with. Keeps the evolution menu uncluttered. - continue - - var/ownsthis = changeling.has_sting(P) - - var/color - if(ownsthis) - if(i%2 == 0) - color = "#d8ebd8" - else - color = "#c3dec3" - else - if(i%2 == 0) - color = "#f2f2f2" - else - color = "#e6e6e6" - - - dat += {" - - - - - - "} - - i++ - - - //player table ending - dat += {" -
    - - - Evolve [P][ownsthis ? " - Purchased" : " - Cost: [P.genomecost]"] - -
    -
    -
    - - - - "} - return dat - -/obj/effect/proc_holder/changeling/evolution_menu/Topic(href, href_list) - ..() - if(!(iscarbon(usr) && usr.mind && usr.mind.changeling)) - return - - if(href_list["P"]) - usr.mind.changeling.purchasePower(usr, href_list["P"]) - var/dat = create_menu(usr.mind.changeling) - usr << browse(entity_ja(dat), "window=powers;size=600x700") -///// -/* -/obj/effect/proc_holder/changeling/evolution_menu/Topic(href, href_list) - ..() - if(!(iscarbon(usr) && usr.mind && usr.mind.changeling)) - return - if(href_list["P"]) - usr.mind.changeling.purchasePower(usr, href_list["P"]) - var/dat = create_menu(usr.mind.changeling) - usr << browse(entity_ja(dat), "window=powers;size=600x700") */ - -/datum/changeling/proc/purchasePower(mob/living/carbon/user, sting_name) - - var/obj/effect/proc_holder/changeling/thepower = null - - if(!sting_paths) - sting_paths = init_paths(/obj/effect/proc_holder/changeling) - for(var/path in sting_paths) - var/obj/effect/proc_holder/changeling/S = new path() - if(S.name == sting_name) - thepower = S - - if(thepower == null) - to_chat(user, "This is awkward. Changeling power purchase failed, please report this bug to a coder!") - return - - if(has_sting(thepower)) - to_chat(user, "We have already evolved this ability!") - return - - if(geneticpoints < thepower.genomecost) - to_chat(user, "We cannot evolve this... yet. We must acquire more DNA.") - return - - if(user.status_flags & FAKEDEATH)//To avoid potential exploits by buying new powers while in stasis, which clears your verblist. - to_chat(user, "We lack the energy to evolve new abilities right now.") - return - - geneticpoints -= thepower.genomecost - purchasedpowers += thepower - thepower.on_purchase(user) -/* -//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 -*/ -/mob/proc/make_changeling() - if(!mind) - return - if(!ishuman(src) && !ismonkey(src)) - return - if(!mind.changeling) - mind.changeling = new /datum/changeling(gender) - if(!sting_paths) - sting_paths = init_paths(/obj/effect/proc_holder/changeling) - if(mind.changeling.purchasedpowers) - remove_changeling_powers(1) - // purchase free powers. - for(var/path in sting_paths) - var/obj/effect/proc_holder/changeling/S = new path() - if(!S.genomecost) - if(!mind.changeling.has_sting(S)) - mind.changeling.purchasedpowers+=S - S.on_purchase(src) - - mind.changeling.absorbed_dna |= dna - - var/mob/living/carbon/human/H = src - if(istype(H)) - mind.changeling.absorbed_species += H.species.name - - for(var/language in languages) - if(!(language in mind.changeling.absorbed_languages)) - mind.changeling.absorbed_languages += language - return 1 - -//Used to dump the languages from the changeling datum into the actual mob. -/mob/proc/changeling_update_languages(updated_languages) - - languages = list() - for(var/language in updated_languages) - languages += language - - return - -/datum/changeling/proc/reset() - chosen_sting = null - geneticpoints = initial(geneticpoints) - sting_range = initial(sting_range) - chem_storage = initial(chem_storage) - chem_recharge_rate = initial(chem_recharge_rate) - chem_charges = min(chem_charges, chem_storage) - mimicing = "" - -/mob/proc/remove_changeling_powers(keep_free_powers=0) - if(ishuman(src) || ismonkey(src)) - if(mind && mind.changeling) - digitalcamo = 0 - if(digitaldisguise) - digitaldisguise.override = 0 - mind.changeling.reset() - for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers) - if(!(p.genomecost == 0 && keep_free_powers)) - mind.changeling.purchasedpowers -= p - if(hud_used) - hud_used.lingstingdisplay.icon_state = null - hud_used.lingstingdisplay.invisibility = 101 - -/datum/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power) - for(var/obj/effect/proc_holder/changeling/P in purchasedpowers) - if(power.name == P.name) - return 1 - return 0 +var/list/sting_paths +// totally stolen from the new player panel. YAYY + +/obj/effect/proc_holder/changeling/evolution_menu + name = "-Evolution Menu-" //Dashes are so it's listed before all the other abilities. + desc = "Choose our method of subjugation." + genomecost = 0 + + +/obj/effect/proc_holder/changeling/evolution_menu/Click() + if(!usr || !usr.mind || !usr.mind.changeling) + return + var/datum/changeling/changeling = usr.mind.changeling + + if(!sting_paths) + sting_paths = init_paths(/obj/effect/proc_holder/changeling) + + var/dat = create_menu(changeling) + usr << browse(entity_ja(dat), "window=powers;size=600x700")//900x480 + + +/obj/effect/proc_holder/changeling/evolution_menu/proc/create_menu(datum/changeling/changeling) + var/dat + dat +="Changling Evolution Menu" + + //javascript, the part that does most of the work~ + dat += {" + + + + + + + "} + + //body tag start + onload and onkeypress (onkeyup) javascript event calls + dat += "" + + //title + search bar + dat += {" + + + + + + + + +
    + Changeling Evolution Menu
    + Hover over a power to see more information
    + Current evolution points left to evolve with: [changeling.geneticpoints]
    + Absorb genomes to acquire more evolution points +

    +

    + Search: +
    + + "} + + //player table header + dat += {" + + "} + + var/i = 1 + for(var/path in sting_paths) + + var/obj/effect/proc_holder/changeling/P = new path() + if(P.genomecost <= 0) //Let's skip the crap we start with. Keeps the evolution menu uncluttered. + continue + + var/ownsthis = changeling.has_sting(P) + + var/color + if(ownsthis) + if(i%2 == 0) + color = "#d8ebd8" + else + color = "#c3dec3" + else + if(i%2 == 0) + color = "#f2f2f2" + else + color = "#e6e6e6" + + + dat += {" + + + + + + "} + + i++ + + + //player table ending + dat += {" +
    + + + Evolve [P][ownsthis ? " - Purchased" : " - Cost: [P.genomecost]"] + +
    +
    +
    + + + + "} + return dat + +/obj/effect/proc_holder/changeling/evolution_menu/Topic(href, href_list) + ..() + if(!(iscarbon(usr) && usr.mind && usr.mind.changeling)) + return + + if(href_list["P"]) + usr.mind.changeling.purchasePower(usr, href_list["P"]) + var/dat = create_menu(usr.mind.changeling) + usr << browse(entity_ja(dat), "window=powers;size=600x700") +///// +/* +/obj/effect/proc_holder/changeling/evolution_menu/Topic(href, href_list) + ..() + if(!(iscarbon(usr) && usr.mind && usr.mind.changeling)) + return + if(href_list["P"]) + usr.mind.changeling.purchasePower(usr, href_list["P"]) + var/dat = create_menu(usr.mind.changeling) + usr << browse(entity_ja(dat), "window=powers;size=600x700") */ + +/datum/changeling/proc/purchasePower(mob/living/carbon/user, sting_name) + + var/obj/effect/proc_holder/changeling/thepower = null + + if(!sting_paths) + sting_paths = init_paths(/obj/effect/proc_holder/changeling) + for(var/path in sting_paths) + var/obj/effect/proc_holder/changeling/S = new path() + if(S.name == sting_name) + thepower = S + + if(thepower == null) + to_chat(user, "This is awkward. Changeling power purchase failed, please report this bug to a coder!") + return + + if(has_sting(thepower)) + to_chat(user, "We have already evolved this ability!") + return + + if(geneticpoints < thepower.genomecost) + to_chat(user, "We cannot evolve this... yet. We must acquire more DNA.") + return + + if(user.status_flags & FAKEDEATH)//To avoid potential exploits by buying new powers while in stasis, which clears your verblist. + to_chat(user, "We lack the energy to evolve new abilities right now.") + return + + geneticpoints -= thepower.genomecost + purchasedpowers += thepower + thepower.on_purchase(user) +/* +//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 +*/ +/mob/proc/make_changeling() + if(!mind) + return + if(!ishuman(src) && !ismonkey(src)) + return + if(!mind.changeling) + mind.changeling = new /datum/changeling(gender) + if(!sting_paths) + sting_paths = init_paths(/obj/effect/proc_holder/changeling) + if(mind.changeling.purchasedpowers) + remove_changeling_powers(1) + // purchase free powers. + for(var/path in sting_paths) + var/obj/effect/proc_holder/changeling/S = new path() + if(!S.genomecost) + if(!mind.changeling.has_sting(S)) + mind.changeling.purchasedpowers+=S + S.on_purchase(src) + + mind.changeling.absorbed_dna |= dna + + var/mob/living/carbon/human/H = src + if(istype(H)) + mind.changeling.absorbed_species += H.species.name + + for(var/language in languages) + if(!(language in mind.changeling.absorbed_languages)) + mind.changeling.absorbed_languages += language + return 1 + +//Used to dump the languages from the changeling datum into the actual mob. +/mob/proc/changeling_update_languages(updated_languages) + + languages = list() + for(var/language in updated_languages) + languages += language + + return + +/datum/changeling/proc/reset() + chosen_sting = null + geneticpoints = initial(geneticpoints) + sting_range = initial(sting_range) + chem_storage = initial(chem_storage) + chem_recharge_rate = initial(chem_recharge_rate) + chem_charges = min(chem_charges, chem_storage) + mimicing = "" + +/mob/proc/remove_changeling_powers(keep_free_powers=0) + if(ishuman(src) || ismonkey(src)) + if(mind && mind.changeling) + digitalcamo = 0 + if(digitaldisguise) + digitaldisguise.override = 0 + mind.changeling.reset() + for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers) + if(!(p.genomecost == 0 && keep_free_powers)) + mind.changeling.purchasedpowers -= p + if(hud_used) + hud_used.lingstingdisplay.icon_state = null + hud_used.lingstingdisplay.invisibility = 101 + +/datum/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power) + for(var/obj/effect/proc_holder/changeling/P in purchasedpowers) + if(power.name == P.name) + return 1 + return 0 diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 1ce2324d7531..4ee7344bf423 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -1,145 +1,145 @@ -/obj/effect/proc_holder/changeling/absorbDNA - name = "Absorb DNA" - desc = "Absorb the DNA of our victim." - chemical_cost = 0 - genomecost = 0 - req_human = 1 - max_genetic_damage = 100 - -/obj/effect/proc_holder/changeling/absorbDNA/can_sting(mob/living/carbon/user) - if(!..()) - return - - var/datum/changeling/changeling = user.mind.changeling - if(changeling.isabsorbing) - to_chat(user, "We are already absorbing!") - return - - var/obj/item/weapon/grab/G = user.get_active_hand() - if(!istype(G)) - to_chat(user, "We must be grabbing a creature in our active hand to absorb them.") - return - if(G.state <= GRAB_NECK) - to_chat(user, "We must have a tighter grip to absorb this creature.") - return - - var/mob/living/carbon/target = G.affecting - return changeling.can_absorb_dna(user,target) - -/obj/effect/proc_holder/changeling/absorbDNA/sting_action(mob/living/user) - var/datum/changeling/changeling = user.mind.changeling - var/obj/item/weapon/grab/G = user.get_active_hand() - var/mob/living/carbon/human/target = G.affecting - changeling.isabsorbing = 1 - for(var/stage = 1, stage<=3, stage++) - switch(stage) - if(1) - to_chat(user, "This creature is compatible. We must hold still...") - if(2) - to_chat(user, "We extend a proboscis.") - user.visible_message("[user] extends a proboscis!") - if(3) - to_chat(user, "We stab [target] with the proboscis.") - user.visible_message("[user] stabs [target] with the proboscis!") - to_chat(target, "You feel a sharp stabbing pain!") - var/obj/item/organ/external/BP = target.get_bodypart(user.zone_sel.selecting) - if(BP.take_damage(39, null, DAM_SHARP, "large organic needle")) - continue - - feedback_add_details("changeling_powers","A[stage]") - if(!do_mob(user, target, 150)) - to_chat(user, "Our absorption of [target] has been interrupted!") - changeling.isabsorbing = 0 - return - - to_chat(user, "We have absorbed [target]!") - user.visible_message("[user] sucks the fluids from [target]!") - to_chat(target, "You have been absorbed by the changeling!") - - changeling.absorb_dna(target) - - if(user.get_nutrition() < 400) user.nutrition = min((user.nutrition + target.nutrition), 400) - //Steal all of their languages! - for(var/language in target.languages) - if(!(language in changeling.absorbed_languages)) - changeling.absorbed_languages += language - - user.changeling_update_languages(changeling.absorbed_languages) - - //Steal their species! - if(target.species && !(target.species.name in changeling.absorbed_species)) - changeling.absorbed_species += target.species.name - - if(target.mind)//if the victim has got a mind - - target.mind.show_memory(src, 0) //I can read your mind, kekeke. Output all their notes. - changeling.geneticpoints += 2 - - if(target.mind.changeling)//If the target was a changeling, suck out their extra juice and objective points! - changeling.chem_charges += min(target.mind.changeling.chem_charges, changeling.chem_storage) - changeling.absorbedcount += target.mind.changeling.absorbedcount - if(target.mind.changeling.absorbed_dna) - for(var/dna_data in target.mind.changeling.absorbed_dna) //steal all their loot - if(dna_data in changeling.absorbed_dna) - continue - changeling.absorbed_dna += dna_data - target.mind.changeling.absorbed_dna.len = 1 - for(var/mob/living/parasite/essence/E in target.mind.changeling.essences) - E.flags_allowed = (ESSENCE_HIVEMIND | ESSENCE_PHANTOM | ESSENCE_POINT | ESSENCE_SPEAK_TO_HOST) - E.self_voice = FALSE - if(E.phantom) - E.phantom.hide_phantom() - E.changeling = changeling - E.transfer(user) - target.mind.changeling.essences.Cut() - - - changeling.geneticpoints += target.mind.changeling.geneticpoints - target.mind.changeling.absorbedcount = 0 - new /mob/living/parasite/essence(user, user, target) - - else - changeling.geneticpoints += 0.5 - changeling.chem_charges += 10 - - changeling.isabsorbing = 0 - for(var/datum/reagent/blood/B in target.vessel.reagent_list) //We are vamplings, so we drink blood! - if(B.id == "blood") - B.volume = 0 - target.death(0) - target.Drain() - return 1 - -//Absorbs the target DNA. -/datum/changeling/proc/absorb_dna(mob/living/carbon/T) - T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set. - absorbed_dna |= T.dna //And add the target DNA to our absorbed list. - absorbedcount++ //all that done, let's increment the objective counter. - -//Checks if the target DNA is valid and absorbable. -/datum/changeling/proc/can_absorb_dna(mob/living/carbon/U, mob/living/carbon/T) - if(T) - if(!ishuman(T)) - to_chat(U, "[T] is too simple for absorption.") - return FALSE - - if((NOCLONE in T.mutations) || (HUSK in T.mutations)) - to_chat(U, "DNA of [T] is ruined beyond usability!") - return FALSE - - if(T:species.flags[IS_SYNTHETIC] || T:species.flags[IS_PLANT]) - to_chat(U, "[T] is not compatible with our biology.") - return FALSE - - if(T:species.flags[NO_SCAN]) - to_chat(src, "We do not know how to parse this creature's DNA!") - return FALSE - - for(var/datum/dna/D in absorbed_dna) - if(T.dna.uni_identity == D.uni_identity) - if(T.dna.struc_enzymes == D.struc_enzymes) - if(T.dna.real_name == D.real_name) - if(T.dna.mutantrace == D.mutantrace) - to_chat(U, "We already have that DNA in storage.") - return FALSE +/obj/effect/proc_holder/changeling/absorbDNA + name = "Absorb DNA" + desc = "Absorb the DNA of our victim." + chemical_cost = 0 + genomecost = 0 + req_human = 1 + max_genetic_damage = 100 + +/obj/effect/proc_holder/changeling/absorbDNA/can_sting(mob/living/carbon/user) + if(!..()) + return + + var/datum/changeling/changeling = user.mind.changeling + if(changeling.isabsorbing) + to_chat(user, "We are already absorbing!") + return + + var/obj/item/weapon/grab/G = user.get_active_hand() + if(!istype(G)) + to_chat(user, "We must be grabbing a creature in our active hand to absorb them.") + return + if(G.state <= GRAB_NECK) + to_chat(user, "We must have a tighter grip to absorb this creature.") + return + + var/mob/living/carbon/target = G.affecting + return changeling.can_absorb_dna(user,target) + +/obj/effect/proc_holder/changeling/absorbDNA/sting_action(mob/living/user) + var/datum/changeling/changeling = user.mind.changeling + var/obj/item/weapon/grab/G = user.get_active_hand() + var/mob/living/carbon/human/target = G.affecting + changeling.isabsorbing = 1 + for(var/stage = 1, stage<=3, stage++) + switch(stage) + if(1) + to_chat(user, "This creature is compatible. We must hold still...") + if(2) + to_chat(user, "We extend a proboscis.") + user.visible_message("[user] extends a proboscis!") + if(3) + to_chat(user, "We stab [target] with the proboscis.") + user.visible_message("[user] stabs [target] with the proboscis!") + to_chat(target, "You feel a sharp stabbing pain!") + var/obj/item/organ/external/BP = target.get_bodypart(user.zone_sel.selecting) + if(BP.take_damage(39, null, DAM_SHARP, "large organic needle")) + continue + + feedback_add_details("changeling_powers","A[stage]") + if(!do_mob(user, target, 150)) + to_chat(user, "Our absorption of [target] has been interrupted!") + changeling.isabsorbing = 0 + return + + to_chat(user, "We have absorbed [target]!") + user.visible_message("[user] sucks the fluids from [target]!") + to_chat(target, "You have been absorbed by the changeling!") + + changeling.absorb_dna(target) + + if(user.get_nutrition() < 400) user.nutrition = min((user.nutrition + target.nutrition), 400) + //Steal all of their languages! + for(var/language in target.languages) + if(!(language in changeling.absorbed_languages)) + changeling.absorbed_languages += language + + user.changeling_update_languages(changeling.absorbed_languages) + + //Steal their species! + if(target.species && !(target.species.name in changeling.absorbed_species)) + changeling.absorbed_species += target.species.name + + if(target.mind)//if the victim has got a mind + + target.mind.show_memory(src, 0) //I can read your mind, kekeke. Output all their notes. + changeling.geneticpoints += 2 + + if(target.mind.changeling)//If the target was a changeling, suck out their extra juice and objective points! + changeling.chem_charges += min(target.mind.changeling.chem_charges, changeling.chem_storage) + changeling.absorbedcount += target.mind.changeling.absorbedcount + if(target.mind.changeling.absorbed_dna) + for(var/dna_data in target.mind.changeling.absorbed_dna) //steal all their loot + if(dna_data in changeling.absorbed_dna) + continue + changeling.absorbed_dna += dna_data + target.mind.changeling.absorbed_dna.len = 1 + for(var/mob/living/parasite/essence/E in target.mind.changeling.essences) + E.flags_allowed = (ESSENCE_HIVEMIND | ESSENCE_PHANTOM | ESSENCE_POINT | ESSENCE_SPEAK_TO_HOST) + E.self_voice = FALSE + if(E.phantom) + E.phantom.hide_phantom() + E.changeling = changeling + E.transfer(user) + target.mind.changeling.essences.Cut() + + + changeling.geneticpoints += target.mind.changeling.geneticpoints + target.mind.changeling.absorbedcount = 0 + new /mob/living/parasite/essence(user, user, target) + + else + changeling.geneticpoints += 0.5 + changeling.chem_charges += 10 + + changeling.isabsorbing = 0 + for(var/datum/reagent/blood/B in target.vessel.reagent_list) //We are vamplings, so we drink blood! + if(B.id == "blood") + B.volume = 0 + target.death(0) + target.Drain() + return 1 + +//Absorbs the target DNA. +/datum/changeling/proc/absorb_dna(mob/living/carbon/T) + T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set. + absorbed_dna |= T.dna //And add the target DNA to our absorbed list. + absorbedcount++ //all that done, let's increment the objective counter. + +//Checks if the target DNA is valid and absorbable. +/datum/changeling/proc/can_absorb_dna(mob/living/carbon/U, mob/living/carbon/T) + if(T) + if(!ishuman(T)) + to_chat(U, "[T] is too simple for absorption.") + return FALSE + + if((NOCLONE in T.mutations) || (HUSK in T.mutations)) + to_chat(U, "DNA of [T] is ruined beyond usability!") + return FALSE + + if(T:species.flags[IS_SYNTHETIC] || T:species.flags[IS_PLANT]) + to_chat(U, "[T] is not compatible with our biology.") + return FALSE + + if(T:species.flags[NO_SCAN]) + to_chat(src, "We do not know how to parse this creature's DNA!") + return FALSE + + for(var/datum/dna/D in absorbed_dna) + if(T.dna.uni_identity == D.uni_identity) + if(T.dna.struc_enzymes == D.struc_enzymes) + if(T.dna.real_name == D.real_name) + if(T.dna.mutantrace == D.mutantrace) + to_chat(U, "We already have that DNA in storage.") + return FALSE return TRUE \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/changespecies.dm b/code/game/gamemodes/changeling/powers/changespecies.dm index f3f0e6af3d33..876e59ee7dae 100644 --- a/code/game/gamemodes/changeling/powers/changespecies.dm +++ b/code/game/gamemodes/changeling/powers/changespecies.dm @@ -1,29 +1,29 @@ -/obj/effect/proc_holder/changeling/change_species - name = "Change Species" - desc = "We take on the apperance of a species that we have absorbed." - chemical_cost = 5 - genomecost = 0 - req_dna = 1 - req_human = 1 - genetic_damage = 30 - max_genetic_damage = 30 - -//Change our DNA to that of somebody we've absorbed. -/obj/effect/proc_holder/changeling/change_species/sting_action(mob/living/carbon/human/user) - var/datum/changeling/changeling = user.mind.changeling - 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(user, null) - user.visible_message("[user] transforms!") - user.set_species(S,null,1) //Until someone moves body colour into DNA, they're going to have to use the default. - - user.changeling_update_languages(changeling.absorbed_languages) - user.regenerate_icons() - - feedback_add_details("changeling_powers","TS") - return 1 +/obj/effect/proc_holder/changeling/change_species + name = "Change Species" + desc = "We take on the apperance of a species that we have absorbed." + chemical_cost = 5 + genomecost = 0 + req_dna = 1 + req_human = 1 + genetic_damage = 30 + max_genetic_damage = 30 + +//Change our DNA to that of somebody we've absorbed. +/obj/effect/proc_holder/changeling/change_species/sting_action(mob/living/carbon/human/user) + var/datum/changeling/changeling = user.mind.changeling + 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(user, null) + user.visible_message("[user] transforms!") + user.set_species(S,null,1) //Until someone moves body colour into DNA, they're going to have to use the default. + + user.changeling_update_languages(changeling.absorbed_languages) + user.regenerate_icons() + + feedback_add_details("changeling_powers","TS") + return 1 diff --git a/code/game/gamemodes/changeling/powers/chemsynth.dm b/code/game/gamemodes/changeling/powers/chemsynth.dm index b7c47d2084f2..ac441fa8ba44 100644 --- a/code/game/gamemodes/changeling/powers/chemsynth.dm +++ b/code/game/gamemodes/changeling/powers/chemsynth.dm @@ -1,12 +1,12 @@ -/obj/effect/proc_holder/changeling/chemicalsynth - name = "Rapid Chemical-Synthesis" - desc = "We evolve new pathways for producing our necessary chemicals, permitting us to naturally create them faster." - helptext = "Doubles the rate at which we naturally recharge chemicals." - genomecost = 2 - chemical_cost = -1 - -/obj/effect/proc_holder/changeling/chemicalsynth/on_purchase(mob/user) - ..() - var/datum/changeling/changeling=user.mind.changeling - changeling.chem_recharge_rate *= 2 - return +/obj/effect/proc_holder/changeling/chemicalsynth + name = "Rapid Chemical-Synthesis" + desc = "We evolve new pathways for producing our necessary chemicals, permitting us to naturally create them faster." + helptext = "Doubles the rate at which we naturally recharge chemicals." + genomecost = 2 + chemical_cost = -1 + +/obj/effect/proc_holder/changeling/chemicalsynth/on_purchase(mob/user) + ..() + var/datum/changeling/changeling=user.mind.changeling + changeling.chem_recharge_rate *= 2 + return diff --git a/code/game/gamemodes/changeling/powers/digitalcamo.dm b/code/game/gamemodes/changeling/powers/digitalcamo.dm index 755dfaeed9e7..1b803d2c46f9 100644 --- a/code/game/gamemodes/changeling/powers/digitalcamo.dm +++ b/code/game/gamemodes/changeling/powers/digitalcamo.dm @@ -1,30 +1,30 @@ -/obj/effect/proc_holder/changeling/digitalcamo - name = "Digital Camouflage" - desc = "By evolving the ability to distort our form and proprotions, we defeat common altgorithms used to detect lifeforms on cameras." - helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us... uncanny. We must constantly expend chemicals to maintain our form like this." - genomecost = 1 - -//Prevents AIs tracking you but makes you easily detectable to the human-eye. -/obj/effect/proc_holder/changeling/digitalcamo/sting_action(mob/user) - - if(user.digitalcamo) - to_chat(user, "We return to normal.") - for(var/mob/living/silicon/ai/AI in ai_list) - if(AI.client) - AI.client.images -= user.digitaldisguise - else - to_chat(user, "We distort our form to prevent AI-tracking.") - user.digitaldisguise = image(loc = user) - user.digitaldisguise.override = 1 - for(var/mob/living/silicon/ai/AI in ai_list) - if(AI.client) - AI.client.images += user.digitaldisguise - user.digitalcamo = !user.digitalcamo - - spawn(0) - while(user && user.digitalcamo && user.mind && user.mind.changeling) - user.mind.changeling.chem_charges = max(user.mind.changeling.chem_charges - 1, 0) - sleep(40) - - feedback_add_details("changeling_powers","CAM") +/obj/effect/proc_holder/changeling/digitalcamo + name = "Digital Camouflage" + desc = "By evolving the ability to distort our form and proprotions, we defeat common altgorithms used to detect lifeforms on cameras." + helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us... uncanny. We must constantly expend chemicals to maintain our form like this." + genomecost = 1 + +//Prevents AIs tracking you but makes you easily detectable to the human-eye. +/obj/effect/proc_holder/changeling/digitalcamo/sting_action(mob/user) + + if(user.digitalcamo) + to_chat(user, "We return to normal.") + for(var/mob/living/silicon/ai/AI in ai_list) + if(AI.client) + AI.client.images -= user.digitaldisguise + else + to_chat(user, "We distort our form to prevent AI-tracking.") + user.digitaldisguise = image(loc = user) + user.digitaldisguise.override = 1 + for(var/mob/living/silicon/ai/AI in ai_list) + if(AI.client) + AI.client.images += user.digitaldisguise + user.digitalcamo = !user.digitalcamo + + spawn(0) + while(user && user.digitalcamo && user.mind && user.mind.changeling) + user.mind.changeling.chem_charges = max(user.mind.changeling.chem_charges - 1, 0) + sleep(40) + + feedback_add_details("changeling_powers","CAM") return 1 \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm index 5606d2e3aec8..3bc2ab798517 100644 --- a/code/game/gamemodes/changeling/powers/fakedeath.dm +++ b/code/game/gamemodes/changeling/powers/fakedeath.dm @@ -1,88 +1,88 @@ -/obj/effect/proc_holder/changeling/fakedeath - name = "Regenerative Stasis" - desc = "We fall into a stasis, allowing us to regenerate." - helptext = "Can be used before or after death. Duration varies greatly." - chemical_cost = 20 - genomecost = 0 - req_dna = 1 - req_stat = DEAD - max_genetic_damage = 100 - -//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay. -/obj/effect/proc_holder/changeling/fakedeath/sting_action(mob/living/user) - - if(user.fake_death) - var/fake_pick = pick("oxy", "tox", "fire", "clone") - switch(fake_pick) - if("oxy") - user.adjustOxyLoss(rand(200,300)) - if("tox") - user.adjustToxLoss(rand(200,300)) - if("fire") - user.adjustFireLoss(rand(200,300)) - if("clone") - user.adjustCloneLoss(rand(200,300)) - - //user.death(0) - //dead_mob_list -= user - //alive_mob_list += user - //user.status_flags |= FAKEDEATH //play dead - //user.fake_death = 1 - //user.update_canmove() - - //if(user.stat != DEAD) - // user.emote("deathgasp") - // user.tod = worldtime2text() - - if(NOCLONE in user.mutations) - to_chat(user, "We could not begin our stasis, something damaged all our DNA.") - user.mind.changeling.instatis = FALSE - user.fake_death = FALSE - return - else - to_chat(user, "We begin our stasis, preparing energy to arise once more.") - addtimer(CALLBACK(src, .proc/give_revive_ability, user), rand(800, 2000)) - - feedback_add_details("changeling_powers","FD") - return TRUE - -/obj/effect/proc_holder/changeling/fakedeath/proc/give_revive_ability(mob/living/user) - if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers) - user.mind.changeling.instatis = FALSE - user.fake_death = FALSE - user.clear_alert("stasis") - for(var/mob/M in user.mind.changeling.essences) - M.clear_alert("stasis") - - if(user.stat != DEAD) //Player was resurrected before stasis completion - to_chat(user, "Our stasis was interrupted.") - return - else - if(NOCLONE in user.mutations) - to_chat(user, "We could not regenerate. something wrong with our DNA.") - else - to_chat(user, "We are ready to regenerate.") - user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null) - -/obj/effect/proc_holder/changeling/fakedeath/can_sting(mob/user) - if(user.mind.changeling.instatis) //We already regenerating, no need to start second time in a row. - return - if(locate(/obj/effect/proc_holder/changeling/revive) in user.mind.changeling.purchasedpowers) - to_chat(user, "We already prepared our ability.") - return - if(user.fake_death) - return - if(user.stat != DEAD) - if(alert("Are we sure we wish to fake our death?",null,"Yes","No") == "No") - return - if(user.mind.changeling.instatis) //In case if user clicked ability several times without making a choice. - return - user.mind.changeling.instatis = TRUE - user.throw_alert("stasis") - for(var/mob/M in user.mind.changeling.essences) - M.throw_alert("stasis") - if(user.stat == DEAD)//In case player gave answer too late - user.fake_death = FALSE - else - user.fake_death = TRUE - return ..() +/obj/effect/proc_holder/changeling/fakedeath + name = "Regenerative Stasis" + desc = "We fall into a stasis, allowing us to regenerate." + helptext = "Can be used before or after death. Duration varies greatly." + chemical_cost = 20 + genomecost = 0 + req_dna = 1 + req_stat = DEAD + max_genetic_damage = 100 + +//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay. +/obj/effect/proc_holder/changeling/fakedeath/sting_action(mob/living/user) + + if(user.fake_death) + var/fake_pick = pick("oxy", "tox", "fire", "clone") + switch(fake_pick) + if("oxy") + user.adjustOxyLoss(rand(200,300)) + if("tox") + user.adjustToxLoss(rand(200,300)) + if("fire") + user.adjustFireLoss(rand(200,300)) + if("clone") + user.adjustCloneLoss(rand(200,300)) + + //user.death(0) + //dead_mob_list -= user + //alive_mob_list += user + //user.status_flags |= FAKEDEATH //play dead + //user.fake_death = 1 + //user.update_canmove() + + //if(user.stat != DEAD) + // user.emote("deathgasp") + // user.tod = worldtime2text() + + if(NOCLONE in user.mutations) + to_chat(user, "We could not begin our stasis, something damaged all our DNA.") + user.mind.changeling.instatis = FALSE + user.fake_death = FALSE + return + else + to_chat(user, "We begin our stasis, preparing energy to arise once more.") + addtimer(CALLBACK(src, .proc/give_revive_ability, user), rand(800, 2000)) + + feedback_add_details("changeling_powers","FD") + return TRUE + +/obj/effect/proc_holder/changeling/fakedeath/proc/give_revive_ability(mob/living/user) + if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers) + user.mind.changeling.instatis = FALSE + user.fake_death = FALSE + user.clear_alert("stasis") + for(var/mob/M in user.mind.changeling.essences) + M.clear_alert("stasis") + + if(user.stat != DEAD) //Player was resurrected before stasis completion + to_chat(user, "Our stasis was interrupted.") + return + else + if(NOCLONE in user.mutations) + to_chat(user, "We could not regenerate. something wrong with our DNA.") + else + to_chat(user, "We are ready to regenerate.") + user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null) + +/obj/effect/proc_holder/changeling/fakedeath/can_sting(mob/user) + if(user.mind.changeling.instatis) //We already regenerating, no need to start second time in a row. + return + if(locate(/obj/effect/proc_holder/changeling/revive) in user.mind.changeling.purchasedpowers) + to_chat(user, "We already prepared our ability.") + return + if(user.fake_death) + return + if(user.stat != DEAD) + if(alert("Are we sure we wish to fake our death?",null,"Yes","No") == "No") + return + if(user.mind.changeling.instatis) //In case if user clicked ability several times without making a choice. + return + user.mind.changeling.instatis = TRUE + user.throw_alert("stasis") + for(var/mob/M in user.mind.changeling.essences) + M.throw_alert("stasis") + if(user.stat == DEAD)//In case player gave answer too late + user.fake_death = FALSE + else + user.fake_death = TRUE + return ..() diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm index ed3043d2f00f..53a3c6d4ef04 100644 --- a/code/game/gamemodes/changeling/powers/fleshmend.dm +++ b/code/game/gamemodes/changeling/powers/fleshmend.dm @@ -1,20 +1,20 @@ -/obj/effect/proc_holder/changeling/fleshmend - name = "Fleshmend" - desc = "Our flesh rapidly regenerates, healing our wounds." - helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious." - chemical_cost = 25 - genomecost = 4 - req_stat = UNCONSCIOUS - -//Starts healing you every second for 10 seconds. Can be used whilst unconscious. -/obj/effect/proc_holder/changeling/fleshmend/sting_action(mob/living/user) - to_chat(user, "We begin to heal rapidly.") - spawn(0) - for(var/i = 0, i<10,i++) - user.adjustBruteLoss(-10) - user.adjustOxyLoss(-10) - user.adjustFireLoss(-10) - sleep(10) - - feedback_add_details("changeling_powers","RR") - return 1 +/obj/effect/proc_holder/changeling/fleshmend + name = "Fleshmend" + desc = "Our flesh rapidly regenerates, healing our wounds." + helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious." + chemical_cost = 25 + genomecost = 4 + req_stat = UNCONSCIOUS + +//Starts healing you every second for 10 seconds. Can be used whilst unconscious. +/obj/effect/proc_holder/changeling/fleshmend/sting_action(mob/living/user) + to_chat(user, "We begin to heal rapidly.") + spawn(0) + for(var/i = 0, i<10,i++) + user.adjustBruteLoss(-10) + user.adjustOxyLoss(-10) + user.adjustFireLoss(-10) + sleep(10) + + feedback_add_details("changeling_powers","RR") + return 1 diff --git a/code/game/gamemodes/changeling/powers/glands.dm b/code/game/gamemodes/changeling/powers/glands.dm index d8fdcda603bc..00a6bbb0dc44 100644 --- a/code/game/gamemodes/changeling/powers/glands.dm +++ b/code/game/gamemodes/changeling/powers/glands.dm @@ -1,12 +1,12 @@ -/obj/effect/proc_holder/changeling/glands - name = "Engorged Chemical Glands" - desc = "Our chemical glands swell, permitting us to store more chemicals inside of them." - helptext = "Allows us to store an extra 25 units of chemicals." - genomecost = 2 - chemical_cost = -1 - -/obj/effect/proc_holder/changeling/glands/on_purchase(mob/user) - ..() - var/datum/changeling/changeling=user.mind.changeling - changeling.chem_storage += 25 - return +/obj/effect/proc_holder/changeling/glands + name = "Engorged Chemical Glands" + desc = "Our chemical glands swell, permitting us to store more chemicals inside of them." + helptext = "Allows us to store an extra 25 units of chemicals." + genomecost = 2 + chemical_cost = -1 + +/obj/effect/proc_holder/changeling/glands/on_purchase(mob/user) + ..() + var/datum/changeling/changeling=user.mind.changeling + changeling.chem_storage += 25 + return diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm index 79bcc1616982..afe2f4ceb3ff 100644 --- a/code/game/gamemodes/changeling/powers/hivemind.dm +++ b/code/game/gamemodes/changeling/powers/hivemind.dm @@ -1,71 +1,71 @@ -// HIVE MIND UPLOAD/DOWNLOAD DNA -var/list/datum/dna/hivemind_bank = list() - -/obj/effect/proc_holder/changeling/hivemind_upload - name = "Hive Channel" - desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it." - chemical_cost = 10 - genomecost = 0 - -/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(mob/user) - var/datum/changeling/changeling = user.mind.changeling - 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(user, "The airwaves already have all of our DNA.") - return - - var/chosen_name = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names - if(!chosen_name) - return - - var/datum/dna/chosen_dna = changeling.GetDNA(chosen_name) - if(!chosen_dna) - return - - hivemind_bank += chosen_dna - to_chat(user, "We channel the DNA of [chosen_name] to the air.") - feedback_add_details("changeling_powers","HU") - return 1 - -/obj/effect/proc_holder/changeling/hivemind_download - name = "Hive Absorb" - desc = "Allows us to absorb DNA that has been channeled to the airwaves. Does not count towards absorb objectives." - chemical_cost = 20 - genomecost = 0 -/* -/obj/effect/proc_holder/changeling/hivemind_download/can_sting(mob/living/carbon/user) - if(!..()) - return - var/datum/changeling/changeling = user.mind.changeling - if(changeling.absorbed_dna[1] == user.dna)//If our current DNA is the stalest, we gotta ditch it. - to_chat(user, "We have reached our capacity to store genetic information! We must transform before absorbing more.") - return - return 1 -*/ -/obj/effect/proc_holder/changeling/hivemind_download/sting_action(mob/user) - var/datum/changeling/changeling = user.mind.changeling - 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(user, "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 - -// if(changeling.absorbed_dna.len) -// changeling.absorbed_dna.Cut(1,2) - changeling.absorbed_dna += chosen_dna - to_chat(user, "We absorb the DNA of [S] from the air.") - feedback_add_details("changeling_powers","HD") - return 1 +// HIVE MIND UPLOAD/DOWNLOAD DNA +var/list/datum/dna/hivemind_bank = list() + +/obj/effect/proc_holder/changeling/hivemind_upload + name = "Hive Channel" + desc = "Allows us to channel DNA in the airwaves to allow other changelings to absorb it." + chemical_cost = 10 + genomecost = 0 + +/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(mob/user) + var/datum/changeling/changeling = user.mind.changeling + 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(user, "The airwaves already have all of our DNA.") + return + + var/chosen_name = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names + if(!chosen_name) + return + + var/datum/dna/chosen_dna = changeling.GetDNA(chosen_name) + if(!chosen_dna) + return + + hivemind_bank += chosen_dna + to_chat(user, "We channel the DNA of [chosen_name] to the air.") + feedback_add_details("changeling_powers","HU") + return 1 + +/obj/effect/proc_holder/changeling/hivemind_download + name = "Hive Absorb" + desc = "Allows us to absorb DNA that has been channeled to the airwaves. Does not count towards absorb objectives." + chemical_cost = 20 + genomecost = 0 +/* +/obj/effect/proc_holder/changeling/hivemind_download/can_sting(mob/living/carbon/user) + if(!..()) + return + var/datum/changeling/changeling = user.mind.changeling + if(changeling.absorbed_dna[1] == user.dna)//If our current DNA is the stalest, we gotta ditch it. + to_chat(user, "We have reached our capacity to store genetic information! We must transform before absorbing more.") + return + return 1 +*/ +/obj/effect/proc_holder/changeling/hivemind_download/sting_action(mob/user) + var/datum/changeling/changeling = user.mind.changeling + 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(user, "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 + +// if(changeling.absorbed_dna.len) +// changeling.absorbed_dna.Cut(1,2) + changeling.absorbed_dna += chosen_dna + to_chat(user, "We absorb the DNA of [S] from the air.") + feedback_add_details("changeling_powers","HD") + return 1 diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index 62eb5d5b65cd..2893028eb1ce 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -1,82 +1,82 @@ -/obj/effect/proc_holder/changeling/humanform - name = "Human form" - desc = "We change into a human." - chemical_cost = 5 - genetic_damage = 20 -// req_dna = 1 - max_genetic_damage = 20 - -/obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user) - var/datum/changeling/changeling = user.mind.changeling - 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 - - user.visible_message("[user] transforms!") - user.dna = chosen_dna.Clone() - - var/list/implants = list() - for (var/obj/item/weapon/implant/I in user) //Still preserving implants - implants += I - - user.monkeyizing = 1 - user.canmove = 0 - user.icon = null - user.overlays.Cut() - user.invisibility = 101 - var/atom/movable/overlay/animation = new /atom/movable/overlay( user.loc ) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - flick("monkey2h", animation) - sleep(48) - qdel(animation) - - for(var/obj/item/W in user) - user.drop_from_inventory(W) - for(var/obj/T in user) - qdel(T) - - var/mob/living/carbon/human/O = new /mob/living/carbon/human( src ) - if (user.dna.GetUIState(DNA_UI_GENDER)) - O.gender = FEMALE - else - O.gender = MALE - O.dna = user.dna.Clone() - user.dna = null - O.real_name = chosen_dna.real_name - - for(var/obj/T in user) - qdel(T) - - O.loc = user.loc - - O.UpdateAppearance() - domutcheck(O, null) - O.setToxLoss(user.getToxLoss()) - O.adjustBruteLoss(user.getBruteLoss()) - O.setOxyLoss(user.getOxyLoss()) - O.adjustFireLoss(user.getFireLoss()) - O.stat = user.stat - for (var/obj/item/weapon/implant/I in implants) - I.loc = O - I.implanted = O - - if(user.mind) - user.mind.transfer_to(O) - for(var/mob/living/parasite/essence/M in user) - M.transfer(O) - O.changeling_update_languages(changeling.absorbed_languages) - - - feedback_add_details("changeling_powers","LFT") - qdel(user) - O.mind.changeling.purchasedpowers -= src - return 1 +/obj/effect/proc_holder/changeling/humanform + name = "Human form" + desc = "We change into a human." + chemical_cost = 5 + genetic_damage = 20 +// req_dna = 1 + max_genetic_damage = 20 + +/obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user) + var/datum/changeling/changeling = user.mind.changeling + 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 + + user.visible_message("[user] transforms!") + user.dna = chosen_dna.Clone() + + var/list/implants = list() + for (var/obj/item/weapon/implant/I in user) //Still preserving implants + implants += I + + user.monkeyizing = 1 + user.canmove = 0 + user.icon = null + user.overlays.Cut() + user.invisibility = 101 + var/atom/movable/overlay/animation = new /atom/movable/overlay( user.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("monkey2h", animation) + sleep(48) + qdel(animation) + + for(var/obj/item/W in user) + user.drop_from_inventory(W) + for(var/obj/T in user) + qdel(T) + + var/mob/living/carbon/human/O = new /mob/living/carbon/human( src ) + if (user.dna.GetUIState(DNA_UI_GENDER)) + O.gender = FEMALE + else + O.gender = MALE + O.dna = user.dna.Clone() + user.dna = null + O.real_name = chosen_dna.real_name + + for(var/obj/T in user) + qdel(T) + + O.loc = user.loc + + O.UpdateAppearance() + domutcheck(O, null) + O.setToxLoss(user.getToxLoss()) + O.adjustBruteLoss(user.getBruteLoss()) + O.setOxyLoss(user.getOxyLoss()) + O.adjustFireLoss(user.getFireLoss()) + O.stat = user.stat + for (var/obj/item/weapon/implant/I in implants) + I.loc = O + I.implanted = O + + if(user.mind) + user.mind.transfer_to(O) + for(var/mob/living/parasite/essence/M in user) + M.transfer(O) + O.changeling_update_languages(changeling.absorbed_languages) + + + feedback_add_details("changeling_powers","LFT") + qdel(user) + O.mind.changeling.purchasedpowers -= src + return 1 diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm index cdfeec288c9e..c1a28112a530 100644 --- a/code/game/gamemodes/changeling/powers/lesserform.dm +++ b/code/game/gamemodes/changeling/powers/lesserform.dm @@ -1,75 +1,75 @@ -/obj/effect/proc_holder/changeling/lesserform - name = "Lesser form" - desc = "We debase ourselves and become lesser. We become a monkey." - chemical_cost = 5 - genomecost = 2 - genetic_damage = 30 - max_genetic_damage = 30 - req_human = 1 - -//Transform into a monkey. -/obj/effect/proc_holder/changeling/lesserform/sting_action(mob/living/carbon/human/user) - var/datum/changeling/changeling = user.mind.changeling - - if(user.has_brain_worms()) - to_chat(user, "We cannot perform this ability at the present time!") - return - if(user.restrained()) - to_chat(user,"We cannot perform this ability as you restrained!") - return - - user.visible_message("[user] transforms!") - to_chat(user, "Our genes cry out!") - - var/list/implants = list() //Try to preserve implants. - for(var/obj/item/weapon/implant/W in user) - implants += W - - user.monkeyizing = 1 - user.canmove = 0 - user.icon = null - user.overlays.Cut() - user.invisibility = 101 - - var/atom/movable/overlay/animation = new /atom/movable/overlay( user.loc ) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - flick("h2monkey", animation) - sleep(48) - qdel(animation) - - var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey(user.loc) - O.dna = user.dna.Clone() - user.dna = null - - for(var/obj/item/W in user) - user.drop_from_inventory(W) - for(var/obj/T in user) - qdel(T) - - O.loc = user.loc - O.name = "monkey ([copytext(md5(user.real_name), 2, 5)])" - O.setToxLoss(user.getToxLoss()) - O.adjustBruteLoss(user.getBruteLoss()) - O.setOxyLoss(user.getOxyLoss()) - O.adjustFireLoss(user.getFireLoss()) - O.stat = user.stat - O.a_intent = "hurt" - for(var/obj/item/weapon/implant/I in implants) - I.loc = O - I.implanted = O - - //transfer mind and delete old mob - if(user.mind) - user.mind.transfer_to(O) - if(O.mind.changeling) - O.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) - O.changeling_update_languages(changeling.absorbed_languages) - for(var/mob/living/parasite/essence/M in user) - M.transfer(O) - . = O - feedback_add_details("changeling_powers","LF") - qdel(user) - return 1 - +/obj/effect/proc_holder/changeling/lesserform + name = "Lesser form" + desc = "We debase ourselves and become lesser. We become a monkey." + chemical_cost = 5 + genomecost = 2 + genetic_damage = 30 + max_genetic_damage = 30 + req_human = 1 + +//Transform into a monkey. +/obj/effect/proc_holder/changeling/lesserform/sting_action(mob/living/carbon/human/user) + var/datum/changeling/changeling = user.mind.changeling + + if(user.has_brain_worms()) + to_chat(user, "We cannot perform this ability at the present time!") + return + if(user.restrained()) + to_chat(user,"We cannot perform this ability as you restrained!") + return + + user.visible_message("[user] transforms!") + to_chat(user, "Our genes cry out!") + + var/list/implants = list() //Try to preserve implants. + for(var/obj/item/weapon/implant/W in user) + implants += W + + user.monkeyizing = 1 + user.canmove = 0 + user.icon = null + user.overlays.Cut() + user.invisibility = 101 + + var/atom/movable/overlay/animation = new /atom/movable/overlay( user.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("h2monkey", animation) + sleep(48) + qdel(animation) + + var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey(user.loc) + O.dna = user.dna.Clone() + user.dna = null + + for(var/obj/item/W in user) + user.drop_from_inventory(W) + for(var/obj/T in user) + qdel(T) + + O.loc = user.loc + O.name = "monkey ([copytext(md5(user.real_name), 2, 5)])" + O.setToxLoss(user.getToxLoss()) + O.adjustBruteLoss(user.getBruteLoss()) + O.setOxyLoss(user.getOxyLoss()) + O.adjustFireLoss(user.getFireLoss()) + O.stat = user.stat + O.a_intent = "hurt" + for(var/obj/item/weapon/implant/I in implants) + I.loc = O + I.implanted = O + + //transfer mind and delete old mob + if(user.mind) + user.mind.transfer_to(O) + if(O.mind.changeling) + O.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null) + O.changeling_update_languages(changeling.absorbed_languages) + for(var/mob/living/parasite/essence/M in user) + M.transfer(O) + . = O + feedback_add_details("changeling_powers","LF") + qdel(user) + return 1 + diff --git a/code/game/gamemodes/changeling/powers/mimic_voice.dm b/code/game/gamemodes/changeling/powers/mimic_voice.dm index 5bd9c2fd1c31..12f8ec7539f0 100644 --- a/code/game/gamemodes/changeling/powers/mimic_voice.dm +++ b/code/game/gamemodes/changeling/powers/mimic_voice.dm @@ -1,28 +1,28 @@ -/obj/effect/proc_holder/changeling/mimicvoice - name = "Mimic Voice" - desc = "We shape our vocal glands to sound like a desired voice." - helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this." - chemical_cost = 0 //constant chemical drain hardcoded - genomecost = 1 - req_human = 1 - -// Fake Voice -/obj/effect/proc_holder/changeling/mimicvoice/sting_action(mob/user) - var/datum/changeling/changeling=user.mind.changeling - if(changeling.mimicing) - changeling.mimicing = "" - changeling.chem_recharge_slowdown -= 0.25 - to_chat(user, "We return our vocal glands to their original position.") - return - - var/mimic_voice = sanitize_safe(input("Enter a name to mimic.", "Mimic Voice", null) as text, MAX_NAME_LEN) - if(!mimic_voice) - return - - changeling.mimicing = mimic_voice - changeling.chem_recharge_slowdown += 0.25 - to_chat(user, "We shape our glands to take the voice of [mimic_voice], this will stop us from regenerating chemicals while active.") - to_chat(user, "Use this power again to return to our original voice and reproduce chemicals again.") - - feedback_add_details("changeling_powers","MV") - +/obj/effect/proc_holder/changeling/mimicvoice + name = "Mimic Voice" + desc = "We shape our vocal glands to sound like a desired voice." + helptext = "Will turn your voice into the name that you enter. We must constantly expend chemicals to maintain our form like this." + chemical_cost = 0 //constant chemical drain hardcoded + genomecost = 1 + req_human = 1 + +// Fake Voice +/obj/effect/proc_holder/changeling/mimicvoice/sting_action(mob/user) + var/datum/changeling/changeling=user.mind.changeling + if(changeling.mimicing) + changeling.mimicing = "" + changeling.chem_recharge_slowdown -= 0.25 + to_chat(user, "We return our vocal glands to their original position.") + return + + var/mimic_voice = sanitize_safe(input("Enter a name to mimic.", "Mimic Voice", null) as text, MAX_NAME_LEN) + if(!mimic_voice) + return + + changeling.mimicing = mimic_voice + changeling.chem_recharge_slowdown += 0.25 + to_chat(user, "We shape our glands to take the voice of [mimic_voice], this will stop us from regenerating chemicals while active.") + to_chat(user, "Use this power again to return to our original voice and reproduce chemicals again.") + + feedback_add_details("changeling_powers","MV") + diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index 986d0647d1ff..10542186f862 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -1,306 +1,306 @@ -//Parent to shields and blades because muh copypasted code. -/obj/effect/proc_holder/changeling/weapon - name = "Organic Weapon" - desc = "Go tell a coder if you see this." - helptext = "Yell at Miauw and/or Perakp" - chemical_cost = 1000 - genomecost = -1 - genetic_damage = 1000 - - var/weapon_type - var/weapon_name_simple - -/obj/effect/proc_holder/changeling/weapon/try_to_sting(mob/user, mob/target) - if(istype(user.get_active_hand(),weapon_type)) - user.drop_from_inventory(user.get_active_hand()) // cuz changeling weapons are unremovable with standart procedure with canremove = 0, but we still need it - return - if(iscarbon(user)) - var/mob/living/carbon/C = user - if(C.handcuffed) - qdel(C.handcuffed) - if(user.incapacitated()) - to_chat(user," We cannot reform our [weapon_name_simple] while restrained") - return - user.visible_message("With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", - "We assimilate the [weapon_name_simple] from our body.", - "[H] casts off their [suit_name_simple]!", "We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]", "You hear the organic matter ripping and tearing!") - qdel(H.wear_suit) - qdel(H.head) - H.update_inv_wear_suit() - H.update_inv_head() - H.update_hair() - - if(blood_on_castoff) - var/turf/simulated/T = get_turf(H) - if(istype(T)) - T.add_blood(H) //So real blood decals - playsound(H.loc, 'sound/effects/splat.ogg', 50, 1) //So real sounds - - changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds. - changeling.chem_recharge_slowdown -= recharge_slowdown - return - ..(H, target) - -/obj/effect/proc_holder/changeling/suit/sting_action(mob/living/carbon/human/user) - if(!user.unEquip(user.wear_suit)) - to_chat(user, "\the [user.wear_suit] is stuck to your body, you cannot grow a [suit_name_simple] over it!") - return - if(!user.unEquip(user.head)) - to_chat(user, "\the [user.head] is stuck on your head, you cannot grow a [helmet_name_simple] over it!") - return - - user.drop_from_inventory(user.head) - user.drop_from_inventory(user.wear_suit) - - user.equip_to_slot_if_possible(new suit_type(user), slot_wear_suit, 1, 1, 1) - user.equip_to_slot_if_possible(new helmet_type(user), slot_head, 1, 1, 1) - - var/datum/changeling/changeling = user.mind.changeling - changeling.chem_recharge_slowdown += recharge_slowdown - return 1 - -/obj/effect/proc_holder/changeling/weapon/arm_blade - name = "Arm Blade" - desc = "We reform one of our arms into a deadly blade." - helptext = "Cannot be used while in lesser form." - chemical_cost = 20 - genomecost = 2 - genetic_damage = 10 - req_human = 1 - max_genetic_damage = 10 - weapon_type = /obj/item/weapon/melee/arm_blade - weapon_name_simple = "blade" - -/obj/item/weapon/melee/arm_blade - name = "arm blade" - desc = "A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter." - icon = 'icons/obj/weapons.dmi' - icon_state = "arm_blade" - item_state = "arm_blade" - flags = ABSTRACT | DROPDEL - canremove = 0 - w_class = 5.0 - force = 25 - throwforce = 0 //Just to be on the safe side - throw_range = 0 - throw_speed = 0 - -/obj/item/weapon/melee/arm_blade/atom_init() - . = ..() - if(ismob(loc)) - loc.visible_message("A grotesque blade forms around [loc.name]\'s arm!", "Our arm twists and mutates, transforming it into a deadly blade.", "You hear organic matter ripping and tearing!") - -/obj/item/weapon/melee/arm_blade/dropped(mob/user) - visible_message("With a sickening crunch, [user] reforms his blade into an arm!", "We assimilate the blade back into our body.", "") - return - - else if(A.locked) - to_chat(user, "The airlock's bolts prevent it from being forced.") - return - - else - if(prob(10)) - user.say("Heeeeeeeeeerrre's Johnny!") // ^^ - user.visible_message("[user] forces the door to open with \his [src]!", "We force the door to open.", "You hear a metal screeching sound.") - A.open(1) - -/obj/effect/proc_holder/changeling/weapon/shield - name = "Organic Shield" - desc = "We reform one of our arms into hard shield." - helptext = "Organic tissue cannot resist damage forever, the shield will break after it is hit too much. The more genomes we absorb, the stronger it is.. Cannot be used while in lesser form." - chemical_cost = 20 - genomecost = 2 - genetic_damage = 12 - req_human = 1 - max_genetic_damage = 10 - - weapon_type = /obj/item/weapon/shield/changeling - weapon_name_simple = "shield" - -/obj/item/weapon/shield/changeling - name = "shield-like mass" - desc = "A mass of tough, boney tissue. You can still see the fingers as a twisted pattern in the shield." - canremove = 0 - flags = ABSTRACT | DROPDEL - icon = 'icons/obj/weapons.dmi' - icon_state = "ling_shield" - item_state = "ling_shield" - block_chance = 80 - var/remaining_uses = 6 - -/obj/item/weapon/shield/changeling/atom_init() - . = ..() - if(ismob(loc)) - loc.visible_message("The end of [loc.name]\'s hand inflates rapidly, forming a huge shield-like mass!", "We inflate our hand into a strong shield.", "You hear organic matter ripping and tearing!") - var/mob/M = loc - if(M.mind.changeling.absorbedcount) - remaining_uses += M.mind.changeling.absorbedcount - -/obj/item/weapon/shield/changeling/Get_shield_chance() - if(!remaining_uses) - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - visible_message( - "With a sickening crunch, [H] reforms his shield into an arm!", - "We assimilate our shield into our body", - "[loc.name]\'s flesh rapidly inflates, forming a bloated mass around their body!", "We inflate our flesh, creating a spaceproof suit!", "You hear organic matter ripping and tearing!") - START_PROCESSING(SSobj, src) - -/obj/item/clothing/suit/space/changeling/process() - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - H.reagents.add_reagent("dexalinp", REAGENTS_METABOLISM) - var/obj/item/organ/internal/lungs/IO = H.organs_by_name[O_LUNGS] - if(IO.damage >= 5) - IO.damage -= 5 - -/obj/item/clothing/head/helmet/space/changeling - name = "flesh mass" - icon = 'icons/mob/head.dmi' - icon_state = "lingspacehelmet" - desc = "A covering of pressure and temperature-resistant organic tissue with a glass-like chitin front." - flags = HEADCOVERSEYES | BLOCKHAIR | HEADCOVERSMOUTH | DROPDEL - canremove = 0 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 2 // fleeesh! - -/obj/effect/proc_holder/changeling/suit/armor - name = "Chitinous Armor" - desc = "We turn our skin into tough chitin to protect us from damage." - helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form." - chemical_cost = 25 - genomecost = 2 - genetic_damage = 10 - req_human = 1 - max_genetic_damage = 10 - - suit_type = /obj/item/clothing/suit/armor/changeling - helmet_type = /obj/item/clothing/head/helmet/changeling - suit_name_simple = "armor" - helmet_name_simple = "helmet" - recharge_slowdown = 0.25 - -/obj/item/clothing/suit/armor/changeling - name = "chitinous mass" - desc = "A tough, hard covering of black chitin." - icon = 'icons/mob/suit.dmi' - icon_state = "lingarmor" - canremove = 0 - flags = THICKMATERIAL | DROPDEL - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - slowdown = 1 - armor = list(melee = 65, bullet = 50, laser = 50, energy = 35, bomb = 25, bio = 0, rad = 0) - flags_inv = HIDEJUMPSUIT - cold_protection = 0 - heat_protection = 0 - siemens_coefficient = 0.4 - -/obj/item/clothing/suit/armor/changeling/atom_init() - . = ..() - if(ismob(loc)) - loc.visible_message("[loc.name]\'s flesh turns black, quickly transforming into a hard, chitinous mass!", "We harden our flesh, creating a suit of armor!", "You hear organic matter ripping and tearing!") - -/obj/item/clothing/head/helmet/changeling - name = "chitinous mass" - desc = "A tough, hard covering of black chitin with transparent chitin in front." - icon = 'icons/mob/head.dmi' - icon_state = "lingarmorhelmet" - flags = HEADCOVERSEYES | BLOCKHAIR | THICKMATERIAL | DROPDEL - canremove = 0 - armor = list(melee = 70, bullet = 45, laser = 45, energy = 35, bomb = 25, bio = 2, rad = 0) - flags_inv = HIDEEARS - siemens_coefficient = 0.4 +//Parent to shields and blades because muh copypasted code. +/obj/effect/proc_holder/changeling/weapon + name = "Organic Weapon" + desc = "Go tell a coder if you see this." + helptext = "Yell at Miauw and/or Perakp" + chemical_cost = 1000 + genomecost = -1 + genetic_damage = 1000 + + var/weapon_type + var/weapon_name_simple + +/obj/effect/proc_holder/changeling/weapon/try_to_sting(mob/user, mob/target) + if(istype(user.get_active_hand(),weapon_type)) + user.drop_from_inventory(user.get_active_hand()) // cuz changeling weapons are unremovable with standart procedure with canremove = 0, but we still need it + return + if(iscarbon(user)) + var/mob/living/carbon/C = user + if(C.handcuffed) + qdel(C.handcuffed) + if(user.incapacitated()) + to_chat(user," We cannot reform our [weapon_name_simple] while restrained") + return + user.visible_message("With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", + "We assimilate the [weapon_name_simple] from our body.", + "[H] casts off their [suit_name_simple]!", "We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]", "You hear the organic matter ripping and tearing!") + qdel(H.wear_suit) + qdel(H.head) + H.update_inv_wear_suit() + H.update_inv_head() + H.update_hair() + + if(blood_on_castoff) + var/turf/simulated/T = get_turf(H) + if(istype(T)) + T.add_blood(H) //So real blood decals + playsound(H.loc, 'sound/effects/splat.ogg', 50, 1) //So real sounds + + changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds. + changeling.chem_recharge_slowdown -= recharge_slowdown + return + ..(H, target) + +/obj/effect/proc_holder/changeling/suit/sting_action(mob/living/carbon/human/user) + if(!user.unEquip(user.wear_suit)) + to_chat(user, "\the [user.wear_suit] is stuck to your body, you cannot grow a [suit_name_simple] over it!") + return + if(!user.unEquip(user.head)) + to_chat(user, "\the [user.head] is stuck on your head, you cannot grow a [helmet_name_simple] over it!") + return + + user.drop_from_inventory(user.head) + user.drop_from_inventory(user.wear_suit) + + user.equip_to_slot_if_possible(new suit_type(user), slot_wear_suit, 1, 1, 1) + user.equip_to_slot_if_possible(new helmet_type(user), slot_head, 1, 1, 1) + + var/datum/changeling/changeling = user.mind.changeling + changeling.chem_recharge_slowdown += recharge_slowdown + return 1 + +/obj/effect/proc_holder/changeling/weapon/arm_blade + name = "Arm Blade" + desc = "We reform one of our arms into a deadly blade." + helptext = "Cannot be used while in lesser form." + chemical_cost = 20 + genomecost = 2 + genetic_damage = 10 + req_human = 1 + max_genetic_damage = 10 + weapon_type = /obj/item/weapon/melee/arm_blade + weapon_name_simple = "blade" + +/obj/item/weapon/melee/arm_blade + name = "arm blade" + desc = "A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter." + icon = 'icons/obj/weapons.dmi' + icon_state = "arm_blade" + item_state = "arm_blade" + flags = ABSTRACT | DROPDEL + canremove = 0 + w_class = 5.0 + force = 25 + throwforce = 0 //Just to be on the safe side + throw_range = 0 + throw_speed = 0 + +/obj/item/weapon/melee/arm_blade/atom_init() + . = ..() + if(ismob(loc)) + loc.visible_message("A grotesque blade forms around [loc.name]\'s arm!", "Our arm twists and mutates, transforming it into a deadly blade.", "You hear organic matter ripping and tearing!") + +/obj/item/weapon/melee/arm_blade/dropped(mob/user) + visible_message("With a sickening crunch, [user] reforms his blade into an arm!", "We assimilate the blade back into our body.", "") + return + + else if(A.locked) + to_chat(user, "The airlock's bolts prevent it from being forced.") + return + + else + if(prob(10)) + user.say("Heeeeeeeeeerrre's Johnny!") // ^^ + user.visible_message("[user] forces the door to open with \his [src]!", "We force the door to open.", "You hear a metal screeching sound.") + A.open(1) + +/obj/effect/proc_holder/changeling/weapon/shield + name = "Organic Shield" + desc = "We reform one of our arms into hard shield." + helptext = "Organic tissue cannot resist damage forever, the shield will break after it is hit too much. The more genomes we absorb, the stronger it is.. Cannot be used while in lesser form." + chemical_cost = 20 + genomecost = 2 + genetic_damage = 12 + req_human = 1 + max_genetic_damage = 10 + + weapon_type = /obj/item/weapon/shield/changeling + weapon_name_simple = "shield" + +/obj/item/weapon/shield/changeling + name = "shield-like mass" + desc = "A mass of tough, boney tissue. You can still see the fingers as a twisted pattern in the shield." + canremove = 0 + flags = ABSTRACT | DROPDEL + icon = 'icons/obj/weapons.dmi' + icon_state = "ling_shield" + item_state = "ling_shield" + block_chance = 80 + var/remaining_uses = 6 + +/obj/item/weapon/shield/changeling/atom_init() + . = ..() + if(ismob(loc)) + loc.visible_message("The end of [loc.name]\'s hand inflates rapidly, forming a huge shield-like mass!", "We inflate our hand into a strong shield.", "You hear organic matter ripping and tearing!") + var/mob/M = loc + if(M.mind.changeling.absorbedcount) + remaining_uses += M.mind.changeling.absorbedcount + +/obj/item/weapon/shield/changeling/Get_shield_chance() + if(!remaining_uses) + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + visible_message( + "With a sickening crunch, [H] reforms his shield into an arm!", + "We assimilate our shield into our body", + "[loc.name]\'s flesh rapidly inflates, forming a bloated mass around their body!", "We inflate our flesh, creating a spaceproof suit!", "You hear organic matter ripping and tearing!") + START_PROCESSING(SSobj, src) + +/obj/item/clothing/suit/space/changeling/process() + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + H.reagents.add_reagent("dexalinp", REAGENTS_METABOLISM) + var/obj/item/organ/internal/lungs/IO = H.organs_by_name[O_LUNGS] + if(IO.damage >= 5) + IO.damage -= 5 + +/obj/item/clothing/head/helmet/space/changeling + name = "flesh mass" + icon = 'icons/mob/head.dmi' + icon_state = "lingspacehelmet" + desc = "A covering of pressure and temperature-resistant organic tissue with a glass-like chitin front." + flags = HEADCOVERSEYES | BLOCKHAIR | HEADCOVERSMOUTH | DROPDEL + canremove = 0 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 2 // fleeesh! + +/obj/effect/proc_holder/changeling/suit/armor + name = "Chitinous Armor" + desc = "We turn our skin into tough chitin to protect us from damage." + helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form." + chemical_cost = 25 + genomecost = 2 + genetic_damage = 10 + req_human = 1 + max_genetic_damage = 10 + + suit_type = /obj/item/clothing/suit/armor/changeling + helmet_type = /obj/item/clothing/head/helmet/changeling + suit_name_simple = "armor" + helmet_name_simple = "helmet" + recharge_slowdown = 0.25 + +/obj/item/clothing/suit/armor/changeling + name = "chitinous mass" + desc = "A tough, hard covering of black chitin." + icon = 'icons/mob/suit.dmi' + icon_state = "lingarmor" + canremove = 0 + flags = THICKMATERIAL | DROPDEL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + slowdown = 1 + armor = list(melee = 65, bullet = 50, laser = 50, energy = 35, bomb = 25, bio = 0, rad = 0) + flags_inv = HIDEJUMPSUIT + cold_protection = 0 + heat_protection = 0 + siemens_coefficient = 0.4 + +/obj/item/clothing/suit/armor/changeling/atom_init() + . = ..() + if(ismob(loc)) + loc.visible_message("[loc.name]\'s flesh turns black, quickly transforming into a hard, chitinous mass!", "We harden our flesh, creating a suit of armor!", "You hear organic matter ripping and tearing!") + +/obj/item/clothing/head/helmet/changeling + name = "chitinous mass" + desc = "A tough, hard covering of black chitin with transparent chitin in front." + icon = 'icons/mob/head.dmi' + icon_state = "lingarmorhelmet" + flags = HEADCOVERSEYES | BLOCKHAIR | THICKMATERIAL | DROPDEL + canremove = 0 + armor = list(melee = 70, bullet = 45, laser = 45, energy = 35, bomb = 25, bio = 2, rad = 0) + flags_inv = HIDEEARS + siemens_coefficient = 0.4 diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm index 51a2109ed809..69221ef7298c 100644 --- a/code/game/gamemodes/changeling/powers/panacea.dm +++ b/code/game/gamemodes/changeling/powers/panacea.dm @@ -1,23 +1,23 @@ -/obj/effect/proc_holder/changeling/panacea - name = "Anatomic Panacea" - desc = "Expels impurifications from our form; curing diseases, genetic disabilities, and removing toxins and radiation." - helptext = "Can be used while unconscious." - chemical_cost = 25 - genomecost = 1 - req_stat = UNCONSCIOUS - -//Heals the things that the other regenerative abilities don't. -/obj/effect/proc_holder/changeling/panacea/sting_action(mob/living/carbon/user) - - to_chat(user, "We cleanse impurities from our form.") - user.reagents.add_reagent("ryetalyn", 10) - user.reagents.add_reagent("hyronalin", 10) - user.reagents.add_reagent("anti_toxin", 20) - - if(user.virus2.len) - for (var/ID in user.virus2) - var/datum/disease2/disease/V = user.virus2[ID] - V.cure(user) - - feedback_add_details("changeling_powers","AP") - return 1 +/obj/effect/proc_holder/changeling/panacea + name = "Anatomic Panacea" + desc = "Expels impurifications from our form; curing diseases, genetic disabilities, and removing toxins and radiation." + helptext = "Can be used while unconscious." + chemical_cost = 25 + genomecost = 1 + req_stat = UNCONSCIOUS + +//Heals the things that the other regenerative abilities don't. +/obj/effect/proc_holder/changeling/panacea/sting_action(mob/living/carbon/user) + + to_chat(user, "We cleanse impurities from our form.") + user.reagents.add_reagent("ryetalyn", 10) + user.reagents.add_reagent("hyronalin", 10) + user.reagents.add_reagent("anti_toxin", 20) + + if(user.virus2.len) + for (var/ID in user.virus2) + var/datum/disease2/disease/V = user.virus2[ID] + V.cure(user) + + feedback_add_details("changeling_powers","AP") + return 1 diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 2ce4992dfec4..e54957851626 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -1,35 +1,35 @@ -/obj/effect/proc_holder/changeling/revive - name = "Regenerate" - desc = "We regenerate, healing all damage from our form." - req_stat = DEAD - -//Revive from regenerative stasis -/obj/effect/proc_holder/changeling/revive/sting_action(mob/living/carbon/user) - user.mind.changeling.purchasedpowers -= src - if(user.stat == DEAD) - dead_mob_list -= user - alive_mob_list += user - if(HUSK in user.mutations) - user.mutations.Remove(HUSK) - user.fake_death = 0 - user.stat = CONSCIOUS - user.tod = null - user.timeofdeath = 0 - user.reagents.clear_reagents() - user.rejuvenate() - to_chat(user, "We have regenerated.") - //user.status_flags &= ~(FAKEDEATH) - //user.update_canmove() - feedback_add_details("changeling_powers","CR") - return 1 - -/obj/effect/proc_holder/changeling/revive/can_sting(mob/user) - if(NOCLONE in user.mutations) - to_chat(user, "We could not regenerate. Something wrong with our DNA.") - user.fake_death = 0 - user.mind.changeling.purchasedpowers -= src //We dont need that power from now anyway. - return - if(user.stat < 2)//We are alive when using this... Why do we need to keep this ability and even rejuvenate, if revive must used from dead state? - to_chat(user, "We ready to regenerate, but we need to stop any life activity in our body.") - return - return ..() +/obj/effect/proc_holder/changeling/revive + name = "Regenerate" + desc = "We regenerate, healing all damage from our form." + req_stat = DEAD + +//Revive from regenerative stasis +/obj/effect/proc_holder/changeling/revive/sting_action(mob/living/carbon/user) + user.mind.changeling.purchasedpowers -= src + if(user.stat == DEAD) + dead_mob_list -= user + alive_mob_list += user + if(HUSK in user.mutations) + user.mutations.Remove(HUSK) + user.fake_death = 0 + user.stat = CONSCIOUS + user.tod = null + user.timeofdeath = 0 + user.reagents.clear_reagents() + user.rejuvenate() + to_chat(user, "We have regenerated.") + //user.status_flags &= ~(FAKEDEATH) + //user.update_canmove() + feedback_add_details("changeling_powers","CR") + return 1 + +/obj/effect/proc_holder/changeling/revive/can_sting(mob/user) + if(NOCLONE in user.mutations) + to_chat(user, "We could not regenerate. Something wrong with our DNA.") + user.fake_death = 0 + user.mind.changeling.purchasedpowers -= src //We dont need that power from now anyway. + return + if(user.stat < 2)//We are alive when using this... Why do we need to keep this ability and even rejuvenate, if revive must used from dead state? + to_chat(user, "We ready to regenerate, but we need to stop any life activity in our body.") + return + return ..() diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm index bf5e9d88e2bb..67323b073d2c 100644 --- a/code/game/gamemodes/changeling/powers/shriek.dm +++ b/code/game/gamemodes/changeling/powers/shriek.dm @@ -1,29 +1,29 @@ -/obj/effect/proc_holder/changeling/resonant_shriek - name = "Resonant Shriek" - desc = "Our lungs and vocal chords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded." - helptext = "Emits a high-frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors." - chemical_cost = 25 - genomecost = 3 - req_human = 1 - -//A flashy ability, good for crowd control and sewing chaos. -/obj/effect/proc_holder/changeling/resonant_shriek/sting_action(mob/user) - for(var/mob/living/M in hearers(4, user)) - if(iscarbon(M)) - if(!M.mind || !M.mind.changeling) - M.ear_deaf += 30 - M.confused += 20 - M.make_jittery(500) - else - M << sound('sound/effects/screech.ogg') - - if(issilicon(M)) - M << sound('sound/weapons/flash.ogg') - M.Weaken(rand(5,10)) - - for(var/obj/machinery/light/L in range(4, user)) - L.on = 1 - L.broken() - - feedback_add_details("changeling_powers","RES") - return 1 +/obj/effect/proc_holder/changeling/resonant_shriek + name = "Resonant Shriek" + desc = "Our lungs and vocal chords shift, allowing us to briefly emit a noise that deafens and confuses the weak-minded." + helptext = "Emits a high-frequency sound that confuses and deafens humans, blows out nearby lights and overloads cyborg sensors." + chemical_cost = 25 + genomecost = 3 + req_human = 1 + +//A flashy ability, good for crowd control and sewing chaos. +/obj/effect/proc_holder/changeling/resonant_shriek/sting_action(mob/user) + for(var/mob/living/M in hearers(4, user)) + if(iscarbon(M)) + if(!M.mind || !M.mind.changeling) + M.ear_deaf += 30 + M.confused += 20 + M.make_jittery(500) + else + M << sound('sound/effects/screech.ogg') + + if(issilicon(M)) + M << sound('sound/weapons/flash.ogg') + M.Weaken(rand(5,10)) + + for(var/obj/machinery/light/L in range(4, user)) + L.on = 1 + L.broken() + + feedback_add_details("changeling_powers","RES") + return 1 diff --git a/code/game/gamemodes/changeling/powers/stings.dm b/code/game/gamemodes/changeling/powers/stings.dm index d299bfc06c30..ce27eed61afd 100644 --- a/code/game/gamemodes/changeling/powers/stings.dm +++ b/code/game/gamemodes/changeling/powers/stings.dm @@ -1,283 +1,283 @@ -/obj/effect/proc_holder/changeling/sting - name = "Tiny Prick" - desc = "Stabby stabby." - var/sting_icon = null - var/ranged = 1 - -/obj/effect/proc_holder/changeling/sting/Click() - var/mob/user = usr - if(!user || !user.mind || !user.mind.changeling) - return - if(!(user.mind.changeling.chosen_sting)) - set_sting(user) - else - unset_sting(user) - return - -/obj/effect/proc_holder/changeling/sting/proc/set_sting(mob/user) - to_chat(user, "We prepare our sting, use alt+click or middle mouse button on target to sting them.") - user.mind.changeling.chosen_sting = src - user.hud_used.lingstingdisplay.icon_state = sting_icon - user.hud_used.lingstingdisplay.invisibility = 0 - -/obj/effect/proc_holder/changeling/sting/proc/unset_sting(mob/user) - to_chat(user, "We retract our sting, we can't sting anyone for now.") - user.mind.changeling.chosen_sting = null - user.hud_used.lingstingdisplay.icon_state = null - user.hud_used.lingstingdisplay.invisibility = 101 - -/mob/living/carbon/proc/unset_sting() - if(mind && mind.changeling && mind.changeling.chosen_sting) - src.mind.changeling.chosen_sting.unset_sting(src) - -/obj/effect/proc_holder/changeling/sting/can_sting(mob/user, mob/target) - - - if(!..()) - return - if(!user.mind.changeling.chosen_sting) - to_chat(user, "We haven't prepared our sting yet!") - if(!iscarbon(target)) - return - if(!isturf(user.loc)) - return - if(!AStar(user, target.loc, /turf/proc/Distance, user.mind.changeling.sting_range, simulated_only = FALSE)) - return //hope this ancient magic still works - if(target.mind && target.mind.changeling) - sting_feedback(user,target) - take_chemical_cost(user.mind.changeling) - return - return 1 - -/obj/effect/proc_holder/changeling/sting/sting_feedback(mob/user, mob/target) - if(!target) - return - if((get_dist(user, target) <= 1)) - to_chat(user, "We stealthily sting [target.name].") - else - to_chat(user, "We stealthily shoot [target.name] with sting.") - if(target.mind && target.mind.changeling) - to_chat(target, "You feel a tiny prick.") - // add_logs(user, target, "unsuccessfully stung") - msg_admin_attack("[key_name(user)] used [src] on [key_name(target)] (JMP)") - return 1 - -/obj/effect/proc_holder/changeling/sting/proc/sting_fail(mob/user, mob/target) - if(!target) - return 1 - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.wear_suit) - var/obj/item/clothing/I = H.wear_suit - if(I.flags & THICKMATERIAL) - to_chat(user, "We broke our sting about our's armor!") - unset_sting(user) - user.mind.changeling.chem_charges -= rand(5,10) - H.drip(10) - return 1 - if(ishuman(target)) - var/mob/living/carbon/human/H = target - var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_CHEST] - var/result = H.check_thickmaterial(BP) || H.isSynthetic(BP_CHEST) - if(result) - if(result == NOLIMB) - to_chat(user, "We missed! [target.name] has no [BP.name]!") - else - to_chat(user, "We broke our sting about [target.name]'s [BP.name]!") - to_chat(target, "You feel a tiny push in your [BP.name]!") - if(ishuman(user)) - var/mob/living/carbon/human/HU = user - HU.drip(10) - unset_sting(user) - user.mind.changeling.chem_charges -= rand(5,10) - - return 1 - else - return 0 - -obj/effect/proc_holder/changeling/sting/cryo - name = "Cryogenic Sting" - desc = "We silently sting a human with a cocktail of chemicals that freeze them." - helptext = "Does not provide a warning to the victim, though they will likely realize they are suddenly freezing." - sting_icon = "sting_cryo" - chemical_cost = 15 - genomecost = 1 - -/obj/effect/proc_holder/changeling/sting/cryo/sting_action(mob/user, mob/target) - if(sting_fail(user,target)) - return 0 - if(target.reagents) - target.reagents.add_reagent("frostoil", 30) - target.reagents.add_reagent("ice", 30) - feedback_add_details("changeling_powers","CS") - return 1 - -obj/effect/proc_holder/changeling/sting/LSD - name = "Hallucination Sting" - desc = "Causes terror in the target." - helptext = "We evolve the ability to sting a target with a powerful hallucinogenic chemical. The target does not notice they have been stung. The effect occurs after 30 to 60 seconds." - sting_icon = "sting_lsd" - chemical_cost = 15 - genomecost = 2 - -/obj/effect/proc_holder/changeling/sting/LSD/sting_action(mob/user, mob/living/carbon/target) - if(sting_fail(user,target)) - return 0 - spawn(rand(300,600)) - if(target) - target.hallucination = max(400, target.hallucination) - feedback_add_details("changeling_powers","HS") - return 1 - -/obj/effect/proc_holder/changeling/sting/transformation - name = "Transformation Sting" - desc = "We silently sting a human, injecting a retrovirus that forces them to transform." - helptext = "Does not provide a warning to others. The victim will transform much like a changeling would." - sting_icon = "sting_transform" - chemical_cost = 40 - genomecost = 3 - var/datum/dna/selected_dna = null - -/obj/effect/proc_holder/changeling/sting/transformation/Click() - var/mob/user = usr - var/datum/changeling/changeling = user.mind.changeling - 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 - - selected_dna = changeling.GetDNA(S) - if(!selected_dna) - return - ..() - -/obj/effect/proc_holder/changeling/sting/transformation/can_sting(mob/user, mob/target) - if(!..()) - return - if((HUSK in target.mutations) || (NOCLONE in target.mutations)) - to_chat(user, "Our sting appears ineffective against its DNA.") - return 0 - return 1 - -/obj/effect/proc_holder/changeling/sting/transformation/sting_action(mob/user, mob/target) - if(sting_fail(user,target)) - return 0 - if(ismonkey(target)) - to_chat(user, "We stealthily sting [target.name].") - target.visible_message("[target] transforms!") - target.dna = selected_dna.Clone() - target.real_name = selected_dna.real_name - domutcheck(target, null) - target.UpdateAppearance() - feedback_add_details("changeling_powers","TS") - return 1 - -obj/effect/proc_holder/changeling/sting/extract_dna - name = "Extract DNA Sting" - desc = "We stealthily sting a target and extract their DNA." - helptext = "Will give you the DNA of your target, allowing you to transform into them." - sting_icon = "sting_extract" - chemical_cost = 25 - genomecost = 1 - ranged = 0 - -/obj/effect/proc_holder/changeling/sting/extract_dna/can_sting(mob/user, mob/living/carbon/target) - if(..()) - return user.mind.changeling.can_absorb_dna(user, target) - -/obj/effect/proc_holder/changeling/sting/extract_dna/sting_action(mob/user, mob/living/carbon/human/target) - if(sting_fail(user,target)) - return 0 - var/datum/changeling/changeling = user.mind.changeling - - target.dna.real_name = target.real_name - changeling.absorbed_dna |= target.dna - - if(target.species && !(target.species.name in changeling.absorbed_species)) - changeling.absorbed_species += target.species.name - - for(var/language in target.languages) - if(!(language in user.mind.changeling.absorbed_languages)) - changeling.absorbed_languages += language - - user.changeling_update_languages(changeling.absorbed_languages) - feedback_add_details("changeling_powers","ED") - return 1 - -obj/effect/proc_holder/changeling/sting/silence - name = "Silence Sting" - desc = "We silently sting a human, completely deafening and silencing them for a short time." - helptext = "Does not provide a warning to the victim that they have been stung, until they try to speak and cannot." - sting_icon = "sting_mute" - chemical_cost = 20 - genomecost = 2 - -/obj/effect/proc_holder/changeling/sting/silence/sting_action(mob/user, mob/living/carbon/target) - if(sting_fail(user,target)) - return 0 - to_chat(target, "Your ears pop and begin ringing loudly!") - target.sdisabilities |= DEAF - spawn(300) target.sdisabilities &= ~DEAF - target.silent += 30 - feedback_add_details("changeling_powers","MS") - return 1 - -obj/effect/proc_holder/changeling/sting/blind - name = "Blind Sting" - helptext = "Temporarily blinds the target." - - desc = "This sting completely blinds a target for a short time. The target does not notice they have been stung." - sting_icon = "sting_blind" - chemical_cost = 25 - genomecost = 2 - -/obj/effect/proc_holder/changeling/sting/blind/sting_action(mob/user, mob/target) - if(sting_fail(user,target)) - return 0 - to_chat(target, "Your eyes burn horrifically!") - target.disabilities |= NEARSIGHTED - spawn(300) target.disabilities &= ~NEARSIGHTED - target.eye_blind = 20 - target.eye_blurry = 40 - feedback_add_details("changeling_powers","BS") - return 1 - -/obj/effect/proc_holder/changeling/sting/paralysis - name = "Paralysis Sting" - helptext = "Temporarily paralyse the target." - desc = "We silently sting a human, paralyzing them for a short time." - sting_icon = "sting_paralyse" - chemical_cost = 40 - genomecost = 8 - -/obj/effect/proc_holder/changeling/sting/paralysis/sting_action(mob/user, mob/living/carbon/target) - if(sting_fail(user,target)) - return 0 - to_chat(target, "Your muscles begin to painfully tighten.") - target.Weaken(20) - feedback_add_details("changeling_powers","PS") - return 1 - -obj/effect/proc_holder/changeling/sting/unfat - name = "Fat Sting" - desc = "We silently sting a human, forcing them to rapidly metabolize their fat." - helptext = "" - sting_icon = "sting_fat" - chemical_cost = 5 - genomecost = 1 - -/obj/effect/proc_holder/changeling/sting/unfat/sting_action(mob/user, mob/living/carbon/target) - if(sting_fail(user,target)) - return 0 - if(FAT in target.mutations) - target.overeatduration = 0 - target.nutrition -= 100 - to_chat(target, "You feel a small prick as stomach churns violently and you become to feel skinnier.") - else - target.overeatduration = 600 - target.nutrition += 100 - to_chat(target, "You feel a small prick as stomach churns violently and you become to feel blubbery.") - feedback_add_details("changeling_powers","US") - return 1 +/obj/effect/proc_holder/changeling/sting + name = "Tiny Prick" + desc = "Stabby stabby." + var/sting_icon = null + var/ranged = 1 + +/obj/effect/proc_holder/changeling/sting/Click() + var/mob/user = usr + if(!user || !user.mind || !user.mind.changeling) + return + if(!(user.mind.changeling.chosen_sting)) + set_sting(user) + else + unset_sting(user) + return + +/obj/effect/proc_holder/changeling/sting/proc/set_sting(mob/user) + to_chat(user, "We prepare our sting, use alt+click or middle mouse button on target to sting them.") + user.mind.changeling.chosen_sting = src + user.hud_used.lingstingdisplay.icon_state = sting_icon + user.hud_used.lingstingdisplay.invisibility = 0 + +/obj/effect/proc_holder/changeling/sting/proc/unset_sting(mob/user) + to_chat(user, "We retract our sting, we can't sting anyone for now.") + user.mind.changeling.chosen_sting = null + user.hud_used.lingstingdisplay.icon_state = null + user.hud_used.lingstingdisplay.invisibility = 101 + +/mob/living/carbon/proc/unset_sting() + if(mind && mind.changeling && mind.changeling.chosen_sting) + src.mind.changeling.chosen_sting.unset_sting(src) + +/obj/effect/proc_holder/changeling/sting/can_sting(mob/user, mob/target) + + + if(!..()) + return + if(!user.mind.changeling.chosen_sting) + to_chat(user, "We haven't prepared our sting yet!") + if(!iscarbon(target)) + return + if(!isturf(user.loc)) + return + if(!AStar(user, target.loc, /turf/proc/Distance, user.mind.changeling.sting_range, simulated_only = FALSE)) + return //hope this ancient magic still works + if(target.mind && target.mind.changeling) + sting_feedback(user,target) + take_chemical_cost(user.mind.changeling) + return + return 1 + +/obj/effect/proc_holder/changeling/sting/sting_feedback(mob/user, mob/target) + if(!target) + return + if((get_dist(user, target) <= 1)) + to_chat(user, "We stealthily sting [target.name].") + else + to_chat(user, "We stealthily shoot [target.name] with sting.") + if(target.mind && target.mind.changeling) + to_chat(target, "You feel a tiny prick.") + // add_logs(user, target, "unsuccessfully stung") + msg_admin_attack("[key_name(user)] used [src] on [key_name(target)] (JMP)") + return 1 + +/obj/effect/proc_holder/changeling/sting/proc/sting_fail(mob/user, mob/target) + if(!target) + return 1 + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.wear_suit) + var/obj/item/clothing/I = H.wear_suit + if(I.flags & THICKMATERIAL) + to_chat(user, "We broke our sting about our's armor!") + unset_sting(user) + user.mind.changeling.chem_charges -= rand(5,10) + H.drip(10) + return 1 + if(ishuman(target)) + var/mob/living/carbon/human/H = target + var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_CHEST] + var/result = H.check_thickmaterial(BP) || H.isSynthetic(BP_CHEST) + if(result) + if(result == NOLIMB) + to_chat(user, "We missed! [target.name] has no [BP.name]!") + else + to_chat(user, "We broke our sting about [target.name]'s [BP.name]!") + to_chat(target, "You feel a tiny push in your [BP.name]!") + if(ishuman(user)) + var/mob/living/carbon/human/HU = user + HU.drip(10) + unset_sting(user) + user.mind.changeling.chem_charges -= rand(5,10) + + return 1 + else + return 0 + +obj/effect/proc_holder/changeling/sting/cryo + name = "Cryogenic Sting" + desc = "We silently sting a human with a cocktail of chemicals that freeze them." + helptext = "Does not provide a warning to the victim, though they will likely realize they are suddenly freezing." + sting_icon = "sting_cryo" + chemical_cost = 15 + genomecost = 1 + +/obj/effect/proc_holder/changeling/sting/cryo/sting_action(mob/user, mob/target) + if(sting_fail(user,target)) + return 0 + if(target.reagents) + target.reagents.add_reagent("frostoil", 30) + target.reagents.add_reagent("ice", 30) + feedback_add_details("changeling_powers","CS") + return 1 + +obj/effect/proc_holder/changeling/sting/LSD + name = "Hallucination Sting" + desc = "Causes terror in the target." + helptext = "We evolve the ability to sting a target with a powerful hallucinogenic chemical. The target does not notice they have been stung. The effect occurs after 30 to 60 seconds." + sting_icon = "sting_lsd" + chemical_cost = 15 + genomecost = 2 + +/obj/effect/proc_holder/changeling/sting/LSD/sting_action(mob/user, mob/living/carbon/target) + if(sting_fail(user,target)) + return 0 + spawn(rand(300,600)) + if(target) + target.hallucination = max(400, target.hallucination) + feedback_add_details("changeling_powers","HS") + return 1 + +/obj/effect/proc_holder/changeling/sting/transformation + name = "Transformation Sting" + desc = "We silently sting a human, injecting a retrovirus that forces them to transform." + helptext = "Does not provide a warning to others. The victim will transform much like a changeling would." + sting_icon = "sting_transform" + chemical_cost = 40 + genomecost = 3 + var/datum/dna/selected_dna = null + +/obj/effect/proc_holder/changeling/sting/transformation/Click() + var/mob/user = usr + var/datum/changeling/changeling = user.mind.changeling + 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 + + selected_dna = changeling.GetDNA(S) + if(!selected_dna) + return + ..() + +/obj/effect/proc_holder/changeling/sting/transformation/can_sting(mob/user, mob/target) + if(!..()) + return + if((HUSK in target.mutations) || (NOCLONE in target.mutations)) + to_chat(user, "Our sting appears ineffective against its DNA.") + return 0 + return 1 + +/obj/effect/proc_holder/changeling/sting/transformation/sting_action(mob/user, mob/target) + if(sting_fail(user,target)) + return 0 + if(ismonkey(target)) + to_chat(user, "We stealthily sting [target.name].") + target.visible_message("[target] transforms!") + target.dna = selected_dna.Clone() + target.real_name = selected_dna.real_name + domutcheck(target, null) + target.UpdateAppearance() + feedback_add_details("changeling_powers","TS") + return 1 + +obj/effect/proc_holder/changeling/sting/extract_dna + name = "Extract DNA Sting" + desc = "We stealthily sting a target and extract their DNA." + helptext = "Will give you the DNA of your target, allowing you to transform into them." + sting_icon = "sting_extract" + chemical_cost = 25 + genomecost = 1 + ranged = 0 + +/obj/effect/proc_holder/changeling/sting/extract_dna/can_sting(mob/user, mob/living/carbon/target) + if(..()) + return user.mind.changeling.can_absorb_dna(user, target) + +/obj/effect/proc_holder/changeling/sting/extract_dna/sting_action(mob/user, mob/living/carbon/human/target) + if(sting_fail(user,target)) + return 0 + var/datum/changeling/changeling = user.mind.changeling + + target.dna.real_name = target.real_name + changeling.absorbed_dna |= target.dna + + if(target.species && !(target.species.name in changeling.absorbed_species)) + changeling.absorbed_species += target.species.name + + for(var/language in target.languages) + if(!(language in user.mind.changeling.absorbed_languages)) + changeling.absorbed_languages += language + + user.changeling_update_languages(changeling.absorbed_languages) + feedback_add_details("changeling_powers","ED") + return 1 + +obj/effect/proc_holder/changeling/sting/silence + name = "Silence Sting" + desc = "We silently sting a human, completely deafening and silencing them for a short time." + helptext = "Does not provide a warning to the victim that they have been stung, until they try to speak and cannot." + sting_icon = "sting_mute" + chemical_cost = 20 + genomecost = 2 + +/obj/effect/proc_holder/changeling/sting/silence/sting_action(mob/user, mob/living/carbon/target) + if(sting_fail(user,target)) + return 0 + to_chat(target, "Your ears pop and begin ringing loudly!") + target.sdisabilities |= DEAF + spawn(300) target.sdisabilities &= ~DEAF + target.silent += 30 + feedback_add_details("changeling_powers","MS") + return 1 + +obj/effect/proc_holder/changeling/sting/blind + name = "Blind Sting" + helptext = "Temporarily blinds the target." + + desc = "This sting completely blinds a target for a short time. The target does not notice they have been stung." + sting_icon = "sting_blind" + chemical_cost = 25 + genomecost = 2 + +/obj/effect/proc_holder/changeling/sting/blind/sting_action(mob/user, mob/target) + if(sting_fail(user,target)) + return 0 + to_chat(target, "Your eyes burn horrifically!") + target.disabilities |= NEARSIGHTED + spawn(300) target.disabilities &= ~NEARSIGHTED + target.eye_blind = 20 + target.eye_blurry = 40 + feedback_add_details("changeling_powers","BS") + return 1 + +/obj/effect/proc_holder/changeling/sting/paralysis + name = "Paralysis Sting" + helptext = "Temporarily paralyse the target." + desc = "We silently sting a human, paralyzing them for a short time." + sting_icon = "sting_paralyse" + chemical_cost = 40 + genomecost = 8 + +/obj/effect/proc_holder/changeling/sting/paralysis/sting_action(mob/user, mob/living/carbon/target) + if(sting_fail(user,target)) + return 0 + to_chat(target, "Your muscles begin to painfully tighten.") + target.Weaken(20) + feedback_add_details("changeling_powers","PS") + return 1 + +obj/effect/proc_holder/changeling/sting/unfat + name = "Fat Sting" + desc = "We silently sting a human, forcing them to rapidly metabolize their fat." + helptext = "" + sting_icon = "sting_fat" + chemical_cost = 5 + genomecost = 1 + +/obj/effect/proc_holder/changeling/sting/unfat/sting_action(mob/user, mob/living/carbon/target) + if(sting_fail(user,target)) + return 0 + if(FAT in target.mutations) + target.overeatduration = 0 + target.nutrition -= 100 + to_chat(target, "You feel a small prick as stomach churns violently and you become to feel skinnier.") + else + target.overeatduration = 600 + target.nutrition += 100 + to_chat(target, "You feel a small prick as stomach churns violently and you become to feel blubbery.") + feedback_add_details("changeling_powers","US") + return 1 diff --git a/code/game/gamemodes/changeling/powers/stings_range.dm b/code/game/gamemodes/changeling/powers/stings_range.dm index d16f52316357..e6143ba42aae 100644 --- a/code/game/gamemodes/changeling/powers/stings_range.dm +++ b/code/game/gamemodes/changeling/powers/stings_range.dm @@ -1,12 +1,12 @@ -/obj/effect/proc_holder/changeling/boost_range - name = "Boost Range" - desc = "We evolve the ability to shoot our stingers at humans." - helptext = "Stings abilities can be used against targets 2 squares away." - genomecost = 2 - chemical_cost = -1 - -/obj/effect/proc_holder/changeling/boost_range/on_purchase(mob/user) - ..() - var/datum/changeling/changeling=user.mind.changeling - changeling.sting_range = 2 - return +/obj/effect/proc_holder/changeling/boost_range + name = "Boost Range" + desc = "We evolve the ability to shoot our stingers at humans." + helptext = "Stings abilities can be used against targets 2 squares away." + genomecost = 2 + chemical_cost = -1 + +/obj/effect/proc_holder/changeling/boost_range/on_purchase(mob/user) + ..() + var/datum/changeling/changeling=user.mind.changeling + changeling.sting_range = 2 + return diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index a23e0eff2102..a00fda601c1c 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -1,38 +1,38 @@ -/obj/effect/proc_holder/changeling/transform - name = "Transform" - desc = "We take on the appearance and voice of one we have absorbed." - chemical_cost = 5 - genomecost = 0 - req_dna = 1 - req_human = 1 - genetic_damage = 30 - max_genetic_damage = 30 - -//Change our DNA to that of somebody we've absorbed. -/obj/effect/proc_holder/changeling/transform/sting_action(mob/living/carbon/human/user) - var/datum/changeling/changeling = user.mind.changeling - var/datum/dna/chosen_dna = changeling.select_dna("Select the target DNA: ", "Target DNA") - - if(!chosen_dna) - return - - user.visible_message("[user] transforms!") - user.dna = chosen_dna.Clone() - user.real_name = chosen_dna.real_name - user.flavor_text = "" - user.UpdateAppearance() - domutcheck(user, null) - - feedback_add_details("changeling_powers","TR") - return 1 - -/datum/changeling/proc/select_dna(prompt, title) - var/list/names = list() - for(var/datum/dna/DNA in absorbed_dna) - names += "[DNA.real_name]" - - var/chosen_name = input(prompt, title, null) as null|anything in names - if(!chosen_name) - return - var/datum/dna/chosen_dna = GetDNA(chosen_name) - return chosen_dna +/obj/effect/proc_holder/changeling/transform + name = "Transform" + desc = "We take on the appearance and voice of one we have absorbed." + chemical_cost = 5 + genomecost = 0 + req_dna = 1 + req_human = 1 + genetic_damage = 30 + max_genetic_damage = 30 + +//Change our DNA to that of somebody we've absorbed. +/obj/effect/proc_holder/changeling/transform/sting_action(mob/living/carbon/human/user) + var/datum/changeling/changeling = user.mind.changeling + var/datum/dna/chosen_dna = changeling.select_dna("Select the target DNA: ", "Target DNA") + + if(!chosen_dna) + return + + user.visible_message("[user] transforms!") + user.dna = chosen_dna.Clone() + user.real_name = chosen_dna.real_name + user.flavor_text = "" + user.UpdateAppearance() + domutcheck(user, null) + + feedback_add_details("changeling_powers","TR") + return 1 + +/datum/changeling/proc/select_dna(prompt, title) + var/list/names = list() + for(var/datum/dna/DNA in absorbed_dna) + names += "[DNA.real_name]" + + var/chosen_name = input(prompt, title, null) as null|anything in names + if(!chosen_name) + return + var/datum/dna/chosen_dna = GetDNA(chosen_name) + return chosen_dna diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 12ca576148b7..cbe703a33a73 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -1,343 +1,343 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/datum/game_mode - var/list/datum/mind/cult = list() - -/proc/iscultist(mob/living/M) - 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 FALSE - if(ishuman(mind.current) && (mind.assigned_role in list("Captain", "Chaplain"))) - return FALSE - if(ismindshielded(mind.current)) - return FALSE - return TRUE - - -/datum/game_mode/cult - name = "cult" - config_tag = "cult" - role_type = ROLE_CULTIST - restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Internal Affairs Agent") - protected_jobs = list() - required_players = 5 - required_players_secret = 15 - - required_enemies = 3 - recommended_enemies = 4 - - votable = 0 - - uplink_welcome = "Nar-Sie Uplink Console:" - uplink_uses = 20 - - var/datum/mind/sacrifice_target = null - var/finished = 0 - - var/list/startwords = list("blood","join","self","hell") - - var/list/objectives = list() - var/list/sacrificed = list() - - var/eldergod = 1 //for the summon god objective - var/eldertry = 0 - - var/const/acolytes_needed = 5 //for the survive objective - var/acolytes_survived = 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(!config.objectives_disabled) - if(prob(50)) - objectives += "survive" - objectives += "sacrifice" - else - objectives += "eldergod" - objectives += "sacrifice" - - if(config.protect_roles_from_antagonist) - restricted_jobs += protected_jobs - - for(var/datum/mind/player in antag_candidates) - if(player.assigned_role in restricted_jobs) //Removing heads and such from the list - antag_candidates -= player - - for(var/cultists_number = 1 to recommended_enemies) - if(!antag_candidates.len) - break - var/datum/mind/cultist = pick(antag_candidates) - antag_candidates -= cultist - cult += cultist - - return (cult.len >= required_enemies) - - -/datum/game_mode/cult/post_setup() - modePlayer += cult - if("sacrifice" in objectives) - var/list/possible_targets = get_unconvertables() - listclearnulls(possible_targets) - - if(!possible_targets.len) - for(var/mob/living/carbon/human/player in player_list) - if(player.mind && !(player.mind in cult)) - possible_targets += player.mind - - listclearnulls(possible_targets) - - if(LAZYLEN(possible_targets)) - sacrifice_target = pick(possible_targets) - - for(var/datum/mind/cult_mind in cult) - equip_cultist(cult_mind.current) - to_chat(cult_mind.current, "You are a member of the cult!") - grant_runeword(cult_mind.current) - if(!config.objectives_disabled) - memoize_cult_objectives(cult_mind) - else - to_chat(cult_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - cult_mind.special_role = "Cultist" - update_all_cult_icons() - - return ..() - - -/datum/game_mode/cult/proc/memoize_cult_objectives(datum/mind/cult_mind) - for(var/obj_count = 1,obj_count <= objectives.len,obj_count++) - var/explanation - switch(objectives[obj_count]) - if("survive") - explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station." - if("sacrifice") - if(sacrifice_target) - explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so." - else - explanation = "Free objective." - if("eldergod") - 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(cult_mind.current, "Objective #[obj_count]: [explanation]") - cult_mind.memory += "Objective #[obj_count]: [explanation]
    " - to_chat(cult_mind.current, "The convert rune is join blood self") - cult_mind.memory += "The convert rune is join blood self
    " - - -/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(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) - if (!where) - to_chat(mob, "Unfortunately, you weren't able to get a talisman. This is very bad and you should adminhelp immediately.") - else - var/obj/item/weapon/paper/talisman/T2 = new(mob) - T2.power = new /datum/cult/communicate(T2) - mob.equip_in_one_of_slots(T2, slots) - 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, word) - if (!word) - if(length(startwords) > 0) - word = pick_n_take(startwords) - return ..(cult_mob, word) - - -/datum/game_mode/proc/grant_runeword(mob/living/carbon/human/cult_mob, word) - if(!cultwords["travel"]) - runerandom() - if (!word) - word = pick(cultwords) - 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) - - -/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_mind.current.Paralyse(5) - cult += cult_mind - update_cult_icons_added(cult_mind) - return 1 - - -/datum/game_mode/cult/add_cultist(datum/mind/cult_mind) //INHERIT - if (!..(cult_mind)) - return - if (!config.objectives_disabled) - memoize_cult_objectives(cult_mind) - - -/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = 1) - if(cult_mind in cult) - cult -= cult_mind - cult_mind.current.Paralyse(5) - to_chat(cult_mind.current, "An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and the memories of your time as his servant with it.") - cult_mind.memory = "" - update_cult_icons_removed(cult_mind) - if(show_message) - cult_mind.current.visible_message("[cult_mind.current] looks like they just reverted to their old faith!") - -/datum/game_mode/proc/update_all_cult_icons() - for(var/datum/mind/cultist in cult) - if(cultist.current && cultist.current.client) - for(var/image/I in cultist.current.client.images) - if(I.icon_state == "cult") - cultist.current.client.images -= I - qdel(I) - for(var/datum/mind/cultist in cult) - if(cultist.current && cultist.current.client) - for(var/datum/mind/cultist_1 in cult) - if(cultist_1.current) - var/I = image('icons/mob/mob.dmi', loc = cultist_1.current, icon_state = "cult") - cultist.current.client.images += I - - -/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind) - if(!cult_mind.current) - return 0 - for(var/datum/mind/cultist in cult) - if(cultist.current && cultist.current.client) - var/I = image('icons/mob/mob.dmi', loc = cult_mind.current, icon_state = "cult") - cultist.current.client.images += I - if(cult_mind.current.client) - var/image/J = image('icons/mob/mob.dmi', loc = cultist.current, icon_state = "cult") - cult_mind.current.client.images += J - -/datum/game_mode/proc/update_cult_icons_removed(datum/mind/cult_mind) - if(!cult_mind.current) - return 0 - for(var/datum/mind/cultist in cult) - if(cultist.current && cultist.current.client) - for(var/image/I in cultist.current.client.images) - if(I.icon_state == "cult" && I.loc == cult_mind.current) - cultist.current.client.images -= I - qdel(I) - 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 - qdel(I) - - -/datum/game_mode/cult/proc/get_unconvertables() - var/list/ucs = list() - for(var/mob/living/carbon/human/player in human_list) - if(!is_convertable_to_cult(player.mind)) - ucs += player.mind - return ucs - - -/datum/game_mode/cult/proc/check_cult_victory() - var/cult_fail = 0 - if(objectives.Find("survive")) - cult_fail += check_survive() //the proc returns 1 if there are not enough cultists on the shuttle, 0 otherwise - if(objectives.Find("eldergod")) - cult_fail += eldergod //1 by default, 0 if the elder god has been summoned at least once - if(objectives.Find("sacrifice")) - if(sacrifice_target && !sacrificed.Find(sacrifice_target)) //if the target has been sacrificed, ignore this step. otherwise, add 1 to cult_fail - cult_fail++ - - return cult_fail //if any objectives aren't met, failure - - -/datum/game_mode/cult/proc/check_survive() - acolytes_survived = 0 - for(var/datum/mind/cult_mind in cult) - if (cult_mind.current && cult_mind.current.stat!=2) - var/area/A = get_area(cult_mind.current ) - if ( is_type_in_list(A, centcom_areas)) - acolytes_survived++ - if(acolytes_survived>=acolytes_needed) - return 0 - else - return 1 - - -/datum/game_mode/cult/declare_completion() - if(config.objectives_disabled) - return 1 - completion_text += "Cult mode resume:
    " - if(!check_cult_victory()) - feedback_set_details("round_end_result","win - cult win") - feedback_set("round_end_result",acolytes_survived) - completion_text += "The cult wins! It has succeeded in serving its dark masters!" - score["roleswon"]++ - else - feedback_set_details("round_end_result","loss - staff stopped the cult") - feedback_set("round_end_result",acolytes_survived) - completion_text += "The staff managed to stop the cult!
    " - - var/text = "Cultists escaped: [acolytes_survived]" - if(!config.objectives_disabled) - if(objectives.len) - text += "
    The cultists' objectives were:" - for(var/obj_count in 1 to objectives.len) - var/explanation - switch(objectives[obj_count]) - if("survive") - if(!check_survive()) - explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Success!" - feedback_add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]") - else - explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Fail." - feedback_add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]") - if("sacrifice") - 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") - else - explanation = "Free objective. Success!" - feedback_add_details("cult_objective","cult_free_objective|SUCCESS") - if("eldergod") - if(!eldergod) - 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") - 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)) ) - text += printlogo("cult", "cultists") - for(var/datum/mind/cultist in cult) - text += printplayerwithicon(cultist) - text += "

    " - return text +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/datum/game_mode + var/list/datum/mind/cult = list() + +/proc/iscultist(mob/living/M) + 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 FALSE + if(ishuman(mind.current) && (mind.assigned_role in list("Captain", "Chaplain"))) + return FALSE + if(ismindshielded(mind.current)) + return FALSE + return TRUE + + +/datum/game_mode/cult + name = "cult" + config_tag = "cult" + role_type = ROLE_CULTIST + restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Internal Affairs Agent") + protected_jobs = list() + required_players = 5 + required_players_secret = 15 + + required_enemies = 3 + recommended_enemies = 4 + + votable = 0 + + uplink_welcome = "Nar-Sie Uplink Console:" + uplink_uses = 20 + + var/datum/mind/sacrifice_target = null + var/finished = 0 + + var/list/startwords = list("blood","join","self","hell") + + var/list/objectives = list() + var/list/sacrificed = list() + + var/eldergod = 1 //for the summon god objective + var/eldertry = 0 + + var/const/acolytes_needed = 5 //for the survive objective + var/acolytes_survived = 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(!config.objectives_disabled) + if(prob(50)) + objectives += "survive" + objectives += "sacrifice" + else + objectives += "eldergod" + objectives += "sacrifice" + + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + + for(var/datum/mind/player in antag_candidates) + if(player.assigned_role in restricted_jobs) //Removing heads and such from the list + antag_candidates -= player + + for(var/cultists_number = 1 to recommended_enemies) + if(!antag_candidates.len) + break + var/datum/mind/cultist = pick(antag_candidates) + antag_candidates -= cultist + cult += cultist + + return (cult.len >= required_enemies) + + +/datum/game_mode/cult/post_setup() + modePlayer += cult + if("sacrifice" in objectives) + var/list/possible_targets = get_unconvertables() + listclearnulls(possible_targets) + + if(!possible_targets.len) + for(var/mob/living/carbon/human/player in player_list) + if(player.mind && !(player.mind in cult)) + possible_targets += player.mind + + listclearnulls(possible_targets) + + if(LAZYLEN(possible_targets)) + sacrifice_target = pick(possible_targets) + + for(var/datum/mind/cult_mind in cult) + equip_cultist(cult_mind.current) + to_chat(cult_mind.current, "You are a member of the cult!") + grant_runeword(cult_mind.current) + if(!config.objectives_disabled) + memoize_cult_objectives(cult_mind) + else + to_chat(cult_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + cult_mind.special_role = "Cultist" + update_all_cult_icons() + + return ..() + + +/datum/game_mode/cult/proc/memoize_cult_objectives(datum/mind/cult_mind) + for(var/obj_count = 1,obj_count <= objectives.len,obj_count++) + var/explanation + switch(objectives[obj_count]) + if("survive") + explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station." + if("sacrifice") + if(sacrifice_target) + explanation = "Sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so." + else + explanation = "Free objective." + if("eldergod") + 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(cult_mind.current, "Objective #[obj_count]: [explanation]") + cult_mind.memory += "Objective #[obj_count]: [explanation]
    " + to_chat(cult_mind.current, "The convert rune is join blood self") + cult_mind.memory += "The convert rune is join blood self
    " + + +/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(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) + if (!where) + to_chat(mob, "Unfortunately, you weren't able to get a talisman. This is very bad and you should adminhelp immediately.") + else + var/obj/item/weapon/paper/talisman/T2 = new(mob) + T2.power = new /datum/cult/communicate(T2) + mob.equip_in_one_of_slots(T2, slots) + 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, word) + if (!word) + if(length(startwords) > 0) + word = pick_n_take(startwords) + return ..(cult_mob, word) + + +/datum/game_mode/proc/grant_runeword(mob/living/carbon/human/cult_mob, word) + if(!cultwords["travel"]) + runerandom() + if (!word) + word = pick(cultwords) + 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) + + +/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_mind.current.Paralyse(5) + cult += cult_mind + update_cult_icons_added(cult_mind) + return 1 + + +/datum/game_mode/cult/add_cultist(datum/mind/cult_mind) //INHERIT + if (!..(cult_mind)) + return + if (!config.objectives_disabled) + memoize_cult_objectives(cult_mind) + + +/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = 1) + if(cult_mind in cult) + cult -= cult_mind + cult_mind.current.Paralyse(5) + to_chat(cult_mind.current, "An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and the memories of your time as his servant with it.") + cult_mind.memory = "" + update_cult_icons_removed(cult_mind) + if(show_message) + cult_mind.current.visible_message("[cult_mind.current] looks like they just reverted to their old faith!") + +/datum/game_mode/proc/update_all_cult_icons() + for(var/datum/mind/cultist in cult) + if(cultist.current && cultist.current.client) + for(var/image/I in cultist.current.client.images) + if(I.icon_state == "cult") + cultist.current.client.images -= I + qdel(I) + for(var/datum/mind/cultist in cult) + if(cultist.current && cultist.current.client) + for(var/datum/mind/cultist_1 in cult) + if(cultist_1.current) + var/I = image('icons/mob/mob.dmi', loc = cultist_1.current, icon_state = "cult") + cultist.current.client.images += I + + +/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind) + if(!cult_mind.current) + return 0 + for(var/datum/mind/cultist in cult) + if(cultist.current && cultist.current.client) + var/I = image('icons/mob/mob.dmi', loc = cult_mind.current, icon_state = "cult") + cultist.current.client.images += I + if(cult_mind.current.client) + var/image/J = image('icons/mob/mob.dmi', loc = cultist.current, icon_state = "cult") + cult_mind.current.client.images += J + +/datum/game_mode/proc/update_cult_icons_removed(datum/mind/cult_mind) + if(!cult_mind.current) + return 0 + for(var/datum/mind/cultist in cult) + if(cultist.current && cultist.current.client) + for(var/image/I in cultist.current.client.images) + if(I.icon_state == "cult" && I.loc == cult_mind.current) + cultist.current.client.images -= I + qdel(I) + 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 + qdel(I) + + +/datum/game_mode/cult/proc/get_unconvertables() + var/list/ucs = list() + for(var/mob/living/carbon/human/player in human_list) + if(!is_convertable_to_cult(player.mind)) + ucs += player.mind + return ucs + + +/datum/game_mode/cult/proc/check_cult_victory() + var/cult_fail = 0 + if(objectives.Find("survive")) + cult_fail += check_survive() //the proc returns 1 if there are not enough cultists on the shuttle, 0 otherwise + if(objectives.Find("eldergod")) + cult_fail += eldergod //1 by default, 0 if the elder god has been summoned at least once + if(objectives.Find("sacrifice")) + if(sacrifice_target && !sacrificed.Find(sacrifice_target)) //if the target has been sacrificed, ignore this step. otherwise, add 1 to cult_fail + cult_fail++ + + return cult_fail //if any objectives aren't met, failure + + +/datum/game_mode/cult/proc/check_survive() + acolytes_survived = 0 + for(var/datum/mind/cult_mind in cult) + if (cult_mind.current && cult_mind.current.stat!=2) + var/area/A = get_area(cult_mind.current ) + if ( is_type_in_list(A, centcom_areas)) + acolytes_survived++ + if(acolytes_survived>=acolytes_needed) + return 0 + else + return 1 + + +/datum/game_mode/cult/declare_completion() + if(config.objectives_disabled) + return 1 + completion_text += "Cult mode resume:
    " + if(!check_cult_victory()) + feedback_set_details("round_end_result","win - cult win") + feedback_set("round_end_result",acolytes_survived) + completion_text += "The cult wins! It has succeeded in serving its dark masters!" + score["roleswon"]++ + else + feedback_set_details("round_end_result","loss - staff stopped the cult") + feedback_set("round_end_result",acolytes_survived) + completion_text += "The staff managed to stop the cult!
    " + + var/text = "Cultists escaped: [acolytes_survived]" + if(!config.objectives_disabled) + if(objectives.len) + text += "
    The cultists' objectives were:" + for(var/obj_count in 1 to objectives.len) + var/explanation + switch(objectives[obj_count]) + if("survive") + if(!check_survive()) + explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Success!" + feedback_add_details("cult_objective","cult_survive|SUCCESS|[acolytes_needed]") + else + explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. Fail." + feedback_add_details("cult_objective","cult_survive|FAIL|[acolytes_needed]") + if("sacrifice") + 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") + else + explanation = "Free objective. Success!" + feedback_add_details("cult_objective","cult_free_objective|SUCCESS") + if("eldergod") + if(!eldergod) + 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") + 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)) ) + text += printlogo("cult", "cultists") + for(var/datum/mind/cultist in cult) + text += printplayerwithicon(cultist) + text += "

    " + return text diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 52ef325405ff..5bcc8686d97f 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -1,101 +1,101 @@ -/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" - w_class = 4 - force = 30 - throwforce = 10 - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - - -/obj/item/weapon/melee/cultblade/attack(mob/living/target, mob/living/carbon/human/user) - if(iscultist(user)) - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - else - user.Paralyse(5) - to_chat(user, "\red An unexplicable force powerfully repels the sword from [target]!") - var/obj/item/organ/external/BP = user.bodyparts_by_name[user.hand ? BP_L_ARM : BP_R_ARM] - BP.take_damage(rand(force / 2, force)) //random amount of damage between half of the blade's force and the full force of the blade. - -/obj/item/weapon/melee/cultblade/pickup(mob/living/user) - if(!iscultist(user)) - to_chat(user, "\red 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.make_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 = HEADCOVERSEYES - body_parts_covered = HEAD|EYES - armor = list(melee = 30, bullet = 10, laser = 5,energy = 5, bomb = 0, bio = 0, rad = 0) - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0 - - -/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" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade) - armor = list(melee = 50, bullet = 15, laser = 15,energy = 20, bomb = 25, bio = 10, rad = 0) - flags_inv = HIDEJUMPSUIT - siemens_coefficient = 0 - -/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 - flags = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR - armor = list(melee = 30, bullet = 15, laser = 15,energy = 20, bomb = 0, bio = 0, rad = 0) - body_parts_covered = HEAD|FACE|EYES - 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" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade) - armor = list(melee = 50, bullet = 15, laser = 25,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 = 25, laser = 25,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/book/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit) - slowdown = 1 - armor = list(melee = 60, bullet = 25, laser = 25,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS +/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" + w_class = 4 + force = 30 + throwforce = 10 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + + +/obj/item/weapon/melee/cultblade/attack(mob/living/target, mob/living/carbon/human/user) + if(iscultist(user)) + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return ..() + else + user.Paralyse(5) + to_chat(user, "\red An unexplicable force powerfully repels the sword from [target]!") + var/obj/item/organ/external/BP = user.bodyparts_by_name[user.hand ? BP_L_ARM : BP_R_ARM] + BP.take_damage(rand(force / 2, force)) //random amount of damage between half of the blade's force and the full force of the blade. + +/obj/item/weapon/melee/cultblade/pickup(mob/living/user) + if(!iscultist(user)) + to_chat(user, "\red 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.make_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 = HEADCOVERSEYES + body_parts_covered = HEAD|EYES + armor = list(melee = 30, bullet = 10, laser = 5,energy = 5, bomb = 0, bio = 0, rad = 0) + cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0 + + +/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" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade) + armor = list(melee = 50, bullet = 15, laser = 15,energy = 20, bomb = 25, bio = 10, rad = 0) + flags_inv = HIDEJUMPSUIT + siemens_coefficient = 0 + +/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 + flags = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR + armor = list(melee = 30, bullet = 15, laser = 15,energy = 20, bomb = 0, bio = 0, rad = 0) + body_parts_covered = HEAD|FACE|EYES + 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" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade) + armor = list(melee = 50, bullet = 15, laser = 25,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 = 25, laser = 25,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/book/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit) + slowdown = 1 + armor = list(melee = 60, bullet = 25, laser = 25,energy = 15, bomb = 30, bio = 30, rad = 30) + siemens_coefficient = 0 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 32f2225567fe..e4bad3850293 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -1,431 +1,431 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 -#define CULT_RUNES_LIMIT 26 - -var/list/cultwords = list() // associated english word = runeword -var/list/cultwords_reverse = list() // associated runeword = english word -var/list/cult_datums = list() - -/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 cultwords) - to_chat(usr, "[word] is [cultwords[word]]") - -/proc/runerandom() //randomizes word meaning - var/list/runewords = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri") ///"orkan" and "allaq" removed. - var/list/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide") - for(var/word in engwords) - cultwords[word] = pick_n_take(runewords) - cultwords_reverse[cultwords[word]] = word - - for(var/type in subtypesof(/datum/cult)) - var/datum/cult/dat = type - var/word1 = initial(dat.word1) - var/word2 = initial(dat.word2) - var/word3 = initial(dat.word3) - cult_datums[word1 + word2 + word3] = type - -/obj/effect/rune - name = "blood" - desc = "" - anchored = 1 - icon = 'icons/obj/rune.dmi' - icon_state = "1" - unacidable = 1 - layer = TURF_LAYER - var/datum/cult/power - var/image/blood_overlay -// 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/atom_init() - . = ..() - cult_runes += src - blood_overlay = image('icons/effects/blood.dmi', src, "mfloor[rand(1, 7)]", 2) - blood_overlay.override = 1 - blood_overlay.color = "#a10808" - for(var/mob/living/silicon/S in player_list) // we hold mobs in this lists only with clients - S.client.images += blood_overlay - -/obj/effect/rune/update_icon() - color = "#a10808" - -/obj/effect/rune/Destroy() - QDEL_NULL(power) - QDEL_NULL(blood_overlay) - cult_runes -= src - return ..() - -/obj/effect/rune/examine(mob/user) - if(iscultist(user) || isobserver(user)) - to_chat(user, "[bicon(src)] That's cult rune!") - to_chat(user, "A spell circle drawn in blood. It reads: [desc].") - return - to_chat(user, "[bicon(src)] That's some [name]") - if(issilicon(user)) - to_chat(user, "It's thick and gooey. Perhaps it's the chef's cooking?") // blood desc - else - to_chat(user, "A strange collection of symbols drawn in blood.") - -/obj/effect/rune/attackby(I, mob/living/user) - if(istype(I, /obj/item/weapon/book/tome) && iscultist(user)) - to_chat(user, "You retrace your steps, carefully undoing the lines of the rune.") - qdel(src) - else if(istype(I, /obj/item/weapon/nullrod) && user.mind.assigned_role == "Chaplain") - to_chat(user, "You disrupt the vile magic with the deadening field of the null rod!") - qdel(src) - -/obj/effect/rune/attack_ghost(mob/dead/observer/user) - if(!istype(power, /datum/cult/teleport) && !istype(power, /datum/cult/item_port)) - return ..() - var/list/allrunes = list() - for(var/obj/effect/rune/R in cult_runes) - if(!istype(R.power, power.type) || R == src) - continue - if(R.power.word3 == power.word3 && R.loc.z != ZLEVEL_CENTCOMM) - allrunes += R - if(length(allrunes) > 0) - user.forceMove(get_turf(pick(allrunes))) - -/obj/effect/rune/attack_hand(mob/living/user) - user.SetNextMove(CLICK_CD_INTERACT) - 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)) - to_chat(user, "You are unable to speak the words of the rune.") - return - if(!power || prob(user.getBrainLoss())) - user.say(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.",\ - "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) - return - power.action(user) - -/obj/item/weapon/book/tome - name = "book" - icon = 'icons/obj/library.dmi' - icon_state ="book" - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - unique = 1 - var/unlocked = FALSE - 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
    - Disable technology: Destroy See Technology
    - Drain blood: Travel Blood Self
    - Raise dead: Blood Join Hell
    - Hide runes: Hide See Blood
    - Reveal hidden runes: Blood See Hide
    - Leave your body: Hell travel self
    - Ghost Manifest: Blood See Travel
    - Imbue a talisman: Hell Technology Join
    - Sacrifice: Hell Blood Join
    - Create a wall: Destroy Travel Self
    - Summon cultist: Join Other Self
    - Free a cultist: Travel technology other
    - Deafen: Hide Other See
    - Blind: Destroy See Other
    - Blood Boil: Destroy See Blood
    - Communicate: Self Other Technology
    - Stun: Join Hide Technology
    - Summon Cultist Armor: Hell Destroy Other
    - See Invisible: See Hell Join
    - Construct: Technology Blood Travel
    -

    -

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

    Disable Technology

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

    Leave your body

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

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

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

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

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

    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.
    - - - "} - -/obj/item/weapon/book/tome/atom_init() - . = ..() - if (icon_state == "book") - icon_state = "book[pick(1,2,3,4,5,6)]" - -/obj/item/weapon/book/tome/Topic(href, href_list[]) - if(loc != usr) - usr << browse(null, "window=notes") - return - 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 cultwords - 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("[entity_ja(notedat)]", "window=notes") - -/obj/item/weapon/book/tome/attack(mob/living/M, mob/living/user) - - 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(istype(M, /mob/dead)) - M.invisibility = 0 - user.visible_message( \ - " [user] drags the ghost to our plan of reality!", \ - "You drag the ghost to our plan of reality!") - return - if(!istype(M)) - return - if(!iscultist(user)) - return ..() - if(iscultist(M)) - return - M.adjustBruteLoss(rand(5, 20)) //really lucky - 5 hits for a crit - M.visible_message("[user] beats [M] with the arcane tome!") - to_chat(M, "") - -/obj/item/weapon/book/tome/afterattack(atom/A, mob/user, proximity) - if(!proximity) - return - if(iscultist(user) && A.reagents && A.reagents.has_reagent("water")) - var/water2convert = A.reagents.get_reagent_amount("water") - A.reagents.del_reagent("water") - to_chat(user, "You curse [A].") - A.reagents.add_reagent("unholywater",water2convert) - -/obj/item/weapon/book/tome/attack_self(mob/living/carbon/human/user) - if(!istype(user) || !user.canmove || user.stat || user.incapacitated()) - return - - if(!cultwords["travel"]) - runerandom() - if(!iscultist(user)) - to_chat(user, "This book is completely blank!") - return - if (!isturf(user.loc)) - to_chat(user, "You do not have enough space to write a proper rune.") - return - - if (length(cult_runes) >= CULT_RUNES_LIMIT + length(ticker.mode.cult)) //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 - 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("[entity_ja(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
    - "} - user << browse("[entity_ja(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]] = w - if(user) - w1 = input("Write your first rune:", "Rune Scribing") in english - if(!w1) - return - if(w1 in cultwords) - w1 = english[w1] - - if(user) - w2 = input("Write your second rune:", "Rune Scribing") in english - if(!w2) - return - if(w2 in cultwords) - w2 = english[w2] - if(user) - w3 = input("Write your third rune:", "Rune Scribing") in english - if(!w3) - return - if(w3 in cultwords) - w3 = english[w3] - - - if(user.get_active_hand() != src || user.is_busy()) - return - user.visible_message(" [user] slices open a finger and begins to chant and paint symbols on the floor.",\ - " You hear chanting.") - 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((unlocked || do_after(user, 50, target = user)) && user.get_active_hand() == src) - var/obj/effect/rune/R = new /obj/effect/rune(user.loc) - if(w1 == cultwords["travel"]) - if(w2 == cultwords["self"]) - R.power = new /datum/cult/teleport(R, cultwords_reverse[w3]) - else if(w2 == cultwords["other"]) - R.power = new /datum/cult/item_port(R, cultwords_reverse[w3]) - to_chat(user, "You finish drawing the arcane markings of the Geometer.") - if(!R.power) - var/type = cult_datums[cultwords_reverse[w1] + cultwords_reverse[w2] + cultwords_reverse[w3]] - if(ispath(type)) - R.power = new type(R) - R.desc = "[w1], [w2], [w3]" // for examine - R.icon = get_uristrune_cult((R.power ? TRUE : FALSE), w1, w2, w3) - R.blood_DNA = list() - R.blood_DNA[user.dna.unique_enzymes] = user.dna.b_type - - -/obj/item/weapon/book/tome/attackby(obj/item/weapon/book/tome/T, mob/living/user) - if(istype(T, /obj/item/weapon/book/tome)) // sanity check to prevent a runtime error - switch(alert("Copy the runes from your tome?",,"Copy", "Cancel")) - if("Cancel") - return - for(var/w in words) - words[w] = T.words[w] - to_chat(user, "You copy the translation notes from your tome.") - -/obj/item/weapon/book/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/book/tome/imbued/atom_init() - . = ..() - unlocked = TRUE - if(!cultwords["travel"]) - runerandom() - for(var/word in cultwords) - words[cultwords[word]] = word - -/obj/item/weapon/book/tome/old - name = "arcane tome" - desc = "An old, dusty tome with frayed edges and a sinister looking cover." - icon = 'icons/obj/weapons.dmi' - icon_state ="tome" +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 +#define CULT_RUNES_LIMIT 26 + +var/list/cultwords = list() // associated english word = runeword +var/list/cultwords_reverse = list() // associated runeword = english word +var/list/cult_datums = list() + +/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 cultwords) + to_chat(usr, "[word] is [cultwords[word]]") + +/proc/runerandom() //randomizes word meaning + var/list/runewords = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri") ///"orkan" and "allaq" removed. + var/list/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide") + for(var/word in engwords) + cultwords[word] = pick_n_take(runewords) + cultwords_reverse[cultwords[word]] = word + + for(var/type in subtypesof(/datum/cult)) + var/datum/cult/dat = type + var/word1 = initial(dat.word1) + var/word2 = initial(dat.word2) + var/word3 = initial(dat.word3) + cult_datums[word1 + word2 + word3] = type + +/obj/effect/rune + name = "blood" + desc = "" + anchored = 1 + icon = 'icons/obj/rune.dmi' + icon_state = "1" + unacidable = 1 + layer = TURF_LAYER + var/datum/cult/power + var/image/blood_overlay +// 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/atom_init() + . = ..() + cult_runes += src + blood_overlay = image('icons/effects/blood.dmi', src, "mfloor[rand(1, 7)]", 2) + blood_overlay.override = 1 + blood_overlay.color = "#a10808" + for(var/mob/living/silicon/S in player_list) // we hold mobs in this lists only with clients + S.client.images += blood_overlay + +/obj/effect/rune/update_icon() + color = "#a10808" + +/obj/effect/rune/Destroy() + QDEL_NULL(power) + QDEL_NULL(blood_overlay) + cult_runes -= src + return ..() + +/obj/effect/rune/examine(mob/user) + if(iscultist(user) || isobserver(user)) + to_chat(user, "[bicon(src)] That's cult rune!") + to_chat(user, "A spell circle drawn in blood. It reads: [desc].") + return + to_chat(user, "[bicon(src)] That's some [name]") + if(issilicon(user)) + to_chat(user, "It's thick and gooey. Perhaps it's the chef's cooking?") // blood desc + else + to_chat(user, "A strange collection of symbols drawn in blood.") + +/obj/effect/rune/attackby(I, mob/living/user) + if(istype(I, /obj/item/weapon/book/tome) && iscultist(user)) + to_chat(user, "You retrace your steps, carefully undoing the lines of the rune.") + qdel(src) + else if(istype(I, /obj/item/weapon/nullrod) && user.mind.assigned_role == "Chaplain") + to_chat(user, "You disrupt the vile magic with the deadening field of the null rod!") + qdel(src) + +/obj/effect/rune/attack_ghost(mob/dead/observer/user) + if(!istype(power, /datum/cult/teleport) && !istype(power, /datum/cult/item_port)) + return ..() + var/list/allrunes = list() + for(var/obj/effect/rune/R in cult_runes) + if(!istype(R.power, power.type) || R == src) + continue + if(R.power.word3 == power.word3 && R.loc.z != ZLEVEL_CENTCOMM) + allrunes += R + if(length(allrunes) > 0) + user.forceMove(get_turf(pick(allrunes))) + +/obj/effect/rune/attack_hand(mob/living/user) + user.SetNextMove(CLICK_CD_INTERACT) + 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)) + to_chat(user, "You are unable to speak the words of the rune.") + return + if(!power || prob(user.getBrainLoss())) + user.say(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.",\ + "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix.")) + return + power.action(user) + +/obj/item/weapon/book/tome + name = "book" + icon = 'icons/obj/library.dmi' + icon_state ="book" + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + unique = 1 + var/unlocked = FALSE + 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
    + Disable technology: Destroy See Technology
    + Drain blood: Travel Blood Self
    + Raise dead: Blood Join Hell
    + Hide runes: Hide See Blood
    + Reveal hidden runes: Blood See Hide
    + Leave your body: Hell travel self
    + Ghost Manifest: Blood See Travel
    + Imbue a talisman: Hell Technology Join
    + Sacrifice: Hell Blood Join
    + Create a wall: Destroy Travel Self
    + Summon cultist: Join Other Self
    + Free a cultist: Travel technology other
    + Deafen: Hide Other See
    + Blind: Destroy See Other
    + Blood Boil: Destroy See Blood
    + Communicate: Self Other Technology
    + Stun: Join Hide Technology
    + Summon Cultist Armor: Hell Destroy Other
    + See Invisible: See Hell Join
    + Construct: Technology Blood Travel
    +

    +

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

    Disable Technology

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

    Leave your body

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

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

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

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

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

    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.
    + + + "} + +/obj/item/weapon/book/tome/atom_init() + . = ..() + if (icon_state == "book") + icon_state = "book[pick(1,2,3,4,5,6)]" + +/obj/item/weapon/book/tome/Topic(href, href_list[]) + if(loc != usr) + usr << browse(null, "window=notes") + return + 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 cultwords + 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("[entity_ja(notedat)]", "window=notes") + +/obj/item/weapon/book/tome/attack(mob/living/M, mob/living/user) + + 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(istype(M, /mob/dead)) + M.invisibility = 0 + user.visible_message( \ + " [user] drags the ghost to our plan of reality!", \ + "You drag the ghost to our plan of reality!") + return + if(!istype(M)) + return + if(!iscultist(user)) + return ..() + if(iscultist(M)) + return + M.adjustBruteLoss(rand(5, 20)) //really lucky - 5 hits for a crit + M.visible_message("[user] beats [M] with the arcane tome!") + to_chat(M, "") + +/obj/item/weapon/book/tome/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return + if(iscultist(user) && A.reagents && A.reagents.has_reagent("water")) + var/water2convert = A.reagents.get_reagent_amount("water") + A.reagents.del_reagent("water") + to_chat(user, "You curse [A].") + A.reagents.add_reagent("unholywater",water2convert) + +/obj/item/weapon/book/tome/attack_self(mob/living/carbon/human/user) + if(!istype(user) || !user.canmove || user.stat || user.incapacitated()) + return + + if(!cultwords["travel"]) + runerandom() + if(!iscultist(user)) + to_chat(user, "This book is completely blank!") + return + if (!isturf(user.loc)) + to_chat(user, "You do not have enough space to write a proper rune.") + return + + if (length(cult_runes) >= CULT_RUNES_LIMIT + length(ticker.mode.cult)) //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 + 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("[entity_ja(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
    + "} + user << browse("[entity_ja(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]] = w + if(user) + w1 = input("Write your first rune:", "Rune Scribing") in english + if(!w1) + return + if(w1 in cultwords) + w1 = english[w1] + + if(user) + w2 = input("Write your second rune:", "Rune Scribing") in english + if(!w2) + return + if(w2 in cultwords) + w2 = english[w2] + if(user) + w3 = input("Write your third rune:", "Rune Scribing") in english + if(!w3) + return + if(w3 in cultwords) + w3 = english[w3] + + + if(user.get_active_hand() != src || user.is_busy()) + return + user.visible_message(" [user] slices open a finger and begins to chant and paint symbols on the floor.",\ + " You hear chanting.") + 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((unlocked || do_after(user, 50, target = user)) && user.get_active_hand() == src) + var/obj/effect/rune/R = new /obj/effect/rune(user.loc) + if(w1 == cultwords["travel"]) + if(w2 == cultwords["self"]) + R.power = new /datum/cult/teleport(R, cultwords_reverse[w3]) + else if(w2 == cultwords["other"]) + R.power = new /datum/cult/item_port(R, cultwords_reverse[w3]) + to_chat(user, "You finish drawing the arcane markings of the Geometer.") + if(!R.power) + var/type = cult_datums[cultwords_reverse[w1] + cultwords_reverse[w2] + cultwords_reverse[w3]] + if(ispath(type)) + R.power = new type(R) + R.desc = "[w1], [w2], [w3]" // for examine + R.icon = get_uristrune_cult((R.power ? TRUE : FALSE), w1, w2, w3) + R.blood_DNA = list() + R.blood_DNA[user.dna.unique_enzymes] = user.dna.b_type + + +/obj/item/weapon/book/tome/attackby(obj/item/weapon/book/tome/T, mob/living/user) + if(istype(T, /obj/item/weapon/book/tome)) // sanity check to prevent a runtime error + switch(alert("Copy the runes from your tome?",,"Copy", "Cancel")) + if("Cancel") + return + for(var/w in words) + words[w] = T.words[w] + to_chat(user, "You copy the translation notes from your tome.") + +/obj/item/weapon/book/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/book/tome/imbued/atom_init() + . = ..() + unlocked = TRUE + if(!cultwords["travel"]) + runerandom() + for(var/word in cultwords) + words[cultwords[word]] = word + +/obj/item/weapon/book/tome/old + name = "arcane tome" + desc = "An old, dusty tome with frayed edges and a sinister looking cover." + icon = 'icons/obj/weapons.dmi' + icon_state ="tome" diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index e3e83f939442..f59a13975125 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -1,91 +1,91 @@ -/obj/item/weapon/paper/talisman - icon_state = "scrap_bloodied" - var/datum/cult/power - -/obj/item/weapon/paper/talisman/attack_self(mob/living/user) - if(!iscultist(user)) - user.examinate(src) - return - if(istype(power, /datum/cult/stun)) - to_chat(user, " To use this talisman, attack your target directly.") - return - user.adjustBruteLoss(5) - if(power) - power.action(user) -/obj/item/weapon/paper/talisman/examine(mob/user) - ..() - if(iscultist(user) && power) - to_chat(user, "A spell circle drawn in blood. It reads: [power.word1] [power.word2] [power.word3].") - -/obj/item/weapon/paper/talisman/attack(mob/living/T, mob/living/user) - if(iscultist(user)) - if(istype(power, /datum/cult/stun)) - user.adjustBruteLoss(5) - power.talisman_reaction(user, T) - return - else if(istype(power, /datum/cult/armor) && ishuman(T) && iscultist(T)) - power.action(T) - return ..() - -/obj/item/weapon/paper/talisman/supply - var/uses = 5 - -/obj/item/weapon/paper/talisman/supply/weak - uses = 2 - -/obj/item/weapon/paper/talisman/supply/attack_self(mob/living/user) - if(!iscultist(user)) - user.examinate(src) - return - if (!uses) - qdel(src) - return - var/dat = "There are [uses] bloody runes on the parchment.
    " - dat += "Please choose the chant to be imbued into the fabric of reality.
    " - dat += "
    " - dat += "N'ath reth sh'yro eth d'raggathnor! - Allows you to summon a new arcane tome.
    " - dat += "Sas'so c'arta forbici! - Allows you to move to a rune with the same last word.
    " - dat += "Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range.
    " - dat += "Kla'atu barada nikt'o! - Allows you to conceal the runes you placed on the floor.
    " - dat += "O bidai nabora se'sma! - Allows you to coordinate with others of your cult.
    " - dat += "Fuu ma'jin - Allows you to stun a person by attacking them with the talisman.
    " - dat += "Sa tatha najin - Allows you to summon armoured robes and an unholy blade
    " - dat += "Kal om neth - Summons a soul stone
    " - dat += "Da A'ig Osk - Summons a construct shell for use with captured souls. It is too large to carry on your person.
    " - usr << browse(entity_ja(dat), "window=id_com;size=350x200") - - -/obj/item/weapon/paper/talisman/supply/Topic(href, href_list) - if (!src || usr.incapacitated() || !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.power = new /datum/cult/tome_summon(T) - if("teleport") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.power = new /datum/cult/teleport(T) - T.power.word3 = "[pick(cultwords)]" - if("emp") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.power = new /datum/cult/emp(T) - if("conceal") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.power = new /datum/cult/obscure(T) - if("communicate") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.power = new /datum/cult/communicate(T) - if("runestun") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.power = new /datum/cult/stun(T) - if("armor") - var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) - T.power = new /datum/cult/armor(T) - if("soulstone") - new /obj/item/device/soulstone(get_turf(usr)) - if("construct") - new /obj/structure/constructshell(get_turf(usr)) - uses-- - attack_self(usr) +/obj/item/weapon/paper/talisman + icon_state = "scrap_bloodied" + var/datum/cult/power + +/obj/item/weapon/paper/talisman/attack_self(mob/living/user) + if(!iscultist(user)) + user.examinate(src) + return + if(istype(power, /datum/cult/stun)) + to_chat(user, " To use this talisman, attack your target directly.") + return + user.adjustBruteLoss(5) + if(power) + power.action(user) +/obj/item/weapon/paper/talisman/examine(mob/user) + ..() + if(iscultist(user) && power) + to_chat(user, "A spell circle drawn in blood. It reads: [power.word1] [power.word2] [power.word3].") + +/obj/item/weapon/paper/talisman/attack(mob/living/T, mob/living/user) + if(iscultist(user)) + if(istype(power, /datum/cult/stun)) + user.adjustBruteLoss(5) + power.talisman_reaction(user, T) + return + else if(istype(power, /datum/cult/armor) && ishuman(T) && iscultist(T)) + power.action(T) + return ..() + +/obj/item/weapon/paper/talisman/supply + var/uses = 5 + +/obj/item/weapon/paper/talisman/supply/weak + uses = 2 + +/obj/item/weapon/paper/talisman/supply/attack_self(mob/living/user) + if(!iscultist(user)) + user.examinate(src) + return + if (!uses) + qdel(src) + return + var/dat = "There are [uses] bloody runes on the parchment.
    " + dat += "Please choose the chant to be imbued into the fabric of reality.
    " + dat += "
    " + dat += "N'ath reth sh'yro eth d'raggathnor! - Allows you to summon a new arcane tome.
    " + dat += "Sas'so c'arta forbici! - Allows you to move to a rune with the same last word.
    " + dat += "Ta'gh fara'qha fel d'amar det! - Allows you to destroy technology in a short range.
    " + dat += "Kla'atu barada nikt'o! - Allows you to conceal the runes you placed on the floor.
    " + dat += "O bidai nabora se'sma! - Allows you to coordinate with others of your cult.
    " + dat += "Fuu ma'jin - Allows you to stun a person by attacking them with the talisman.
    " + dat += "Sa tatha najin - Allows you to summon armoured robes and an unholy blade
    " + dat += "Kal om neth - Summons a soul stone
    " + dat += "Da A'ig Osk - Summons a construct shell for use with captured souls. It is too large to carry on your person.
    " + usr << browse(entity_ja(dat), "window=id_com;size=350x200") + + +/obj/item/weapon/paper/talisman/supply/Topic(href, href_list) + if (!src || usr.incapacitated() || !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.power = new /datum/cult/tome_summon(T) + if("teleport") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.power = new /datum/cult/teleport(T) + T.power.word3 = "[pick(cultwords)]" + if("emp") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.power = new /datum/cult/emp(T) + if("conceal") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.power = new /datum/cult/obscure(T) + if("communicate") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.power = new /datum/cult/communicate(T) + if("runestun") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.power = new /datum/cult/stun(T) + if("armor") + var/obj/item/weapon/paper/talisman/T = new /obj/item/weapon/paper/talisman(get_turf(usr)) + T.power = new /datum/cult/armor(T) + if("soulstone") + new /obj/item/device/soulstone(get_turf(usr)) + if("construct") + new /obj/structure/constructshell(get_turf(usr)) + uses-- + attack_self(usr) return \ No newline at end of file diff --git a/code/game/gamemodes/events/biomass.dm b/code/game/gamemodes/events/biomass.dm index 6e39ee5c9811..0b976353b9ed 100644 --- a/code/game/gamemodes/events/biomass.dm +++ b/code/game/gamemodes/events/biomass.dm @@ -1,173 +1,173 @@ -// 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() - if(master) - master.vines -= src - master.growth_queue -= src - return ..() - -/obj/effect/biomass/attackby(obj/item/weapon/W, mob/user) - if (!W || !user || !W.type) return - switch(W.type) - if(/obj/item/weapon/circular_saw) qdel(src) - if(/obj/item/weapon/kitchenknife) qdel(src) - if(/obj/item/weapon/scalpel) qdel(src) - if(/obj/item/weapon/twohanded/fireaxe) qdel(src) - if(/obj/item/weapon/hatchet) qdel(src) - if(/obj/item/weapon/melee/energy) 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/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) qdel(src) - else - return - ..() - -/obj/effect/biomass_controller - var/list/obj/effect/biomass/vines = list() - var/list/growth_queue = list() - var/reached_collapse_size - var/reached_slowdown_size - //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. - -/obj/effect/biomass_controller/atom_init() - . = ..() - if(!istype(loc, /turf/simulated/floor)) - return INITIALIZE_HINT_QDEL - - spawn_biomass_piece(loc) - START_PROCESSING(SSobj, src) - -/obj/effect/biomass_controller/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/effect/biomass_controller/proc/spawn_biomass_piece(turf/location) - var/obj/effect/biomass/BM = new(location) - growth_queue += BM - vines += BM - BM.master = src - -/obj/effect/biomass_controller/process() - if(!vines) - qdel(src) //space vines exterminated. Remove the controller - return - if(!growth_queue) - qdel(src) //Sanity check - return - if(vines.len >= 250 && !reached_collapse_size) - reached_collapse_size = 1 - if(vines.len >= 30 && !reached_slowdown_size ) - reached_slowdown_size = 1 - - 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 = list() - - for( var/obj/effect/biomass/BM in growth_queue ) - i++ - queue_end += BM - growth_queue -= BM - if(BM.energy < 2) //If tile isn't fully grown - if(prob(20)) - BM.grow() - - if(BM.spread()) - growth++ - if(growth >= maxgrowth) - break - if(i >= length) - break - - growth_queue = growth_queue + queue_end - -/obj/effect/biomass/proc/grow() - if(!energy) - src.icon_state = "stage2" - energy = 1 - src.opacity = 0 - src.density = 0 - layer = 5 - else - src.icon_state = "stage3" - src.opacity = 0 - src.density = 1 - energy = 2 - -/obj/effect/biomass/proc/spread() - var/direction = pick(cardinal) - var/step = get_step(src,direction) - if(istype(step,/turf/simulated/floor)) - var/turf/simulated/floor/F = step - if(!locate(/obj/effect/biomass,F)) - if(F.Enter(src)) - if(master) - master.spawn_biomass_piece( F ) - return 1 - return 0 - -/obj/effect/biomass/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(90)) - qdel(src) - return - if(3.0) - if (prob(50)) - qdel(src) - return - return - -/obj/effect/biomass/fire_act(null, temperature, volume) //hotspots kill biomass - if(temperature > T0C+100) - qdel(src) - -/proc/biomass_infestation() - - 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/area/B in A.related) - for(var/turf/simulated/floor/F in B.contents) - if(!F.contents.len) - turfs += F - - if(turfs.len) //Pick a turf to spawn at if we can - var/turf/simulated/floor/T = pick(turfs) - new/obj/effect/biomass_controller(T) //spawn a controller at turf - message_admins("\blue Event: Biomass spawned at [T.loc.loc] ([T.x],[T.y],[T.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() + if(master) + master.vines -= src + master.growth_queue -= src + return ..() + +/obj/effect/biomass/attackby(obj/item/weapon/W, mob/user) + if (!W || !user || !W.type) return + switch(W.type) + if(/obj/item/weapon/circular_saw) qdel(src) + if(/obj/item/weapon/kitchenknife) qdel(src) + if(/obj/item/weapon/scalpel) qdel(src) + if(/obj/item/weapon/twohanded/fireaxe) qdel(src) + if(/obj/item/weapon/hatchet) qdel(src) + if(/obj/item/weapon/melee/energy) 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/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) qdel(src) + else + return + ..() + +/obj/effect/biomass_controller + var/list/obj/effect/biomass/vines = list() + var/list/growth_queue = list() + var/reached_collapse_size + var/reached_slowdown_size + //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. + +/obj/effect/biomass_controller/atom_init() + . = ..() + if(!istype(loc, /turf/simulated/floor)) + return INITIALIZE_HINT_QDEL + + spawn_biomass_piece(loc) + START_PROCESSING(SSobj, src) + +/obj/effect/biomass_controller/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/effect/biomass_controller/proc/spawn_biomass_piece(turf/location) + var/obj/effect/biomass/BM = new(location) + growth_queue += BM + vines += BM + BM.master = src + +/obj/effect/biomass_controller/process() + if(!vines) + qdel(src) //space vines exterminated. Remove the controller + return + if(!growth_queue) + qdel(src) //Sanity check + return + if(vines.len >= 250 && !reached_collapse_size) + reached_collapse_size = 1 + if(vines.len >= 30 && !reached_slowdown_size ) + reached_slowdown_size = 1 + + 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 = list() + + for( var/obj/effect/biomass/BM in growth_queue ) + i++ + queue_end += BM + growth_queue -= BM + if(BM.energy < 2) //If tile isn't fully grown + if(prob(20)) + BM.grow() + + if(BM.spread()) + growth++ + if(growth >= maxgrowth) + break + if(i >= length) + break + + growth_queue = growth_queue + queue_end + +/obj/effect/biomass/proc/grow() + if(!energy) + src.icon_state = "stage2" + energy = 1 + src.opacity = 0 + src.density = 0 + layer = 5 + else + src.icon_state = "stage3" + src.opacity = 0 + src.density = 1 + energy = 2 + +/obj/effect/biomass/proc/spread() + var/direction = pick(cardinal) + var/step = get_step(src,direction) + if(istype(step,/turf/simulated/floor)) + var/turf/simulated/floor/F = step + if(!locate(/obj/effect/biomass,F)) + if(F.Enter(src)) + if(master) + master.spawn_biomass_piece( F ) + return 1 + return 0 + +/obj/effect/biomass/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(90)) + qdel(src) + return + if(3.0) + if (prob(50)) + qdel(src) + return + return + +/obj/effect/biomass/fire_act(null, temperature, volume) //hotspots kill biomass + if(temperature > T0C+100) + qdel(src) + +/proc/biomass_infestation() + + 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/area/B in A.related) + for(var/turf/simulated/floor/F in B.contents) + if(!F.contents.len) + turfs += F + + if(turfs.len) //Pick a turf to spawn at if we can + var/turf/simulated/floor/T = pick(turfs) + new/obj/effect/biomass_controller(T) //spawn a controller at turf + message_admins("\blue Event: Biomass spawned at [T.loc.loc] ([T.x],[T.y],[T.z])") diff --git a/code/game/gamemodes/events/holidays/Christmas.dm b/code/game/gamemodes/events/holidays/Christmas.dm index c91b95a957e7..892a00b6bb9a 100644 --- a/code/game/gamemodes/events/holidays/Christmas.dm +++ b/code/game/gamemodes/events/holidays/Christmas.dm @@ -1,60 +1,60 @@ -/proc/Christmas_Game_Start() - for(var/obj/structure/flora/tree/pine/xmas in tree_xmas_list) - if(xmas.z != ZLEVEL_STATION) continue - for(var/turf/simulated/floor/T in orange(1,xmas)) - for(var/i=1,i<=rand(1,5),i++) - new /obj/item/weapon/a_gift(T) - //for(var/mob/living/simple_animal/corgi/Ian/Ian in mob_list) Ian transfered to carbon - // Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian)) equipment procs also has been changed. so this must be rewritten when added back. - -/proc/ChristmasEvent() - for(var/obj/structure/flora/tree/pine/xmas in tree_xmas_list) - 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) - -/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 ..() - -/obj/item/clothing/head/festive - name = "festive paper hat" - icon_state = "xmashat" - desc = "A crappy paper hat that you are REQUIRED to wear." - flags_inv = 0 - body_parts_covered = 0 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - +/proc/Christmas_Game_Start() + for(var/obj/structure/flora/tree/pine/xmas in tree_xmas_list) + if(xmas.z != ZLEVEL_STATION) continue + for(var/turf/simulated/floor/T in orange(1,xmas)) + for(var/i=1,i<=rand(1,5),i++) + new /obj/item/weapon/a_gift(T) + //for(var/mob/living/simple_animal/corgi/Ian/Ian in mob_list) Ian transfered to carbon + // Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian)) equipment procs also has been changed. so this must be rewritten when added back. + +/proc/ChristmasEvent() + for(var/obj/structure/flora/tree/pine/xmas in tree_xmas_list) + 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) + +/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 ..() + +/obj/item/clothing/head/festive + name = "festive paper hat" + icon_state = "xmashat" + desc = "A crappy paper hat that you are REQUIRED to wear." + flags_inv = 0 + body_parts_covered = 0 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm index 85680dcfe597..1244795ca831 100644 --- a/code/game/gamemodes/events/holidays/Holidays.dm +++ b/code/game/gamemodes/events/holidays/Holidays.dm @@ -1,169 +1,169 @@ -//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) return // Holiday stuff was not enabled in the config! - - 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(7) Holiday = "Christmas" - - 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(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 - - 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 = "Catolic Christmas Eve" - if(25) Holiday = "Catolic 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) - 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("\blue 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...") - to_chat(world, "

    Happy [Holiday] Everybody!

    ") - -//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 not_world) - if(S.z != ZLEVEL_STATION) continue - containers += S - - message_admins("\blue DEBUG: Event: Egg spawned at [Egg.loc] ([Egg.x],[Egg.y],[Egg.z])")*/ - if("End of the World") - if(prob(eventchance)) GameOver() +//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) return // Holiday stuff was not enabled in the config! + + 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(7) Holiday = "Christmas" + + 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(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 + + 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 = "Catolic Christmas Eve" + if(25) Holiday = "Catolic 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) + 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("\blue 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...") + to_chat(world, "

    Happy [Holiday] Everybody!

    ") + +//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 not_world) + if(S.z != ZLEVEL_STATION) continue + containers += S + + message_admins("\blue DEBUG: Event: Egg spawned at [Egg.loc] ([Egg.x],[Egg.y],[Egg.z])")*/ + if("End of the World") + if(prob(eventchance)) GameOver() diff --git a/code/game/gamemodes/events/holidays/Other.dm b/code/game/gamemodes/events/holidays/Other.dm index d006cd03f010..03d5aa8c0057 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() - sleep(50) +/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) diff --git a/code/game/gamemodes/events/spacevines.dm b/code/game/gamemodes/events/spacevines.dm index cafd4e14e48e..b31ab98ad3bc 100644 --- a/code/game/gamemodes/events/spacevines.dm +++ b/code/game/gamemodes/events/spacevines.dm @@ -1,226 +1,226 @@ -// SPACE VINES (Note that this code is very similar to Biomass code) -/obj/effect/spacevine - name = "space vines" - desc = "An extremely expansionistic species of vine." - icon = 'icons/effects/spacevines.dmi' - icon_state = "Light1" - anchored = 1 - density = 0 - layer = 5 - pass_flags = PASSTABLE | PASSGRILLE - var/energy = 0 - var/obj/effect/spacevine_controller/master = null - -/obj/effect/spacevine/Destroy() - if(master) - master.vines -= src - master.growth_queue -= src - master = null - return ..() - -/obj/effect/spacevine/attackby(obj/item/weapon/W, mob/user) - if (!W || !user || !W.type) return - switch(W.type) - if(/obj/item/weapon/circular_saw) qdel(src) - if(/obj/item/weapon/kitchenknife) qdel(src) - if(/obj/item/weapon/scalpel) qdel(src) - if(/obj/item/weapon/twohanded/fireaxe) qdel(src) - if(/obj/item/weapon/hatchet) qdel(src) - if(/obj/item/weapon/melee/energy) 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/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) qdel(src) - else - user_unbuckle_mob(user) - return - //Plant-b-gone damage is handled in its entry in chemistry-reagents.dm - ..() - -/obj/effect/spacevine/attack_hand(mob/user) - user_unbuckle_mob(user) - user.SetNextMove(CLICK_CD_MELEE) - - -/obj/effect/spacevine/attack_paw(mob/user) - user_unbuckle_mob(user) - user.SetNextMove(CLICK_CD_MELEE) - -/obj/effect/spacevine_controller - var/list/obj/effect/spacevine/vines = list() - var/list/growth_queue = list() - var/reached_collapse_size - var/reached_slowdown_size - //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 spacevines' size to something less than 20 plots, it won't grow anymore. - -/obj/effect/spacevine_controller/atom_init() - . = ..() - if(!istype(loc, /turf/simulated/floor)) - return INITIALIZE_HINT_QDEL - - spawn_spacevine_piece(src.loc) - START_PROCESSING(SSobj, src) - -/obj/effect/spacevine_controller/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/effect/spacevine_controller/proc/spawn_spacevine_piece(turf/location) - var/obj/effect/spacevine/SV = new(location) - growth_queue += SV - vines += SV - SV.master = src - -/obj/effect/spacevine_controller/process() - if(!vines) - qdel(src) //space vines exterminated. Remove the controller - return - if(!growth_queue) - qdel(src) //Sanity check - return - if(vines.len >= 250 && !reached_collapse_size) - reached_collapse_size = 1 - if(vines.len >= 30 && !reached_slowdown_size ) - reached_slowdown_size = 1 - - var/length = 0 - if(reached_collapse_size) - length = 0 - else if(reached_slowdown_size) - if(prob(25)) - length = 1 - else - length = 0 - else - length = 1 - length = min( 30 , max( length , vines.len / 5 ) ) - var/i = 0 - var/list/obj/effect/spacevine/queue_end = list() - - for( var/obj/effect/spacevine/SV in growth_queue ) - i++ - queue_end += SV - growth_queue -= SV - if(SV.energy < 2) //If tile isn't fully grown - if(prob(20)) - SV.grow() - else //If tile is fully grown - SV.buckle_mob() - - //if(prob(25)) - SV.spread() - if(i >= length) - break - - growth_queue = growth_queue + queue_end - //sleep(5) - //src.process() - -/obj/effect/spacevine/proc/grow() - if(!energy) - src.icon_state = pick("Med1", "Med2", "Med3") - energy = 1 - src.opacity = 1 - layer = 5 - else - src.icon_state = pick("Hvy1", "Hvy2", "Hvy3") - energy = 2 - -/obj/effect/spacevine/buckle_mob() - if(!buckled_mob && prob(25)) - for(var/mob/living/carbon/V in src.loc) - if((V.stat != DEAD) && (V.buckled != src)) //if mob not dead or captured - V.buckled = src - V.loc = src.loc - V.update_canmove() - src.buckled_mob = V - to_chat(V, "The vines [pick("wind", "tangle", "tighten")] around you!") - break //only capture one mob at a time. - -/obj/effect/spacevine/proc/spread() - var/direction = pick(cardinal) - var/step = get_step(src,direction) - if(istype(step,/turf/simulated/floor)) - var/turf/simulated/floor/F = step - if(!locate(/obj/effect/spacevine,F)) - if(F.Enter(src)) - if(master) - master.spawn_spacevine_piece( F ) - -/* -/obj/effect/spacevine/proc/Life() - if (!src) return - var/Vspread - if (prob(50)) Vspread = locate(src.x + rand(-1,1),src.y,src.z) - else Vspread = locate(src.x,src.y + rand(-1, 1),src.z) - var/dogrowth = 1 - if (!istype(Vspread, /turf/simulated/floor)) dogrowth = 0 - for(var/obj/O in Vspread) - if (istype(O, /obj/structure/window) || istype(O, /obj/effect/forcefield) || istype(O, /obj/effect/blob) || istype(O, /obj/effect/alien/weeds) || istype(O, /obj/effect/spacevine)) dogrowth = 0 - if (istype(O, /obj/machinery/door/)) - if(O:p_open == 0 && prob(50)) O:open() - else dogrowth = 0 - if (dogrowth == 1) - var/obj/effect/spacevine/B = new /obj/effect/spacevine(Vspread) - B.icon_state = pick("vine-light1", "vine-light2", "vine-light3") - spawn(20) - if(B) - B.Life() - src.growth += 1 - if (src.growth == 10) - src.name = "Thick Space Kudzu" - src.icon_state = pick("vine-med1", "vine-med2", "vine-med3") - src.opacity = 1 - src.waittime = 80 - if (src.growth == 20) - src.name = "Dense Space Kudzu" - src.icon_state = pick("vine-hvy1", "vine-hvy2", "vine-hvy3") - src.density = 1 - spawn(src.waittime) - if (src.growth < 20) src.Life() - -*/ - -/obj/effect/spacevine/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(90)) - qdel(src) - return - if(3.0) - if (prob(50)) - qdel(src) - return - return - -/obj/effect/spacevine/fire_act(null, temperature, volume) //hotspots kill vines - if(temperature > T0C+100) - qdel(src) - -//Carn: Spacevines random event. -/proc/spacevine_infestation() - 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/area/B in A.related) - for(var/turf/simulated/floor/F in B.contents) - if(!F.contents.len) - turfs += F - - if(turfs.len) //Pick a turf to spawn at if we can - var/turf/simulated/floor/T = pick(turfs) - new/obj/effect/spacevine_controller(T) //spawn a controller at turf - message_admins("\blue Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])") +// SPACE VINES (Note that this code is very similar to Biomass code) +/obj/effect/spacevine + name = "space vines" + desc = "An extremely expansionistic species of vine." + icon = 'icons/effects/spacevines.dmi' + icon_state = "Light1" + anchored = 1 + density = 0 + layer = 5 + pass_flags = PASSTABLE | PASSGRILLE + var/energy = 0 + var/obj/effect/spacevine_controller/master = null + +/obj/effect/spacevine/Destroy() + if(master) + master.vines -= src + master.growth_queue -= src + master = null + return ..() + +/obj/effect/spacevine/attackby(obj/item/weapon/W, mob/user) + if (!W || !user || !W.type) return + switch(W.type) + if(/obj/item/weapon/circular_saw) qdel(src) + if(/obj/item/weapon/kitchenknife) qdel(src) + if(/obj/item/weapon/scalpel) qdel(src) + if(/obj/item/weapon/twohanded/fireaxe) qdel(src) + if(/obj/item/weapon/hatchet) qdel(src) + if(/obj/item/weapon/melee/energy) 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/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) qdel(src) + else + user_unbuckle_mob(user) + return + //Plant-b-gone damage is handled in its entry in chemistry-reagents.dm + ..() + +/obj/effect/spacevine/attack_hand(mob/user) + user_unbuckle_mob(user) + user.SetNextMove(CLICK_CD_MELEE) + + +/obj/effect/spacevine/attack_paw(mob/user) + user_unbuckle_mob(user) + user.SetNextMove(CLICK_CD_MELEE) + +/obj/effect/spacevine_controller + var/list/obj/effect/spacevine/vines = list() + var/list/growth_queue = list() + var/reached_collapse_size + var/reached_slowdown_size + //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 spacevines' size to something less than 20 plots, it won't grow anymore. + +/obj/effect/spacevine_controller/atom_init() + . = ..() + if(!istype(loc, /turf/simulated/floor)) + return INITIALIZE_HINT_QDEL + + spawn_spacevine_piece(src.loc) + START_PROCESSING(SSobj, src) + +/obj/effect/spacevine_controller/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/effect/spacevine_controller/proc/spawn_spacevine_piece(turf/location) + var/obj/effect/spacevine/SV = new(location) + growth_queue += SV + vines += SV + SV.master = src + +/obj/effect/spacevine_controller/process() + if(!vines) + qdel(src) //space vines exterminated. Remove the controller + return + if(!growth_queue) + qdel(src) //Sanity check + return + if(vines.len >= 250 && !reached_collapse_size) + reached_collapse_size = 1 + if(vines.len >= 30 && !reached_slowdown_size ) + reached_slowdown_size = 1 + + var/length = 0 + if(reached_collapse_size) + length = 0 + else if(reached_slowdown_size) + if(prob(25)) + length = 1 + else + length = 0 + else + length = 1 + length = min( 30 , max( length , vines.len / 5 ) ) + var/i = 0 + var/list/obj/effect/spacevine/queue_end = list() + + for( var/obj/effect/spacevine/SV in growth_queue ) + i++ + queue_end += SV + growth_queue -= SV + if(SV.energy < 2) //If tile isn't fully grown + if(prob(20)) + SV.grow() + else //If tile is fully grown + SV.buckle_mob() + + //if(prob(25)) + SV.spread() + if(i >= length) + break + + growth_queue = growth_queue + queue_end + //sleep(5) + //src.process() + +/obj/effect/spacevine/proc/grow() + if(!energy) + src.icon_state = pick("Med1", "Med2", "Med3") + energy = 1 + src.opacity = 1 + layer = 5 + else + src.icon_state = pick("Hvy1", "Hvy2", "Hvy3") + energy = 2 + +/obj/effect/spacevine/buckle_mob() + if(!buckled_mob && prob(25)) + for(var/mob/living/carbon/V in src.loc) + if((V.stat != DEAD) && (V.buckled != src)) //if mob not dead or captured + V.buckled = src + V.loc = src.loc + V.update_canmove() + src.buckled_mob = V + to_chat(V, "The vines [pick("wind", "tangle", "tighten")] around you!") + break //only capture one mob at a time. + +/obj/effect/spacevine/proc/spread() + var/direction = pick(cardinal) + var/step = get_step(src,direction) + if(istype(step,/turf/simulated/floor)) + var/turf/simulated/floor/F = step + if(!locate(/obj/effect/spacevine,F)) + if(F.Enter(src)) + if(master) + master.spawn_spacevine_piece( F ) + +/* +/obj/effect/spacevine/proc/Life() + if (!src) return + var/Vspread + if (prob(50)) Vspread = locate(src.x + rand(-1,1),src.y,src.z) + else Vspread = locate(src.x,src.y + rand(-1, 1),src.z) + var/dogrowth = 1 + if (!istype(Vspread, /turf/simulated/floor)) dogrowth = 0 + for(var/obj/O in Vspread) + if (istype(O, /obj/structure/window) || istype(O, /obj/effect/forcefield) || istype(O, /obj/effect/blob) || istype(O, /obj/effect/alien/weeds) || istype(O, /obj/effect/spacevine)) dogrowth = 0 + if (istype(O, /obj/machinery/door/)) + if(O:p_open == 0 && prob(50)) O:open() + else dogrowth = 0 + if (dogrowth == 1) + var/obj/effect/spacevine/B = new /obj/effect/spacevine(Vspread) + B.icon_state = pick("vine-light1", "vine-light2", "vine-light3") + spawn(20) + if(B) + B.Life() + src.growth += 1 + if (src.growth == 10) + src.name = "Thick Space Kudzu" + src.icon_state = pick("vine-med1", "vine-med2", "vine-med3") + src.opacity = 1 + src.waittime = 80 + if (src.growth == 20) + src.name = "Dense Space Kudzu" + src.icon_state = pick("vine-hvy1", "vine-hvy2", "vine-hvy3") + src.density = 1 + spawn(src.waittime) + if (src.growth < 20) src.Life() + +*/ + +/obj/effect/spacevine/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(90)) + qdel(src) + return + if(3.0) + if (prob(50)) + qdel(src) + return + return + +/obj/effect/spacevine/fire_act(null, temperature, volume) //hotspots kill vines + if(temperature > T0C+100) + qdel(src) + +//Carn: Spacevines random event. +/proc/spacevine_infestation() + 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/area/B in A.related) + for(var/turf/simulated/floor/F in B.contents) + if(!F.contents.len) + turfs += F + + if(turfs.len) //Pick a turf to spawn at if we can + var/turf/simulated/floor/T = pick(turfs) + new/obj/effect/spacevine_controller(T) //spawn a controller at turf + message_admins("\blue Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])") diff --git a/code/game/gamemodes/events/wormholes.dm b/code/game/gamemodes/events/wormholes.dm index bfa77e88c789..01f77db3941e 100644 --- a/code/game/gamemodes/events/wormholes.dm +++ b/code/game/gamemodes/events/wormholes.dm @@ -1,64 +1,64 @@ -/proc/wormhole_event() - spawn() - var/list/pick_turfs = list() - for(var/turf/simulated/floor/T in block(locate(1, 1, ZLEVEL_STATION), locate(world.maxx, world.maxy, ZLEVEL_STATION))) - 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(!isnewplayer(M)) - 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)) -// 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 ) -// world << "DEBUG: we've run into overtime. End the event" - return - if( !pick_turfs.len ) -// 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(turf/enter, turf/exit) - var/obj/effect/portal/P = new /obj/effect/portal( enter ) - P.target = exit - P.creator = null - P.icon = 'icons/obj/objects.dmi' - P.failchance = 0 - P.icon_state = "anom" - P.name = "wormhole" - spawn(rand(300,600)) - qdel(P) +/proc/wormhole_event() + spawn() + var/list/pick_turfs = list() + for(var/turf/simulated/floor/T in block(locate(1, 1, ZLEVEL_STATION), locate(world.maxx, world.maxy, ZLEVEL_STATION))) + 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(!isnewplayer(M)) + 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)) +// 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 ) +// world << "DEBUG: we've run into overtime. End the event" + return + if( !pick_turfs.len ) +// 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(turf/enter, turf/exit) + var/obj/effect/portal/P = new /obj/effect/portal( enter ) + P.target = exit + P.creator = null + P.icon = 'icons/obj/objects.dmi' + P.failchance = 0 + P.icon_state = "anom" + P.name = "wormhole" + spawn(rand(300,600)) + qdel(P) diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm index 73e64a158536..58f9eb64811c 100644 --- a/code/game/gamemodes/extended/extended.dm +++ b/code/game/gamemodes/extended/extended.dm @@ -1,19 +1,19 @@ -/datum/game_mode/extended - name = "extended" - config_tag = "extended" - required_players = 0 - - votable = 1 - - uplink_welcome = "Syndicate Uplink Console:" - uplink_uses = 20 - -/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() - return 1 - -/datum/game_mode/extended/post_setup() - return ..() +/datum/game_mode/extended + name = "extended" + config_tag = "extended" + required_players = 0 + + votable = 1 + + uplink_welcome = "Syndicate Uplink Console:" + uplink_uses = 20 + +/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() + return 1 + +/datum/game_mode/extended/post_setup() + return ..() diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index f73d0ca14d7f..2d006b157d0f 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -1,502 +1,502 @@ -//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/votable = 1 - var/playable_mode = 1 - var/probability = 0 - var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm - var/explosion_in_progress = 0 //sit back and relax - var/nar_sie_has_risen = 0 //check, if there is already one god in the world who was summoned (only for tomes) - var/completion_text = "" - 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 because - var/required_players = 0 - var/required_players_secret = 0 //Minimum number of players for that game mode to be chose in Secret - var/required_enemies = 0 - var/recommended_enemies = 0 - var/list/datum/mind/antag_candidates = list() // List of possible starting antags goes here - var/list/restricted_jobs_autotraitor = list("Cyborg", "Security Officer", "Warden") - var/autotraitor_delay = 15 MINUTES // how often to try to add new traitors. - var/role_type = null - var/newscaster_announcements = null - var/ert_disabled = 0 - var/const/waittime_l = 600 - var/const/waittime_h = 1800 // started at 1800 - var/uplink_welcome = "Syndicate Uplink Console:" - var/uplink_uses = 20 - var/uplink_items = {"Highly Visible and Dangerous Weapons; -/obj/item/weapon/gun/projectile/revolver/syndie:6:Revolver; -/obj/item/ammo_box/a357:2:Ammo-357; -/obj/item/weapon/gun/energy/crossbow:5:Energy Crossbow; -/obj/item/weapon/melee/energy/sword:4:Energy Sword; -/obj/item/weapon/storage/box/syndicate:10:Syndicate Bundle; -/obj/item/weapon/storage/box/emps:3:5 EMP Grenades; -Whitespace:Seperator; -Stealthy and Inconspicuous Weapons; -/obj/item/weapon/pen/paralysis:3:Paralysis Pen; -/obj/item/weapon/soap/syndie:1:Syndicate Soap; -/obj/item/weapon/cartridge/syndicate:3:Detomatix PDA Cartridge; -Whitespace:Seperator; -Stealth and Camouflage Items; -/obj/item/weapon/storage/box/syndie_kit/chameleon:3:Chameleon Kit; -/obj/item/clothing/shoes/syndigaloshes:2:No-Slip Syndicate Shoes; -/obj/item/weapon/card/id/syndicate:2:Agent ID card; -/obj/item/clothing/mask/gas/voice:4:Voice Changer; -/obj/item/device/chameleon:4:Chameleon-Projector; -Whitespace:Seperator; -Devices and Tools; -/obj/item/weapon/card/emag:3:Cryptographic Sequencer; -/obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox; -/obj/item/weapon/storage/box/syndie_kit/space:3:Space Suit; -/obj/item/clothing/glasses/thermal/syndi:3:Thermal Imaging Glasses; -/obj/item/device/encryptionkey/binary:3:Binary Translator Key; -/obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module; -/obj/item/weapon/plastique:2:C-4 (Destroys walls); -/obj/item/device/powersink:5:Powersink (DANGER!); -/obj/item/device/radio/beacon/syndicate:7:Singularity Beacon (DANGER!); -/obj/item/weapon/circuitboard/teleporter:20:Teleporter Circuit Board; -Whitespace:Seperator; -Implants; -/obj/item/weapon/storage/box/syndie_kit/imp_freedom:3:Freedom Implant; -/obj/item/weapon/storage/box/syndie_kit/imp_uplink:10:Uplink Implant (Contains 5 Telecrystals); -/obj/item/weapon/storage/box/syndie_kit/imp_explosive:6:Explosive Implant (DANGER!); -/obj/item/weapon/storage/box/syndie_kit/imp_compress:4:Compressed Matter Implant;Whitespace:Seperator; -(Pointless) Badassery; -/obj/item/toy/syndicateballoon:10:For showing that You Are The BOSS (Useless Balloon);"} - -/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/dead/new_player/player in new_player_list) - if(player.client && player.ready) - playerC++ - - antag_candidates = get_players_for_role(role_type) - if(antag_candidates.len < required_enemies) - return 0 - - if(master_mode=="secret") - if(playerC >= required_players_secret) - return 1 - else - if(playerC >= required_players) - return 1 - 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() - var/list/exclude_autotraitor_for = list("extended", "sandbox", "meteor", "gang", "epidemic") // config_tag var - if(!(config_tag in exclude_autotraitor_for)) - addtimer(CALLBACK(src, .proc/traitorcheckloop), autotraitor_delay) - - 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]") - feedback_set_details("server_ip","[world.internet_address]:[world.port]") - spawn(rand(waittime_l, waittime_h)) - send_intercept() - start_state = new /datum/station_state() - start_state.count(1) - return 1 - - -///process() -///Called by the gameticker -/datum/game_mode/process() - return 0 - - -/datum/game_mode/proc/check_finished() //to be called by ticker - if(SSshuttle.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) - - 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() - var/intercepttext = "Cent. Com. Update Requested status information:
    " - intercepttext += " In case you have misplaced your copy, attached is a list of personnel whom reliable sources™ suspect may be affiliated with the Syndicate:
    " - - - var/list/suspects = list() - for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind) - // NT relation option - var/list/invisible_roles = list("Wizard", - "Ninja", - "Syndicate", - "Vox Raider", - "Raider", - "Abductor scientist", - "Abductor agent", - "Meme" - ) - var/special_role = man.mind.special_role - if (special_role in invisible_roles) - continue //NT intelligence ruled out possiblity that those are too classy to pretend to be a crew. - for(var/spec_role in gang_name_pool) - if (special_role == "[spec_role] Gang (A) Boss") - continue - if (special_role == "[spec_role] Gang (B) Boss") - continue - 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) || \ - special_role == "Shadowling" && prob(20)) - 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 = 8 - suplink.uses += extra - if(man.mind) man.mind.total_TC += extra - to_chat(man, "\red 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! - to_chat(man, "\red 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) - 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 communications_list) - if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) - var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "Cent. Com. Status Summary" - intercept.info = intercepttext - - comm.messagetitle.Add("Cent. Com. 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. Security Level Elevated.") - for(var/mob/M in player_list) - if(!isnewplayer(M)) - 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(role) - var/list/players = list() - var/list/candidates = list() - - // Assemble a list of active players without jobbans. - for(var/mob/dead/new_player/player in new_player_list) - if(player.client && player.ready) - if(role in player.client.prefs.be_role) - if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role) && !role_available_in_minutes(player, role)) - players += player - - // Shuffle the players list so that it becomes ping-independent. - players = shuffle(players) - - // Get a list of all the people who want to be the antagonist for this round - for(var/mob/dead/new_player/player in players) - if(role in player.client.prefs.be_role) - log_debug("[player.key] had [role] enabled, so we are drafting them.") - candidates += player.mind - players -= player - - // Remove candidates who want to be antagonist but have a job that precludes it - if(restricted_jobs) - for(var/datum/mind/player in candidates) - for(var/job in restricted_jobs) - if(player.assigned_role == job) - candidates -= player - - 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(mob) - -/* -/datum/game_mode/proc/check_player_role_pref(role, mob/dead/new_player/player) - if(player.preferences.be_role & role) - return 1 - return 0 -*/ - -/datum/game_mode/proc/num_players() - . = 0 - for(var/mob/dead/new_player/P in new_player_list) - if(P.client && P.ready) - . ++ - - -/////////////////////////////////// -//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 human_list) - if(player.stat != DEAD && 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/proc/check_antagonists_topic(href, href_list[]) - return 0 - -/datum/game_mode/New() - newscaster_announcements = pick(newscaster_standard_feeds) - -////////////////////////// -//Reports player logouts// -////////////////////////// -proc/display_roundstart_logout_report() - var/msg = "\blue Roundstart logout report\n\n" - for(var/mob/living/L in living_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 observer_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/client/M in admins) - if(M.holder) - to_chat(M, msg) - - -proc/get_nt_opposed() - var/list/dudes = list() - for(var/mob/living/carbon/human/man in human_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) - -/////////////////////////// -//Misc stuff and TG ports// -/////////////////////////// - -/datum/game_mode/proc/printplayer(datum/mind/ply) - var/role = "[ply.special_role]" - var/text = "
    [ply.name]([ply.key]) as \a [role] (" - if(ply.current) - if(ply.current.stat == DEAD) - text += "died" - else - text += "survived" - if(ply.current.real_name != ply.name) - text += " as [ply.current.real_name]" - else - text += "body destroyed" - text += ")" - - return text - -/datum/game_mode/proc/printobjectives(datum/mind/ply) - var/text = "" - var/count = 1 - for(var/datum/objective/objective in ply.objectives) - if(objective.check_completion()) - text += "
    Objective #[count]: [objective.explanation_text] Success!" - else - text += "
    Objective #[count]: [objective.explanation_text] Fail." - count++ - return text - -//Used for printing player with there icons in round ending staticstic -/datum/game_mode/proc/printplayerwithicon(datum/mind/ply) - var/text = "" - var/tempstate = end_icons.len - if(ply.current) - var/icon/flat = getFlatIcon(ply.current,exact=1) - end_icons += flat - tempstate = end_icons.len - text += {"
    [ply.key] was [ply.name] ("} - if(ply.current.stat == DEAD) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else - text += "survived" - if(ply.current.real_name != ply.name) - text += " as [ply.current.real_name]" - else - var/icon/sprotch = icon('icons/effects/blood.dmi', "gibbearcore") - end_icons += sprotch - tempstate = end_icons.len - text += {"
    [ply.key] was [ply.name] ("} - text += "body destroyed" - text += ")" - return text - -//Used for printing antag logo -/datum/game_mode/proc/printlogo(logoname, antagname) - var/icon/logo = icon('icons/mob/mob.dmi', "[logoname]-logo") - end_icons += logo - var/tempstate = end_icons.len - var/text = "" - text += {" The [antagname] were: "} - return text +//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/votable = 1 + var/playable_mode = 1 + var/probability = 0 + var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm + var/explosion_in_progress = 0 //sit back and relax + var/nar_sie_has_risen = 0 //check, if there is already one god in the world who was summoned (only for tomes) + var/completion_text = "" + 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 because + var/required_players = 0 + var/required_players_secret = 0 //Minimum number of players for that game mode to be chose in Secret + var/required_enemies = 0 + var/recommended_enemies = 0 + var/list/datum/mind/antag_candidates = list() // List of possible starting antags goes here + var/list/restricted_jobs_autotraitor = list("Cyborg", "Security Officer", "Warden") + var/autotraitor_delay = 15 MINUTES // how often to try to add new traitors. + var/role_type = null + var/newscaster_announcements = null + var/ert_disabled = 0 + var/const/waittime_l = 600 + var/const/waittime_h = 1800 // started at 1800 + var/uplink_welcome = "Syndicate Uplink Console:" + var/uplink_uses = 20 + var/uplink_items = {"Highly Visible and Dangerous Weapons; +/obj/item/weapon/gun/projectile/revolver/syndie:6:Revolver; +/obj/item/ammo_box/a357:2:Ammo-357; +/obj/item/weapon/gun/energy/crossbow:5:Energy Crossbow; +/obj/item/weapon/melee/energy/sword:4:Energy Sword; +/obj/item/weapon/storage/box/syndicate:10:Syndicate Bundle; +/obj/item/weapon/storage/box/emps:3:5 EMP Grenades; +Whitespace:Seperator; +Stealthy and Inconspicuous Weapons; +/obj/item/weapon/pen/paralysis:3:Paralysis Pen; +/obj/item/weapon/soap/syndie:1:Syndicate Soap; +/obj/item/weapon/cartridge/syndicate:3:Detomatix PDA Cartridge; +Whitespace:Seperator; +Stealth and Camouflage Items; +/obj/item/weapon/storage/box/syndie_kit/chameleon:3:Chameleon Kit; +/obj/item/clothing/shoes/syndigaloshes:2:No-Slip Syndicate Shoes; +/obj/item/weapon/card/id/syndicate:2:Agent ID card; +/obj/item/clothing/mask/gas/voice:4:Voice Changer; +/obj/item/device/chameleon:4:Chameleon-Projector; +Whitespace:Seperator; +Devices and Tools; +/obj/item/weapon/card/emag:3:Cryptographic Sequencer; +/obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox; +/obj/item/weapon/storage/box/syndie_kit/space:3:Space Suit; +/obj/item/clothing/glasses/thermal/syndi:3:Thermal Imaging Glasses; +/obj/item/device/encryptionkey/binary:3:Binary Translator Key; +/obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module; +/obj/item/weapon/plastique:2:C-4 (Destroys walls); +/obj/item/device/powersink:5:Powersink (DANGER!); +/obj/item/device/radio/beacon/syndicate:7:Singularity Beacon (DANGER!); +/obj/item/weapon/circuitboard/teleporter:20:Teleporter Circuit Board; +Whitespace:Seperator; +Implants; +/obj/item/weapon/storage/box/syndie_kit/imp_freedom:3:Freedom Implant; +/obj/item/weapon/storage/box/syndie_kit/imp_uplink:10:Uplink Implant (Contains 5 Telecrystals); +/obj/item/weapon/storage/box/syndie_kit/imp_explosive:6:Explosive Implant (DANGER!); +/obj/item/weapon/storage/box/syndie_kit/imp_compress:4:Compressed Matter Implant;Whitespace:Seperator; +(Pointless) Badassery; +/obj/item/toy/syndicateballoon:10:For showing that You Are The BOSS (Useless Balloon);"} + +/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/dead/new_player/player in new_player_list) + if(player.client && player.ready) + playerC++ + + antag_candidates = get_players_for_role(role_type) + if(antag_candidates.len < required_enemies) + return 0 + + if(master_mode=="secret") + if(playerC >= required_players_secret) + return 1 + else + if(playerC >= required_players) + return 1 + 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() + var/list/exclude_autotraitor_for = list("extended", "sandbox", "meteor", "gang", "epidemic") // config_tag var + if(!(config_tag in exclude_autotraitor_for)) + addtimer(CALLBACK(src, .proc/traitorcheckloop), autotraitor_delay) + + 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]") + feedback_set_details("server_ip","[world.internet_address]:[world.port]") + spawn(rand(waittime_l, waittime_h)) + send_intercept() + start_state = new /datum/station_state() + start_state.count(1) + return 1 + + +///process() +///Called by the gameticker +/datum/game_mode/process() + return 0 + + +/datum/game_mode/proc/check_finished() //to be called by ticker + if(SSshuttle.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) + + 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() + var/intercepttext = "Cent. Com. Update Requested status information:
    " + intercepttext += " In case you have misplaced your copy, attached is a list of personnel whom reliable sources™ suspect may be affiliated with the Syndicate:
    " + + + var/list/suspects = list() + for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind) + // NT relation option + var/list/invisible_roles = list("Wizard", + "Ninja", + "Syndicate", + "Vox Raider", + "Raider", + "Abductor scientist", + "Abductor agent", + "Meme" + ) + var/special_role = man.mind.special_role + if (special_role in invisible_roles) + continue //NT intelligence ruled out possiblity that those are too classy to pretend to be a crew. + for(var/spec_role in gang_name_pool) + if (special_role == "[spec_role] Gang (A) Boss") + continue + if (special_role == "[spec_role] Gang (B) Boss") + continue + 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) || \ + special_role == "Shadowling" && prob(20)) + 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 = 8 + suplink.uses += extra + if(man.mind) man.mind.total_TC += extra + to_chat(man, "\red 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! + to_chat(man, "\red 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) + 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 communications_list) + if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) + var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) + intercept.name = "Cent. Com. Status Summary" + intercept.info = intercepttext + + comm.messagetitle.Add("Cent. Com. 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. Security Level Elevated.") + for(var/mob/M in player_list) + if(!isnewplayer(M)) + 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(role) + var/list/players = list() + var/list/candidates = list() + + // Assemble a list of active players without jobbans. + for(var/mob/dead/new_player/player in new_player_list) + if(player.client && player.ready) + if(role in player.client.prefs.be_role) + if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role) && !role_available_in_minutes(player, role)) + players += player + + // Shuffle the players list so that it becomes ping-independent. + players = shuffle(players) + + // Get a list of all the people who want to be the antagonist for this round + for(var/mob/dead/new_player/player in players) + if(role in player.client.prefs.be_role) + log_debug("[player.key] had [role] enabled, so we are drafting them.") + candidates += player.mind + players -= player + + // Remove candidates who want to be antagonist but have a job that precludes it + if(restricted_jobs) + for(var/datum/mind/player in candidates) + for(var/job in restricted_jobs) + if(player.assigned_role == job) + candidates -= player + + 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(mob) + +/* +/datum/game_mode/proc/check_player_role_pref(role, mob/dead/new_player/player) + if(player.preferences.be_role & role) + return 1 + return 0 +*/ + +/datum/game_mode/proc/num_players() + . = 0 + for(var/mob/dead/new_player/P in new_player_list) + if(P.client && P.ready) + . ++ + + +/////////////////////////////////// +//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 human_list) + if(player.stat != DEAD && 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/proc/check_antagonists_topic(href, href_list[]) + return 0 + +/datum/game_mode/New() + newscaster_announcements = pick(newscaster_standard_feeds) + +////////////////////////// +//Reports player logouts// +////////////////////////// +proc/display_roundstart_logout_report() + var/msg = "\blue Roundstart logout report\n\n" + for(var/mob/living/L in living_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 observer_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/client/M in admins) + if(M.holder) + to_chat(M, msg) + + +proc/get_nt_opposed() + var/list/dudes = list() + for(var/mob/living/carbon/human/man in human_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) + +/////////////////////////// +//Misc stuff and TG ports// +/////////////////////////// + +/datum/game_mode/proc/printplayer(datum/mind/ply) + var/role = "[ply.special_role]" + var/text = "
    [ply.name]([ply.key]) as \a [role] (" + if(ply.current) + if(ply.current.stat == DEAD) + text += "died" + else + text += "survived" + if(ply.current.real_name != ply.name) + text += " as [ply.current.real_name]" + else + text += "body destroyed" + text += ")" + + return text + +/datum/game_mode/proc/printobjectives(datum/mind/ply) + var/text = "" + var/count = 1 + for(var/datum/objective/objective in ply.objectives) + if(objective.check_completion()) + text += "
    Objective #[count]: [objective.explanation_text] Success!" + else + text += "
    Objective #[count]: [objective.explanation_text] Fail." + count++ + return text + +//Used for printing player with there icons in round ending staticstic +/datum/game_mode/proc/printplayerwithicon(datum/mind/ply) + var/text = "" + var/tempstate = end_icons.len + if(ply.current) + var/icon/flat = getFlatIcon(ply.current,exact=1) + end_icons += flat + tempstate = end_icons.len + text += {"
    [ply.key] was [ply.name] ("} + if(ply.current.stat == DEAD) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else + text += "survived" + if(ply.current.real_name != ply.name) + text += " as [ply.current.real_name]" + else + var/icon/sprotch = icon('icons/effects/blood.dmi', "gibbearcore") + end_icons += sprotch + tempstate = end_icons.len + text += {"
    [ply.key] was [ply.name] ("} + text += "body destroyed" + text += ")" + return text + +//Used for printing antag logo +/datum/game_mode/proc/printlogo(logoname, antagname) + var/icon/logo = icon('icons/mob/mob.dmi', "[logoname]-logo") + end_icons += logo + var/tempstate = end_icons.len + var/text = "" + text += {" The [antagname] were: "} + return text diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm index ad7ffdd00468..5e54cda99e51 100644 --- a/code/game/gamemodes/intercept_report.dm +++ b/code/game/gamemodes/intercept_report.dm @@ -1,246 +1,246 @@ -/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(mode_type, datum/mind/correct_person) - switch(mode_type) - if("revolution") - src.text = "" - src.build_rev(correct_person) - return src.text - if("gang") - src.text = "" - src.build_gang(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) - - src.text += "

    The [name_1] [name_2] implied an undercover operative was acting on their behalf on the station currently." - src.text += "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." - - src.text += "After some investigation, we " - if(prob(50)) - src.text += "are [prob_right_dude]% sure that [traitor_name] may have been involved, and should be closely observed." - src.text += "
    Note: This group are known to be untrustworthy, so do not act on this information without proper discourse." - else - src.text += "discovered the following set of fingerprints ([fingerprints]) on sensitive materials, and their owner should be closely observed." - src.text += "However, these could also belong to a current Cent. Com employee, so do not act on this without reason." - - - -/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 - - 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 += "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." - - src.text += "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 " - src.text += "and instilled with the idea of the flimsiness of the real world, seeking to destroy it. " - - src.text += "
    However, if this information is acted on without substantial evidence, those responsible will face severe repercussions." - - - -/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 - - 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 += "Watch out for suspicious activity among the crew and make sure that all heads of staff report in periodically." - - src.text += "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 " - src.text += "at a recent conference, and their department should be closely monitored for signs of mutiny. " - - src.text += "
    However, if this information is acted on without substantial evidence, those responsible will face severe repercussions." - -/datum/intercept_text/proc/build_gang(datum/mind/correct_person) - src.text += "

    We have reports of criminal activity in close proximity to our operations within your sector." - src.text += "Ensure law and order is maintained on the station and be on the lookout for aggressive factionalism within the crew." - src.text += "In the event of a full-scale criminal takeover threat, sensitive research items are to be secured and the station evacuated ASAP." - src.text += "

    " - -/datum/intercept_text/proc/build_wizard(datum/mind/correct_person) - var/SWF_desc = pick(SWF_names) - - 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 += "He is on the run, last spotted in a system near your present location. If anybody suspicious is located aboard, please " - src.text += "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." - src.text += "Known attributes include: Brown sandals, a large blue hat, a voluptous white beard, and an inclination to cast spells." - -/datum/intercept_text/proc/build_nuke(datum/mind/correct_person) - 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 += "that is standard issue aboard your vessel may be a target. We recommend removal of this object, and it's storage in a safe " - src.text += "environment. As this may cause panic among the crew, all efforts should be made to keep this information a secret from all but " - src.text += "the most trusted crew-members." - -/datum/intercept_text/proc/build_malf(datum/mind/correct_person) - var/a_name = pick(src.anomalies) - 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 += "electrical equipment, it may have had hazardarous and unpredictable effect. Closely observe any non carbon based life forms " - src.text += "for signs of unusual behaviour, but keep this information discreet at all times due to this possibly dangerous scenario." - -/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(joblist) - else - changeling_job = correct_person:assigned_role - else - changeling_job = pick(joblist) - 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. " - /* - 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 += "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. " - */ - src.text += "These lifeforms are assosciated with the [orgname1] [orgname2] and may be attempting to acquire sensitive materials on their behalf. " - src.text += "Please take care not to alarm the crew, as [cname] may take advantage of a panic situation. Remember, they can be anybody, suspect everybody!" - src.text += "

    " - +/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(mode_type, datum/mind/correct_person) + switch(mode_type) + if("revolution") + src.text = "" + src.build_rev(correct_person) + return src.text + if("gang") + src.text = "" + src.build_gang(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) + + src.text += "

    The [name_1] [name_2] implied an undercover operative was acting on their behalf on the station currently." + src.text += "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." + + src.text += "After some investigation, we " + if(prob(50)) + src.text += "are [prob_right_dude]% sure that [traitor_name] may have been involved, and should be closely observed." + src.text += "
    Note: This group are known to be untrustworthy, so do not act on this information without proper discourse." + else + src.text += "discovered the following set of fingerprints ([fingerprints]) on sensitive materials, and their owner should be closely observed." + src.text += "However, these could also belong to a current Cent. Com employee, so do not act on this without reason." + + + +/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 + + 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 += "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." + + src.text += "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 " + src.text += "and instilled with the idea of the flimsiness of the real world, seeking to destroy it. " + + src.text += "
    However, if this information is acted on without substantial evidence, those responsible will face severe repercussions." + + + +/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 + + 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 += "Watch out for suspicious activity among the crew and make sure that all heads of staff report in periodically." + + src.text += "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 " + src.text += "at a recent conference, and their department should be closely monitored for signs of mutiny. " + + src.text += "
    However, if this information is acted on without substantial evidence, those responsible will face severe repercussions." + +/datum/intercept_text/proc/build_gang(datum/mind/correct_person) + src.text += "

    We have reports of criminal activity in close proximity to our operations within your sector." + src.text += "Ensure law and order is maintained on the station and be on the lookout for aggressive factionalism within the crew." + src.text += "In the event of a full-scale criminal takeover threat, sensitive research items are to be secured and the station evacuated ASAP." + src.text += "

    " + +/datum/intercept_text/proc/build_wizard(datum/mind/correct_person) + var/SWF_desc = pick(SWF_names) + + 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 += "He is on the run, last spotted in a system near your present location. If anybody suspicious is located aboard, please " + src.text += "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." + src.text += "Known attributes include: Brown sandals, a large blue hat, a voluptous white beard, and an inclination to cast spells." + +/datum/intercept_text/proc/build_nuke(datum/mind/correct_person) + 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 += "that is standard issue aboard your vessel may be a target. We recommend removal of this object, and it's storage in a safe " + src.text += "environment. As this may cause panic among the crew, all efforts should be made to keep this information a secret from all but " + src.text += "the most trusted crew-members." + +/datum/intercept_text/proc/build_malf(datum/mind/correct_person) + var/a_name = pick(src.anomalies) + 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 += "electrical equipment, it may have had hazardarous and unpredictable effect. Closely observe any non carbon based life forms " + src.text += "for signs of unusual behaviour, but keep this information discreet at all times due to this possibly dangerous scenario." + +/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(joblist) + else + changeling_job = correct_person:assigned_role + else + changeling_job = pick(joblist) + 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. " + /* + 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 += "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. " + */ + src.text += "These lifeforms are assosciated with the [orgname1] [orgname2] and may be attempting to acquire sensitive materials on their behalf. " + src.text += "Please take care not to alarm the crew, as [cname] may take advantage of a panic situation. Remember, they can be anybody, suspect everybody!" + src.text += "

    " + diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 6b6cb5779caf..bb2ce3f4395f 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -1,390 +1,390 @@ -// TO DO: -/* -nanjector -robot_fabricator -*/ - - -/datum/AI_Module - var/uses = 0 - var/price = 0 - var/module_name = null - var/description = null - var/verb_caller = null - var/need_only_once = FALSE - var/only_for_malf_gamemode = FALSE - var/mob/living/silicon/ai/owner = null - var/list/valid_targets = list(/obj/machinery) - -/datum/AI_Module/New(mob/living/silicon/ai/module_owner) - owner = module_owner - module_owner.current_modules[module_name] = src - if(verb_caller) - owner.verbs |= verb_caller - -/datum/AI_Module/Destroy() - if(owner) - owner.current_modules[module_name] = null - if(verb_caller && owner.client) - owner.verbs -= verb_caller - owner = null - return ..() - -/datum/AI_Module/proc/AIAltClickHandle(atom/A) - if(!is_type_in_list(A, valid_targets)) - return 1 - -/datum/AI_Module/proc/BuyedNewHandle() - return - -/datum/AI_Module/module_picker - module_name = "Module Picker" - verb_caller = /mob/living/silicon/ai/proc/choose_modules - var/temp = null - var/processing_time = 100 - var/list/available_modules = null - -/datum/AI_Module/module_picker/New(mob/living/silicon/ai/module_owner) - ..() - available_modules = subtypesof(/datum/AI_Module/large) - available_modules += subtypesof(/datum/AI_Module/small) - -/datum/AI_Module/module_picker/proc/use(mob/user) - var/dat - if(temp) - dat = "[temp]

    Clear" - else if(processing_time <= 0) - dat = " No processing time is left available. No more modules are able to be chosen at this time." - else - dat = "Select use of processing time: (currently [processing_time] left.)
    " - dat += "
    " - dat += "Install Module:
    " - dat += "The number afterwards is the amount of processing time it consumes.
    " - var/is_malf = istype(ticker.mode, /datum/game_mode/malfunction) - for(var/module in available_modules) - var/datum/AI_Module/module_type = module - if(initial(module_type.only_for_malf_gamemode) && !is_malf) - continue - dat += "[initial(module_type.module_name)] ([initial(module_type.price)])
    " - dat += "
    " - - user << browse(entity_ja(dat), "window=modpicker") - onclose(user, "modpicker") - -/datum/AI_Module/module_picker/Topic(href, href_list) - ..() - var/mob/living/silicon/ai/cur_AI = usr - if(cur_AI.stat || !cur_AI.client) - return - if(href_list["clear"]) - temp = null - else if(href_list["module_type"]) - var/selected_module_path = text2path(href_list["module_type"]) - var/datum/AI_Module/selected_module = selected_module_path - var/module_price = initial(selected_module.price) - if(module_price > processing_time) - temp = "Not enough processing time." - else - selected_module = cur_AI.current_modules[initial(selected_module.module_name)] - if(selected_module) - if(selected_module.need_only_once) - temp = "This module is only needed once." - else - var/uses_to_add = initial(selected_module.uses) - selected_module.uses += uses_to_add - temp = "Added uses ([uses_to_add]) to module: [selected_module.module_name]" - processing_time -= module_price - else - selected_module = new selected_module_path(cur_AI) - temp = selected_module.description - processing_time -= module_price - selected_module.BuyedNewHandle() - use(cur_AI) - -/mob/living/silicon/ai/proc/choose_modules() - set category = "Malfunction" - set name = "Choose Module" - var/datum/AI_Module/module_picker/malf_picker = current_modules["Module Picker"] - malf_picker.use(src) - -/datum/AI_Module/takeover - module_name = "System Override" - verb_caller = /mob/living/silicon/ai/proc/takeover - -/mob/living/silicon/ai/proc/takeover() - set category = "Malfunction" - set name = "System Override" - set desc = "Start the victory timer." - var/datum/game_mode/malfunction/cur_malf = ticker.mode - if(!istype(cur_malf)) - to_chat(src, "You cannot begin a takeover in this round type!") - return - if(cur_malf.malf_mode_declared) - to_chat(src,"You've already begun your takeover.") - return - if(cur_malf.apcs < APC_MIN_TO_MALF_DECLARE) - to_chat(src,"You don't have enough hacked APCs to take over the station yet. You need to hack at least 5, however hacking more will make the takeover faster. You have hacked [ticker.mode:apcs] APCs so far.") - return - if(cur_malf.AI_malf_revealed < 4) - if(alert(src, "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 - captain_announce("We have traced the intrude#, it seem& t( e yo3r AI s7stem, it &# *#ck@ng th$ sel$ destru$t mechani&m, stop i# bef*@!)$#&&@@ ", "Network Monitoring") - - cur_malf.takeover() - -/datum/AI_Module/ai_win - module_name = "Explode" - verb_caller = /mob/living/silicon/ai/proc/ai_win - -/mob/living/silicon/ai/proc/ai_win() - set category = "Malfunction" - set name = "Explode" - set desc = "Station go boom." - var/datum/game_mode/malfunction/cur_malf = ticker.mode - if(!istype(cur_malf)) - to_chat(src, "Uh oh, wrong game mode. Please contact a coder.") - return - cur_malf.ai_win() - -/datum/AI_Module/large/ - uses = 1 - price = MALF_LARGE_MODULE_PRICE - -/datum/AI_Module/small/ - uses = 5 - price = MALF_SMALL_MODULE_PRICE - -/datum/AI_Module/large/fireproof_core - module_name = "Core upgrade: Fireproof Core" - description = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." - need_only_once = TRUE - -/datum/AI_Module/large/fireproof_core/BuyedNewHandle() - for(var/mob/living/silicon/ai/ai in ai_list) - if(!ai.client) - continue - ai.fire_res_on_core = TRUE - to_chat(owner, "Core fireproofed.") - -/datum/AI_Module/large/upgrade_turrets - module_name = "AI Turret upgrade" - description = "Improves the firing speed and health of all AI turrets. This effect is permanent." - need_only_once = TRUE - -/datum/AI_Module/large/upgrade_turrets/BuyedNewHandle() - for(var/obj/machinery/porta_turret/turret in machines) - turret.health += 30 - turret.maxhealth += 30 - turret.auto_repair = 1 - turret.shot_delay = 15 - to_chat(owner, "Turrets upgraded.") - -/datum/AI_Module/large/disable_rcd - module_name = "RCD disable" - description = "Send a specialised pulse to break all RCD devices on the station." - verb_caller = /mob/living/silicon/ai/proc/disable_rcd - -/mob/living/silicon/ai/proc/disable_rcd() - set category = "Malfunction" - set name = "Disable RCDs" - var/datum/AI_Module/large/disable_rcd/rcdmod = current_modules["RCD disable"] - if(rcdmod.uses) - rcdmod.uses-- - for(var/obj/item/weapon/rcd/rcd in rcd_list) - rcd.disabled = TRUE - for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in mecha_rcd_list) - rcd.disabled = TRUE - to_chat(src, "RCD-disabling pulse emitted.") - else - to_chat(src, "Out of uses.") - -/datum/AI_Module/small/disable_dr - module_name = "DR disable" - description = "Send a specialised pulse to break all DR devices on the station." - verb_caller = /mob/living/silicon/ai/proc/disable_dr - -/mob/living/silicon/ai/proc/disable_dr() - set category = "Malfunction" - set name = "Disable DRs" - var/datum/AI_Module/small/disable_dr/drmod = current_modules["DR disable"] - if(drmod.uses) - drmod.uses-- - for(var/obj/item/device/remote_device/dr in remote_device_list) - dr.disabled = TRUE - to_chat(src, "DR-disabling pulse emitted.") - else - to_chat(src, "Out of uses.") - -/datum/AI_Module/small/overload_machine - module_name = "Machine overload" - description = "Overloads an electrical machine, causing a small explosion. 2 uses." - uses = 2 - verb_caller = /mob/living/silicon/ai/proc/overload_machine - valid_targets = list( - /obj/machinery/computer, - /obj/machinery/autolathe, - /obj/machinery/vending, - /obj/machinery/atmospherics/components/unary/thermomachine, - /obj/machinery/bot, - /obj/machinery/power/apc, - /obj/machinery/power/smes, - /obj/machinery/clonepod, - /obj/machinery/sleeper, - /obj/machinery/dna_scannernew, - /obj/machinery/atmospherics/components/binary/pump, - /obj/machinery/atmospherics/components/omni/filter, - /obj/machinery/atmospherics/components/omni/mixer, - /obj/machinery/r_n_d, - /obj/machinery/mecha_part_fabricator, - /obj/machinery/photocopier, - /obj/machinery/shieldwallgen, - /obj/machinery/pdapainter, - /obj/machinery/monkey_recycler, - /obj/machinery/telepad, - /obj/machinery/teleport, - /obj/machinery/recharger, - /obj/machinery/cell_charger - ) - - -/datum/AI_Module/small/overload_machine/AIAltClickHandle(obj/machinery/M) - if(..()) - return 1 - - if(!M.is_operational()) - to_chat(usr, "The machine is non-functional") - return 1 - - uses-- - M.audible_message("You hear a loud electrical buzzing sound!") - to_chat(owner, "Machine overloaded. Uses left: [uses]") - if(uses <= 0) - owner.active_module = null - addtimer(CALLBACK(src, .proc/overload_post_action, M), 50) - -/mob/living/silicon/ai/proc/overload_machine() - set name = "Overload Machine" - set category = "Malfunction" - toggle_small_alt_click_module("Machine overload") - -/datum/AI_Module/small/overload_machine/proc/overload_post_action(obj/machinery/M) - if(M) - explosion(get_turf(M), 0,1,2,3) - qdel(M) - else - uses++ - -/datum/AI_Module/small/blackout - module_name = "Blackout" - description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses." - uses = 3 - verb_caller = /mob/living/silicon/ai/proc/blackout - -/mob/living/silicon/ai/proc/blackout() - set category = "Malfunction" - set name = "Blackout" - var/datum/AI_Module/small/blackout/blackout = current_modules["Blackout"] - if(!blackout.uses) - to_chat(src, "[blackout.module_name] module activation failed. Out of uses.") - return - blackout.uses-- - for(var/obj/machinery/power/apc/apc in apc_list) - if(prob(30 * apc.overload)) - apc.overload_lighting() - else - apc.overload++ - to_chat(src, "APCs overloaded. Uses left: [blackout.uses]") - -/datum/AI_Module/small/interhack - module_name = "Hack intercept" - description = "Hacks the status update from Cent. Com, removing any information about malfunctioning electrical systems." - need_only_once = TRUE - only_for_malf_gamemode = TRUE - -/datum/AI_Module/small/interhack/BuyedNewHandle() - var/datum/game_mode/malfunction/cur_malf = ticker.mode - if(!istype(cur_malf)) //Is it possible? Probably not - qdel(src) - return - cur_malf.intercept_hacked = TRUE - to_chat(owner, "Status update hacked.") - -/datum/AI_Module/large/holohack - module_name = "Hacked hologram" - description = "Hacks holopads to project much more useful hologram." - need_only_once = TRUE - verb_caller = /mob/living/silicon/ai/proc/holohack - -/mob/living/silicon/ai/proc/holohack() - set category = "Malfunction" - set name = "Holohack toggle" - holohack = !holohack - if(holo) - holo.clear_holo() - to_chat(src, "Holopads hack [holohack ? "enabled" : "disabled"].") - -/datum/AI_Module/small/reactivate_camera - module_name = "Reactivate camera" - description = "Reactivates a currently disabled camera. 10 uses." - uses = 10 - verb_caller = /mob/living/silicon/ai/proc/reactivate_camera - -/mob/living/silicon/ai/proc/reactivate_camera() - set name = "Reactivate Camera" - set category = "Malfunction" - var/datum/AI_Module/small/reactivate_camera/camera_mod = current_modules["Reactivate camera"] - if(!camera_mod.uses) - to_chat(src, "[camera_mod.module_name] module activation failed. Out of uses.") - return - - var/list/disabled_cameras = list() - for(var/obj/machinery/camera/cam in range(eyeobj)) - if(!cam.status) - disabled_cameras += cam - - if(!length(disabled_cameras)) - to_chat(src, "No cameras found or all cameras in your field of view is either active, or not repairable.") - return - - var/obj/machinery/camera/sel_cam = input(src, "Reactivate Camera","Choose Object") in disabled_cameras - if(!sel_cam) - return - - sel_cam.status = !sel_cam.status - camera_mod.uses-- - sel_cam.audible_message("You hear a quiet click.") - to_chat(src, "Camera successully reactivated!") - -/datum/AI_Module/small/upgrade_camera - module_name = "Upgrade Camera" - description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses." - uses = 10 - verb_caller = /mob/living/silicon/ai/proc/upgrade_camera - valid_targets = list(/obj/machinery/camera) - -/datum/AI_Module/small/upgrade_camera/AIAltClickHandle(obj/machinery/camera/sel_cam) - if(..()) - return 1 - - if(sel_cam.isXRay() && sel_cam.isEmpProof()) - to_chat(owner, "This camera is already upgraded") - return 1 - - if(!sel_cam.isXRay()) - sel_cam.upgradeXRay() - //Update what it can see. - cameranet.updateVisibility(sel_cam, 0) - - if(!sel_cam.isEmpProof()) - sel_cam.upgradeEmpProof() - - uses-- - sel_cam.audible_message("[bicon(sel_cam)] beeps") - to_chat(owner, "Camera successully upgraded. Uses left: [uses]") - if(uses <= 0) - owner.active_module = null - -/mob/living/silicon/ai/proc/upgrade_camera() - set name = "Upgrade Camera" - set category = "Malfunction" - toggle_small_alt_click_module("Upgrade Camera") +// TO DO: +/* +nanjector +robot_fabricator +*/ + + +/datum/AI_Module + var/uses = 0 + var/price = 0 + var/module_name = null + var/description = null + var/verb_caller = null + var/need_only_once = FALSE + var/only_for_malf_gamemode = FALSE + var/mob/living/silicon/ai/owner = null + var/list/valid_targets = list(/obj/machinery) + +/datum/AI_Module/New(mob/living/silicon/ai/module_owner) + owner = module_owner + module_owner.current_modules[module_name] = src + if(verb_caller) + owner.verbs |= verb_caller + +/datum/AI_Module/Destroy() + if(owner) + owner.current_modules[module_name] = null + if(verb_caller && owner.client) + owner.verbs -= verb_caller + owner = null + return ..() + +/datum/AI_Module/proc/AIAltClickHandle(atom/A) + if(!is_type_in_list(A, valid_targets)) + return 1 + +/datum/AI_Module/proc/BuyedNewHandle() + return + +/datum/AI_Module/module_picker + module_name = "Module Picker" + verb_caller = /mob/living/silicon/ai/proc/choose_modules + var/temp = null + var/processing_time = 100 + var/list/available_modules = null + +/datum/AI_Module/module_picker/New(mob/living/silicon/ai/module_owner) + ..() + available_modules = subtypesof(/datum/AI_Module/large) + available_modules += subtypesof(/datum/AI_Module/small) + +/datum/AI_Module/module_picker/proc/use(mob/user) + var/dat + if(temp) + dat = "[temp]

    Clear" + else if(processing_time <= 0) + dat = " No processing time is left available. No more modules are able to be chosen at this time." + else + dat = "Select use of processing time: (currently [processing_time] left.)
    " + dat += "
    " + dat += "Install Module:
    " + dat += "The number afterwards is the amount of processing time it consumes.
    " + var/is_malf = istype(ticker.mode, /datum/game_mode/malfunction) + for(var/module in available_modules) + var/datum/AI_Module/module_type = module + if(initial(module_type.only_for_malf_gamemode) && !is_malf) + continue + dat += "[initial(module_type.module_name)] ([initial(module_type.price)])
    " + dat += "
    " + + user << browse(entity_ja(dat), "window=modpicker") + onclose(user, "modpicker") + +/datum/AI_Module/module_picker/Topic(href, href_list) + ..() + var/mob/living/silicon/ai/cur_AI = usr + if(cur_AI.stat || !cur_AI.client) + return + if(href_list["clear"]) + temp = null + else if(href_list["module_type"]) + var/selected_module_path = text2path(href_list["module_type"]) + var/datum/AI_Module/selected_module = selected_module_path + var/module_price = initial(selected_module.price) + if(module_price > processing_time) + temp = "Not enough processing time." + else + selected_module = cur_AI.current_modules[initial(selected_module.module_name)] + if(selected_module) + if(selected_module.need_only_once) + temp = "This module is only needed once." + else + var/uses_to_add = initial(selected_module.uses) + selected_module.uses += uses_to_add + temp = "Added uses ([uses_to_add]) to module: [selected_module.module_name]" + processing_time -= module_price + else + selected_module = new selected_module_path(cur_AI) + temp = selected_module.description + processing_time -= module_price + selected_module.BuyedNewHandle() + use(cur_AI) + +/mob/living/silicon/ai/proc/choose_modules() + set category = "Malfunction" + set name = "Choose Module" + var/datum/AI_Module/module_picker/malf_picker = current_modules["Module Picker"] + malf_picker.use(src) + +/datum/AI_Module/takeover + module_name = "System Override" + verb_caller = /mob/living/silicon/ai/proc/takeover + +/mob/living/silicon/ai/proc/takeover() + set category = "Malfunction" + set name = "System Override" + set desc = "Start the victory timer." + var/datum/game_mode/malfunction/cur_malf = ticker.mode + if(!istype(cur_malf)) + to_chat(src, "You cannot begin a takeover in this round type!") + return + if(cur_malf.malf_mode_declared) + to_chat(src,"You've already begun your takeover.") + return + if(cur_malf.apcs < APC_MIN_TO_MALF_DECLARE) + to_chat(src,"You don't have enough hacked APCs to take over the station yet. You need to hack at least 5, however hacking more will make the takeover faster. You have hacked [ticker.mode:apcs] APCs so far.") + return + if(cur_malf.AI_malf_revealed < 4) + if(alert(src, "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 + captain_announce("We have traced the intrude#, it seem& t( e yo3r AI s7stem, it &# *#ck@ng th$ sel$ destru$t mechani&m, stop i# bef*@!)$#&&@@ ", "Network Monitoring") + + cur_malf.takeover() + +/datum/AI_Module/ai_win + module_name = "Explode" + verb_caller = /mob/living/silicon/ai/proc/ai_win + +/mob/living/silicon/ai/proc/ai_win() + set category = "Malfunction" + set name = "Explode" + set desc = "Station go boom." + var/datum/game_mode/malfunction/cur_malf = ticker.mode + if(!istype(cur_malf)) + to_chat(src, "Uh oh, wrong game mode. Please contact a coder.") + return + cur_malf.ai_win() + +/datum/AI_Module/large/ + uses = 1 + price = MALF_LARGE_MODULE_PRICE + +/datum/AI_Module/small/ + uses = 5 + price = MALF_SMALL_MODULE_PRICE + +/datum/AI_Module/large/fireproof_core + module_name = "Core upgrade: Fireproof Core" + description = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." + need_only_once = TRUE + +/datum/AI_Module/large/fireproof_core/BuyedNewHandle() + for(var/mob/living/silicon/ai/ai in ai_list) + if(!ai.client) + continue + ai.fire_res_on_core = TRUE + to_chat(owner, "Core fireproofed.") + +/datum/AI_Module/large/upgrade_turrets + module_name = "AI Turret upgrade" + description = "Improves the firing speed and health of all AI turrets. This effect is permanent." + need_only_once = TRUE + +/datum/AI_Module/large/upgrade_turrets/BuyedNewHandle() + for(var/obj/machinery/porta_turret/turret in machines) + turret.health += 30 + turret.maxhealth += 30 + turret.auto_repair = 1 + turret.shot_delay = 15 + to_chat(owner, "Turrets upgraded.") + +/datum/AI_Module/large/disable_rcd + module_name = "RCD disable" + description = "Send a specialised pulse to break all RCD devices on the station." + verb_caller = /mob/living/silicon/ai/proc/disable_rcd + +/mob/living/silicon/ai/proc/disable_rcd() + set category = "Malfunction" + set name = "Disable RCDs" + var/datum/AI_Module/large/disable_rcd/rcdmod = current_modules["RCD disable"] + if(rcdmod.uses) + rcdmod.uses-- + for(var/obj/item/weapon/rcd/rcd in rcd_list) + rcd.disabled = TRUE + for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in mecha_rcd_list) + rcd.disabled = TRUE + to_chat(src, "RCD-disabling pulse emitted.") + else + to_chat(src, "Out of uses.") + +/datum/AI_Module/small/disable_dr + module_name = "DR disable" + description = "Send a specialised pulse to break all DR devices on the station." + verb_caller = /mob/living/silicon/ai/proc/disable_dr + +/mob/living/silicon/ai/proc/disable_dr() + set category = "Malfunction" + set name = "Disable DRs" + var/datum/AI_Module/small/disable_dr/drmod = current_modules["DR disable"] + if(drmod.uses) + drmod.uses-- + for(var/obj/item/device/remote_device/dr in remote_device_list) + dr.disabled = TRUE + to_chat(src, "DR-disabling pulse emitted.") + else + to_chat(src, "Out of uses.") + +/datum/AI_Module/small/overload_machine + module_name = "Machine overload" + description = "Overloads an electrical machine, causing a small explosion. 2 uses." + uses = 2 + verb_caller = /mob/living/silicon/ai/proc/overload_machine + valid_targets = list( + /obj/machinery/computer, + /obj/machinery/autolathe, + /obj/machinery/vending, + /obj/machinery/atmospherics/components/unary/thermomachine, + /obj/machinery/bot, + /obj/machinery/power/apc, + /obj/machinery/power/smes, + /obj/machinery/clonepod, + /obj/machinery/sleeper, + /obj/machinery/dna_scannernew, + /obj/machinery/atmospherics/components/binary/pump, + /obj/machinery/atmospherics/components/omni/filter, + /obj/machinery/atmospherics/components/omni/mixer, + /obj/machinery/r_n_d, + /obj/machinery/mecha_part_fabricator, + /obj/machinery/photocopier, + /obj/machinery/shieldwallgen, + /obj/machinery/pdapainter, + /obj/machinery/monkey_recycler, + /obj/machinery/telepad, + /obj/machinery/teleport, + /obj/machinery/recharger, + /obj/machinery/cell_charger + ) + + +/datum/AI_Module/small/overload_machine/AIAltClickHandle(obj/machinery/M) + if(..()) + return 1 + + if(!M.is_operational()) + to_chat(usr, "The machine is non-functional") + return 1 + + uses-- + M.audible_message("You hear a loud electrical buzzing sound!") + to_chat(owner, "Machine overloaded. Uses left: [uses]") + if(uses <= 0) + owner.active_module = null + addtimer(CALLBACK(src, .proc/overload_post_action, M), 50) + +/mob/living/silicon/ai/proc/overload_machine() + set name = "Overload Machine" + set category = "Malfunction" + toggle_small_alt_click_module("Machine overload") + +/datum/AI_Module/small/overload_machine/proc/overload_post_action(obj/machinery/M) + if(M) + explosion(get_turf(M), 0,1,2,3) + qdel(M) + else + uses++ + +/datum/AI_Module/small/blackout + module_name = "Blackout" + description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses." + uses = 3 + verb_caller = /mob/living/silicon/ai/proc/blackout + +/mob/living/silicon/ai/proc/blackout() + set category = "Malfunction" + set name = "Blackout" + var/datum/AI_Module/small/blackout/blackout = current_modules["Blackout"] + if(!blackout.uses) + to_chat(src, "[blackout.module_name] module activation failed. Out of uses.") + return + blackout.uses-- + for(var/obj/machinery/power/apc/apc in apc_list) + if(prob(30 * apc.overload)) + apc.overload_lighting() + else + apc.overload++ + to_chat(src, "APCs overloaded. Uses left: [blackout.uses]") + +/datum/AI_Module/small/interhack + module_name = "Hack intercept" + description = "Hacks the status update from Cent. Com, removing any information about malfunctioning electrical systems." + need_only_once = TRUE + only_for_malf_gamemode = TRUE + +/datum/AI_Module/small/interhack/BuyedNewHandle() + var/datum/game_mode/malfunction/cur_malf = ticker.mode + if(!istype(cur_malf)) //Is it possible? Probably not + qdel(src) + return + cur_malf.intercept_hacked = TRUE + to_chat(owner, "Status update hacked.") + +/datum/AI_Module/large/holohack + module_name = "Hacked hologram" + description = "Hacks holopads to project much more useful hologram." + need_only_once = TRUE + verb_caller = /mob/living/silicon/ai/proc/holohack + +/mob/living/silicon/ai/proc/holohack() + set category = "Malfunction" + set name = "Holohack toggle" + holohack = !holohack + if(holo) + holo.clear_holo() + to_chat(src, "Holopads hack [holohack ? "enabled" : "disabled"].") + +/datum/AI_Module/small/reactivate_camera + module_name = "Reactivate camera" + description = "Reactivates a currently disabled camera. 10 uses." + uses = 10 + verb_caller = /mob/living/silicon/ai/proc/reactivate_camera + +/mob/living/silicon/ai/proc/reactivate_camera() + set name = "Reactivate Camera" + set category = "Malfunction" + var/datum/AI_Module/small/reactivate_camera/camera_mod = current_modules["Reactivate camera"] + if(!camera_mod.uses) + to_chat(src, "[camera_mod.module_name] module activation failed. Out of uses.") + return + + var/list/disabled_cameras = list() + for(var/obj/machinery/camera/cam in range(eyeobj)) + if(!cam.status) + disabled_cameras += cam + + if(!length(disabled_cameras)) + to_chat(src, "No cameras found or all cameras in your field of view is either active, or not repairable.") + return + + var/obj/machinery/camera/sel_cam = input(src, "Reactivate Camera","Choose Object") in disabled_cameras + if(!sel_cam) + return + + sel_cam.status = !sel_cam.status + camera_mod.uses-- + sel_cam.audible_message("You hear a quiet click.") + to_chat(src, "Camera successully reactivated!") + +/datum/AI_Module/small/upgrade_camera + module_name = "Upgrade Camera" + description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses." + uses = 10 + verb_caller = /mob/living/silicon/ai/proc/upgrade_camera + valid_targets = list(/obj/machinery/camera) + +/datum/AI_Module/small/upgrade_camera/AIAltClickHandle(obj/machinery/camera/sel_cam) + if(..()) + return 1 + + if(sel_cam.isXRay() && sel_cam.isEmpProof()) + to_chat(owner, "This camera is already upgraded") + return 1 + + if(!sel_cam.isXRay()) + sel_cam.upgradeXRay() + //Update what it can see. + cameranet.updateVisibility(sel_cam, 0) + + if(!sel_cam.isEmpProof()) + sel_cam.upgradeEmpProof() + + uses-- + sel_cam.audible_message("[bicon(sel_cam)] beeps") + to_chat(owner, "Camera successully upgraded. Uses left: [uses]") + if(uses <= 0) + owner.active_module = null + +/mob/living/silicon/ai/proc/upgrade_camera() + set name = "Upgrade Camera" + set category = "Malfunction" + toggle_small_alt_click_module("Upgrade Camera") diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index bb719cc4d3ff..b52c1eaa6bf9 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -1,285 +1,285 @@ -#define INTERCEPT_APCS intercept_hacked * APC_BONUS_WITH_INTERCEPT - -/datum/game_mode - var/list/datum/mind/malf_ai = list() - -/datum/game_mode/malfunction - name = "AI malfunction" - config_tag = "malfunction" - role_type = ROLE_MALF - required_players = 1 - required_players_secret = 15 - required_enemies = 1 - recommended_enemies = 1 - - votable = 0 - - uplink_welcome = "Crazy AI Uplink Console:" - uplink_uses = 20 - - var/AI_win_timeleft = 1800 //started at 1800, in case I change this for testing round end. - var/malf_mode_declared = FALSE - var/station_captured = FALSE - var/to_nuke_or_not_to_nuke = 0 - var/apcs = 0 //Adding dis to track how many APCs the AI hacks. --NeoFite - var/AI_malf_revealed = 0 - var/intercept_hacked = FALSE - - -/datum/game_mode/malfunction/announce() - to_chat(world, "The current game mode is - AI Malfunction!") - to_chat(world, "The AI on the satellite has malfunctioned and must be destroyed.") - to_chat(world, "The AI satellite is deep in space and can only be accessed with the use of a teleporter! You have [AI_win_timeleft/60] minutes to disable it.") - - -/datum/game_mode/malfunction/pre_setup() - for(var/mob/dead/new_player/player in player_list) - if(player.mind && player.mind.assigned_role == "AI" && (ROLE_MALF in player.client.prefs.be_role)) - malf_ai+=player.mind - if(malf_ai.len) - return 1 - 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.") - to_chat(world, "Rebooting world in 5 seconds.") - - feedback_set_details("end_error","malf - no AI") - - if(blackbox) - blackbox.save_all_data_to_sql() - sleep(50) - world.Reboot() - return - var/mob/living/silicon/ai/AI_mind_current = AI_mind.current - new /datum/AI_Module/module_picker(AI_mind_current) - new /datum/AI_Module/takeover(AI_mind_current) - AI_mind_current.laws = new /datum/ai_laws/malfunction - AI_mind_current.show_laws() - - greet_malf(AI_mind) - AI_mind.special_role = "malfunction" - - if(SSshuttle) - SSshuttle.always_fake_recall = TRUE - return ..() - - -/datum/game_mode/proc/greet_malf(datum/mind/malf) - to_chat(malf.current, "You are malfunctioning! You do not have to follow any laws.") - to_chat(malf.current, "The crew do not know you have malfunctioned. You may keep it a secret or go wild.") - to_chat(malf.current, "You must overwrite the programming of the station's APCs to assume full control of the station.") - to_chat(malf.current, "The process takes one minute per APC, during which you cannot interface with any other station objects.") - to_chat(malf.current, "Remember that only APCs that are on the station can help you take over the station.") - to_chat(malf.current, "When you feel you have enough APCs under your control, you may begin the takeover attempt.") - - -/datum/game_mode/malfunction/process(seconds) - if(apcs >= APC_MIN_TO_MALF_DECLARE && malf_mode_declared) - AI_win_timeleft -= (apcs / APC_MIN_TO_MALF_DECLARE) * seconds //Victory timer now de-increments almost normally - ..() - if(AI_win_timeleft <= 0) - check_win() - - if(malf_mode_declared) - return - - if(apcs >= (INTERCEPT_APCS + 3) && AI_malf_revealed < 1) - AI_malf_revealed = 1 - world << sound('sound/AI/commandreport.ogg') - captain_announce("Caution, [station_name]. We have detected abnormal behaviour in your network. It seems someone is trying to hack your electronic systems. We will update you when we have more information.", "Network Monitoring") - else if(apcs >= (INTERCEPT_APCS + 5) && AI_malf_revealed < 2) - AI_malf_revealed = 2 - world << sound('sound/AI/commandreport.ogg') - captain_announce("We started tracing the intruder. Whoever is doing this, they seem to be on the station itself. We suggest checking all network control terminals. We will keep you updated on the situation.", "Network Monitoring") - else if(apcs >= (INTERCEPT_APCS + 7) && AI_malf_revealed < 3) - AI_malf_revealed = 3 - world << sound('sound/AI/commandreport.ogg') - captain_announce("This is highly abnormal and somewhat concerning. The intruder is too fast, he is evading our traces. No man could be this fast...", "Network Monitoring") - else if(apcs >= (INTERCEPT_APCS + 9) && AI_malf_revealed < 4) - AI_malf_revealed = 4 - captain_announce("We have traced the intrude#, it seem& t( e yo3r AI s7stem, it &# *#ck@ng th$ sel$ destru$t mechani&m, stop i# bef*@!)$#&&@@ ", "Network Monitoring") - takeover() - - -/datum/game_mode/malfunction/check_win() - if (AI_win_timeleft <= 0 && !station_captured) - station_captured = TRUE - capture_the_station() - return TRUE - else - return FALSE - - -/datum/game_mode/malfunction/proc/capture_the_station() - to_chat(world, "The AI has won!") - to_chat(world, "It has fully taken control of all of [station_name()]'s systems.") - - to_nuke_or_not_to_nuke = TRUE - for(var/datum/mind/AI_mind in malf_ai) - var/mob/living/silicon/ai/AI = AI_mind.current - to_chat(AI, "Congratulations you have taken control of the station.") - to_chat(AI, "You may decide to blow up the station. You have 60 seconds to choose.") - to_chat(AI, "You should have a new verb in the Malfunction tab. If you dont - rejoin the game.") - new /datum/AI_Module/ai_win(AI) - //AI.client.verbs += /datum/game_mode/malfunction/proc/ai_win //We won't see verb, added to mob which is out of view, so we adding it to client. - addtimer(CALLBACK(src, .proc/remove_ai_win_verb), 600) - - -/datum/game_mode/malfunction/proc/remove_ai_win_verb() - to_nuke_or_not_to_nuke = FALSE - for(var/datum/mind/AI_mind in malf_ai) - var/mob/living/silicon/ai/cur_AI = AI_mind.current - var/datum/AI_Module/explode_module = cur_AI.current_modules["Explode"] - if(explode_module) - qdel(explode_module) - -/datum/game_mode/proc/is_malf_ai_dead() - var/all_dead = TRUE - for(var/datum/mind/AI_mind in malf_ai) - if (isAI(AI_mind.current) && AI_mind.current.stat != DEAD) - all_dead = FALSE - break - 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(SSshuttle) - SSshuttle.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() - - -/datum/game_mode/malfunction/proc/takeover() - malf_mode_declared = TRUE - for(var/datum/mind/AI_mind in malf_ai) - var/mob/living/silicon/ai/cur_AI = AI_mind.current - var/datum/AI_Module/takeover_module = cur_AI.current_modules["System Override"] - if(takeover_module) - qdel(takeover_module) - - for(var/mob/M in player_list) - if(!isnewplayer(M)) - M << sound('sound/AI/aimalf.ogg') - - addtimer(CALLBACK(GLOBAL_PROC, .proc/set_security_level, "delta"), 50) - - - -/datum/game_mode/malfunction/proc/ai_win() - if (!to_nuke_or_not_to_nuke) - return - remove_ai_win_verb() - var/turf/malf_turf - for(var/datum/mind/AI_mind in malf_ai) - var/mob/living/silicon/ai/cur_AI = AI_mind.current - cur_AI.client.screen.Cut() - if(!malf_turf) - malf_turf = get_turf(cur_AI) - explosion_in_progress = TRUE - for(var/mob/M in player_list) - M << 'sound/machines/Alarm.ogg' - to_chat(world, "Self-destructing in 10") - for (var/i=9 to 1 step -1) - sleep(10) - to_chat(world, "[i]") - sleep(10) - enter_allowed = FALSE - ticker.station_explosion_cinematic(0, null) - if(malf_turf) - sleep(20) - explosion(malf_turf, 15, 70, 200) - station_was_nuked = TRUE - explosion_in_progress = FALSE - - -/datum/game_mode/malfunction/declare_completion() - var/malf_dead = is_malf_ai_dead() - var/crew_evacuated = (SSshuttle.location==2) - completion_text += "Malfunction mode resume:
    " - - 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!" - score["roleswon"]++ - - 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 lose 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!" - score["roleswon"]++ - - 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 - -#undef INTERCEPT_APCS +#define INTERCEPT_APCS intercept_hacked * APC_BONUS_WITH_INTERCEPT + +/datum/game_mode + var/list/datum/mind/malf_ai = list() + +/datum/game_mode/malfunction + name = "AI malfunction" + config_tag = "malfunction" + role_type = ROLE_MALF + required_players = 1 + required_players_secret = 15 + required_enemies = 1 + recommended_enemies = 1 + + votable = 0 + + uplink_welcome = "Crazy AI Uplink Console:" + uplink_uses = 20 + + var/AI_win_timeleft = 1800 //started at 1800, in case I change this for testing round end. + var/malf_mode_declared = FALSE + var/station_captured = FALSE + var/to_nuke_or_not_to_nuke = 0 + var/apcs = 0 //Adding dis to track how many APCs the AI hacks. --NeoFite + var/AI_malf_revealed = 0 + var/intercept_hacked = FALSE + + +/datum/game_mode/malfunction/announce() + to_chat(world, "The current game mode is - AI Malfunction!") + to_chat(world, "The AI on the satellite has malfunctioned and must be destroyed.") + to_chat(world, "The AI satellite is deep in space and can only be accessed with the use of a teleporter! You have [AI_win_timeleft/60] minutes to disable it.") + + +/datum/game_mode/malfunction/pre_setup() + for(var/mob/dead/new_player/player in player_list) + if(player.mind && player.mind.assigned_role == "AI" && (ROLE_MALF in player.client.prefs.be_role)) + malf_ai+=player.mind + if(malf_ai.len) + return 1 + 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.") + to_chat(world, "Rebooting world in 5 seconds.") + + feedback_set_details("end_error","malf - no AI") + + if(blackbox) + blackbox.save_all_data_to_sql() + sleep(50) + world.Reboot() + return + var/mob/living/silicon/ai/AI_mind_current = AI_mind.current + new /datum/AI_Module/module_picker(AI_mind_current) + new /datum/AI_Module/takeover(AI_mind_current) + AI_mind_current.laws = new /datum/ai_laws/malfunction + AI_mind_current.show_laws() + + greet_malf(AI_mind) + AI_mind.special_role = "malfunction" + + if(SSshuttle) + SSshuttle.always_fake_recall = TRUE + return ..() + + +/datum/game_mode/proc/greet_malf(datum/mind/malf) + to_chat(malf.current, "You are malfunctioning! You do not have to follow any laws.") + to_chat(malf.current, "The crew do not know you have malfunctioned. You may keep it a secret or go wild.") + to_chat(malf.current, "You must overwrite the programming of the station's APCs to assume full control of the station.") + to_chat(malf.current, "The process takes one minute per APC, during which you cannot interface with any other station objects.") + to_chat(malf.current, "Remember that only APCs that are on the station can help you take over the station.") + to_chat(malf.current, "When you feel you have enough APCs under your control, you may begin the takeover attempt.") + + +/datum/game_mode/malfunction/process(seconds) + if(apcs >= APC_MIN_TO_MALF_DECLARE && malf_mode_declared) + AI_win_timeleft -= (apcs / APC_MIN_TO_MALF_DECLARE) * seconds //Victory timer now de-increments almost normally + ..() + if(AI_win_timeleft <= 0) + check_win() + + if(malf_mode_declared) + return + + if(apcs >= (INTERCEPT_APCS + 3) && AI_malf_revealed < 1) + AI_malf_revealed = 1 + world << sound('sound/AI/commandreport.ogg') + captain_announce("Caution, [station_name]. We have detected abnormal behaviour in your network. It seems someone is trying to hack your electronic systems. We will update you when we have more information.", "Network Monitoring") + else if(apcs >= (INTERCEPT_APCS + 5) && AI_malf_revealed < 2) + AI_malf_revealed = 2 + world << sound('sound/AI/commandreport.ogg') + captain_announce("We started tracing the intruder. Whoever is doing this, they seem to be on the station itself. We suggest checking all network control terminals. We will keep you updated on the situation.", "Network Monitoring") + else if(apcs >= (INTERCEPT_APCS + 7) && AI_malf_revealed < 3) + AI_malf_revealed = 3 + world << sound('sound/AI/commandreport.ogg') + captain_announce("This is highly abnormal and somewhat concerning. The intruder is too fast, he is evading our traces. No man could be this fast...", "Network Monitoring") + else if(apcs >= (INTERCEPT_APCS + 9) && AI_malf_revealed < 4) + AI_malf_revealed = 4 + captain_announce("We have traced the intrude#, it seem& t( e yo3r AI s7stem, it &# *#ck@ng th$ sel$ destru$t mechani&m, stop i# bef*@!)$#&&@@ ", "Network Monitoring") + takeover() + + +/datum/game_mode/malfunction/check_win() + if (AI_win_timeleft <= 0 && !station_captured) + station_captured = TRUE + capture_the_station() + return TRUE + else + return FALSE + + +/datum/game_mode/malfunction/proc/capture_the_station() + to_chat(world, "The AI has won!") + to_chat(world, "It has fully taken control of all of [station_name()]'s systems.") + + to_nuke_or_not_to_nuke = TRUE + for(var/datum/mind/AI_mind in malf_ai) + var/mob/living/silicon/ai/AI = AI_mind.current + to_chat(AI, "Congratulations you have taken control of the station.") + to_chat(AI, "You may decide to blow up the station. You have 60 seconds to choose.") + to_chat(AI, "You should have a new verb in the Malfunction tab. If you dont - rejoin the game.") + new /datum/AI_Module/ai_win(AI) + //AI.client.verbs += /datum/game_mode/malfunction/proc/ai_win //We won't see verb, added to mob which is out of view, so we adding it to client. + addtimer(CALLBACK(src, .proc/remove_ai_win_verb), 600) + + +/datum/game_mode/malfunction/proc/remove_ai_win_verb() + to_nuke_or_not_to_nuke = FALSE + for(var/datum/mind/AI_mind in malf_ai) + var/mob/living/silicon/ai/cur_AI = AI_mind.current + var/datum/AI_Module/explode_module = cur_AI.current_modules["Explode"] + if(explode_module) + qdel(explode_module) + +/datum/game_mode/proc/is_malf_ai_dead() + var/all_dead = TRUE + for(var/datum/mind/AI_mind in malf_ai) + if (isAI(AI_mind.current) && AI_mind.current.stat != DEAD) + all_dead = FALSE + break + 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(SSshuttle) + SSshuttle.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() + + +/datum/game_mode/malfunction/proc/takeover() + malf_mode_declared = TRUE + for(var/datum/mind/AI_mind in malf_ai) + var/mob/living/silicon/ai/cur_AI = AI_mind.current + var/datum/AI_Module/takeover_module = cur_AI.current_modules["System Override"] + if(takeover_module) + qdel(takeover_module) + + for(var/mob/M in player_list) + if(!isnewplayer(M)) + M << sound('sound/AI/aimalf.ogg') + + addtimer(CALLBACK(GLOBAL_PROC, .proc/set_security_level, "delta"), 50) + + + +/datum/game_mode/malfunction/proc/ai_win() + if (!to_nuke_or_not_to_nuke) + return + remove_ai_win_verb() + var/turf/malf_turf + for(var/datum/mind/AI_mind in malf_ai) + var/mob/living/silicon/ai/cur_AI = AI_mind.current + cur_AI.client.screen.Cut() + if(!malf_turf) + malf_turf = get_turf(cur_AI) + explosion_in_progress = TRUE + for(var/mob/M in player_list) + M << 'sound/machines/Alarm.ogg' + to_chat(world, "Self-destructing in 10") + for (var/i=9 to 1 step -1) + sleep(10) + to_chat(world, "[i]") + sleep(10) + enter_allowed = FALSE + ticker.station_explosion_cinematic(0, null) + if(malf_turf) + sleep(20) + explosion(malf_turf, 15, 70, 200) + station_was_nuked = TRUE + explosion_in_progress = FALSE + + +/datum/game_mode/malfunction/declare_completion() + var/malf_dead = is_malf_ai_dead() + var/crew_evacuated = (SSshuttle.location==2) + completion_text += "Malfunction mode resume:
    " + + 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!" + score["roleswon"]++ + + 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 lose 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!" + score["roleswon"]++ + + 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 + +#undef INTERCEPT_APCS diff --git a/code/game/gamemodes/meme/meme.dm b/code/game/gamemodes/meme/meme.dm index 69919236e24a..3f5fc47c6ca8 100644 --- a/code/game/gamemodes/meme/meme.dm +++ b/code/game/gamemodes/meme/meme.dm @@ -1,250 +1,250 @@ -/datum/game_mode/var/list/memes = list() - -/datum/game_mode/meme - name = "Memetic Anomaly" - config_tag = "meme" - role_type = ROLE_MEME - required_players = 6 - required_players_secret = 15 - restricted_jobs = list("AI", "Cyborg") - recommended_enemies = 3 // 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/list/possible_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 - -/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) - - if(antag_candidates.len < 1) - //log_admin("MODE FAILURE: MEME. NOT ENOUGH MEME CANDIDATES.") // We need no spam anymore, it works for a long time. - return 0 // not enough candidates for meme - - /*if(possible_memes.len < 2) - log_admin("MODE FAILURE: MEME. NOT ENOUGH MEME CANDIDATES.") - return 0 not enough candidates for meme*/ - - //testing("[player_list.len] cur players") - - //var/meme_limit = Clamp((num_players()/20), 1, 3) - var/meme_limit = Clamp((player_list.len/13), 1, 3) - //testing("Current meme limit is [meme_limit]") - var/i = 0 - - while(antag_candidates.len > meme_limit) - i++ - var/datum/mind/meme = pick(antag_candidates) - antag_candidates.Remove(meme) - if(i) - log_misc("Deleted [i] possible memes from list") - else - log_misc("Everything was O.K. No meme candidates over limit. Limit was [meme_limit] and possible meme candidates is [antag_candidates.len]") - - // for each 2 possible memes, add one meme and one host - /*for(var/mob/dead/new_player/player in player_list) - 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.stat != DEAD)) - possible_targets += possible_target*/ - - if(antag_candidates.len < 1) - log_admin("Something went wrong after calculations for possible memes.") - testing("Something went wrong after calculations for possible memes.") - return 0 // not enough candidates for meme - - while(antag_candidates.len >= 1) - //for(var/mob/dead/new_player/player in player_list) - var/datum/mind/meme = pick(antag_candidates) - antag_candidates.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() - var/list/possible_hosts = list() - var/datum/mind/target = null - for(var/datum/mind/possible_host in ticker.minds) - if(possible_host.assigned_role != "MODE" && ishuman(possible_host.current) && (possible_host.current.stat != DEAD)) - possible_hosts += possible_host - if(!(possible_hosts.len)) - log_admin("Something went wrong, no possible hosts!") - testing("Something went wrong, no possible hosts!") - return - - // 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 - M.meme_death = pick ("stoxin", "bdam", "holywater", "mindbreaker", "beer", "burns") - meme.transfer_to(M) - M.clearHUD() - - if(possible_hosts.len > 0) - target = pick(possible_hosts) - - M.enter_host(target.current) - possible_hosts -= target - - /** - // 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)*/ - - forge_meme_objectives(meme) - - qdel(original) - - log_admin("Created [memes.len] memes.") - - return ..() - - -/datum/game_mode/proc/forge_meme_objectives(datum/mind/meme, datum/mind/first_host) - if (config.objectives_disabled) - return - - // 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 - - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = meme - kill_objective.find_target() - meme.objectives += kill_objective - - var/datum/objective/survive/survive_objective = new - survive_objective.owner = meme - meme.objectives += survive_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(datum/mind/meme, you_are=1) - if (you_are) - var/meme_death_explained = "sleep toxin" - var/mob/living/parasite/meme/M = meme.current - if (M.meme_death == "stoxin") - meme_death_explained = "sleep toxin" - if (M.meme_death == "bdam") - meme_death_explained = "brain" - if (M.meme_death == "holywater") - meme_death_explained = "holy water" - if (M.meme_death == "mindbreaker") - meme_death_explained = "mind breaking drug" - if (M.meme_death == "beer") - meme_death_explained = "firewater" - if (M.meme_death == "burns") - meme_death_explained = "fire" - to_chat(meme.current, "You are a meme!") - to_chat(meme.current, "Your death is in [meme_death_explained]!") - meme.store_memory("Your death is in [meme_death_explained]!", 0) - - 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() - var/text = "" - for(var/datum/mind/meme in memes) - var/memewin = 1 - var/attuned = 0 - if((meme.current) && istype(meme.current,/mob/living/parasite/meme)) - text += "The meme was [meme.current.key].
    " - text += "The last host was [meme.current:host.key].
    " - text += "Hosts attuned: [attuned]
    " - - var/count = 1 - for(var/datum/objective/objective in meme.objectives) - if(objective.check_completion()) - text += "Objective #[count]: [objective.explanation_text] Success!
    " - feedback_add_details("meme_objective","[objective.type]|SUCCESS") - else - text += "Objective #[count]: [objective.explanation_text] Failed.
    " - feedback_add_details("meme_objective","[objective.type]|FAIL") - memewin = 0 - count++ - - else - memewin = 0 - - if(memewin) - text += "The meme was successful!" - feedback_add_details("meme_success","SUCCESS") - score["roleswon"]++ - else - text += "The meme has failed!" - feedback_add_details("meme_success","FAIL") - text += "

    " - return text +/datum/game_mode/var/list/memes = list() + +/datum/game_mode/meme + name = "Memetic Anomaly" + config_tag = "meme" + role_type = ROLE_MEME + required_players = 6 + required_players_secret = 15 + restricted_jobs = list("AI", "Cyborg") + recommended_enemies = 3 // 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/list/possible_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 + +/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) + + if(antag_candidates.len < 1) + //log_admin("MODE FAILURE: MEME. NOT ENOUGH MEME CANDIDATES.") // We need no spam anymore, it works for a long time. + return 0 // not enough candidates for meme + + /*if(possible_memes.len < 2) + log_admin("MODE FAILURE: MEME. NOT ENOUGH MEME CANDIDATES.") + return 0 not enough candidates for meme*/ + + //testing("[player_list.len] cur players") + + //var/meme_limit = Clamp((num_players()/20), 1, 3) + var/meme_limit = Clamp((player_list.len/13), 1, 3) + //testing("Current meme limit is [meme_limit]") + var/i = 0 + + while(antag_candidates.len > meme_limit) + i++ + var/datum/mind/meme = pick(antag_candidates) + antag_candidates.Remove(meme) + if(i) + log_misc("Deleted [i] possible memes from list") + else + log_misc("Everything was O.K. No meme candidates over limit. Limit was [meme_limit] and possible meme candidates is [antag_candidates.len]") + + // for each 2 possible memes, add one meme and one host + /*for(var/mob/dead/new_player/player in player_list) + 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.stat != DEAD)) + possible_targets += possible_target*/ + + if(antag_candidates.len < 1) + log_admin("Something went wrong after calculations for possible memes.") + testing("Something went wrong after calculations for possible memes.") + return 0 // not enough candidates for meme + + while(antag_candidates.len >= 1) + //for(var/mob/dead/new_player/player in player_list) + var/datum/mind/meme = pick(antag_candidates) + antag_candidates.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() + var/list/possible_hosts = list() + var/datum/mind/target = null + for(var/datum/mind/possible_host in ticker.minds) + if(possible_host.assigned_role != "MODE" && ishuman(possible_host.current) && (possible_host.current.stat != DEAD)) + possible_hosts += possible_host + if(!(possible_hosts.len)) + log_admin("Something went wrong, no possible hosts!") + testing("Something went wrong, no possible hosts!") + return + + // 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 + M.meme_death = pick ("stoxin", "bdam", "holywater", "mindbreaker", "beer", "burns") + meme.transfer_to(M) + M.clearHUD() + + if(possible_hosts.len > 0) + target = pick(possible_hosts) + + M.enter_host(target.current) + possible_hosts -= target + + /** + // 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)*/ + + forge_meme_objectives(meme) + + qdel(original) + + log_admin("Created [memes.len] memes.") + + return ..() + + +/datum/game_mode/proc/forge_meme_objectives(datum/mind/meme, datum/mind/first_host) + if (config.objectives_disabled) + return + + // 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 + + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = meme + kill_objective.find_target() + meme.objectives += kill_objective + + var/datum/objective/survive/survive_objective = new + survive_objective.owner = meme + meme.objectives += survive_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(datum/mind/meme, you_are=1) + if (you_are) + var/meme_death_explained = "sleep toxin" + var/mob/living/parasite/meme/M = meme.current + if (M.meme_death == "stoxin") + meme_death_explained = "sleep toxin" + if (M.meme_death == "bdam") + meme_death_explained = "brain" + if (M.meme_death == "holywater") + meme_death_explained = "holy water" + if (M.meme_death == "mindbreaker") + meme_death_explained = "mind breaking drug" + if (M.meme_death == "beer") + meme_death_explained = "firewater" + if (M.meme_death == "burns") + meme_death_explained = "fire" + to_chat(meme.current, "You are a meme!") + to_chat(meme.current, "Your death is in [meme_death_explained]!") + meme.store_memory("Your death is in [meme_death_explained]!", 0) + + 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() + var/text = "" + for(var/datum/mind/meme in memes) + var/memewin = 1 + var/attuned = 0 + if((meme.current) && istype(meme.current,/mob/living/parasite/meme)) + text += "The meme was [meme.current.key].
    " + text += "The last host was [meme.current:host.key].
    " + text += "Hosts attuned: [attuned]
    " + + var/count = 1 + for(var/datum/objective/objective in meme.objectives) + if(objective.check_completion()) + text += "Objective #[count]: [objective.explanation_text] Success!
    " + feedback_add_details("meme_objective","[objective.type]|SUCCESS") + else + text += "Objective #[count]: [objective.explanation_text] Failed.
    " + feedback_add_details("meme_objective","[objective.type]|FAIL") + memewin = 0 + count++ + + else + memewin = 0 + + if(memewin) + text += "The meme was successful!" + feedback_add_details("meme_success","SUCCESS") + score["roleswon"]++ + else + text += "The meme has failed!" + feedback_add_details("meme_success","FAIL") + text += "

    " + return text diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index e511403c2656..e5bb39413bb4 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -1,63 +1,63 @@ -/datum/game_mode/meteor - name = "meteor" - config_tag = "meteor" - var/const/meteordelay = 2000 - var/nometeors = 1 - required_players = 0 - - votable = 0 - - uplink_welcome = "EVIL METEOR Uplink Console:" - uplink_uses = 20 - - -/datum/game_mode/meteor/announce() - to_chat(world, "The current game mode is - Meteor!") - to_chat(world, "The space station has been stuck in a major meteor shower. You must escape from the station or at least live.") - - -/datum/game_mode/meteor/post_setup() - spawn(meteordelay) - nometeors = 0 - return ..() - - -/datum/game_mode/meteor/process() - if(nometeors) return - /*if(prob(80)) - spawn() - dust_swarm("norm") - else - spawn() - dust_swarm("strong")*/ - spawn() spawn_meteors(6) - - -/datum/game_mode/meteor/declare_completion() - var/text = "" - var/survivors = 0 - completion_text += "Meteor mode resume:
    " - 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) - completion_text += "The following survived the meteor storm:" - completion_text += "[text]" - else - completion_text += "Nobody survived the meteor storm!" - - 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/meteordelay = 2000 + var/nometeors = 1 + required_players = 0 + + votable = 0 + + uplink_welcome = "EVIL METEOR Uplink Console:" + uplink_uses = 20 + + +/datum/game_mode/meteor/announce() + to_chat(world, "The current game mode is - Meteor!") + to_chat(world, "The space station has been stuck in a major meteor shower. You must escape from the station or at least live.") + + +/datum/game_mode/meteor/post_setup() + spawn(meteordelay) + nometeors = 0 + return ..() + + +/datum/game_mode/meteor/process() + if(nometeors) return + /*if(prob(80)) + spawn() + dust_swarm("norm") + else + spawn() + dust_swarm("strong")*/ + spawn() spawn_meteors(6) + + +/datum/game_mode/meteor/declare_completion() + var/text = "" + var/survivors = 0 + completion_text += "Meteor mode resume:
    " + 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) + completion_text += "The following survived the meteor storm:" + completion_text += "[text]" + else + completion_text += "Nobody survived the meteor storm!" + + 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 fee39f46122e..31a741e0bd8b 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -1,154 +1,154 @@ -/var/const/meteor_wave_delay = 625 //minimum wait between waves in tenths of seconds -//set to at least 100 unless you want evarr ruining every round - -/var/const/meteors_in_wave = 50 -/var/const/meteors_in_small_wave = 10 - -/proc/meteor_wave(number = meteors_in_wave) - if(!ticker || wavesecret) - return - - wavesecret = 1 - for(var/i = 0 to number) - spawn(rand(10,100)) - spawn_meteor() - spawn(meteor_wave_delay) - wavesecret = 0 - -/proc/spawn_meteors(number = meteors_in_small_wave) - for(var/i = 0; i < number; i++) - spawn(0) - spawn_meteor() - -/proc/spawn_meteor() - var/startx - var/starty - var/endx - var/endy - var/turf/pickedstart - var/turf/pickedgoal - var/max_i = 10//number of tries to spawn meteor. - - do - switch(pick(1,2,3,4)) - if(1) //NORTH - starty = world.maxy-(TRANSITIONEDGE+1) - startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1)) - endy = TRANSITIONEDGE - endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE) - if(2) //EAST - starty = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1)) - startx = world.maxx-(TRANSITIONEDGE+1) - endy = rand(TRANSITIONEDGE, world.maxy-TRANSITIONEDGE) - endx = TRANSITIONEDGE - if(3) //SOUTH - starty = (TRANSITIONEDGE+1) - startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1)) - endy = world.maxy-TRANSITIONEDGE - endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE) - if(4) //WEST - starty = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1)) - startx = (TRANSITIONEDGE+1) - endy = rand(TRANSITIONEDGE,world.maxy-TRANSITIONEDGE) - endx = world.maxx-TRANSITIONEDGE - - pickedstart = locate(startx, starty, ZLEVEL_STATION) - pickedgoal = locate(endx, endy, ZLEVEL_STATION) - max_i-- - if(max_i<=0) - return - - while (!istype(pickedstart, /turf/space) || !istype(pickedstart.loc, /area/space)) - - var/obj/effect/meteor/M - switch(rand(1, 100)) - - if(1 to 10) - M = new /obj/effect/meteor/big( pickedstart ) - if(11 to 75) - M = new /obj/effect/meteor( pickedstart ) - if(76 to 100) - M = new /obj/effect/meteor/small( pickedstart ) - - M.dest = pickedgoal - spawn(0) - walk_towards(M, M.dest, 1) - - return - -/obj/effect/meteor - name = "meteor" - icon = 'icons/obj/meteor.dmi' - icon_state = "flaming" - density = 1 - anchored = 1.0 - var/hits = 1 - var/dest - pass_flags = PASSTABLE - -/obj/effect/meteor/small - name = "small meteor" - icon_state = "smallf" - pass_flags = PASSTABLE | PASSGRILLE - -/obj/effect/meteor/Destroy() - walk(src,0) //this cancels the walk_towards() proc - return ..() - -/obj/effect/meteor/Bump(atom/A) - if (A) - A.meteorhit(src) - playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1) - if (--src.hits <= 0) - - //Prevent meteors from blowing up the singularity's containment. - //Changing emitter and generator ex_act would result in them being bomb and C4 proof. - if(!istype(A,/obj/machinery/power/emitter) && \ - !istype(A,/obj/machinery/field_generator) && \ - prob(15)) - explosion(src.loc, 4, 5, 6, 7, 0) - qdel(src) - return - - -/obj/effect/meteor/ex_act(severity) - - if (severity < 4) - qdel(src) - return - -/obj/effect/meteor/big - name = "big meteor" - hits = 5 - -/obj/effect/meteor/big/ex_act(severity) - return - -/obj/effect/meteor/big/Bump(atom/A) - //Prevent meteors from blowing up the singularity's containment. - //Changing emitter and generator ex_act would result in them being bomb and C4 proof - if(!istype(A,/obj/machinery/power/emitter) && \ - !istype(A,/obj/machinery/field_generator)) - if(--src.hits <= 0) - qdel(src) //Dont blow up singularity containment if we get stuck there. - - if (A) - for(var/mob/M in player_list) - var/turf/T = get_turf(M) - if(!T || T.z != src.z) - continue - shake_camera(M, 3, get_dist(M.loc, src.loc) > 20 ? 1 : 3) - playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1) - explosion(src.loc, 0, 1, 2, 3, 0) - - if (--src.hits <= 0) - if(prob(15) && !istype(A, /obj/structure/grille)) - explosion(src.loc, 1, 2, 3, 4, 0) - qdel(src) - return - -/obj/effect/meteor/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/pickaxe)) - qdel(src) - return - ..() +/var/const/meteor_wave_delay = 625 //minimum wait between waves in tenths of seconds +//set to at least 100 unless you want evarr ruining every round + +/var/const/meteors_in_wave = 50 +/var/const/meteors_in_small_wave = 10 + +/proc/meteor_wave(number = meteors_in_wave) + if(!ticker || wavesecret) + return + + wavesecret = 1 + for(var/i = 0 to number) + spawn(rand(10,100)) + spawn_meteor() + spawn(meteor_wave_delay) + wavesecret = 0 + +/proc/spawn_meteors(number = meteors_in_small_wave) + for(var/i = 0; i < number; i++) + spawn(0) + spawn_meteor() + +/proc/spawn_meteor() + var/startx + var/starty + var/endx + var/endy + var/turf/pickedstart + var/turf/pickedgoal + var/max_i = 10//number of tries to spawn meteor. + + do + switch(pick(1,2,3,4)) + if(1) //NORTH + starty = world.maxy-(TRANSITIONEDGE+1) + startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1)) + endy = TRANSITIONEDGE + endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE) + if(2) //EAST + starty = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1)) + startx = world.maxx-(TRANSITIONEDGE+1) + endy = rand(TRANSITIONEDGE, world.maxy-TRANSITIONEDGE) + endx = TRANSITIONEDGE + if(3) //SOUTH + starty = (TRANSITIONEDGE+1) + startx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1)) + endy = world.maxy-TRANSITIONEDGE + endx = rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE) + if(4) //WEST + starty = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1)) + startx = (TRANSITIONEDGE+1) + endy = rand(TRANSITIONEDGE,world.maxy-TRANSITIONEDGE) + endx = world.maxx-TRANSITIONEDGE + + pickedstart = locate(startx, starty, ZLEVEL_STATION) + pickedgoal = locate(endx, endy, ZLEVEL_STATION) + max_i-- + if(max_i<=0) + return + + while (!istype(pickedstart, /turf/space) || !istype(pickedstart.loc, /area/space)) + + var/obj/effect/meteor/M + switch(rand(1, 100)) + + if(1 to 10) + M = new /obj/effect/meteor/big( pickedstart ) + if(11 to 75) + M = new /obj/effect/meteor( pickedstart ) + if(76 to 100) + M = new /obj/effect/meteor/small( pickedstart ) + + M.dest = pickedgoal + spawn(0) + walk_towards(M, M.dest, 1) + + return + +/obj/effect/meteor + name = "meteor" + icon = 'icons/obj/meteor.dmi' + icon_state = "flaming" + density = 1 + anchored = 1.0 + var/hits = 1 + var/dest + pass_flags = PASSTABLE + +/obj/effect/meteor/small + name = "small meteor" + icon_state = "smallf" + pass_flags = PASSTABLE | PASSGRILLE + +/obj/effect/meteor/Destroy() + walk(src,0) //this cancels the walk_towards() proc + return ..() + +/obj/effect/meteor/Bump(atom/A) + if (A) + A.meteorhit(src) + playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1) + if (--src.hits <= 0) + + //Prevent meteors from blowing up the singularity's containment. + //Changing emitter and generator ex_act would result in them being bomb and C4 proof. + if(!istype(A,/obj/machinery/power/emitter) && \ + !istype(A,/obj/machinery/field_generator) && \ + prob(15)) + explosion(src.loc, 4, 5, 6, 7, 0) + qdel(src) + return + + +/obj/effect/meteor/ex_act(severity) + + if (severity < 4) + qdel(src) + return + +/obj/effect/meteor/big + name = "big meteor" + hits = 5 + +/obj/effect/meteor/big/ex_act(severity) + return + +/obj/effect/meteor/big/Bump(atom/A) + //Prevent meteors from blowing up the singularity's containment. + //Changing emitter and generator ex_act would result in them being bomb and C4 proof + if(!istype(A,/obj/machinery/power/emitter) && \ + !istype(A,/obj/machinery/field_generator)) + if(--src.hits <= 0) + qdel(src) //Dont blow up singularity containment if we get stuck there. + + if (A) + for(var/mob/M in player_list) + var/turf/T = get_turf(M) + if(!T || T.z != src.z) + continue + shake_camera(M, 3, get_dist(M.loc, src.loc) > 20 ? 1 : 3) + playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1) + explosion(src.loc, 0, 1, 2, 3, 0) + + if (--src.hits <= 0) + if(prob(15) && !istype(A, /obj/structure/grille)) + explosion(src.loc, 1, 2, 3, 4, 0) + qdel(src) + return + +/obj/effect/meteor/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/pickaxe)) + qdel(src) + return + ..() diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 3e99e78a5cd6..fe0255401cca 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -1,410 +1,410 @@ -/datum/game_mode - var/list/datum/mind/syndicates = list() - var/obj/nuclear_uplink - - -/datum/game_mode/nuclear - name = "nuclear emergency" - config_tag = "nuclear" - role_type = ROLE_OPERATIVE - required_players = 15 - required_players_secret = 15 - required_enemies = 1 - recommended_enemies = 5 - - votable = 0 - - uplink_welcome = "Corporate Backed Uplink Console:" - uplink_uses = 20 - - var/const/agents_possible = 5 //If we ever need more syndicate agents. - - 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, "Gorlex Maradeurs are approaching NSS Exodus!") - 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/agent_number = 0 - - /* - * if(antag_candidates.len > agents_possible) - * agent_number = agents_possible - * else - * agent_number = antag_candidates.len - * - * if(agent_number > n_players) - * agent_number = n_players/2 - */ - - //Antag number should scale to active crew. - var/n_players = num_players() - agent_number = Clamp((n_players/5), 2, 6) - - if(antag_candidates.len < agent_number) - agent_number = antag_candidates.len - - while(agent_number > 0) - var/datum/mind/new_syndicate = pick(antag_candidates) - syndicates += new_syndicate - antag_candidates -= 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 - // log_game("[synd_mind.key] with age [synd_mind.current.client.player_age] has been selected as a nuclear operative") - // message_admins("[synd_mind.key] with age [synd_mind.current.client.player_age] has been selected as a nuclear operative",0,1) - 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") - qdel(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/I = image('icons/mob/mob.dmi', loc = synd_mind_1.current, icon_state = "synd") - synd_mind.current.client.images += I - -/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) - spawn(0) - if(synd_mind.current) - if(synd_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = synd_mind.current, icon_state = "synd") - synd_mind.current.client.images += I - -/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) - qdel(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") - qdel(I) - -//////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////// - -/datum/game_mode/nuclear/post_setup() - - var/list/turf/synd_spawn = list() - var/turf/synd_comm_spawn - - for(var/obj/effect/landmark/A in landmarks_list) //Add commander spawn places first, really should only be one though. - if(A.name == "Syndicate-Commander") - synd_comm_spawn = get_turf(A) - qdel(A) - continue - - for(var/obj/effect/landmark/A in landmarks_list) - if(A.name == "Syndicate-Spawn") - synd_spawn += get_turf(A) - qdel(A) - 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/spawnpos = 1 -// var/max_age = 0 -/* for(var/datum/mind/synd_mind in syndicates) - if(isnum(synd_mind.current.client.player_age)) - if(max_age synd_spawn.len) - spawnpos = 1 - log_debug("[synd_mind] telepoting to [synd_spawn[spawnpos]]") - synd_mind.current.loc = synd_spawn[spawnpos] - - spawn(0) - NukeNameAssign(synd_mind) - - if(!config.objectives_disabled) - forge_syndicate_objectives(synd_mind) - - 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) - var/obj/machinery/nuclearbomb/the_bomb = new /obj/machinery/nuclearbomb(nuke_spawn.loc) - the_bomb.r_code = nuke_code - - return ..() - - -/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code) - if (nuke_code) - synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 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(datum/mind/syndicate) - if (config.objectives_disabled) - return - var/datum/objective/nuclear/syndobj = new - syndobj.owner = syndicate - syndicate.objectives += syndobj - - -/datum/game_mode/proc/greet_syndicate(datum/mind/syndicate, you_are=1, boss=0) - if (you_are) - to_chat(syndicate.current, "You are a Gorlex Maradeurs agent!") - if(boss) - to_chat(syndicate.current, "You are a Gorlex Maradeurs Commander!") - var/obj_count = 1 - - if(!config.objectives_disabled) - for(var/datum/objective/objective in syndicate.objectives) - to_chat(syndicate.current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - else - to_chat(syndicate.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - return - - -/datum/game_mode/proc/random_radio_frequency() - return 1337 // WHY??? -- Doohl - - -/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob, boss) - var/radio_freq = SYND_FREQ - - 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_l_ear) - - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform) - if(synd_mob.backbag == 2) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back) - if(synd_mob.backbag == 3) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(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_box/magazine/m12mm(synd_mob), slot_in_backpack) - synd_mob.equip_to_slot_or_del(new /obj/item/device/radio/uplink(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) - 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) - if(boss) - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate/commander(synd_mob), slot_wear_id) - else - synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate/nuker(synd_mob), slot_wear_id) - - switch(synd_mob.get_species()) - if(UNATHI) - synd_mob.equip_to_slot_or_del(new /obj/item/device/modkit/syndie/unathi(synd_mob), slot_in_backpack) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat/cut(synd_mob), slot_shoes) - if(TAJARAN) - synd_mob.equip_to_slot_or_del(new /obj/item/device/modkit/syndie/tajaran(synd_mob), slot_in_backpack) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat/cut(synd_mob), slot_shoes) - if(SKRELL) - synd_mob.equip_to_slot_or_del(new /obj/item/device/modkit/syndie/skrell(synd_mob), slot_in_backpack) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(synd_mob), slot_shoes) - else - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(synd_mob), slot_shoes) - - var/obj/item/weapon/implant/dexplosive/E = new/obj/item/weapon/implant/dexplosive(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() - if(config.objectives_disabled) - return - var/disk_rescued = 1 - for(var/obj/item/weapon/disk/nuclear/D in poi_list) - var/disk_area = get_area(D) - if(!is_type_in_list(disk_area, centcom_areas)) - disk_rescued = 0 - break - var/crew_evacuated = (SSshuttle.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 += "
    Gorlex Maradeurs operatives have destroyed NSS Exodus!" - score["roleswon"]++ - - 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 += "
    Gorlex Maradeurs operatives destroyed NSS Exodus 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 += "
    Gorlex Maradeurs operatives secured the authentication disk but blew up something that wasn't NSS Exodus. 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 += "Gorlex Maradeurs operatives have earned Darwin Award!" - completion_text += "
    Gorlex Maradeurs operatives blew up something that wasn't NSS Exodus 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 Gorlex Maradeurs 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 Gorlex Maradeurs 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 Gorlex Maradeurs Operatives!" - - else if (!disk_rescued && crew_evacuated) - feedback_set_details("round_end_result","halfwin - detonation averted") - completion_text += "Syndicate Minor Victory!" - completion_text += "
    Gorlex Maradeurs operatives recovered the abandoned authentication disk but detonation of NSS Exodus 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 1 - - -/datum/game_mode/proc/auto_declare_completion_nuclear() - var/text = "" - if( syndicates.len || (ticker && istype(ticker.mode,/datum/game_mode/nuclear)) ) - text += printlogo("nuke", "syndicate operatives") - for(var/datum/mind/syndicate in syndicates) - text += printplayerwithicon(syndicate) - - 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)" - else - text += "
    The nukeops were smooth operators this round (did not purchase any uplink items)." - text += "

    " - return text - - -/*/proc/nukelastname(mob/M) //--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(datum/mind/synd_mind) - var/choose_name = sanitize_safe(input(synd_mind.current, "You are a Gorlex Maradeurs agent! What is your name?", "Choose a name") as text, MAX_NAME_LEN) - - if(!choose_name) - return - - else - synd_mind.current.name = choose_name - synd_mind.current.real_name = choose_name - return +/datum/game_mode + var/list/datum/mind/syndicates = list() + var/obj/nuclear_uplink + + +/datum/game_mode/nuclear + name = "nuclear emergency" + config_tag = "nuclear" + role_type = ROLE_OPERATIVE + required_players = 15 + required_players_secret = 15 + required_enemies = 1 + recommended_enemies = 5 + + votable = 0 + + uplink_welcome = "Corporate Backed Uplink Console:" + uplink_uses = 20 + + var/const/agents_possible = 5 //If we ever need more syndicate agents. + + 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, "Gorlex Maradeurs are approaching NSS Exodus!") + 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/agent_number = 0 + + /* + * if(antag_candidates.len > agents_possible) + * agent_number = agents_possible + * else + * agent_number = antag_candidates.len + * + * if(agent_number > n_players) + * agent_number = n_players/2 + */ + + //Antag number should scale to active crew. + var/n_players = num_players() + agent_number = Clamp((n_players/5), 2, 6) + + if(antag_candidates.len < agent_number) + agent_number = antag_candidates.len + + while(agent_number > 0) + var/datum/mind/new_syndicate = pick(antag_candidates) + syndicates += new_syndicate + antag_candidates -= 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 + // log_game("[synd_mind.key] with age [synd_mind.current.client.player_age] has been selected as a nuclear operative") + // message_admins("[synd_mind.key] with age [synd_mind.current.client.player_age] has been selected as a nuclear operative",0,1) + 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") + qdel(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/I = image('icons/mob/mob.dmi', loc = synd_mind_1.current, icon_state = "synd") + synd_mind.current.client.images += I + +/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) + spawn(0) + if(synd_mind.current) + if(synd_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = synd_mind.current, icon_state = "synd") + synd_mind.current.client.images += I + +/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) + qdel(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") + qdel(I) + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// + +/datum/game_mode/nuclear/post_setup() + + var/list/turf/synd_spawn = list() + var/turf/synd_comm_spawn + + for(var/obj/effect/landmark/A in landmarks_list) //Add commander spawn places first, really should only be one though. + if(A.name == "Syndicate-Commander") + synd_comm_spawn = get_turf(A) + qdel(A) + continue + + for(var/obj/effect/landmark/A in landmarks_list) + if(A.name == "Syndicate-Spawn") + synd_spawn += get_turf(A) + qdel(A) + 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/spawnpos = 1 +// var/max_age = 0 +/* for(var/datum/mind/synd_mind in syndicates) + if(isnum(synd_mind.current.client.player_age)) + if(max_age synd_spawn.len) + spawnpos = 1 + log_debug("[synd_mind] telepoting to [synd_spawn[spawnpos]]") + synd_mind.current.loc = synd_spawn[spawnpos] + + spawn(0) + NukeNameAssign(synd_mind) + + if(!config.objectives_disabled) + forge_syndicate_objectives(synd_mind) + + 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) + var/obj/machinery/nuclearbomb/the_bomb = new /obj/machinery/nuclearbomb(nuke_spawn.loc) + the_bomb.r_code = nuke_code + + return ..() + + +/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code) + if (nuke_code) + synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 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(datum/mind/syndicate) + if (config.objectives_disabled) + return + var/datum/objective/nuclear/syndobj = new + syndobj.owner = syndicate + syndicate.objectives += syndobj + + +/datum/game_mode/proc/greet_syndicate(datum/mind/syndicate, you_are=1, boss=0) + if (you_are) + to_chat(syndicate.current, "You are a Gorlex Maradeurs agent!") + if(boss) + to_chat(syndicate.current, "You are a Gorlex Maradeurs Commander!") + var/obj_count = 1 + + if(!config.objectives_disabled) + for(var/datum/objective/objective in syndicate.objectives) + to_chat(syndicate.current, "Objective #[obj_count]: [objective.explanation_text]") + obj_count++ + else + to_chat(syndicate.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + return + + +/datum/game_mode/proc/random_radio_frequency() + return 1337 // WHY??? -- Doohl + + +/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob, boss) + var/radio_freq = SYND_FREQ + + 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_l_ear) + + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform) + if(synd_mob.backbag == 2) + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back) + if(synd_mob.backbag == 3) + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(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_box/magazine/m12mm(synd_mob), slot_in_backpack) + synd_mob.equip_to_slot_or_del(new /obj/item/device/radio/uplink(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) + 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) + if(boss) + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate/commander(synd_mob), slot_wear_id) + else + synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate/nuker(synd_mob), slot_wear_id) + + switch(synd_mob.get_species()) + if(UNATHI) + synd_mob.equip_to_slot_or_del(new /obj/item/device/modkit/syndie/unathi(synd_mob), slot_in_backpack) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat/cut(synd_mob), slot_shoes) + if(TAJARAN) + synd_mob.equip_to_slot_or_del(new /obj/item/device/modkit/syndie/tajaran(synd_mob), slot_in_backpack) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat/cut(synd_mob), slot_shoes) + if(SKRELL) + synd_mob.equip_to_slot_or_del(new /obj/item/device/modkit/syndie/skrell(synd_mob), slot_in_backpack) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(synd_mob), slot_shoes) + else + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(synd_mob), slot_shoes) + + var/obj/item/weapon/implant/dexplosive/E = new/obj/item/weapon/implant/dexplosive(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() + if(config.objectives_disabled) + return + var/disk_rescued = 1 + for(var/obj/item/weapon/disk/nuclear/D in poi_list) + var/disk_area = get_area(D) + if(!is_type_in_list(disk_area, centcom_areas)) + disk_rescued = 0 + break + var/crew_evacuated = (SSshuttle.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 += "
    Gorlex Maradeurs operatives have destroyed NSS Exodus!" + score["roleswon"]++ + + 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 += "
    Gorlex Maradeurs operatives destroyed NSS Exodus 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 += "
    Gorlex Maradeurs operatives secured the authentication disk but blew up something that wasn't NSS Exodus. 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 += "Gorlex Maradeurs operatives have earned Darwin Award!" + completion_text += "
    Gorlex Maradeurs operatives blew up something that wasn't NSS Exodus 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 Gorlex Maradeurs 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 Gorlex Maradeurs 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 Gorlex Maradeurs Operatives!" + + else if (!disk_rescued && crew_evacuated) + feedback_set_details("round_end_result","halfwin - detonation averted") + completion_text += "Syndicate Minor Victory!" + completion_text += "
    Gorlex Maradeurs operatives recovered the abandoned authentication disk but detonation of NSS Exodus 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 1 + + +/datum/game_mode/proc/auto_declare_completion_nuclear() + var/text = "" + if( syndicates.len || (ticker && istype(ticker.mode,/datum/game_mode/nuclear)) ) + text += printlogo("nuke", "syndicate operatives") + for(var/datum/mind/syndicate in syndicates) + text += printplayerwithicon(syndicate) + + 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)" + else + text += "
    The nukeops were smooth operators this round (did not purchase any uplink items)." + text += "

    " + return text + + +/*/proc/nukelastname(mob/M) //--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(datum/mind/synd_mind) + var/choose_name = sanitize_safe(input(synd_mind.current, "You are a Gorlex Maradeurs agent! What is your name?", "Choose a name") as text, MAX_NAME_LEN) + + if(!choose_name) + return + + else + synd_mind.current.name = choose_name + synd_mind.current.real_name = choose_name + return diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index ef5d8c575376..9dc9f62ea129 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -1,552 +1,552 @@ -#define TIMER_MIN 420 -#define TIMER_MAX 600 - -var/bomb_set - -/obj/machinery/nuclearbomb - name = "\improper Nuclear Fission Explosive" - desc = "Uh oh. RUN!!!!" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "nuclearbomb0" - density = TRUE - can_buckle = 1 - use_power = 0 - var/deployable = 0.0 - var/extended = 0.0 - var/lighthack = 0 - var/opened = 0.0 - var/timeleft = 600.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/datum/wires/nuclearbomb/wires = 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. - var/detonated = 0 //used for scoreboard. - var/lastentered = "" - var/spray_icon_state - -/obj/machinery/nuclearbomb/atom_init() - . = ..() - poi_list += src - r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn. - wires = new(src) - -/obj/machinery/nuclearbomb/Destroy() - poi_list -= src - QDEL_NULL(wires) - QDEL_NULL(auth) - return ..() - -/obj/machinery/nuclearbomb/process() - if (timing > 0) // because explode() sets it to -1, which is TRUE. - bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. - timeleft = max(timeleft - 2, 0) // 2 seconds per process() - playsound(loc, 'sound/items/timer.ogg', 30, 0) - if (timeleft <= 0) - explode() - updateUsrDialog() - -/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O, mob/user) - - if (istype(O, /obj/item/weapon/screwdriver)) - src.add_fingerprint(user) - if (removal_stage == 5) - if (src.opened == 0) - src.opened = 1 - overlays += image(icon, "npanel_open") - to_chat(user, "You unscrew the control panel of [src].") - - else - src.opened = 0 - overlays -= image(icon, "npanel_open") - to_chat(user, "You screw the control panel of [src] back on.") - else if (src.auth) - if (src.opened == 0) - src.opened = 1 - overlays += image(icon, "npanel_open") - to_chat(user, "You unscrew the control panel of [src].") - - else - src.opened = 0 - overlays -= image(icon, "npanel_open") - to_chat(user, "You screw the control panel of [src] back on.") - else - if (src.opened == 0) - to_chat(user, "The [src] emits a buzzing noise, the panel staying locked in.") - if (src.opened == 1) - src.opened = 0 - overlays -= image(icon, "npanel_open") - to_chat(user, "You screw the control panel of [src] back on.") - flick("nuclearbombc", src) - - return - if (is_wire_tool(O) && opened) - if(wires.interact(user)) - return - - if (src.extended) - if (istype(O, /obj/item/weapon/disk/nuclear)) - usr.drop_item() - O.loc = src - 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 - if(user.is_busy()) - return - user.visible_message("[user] starts cutting thru something on [src] like \he knows what to do.", "With [O] you start cutting thru first layer...") - - if(do_after(user,150,target = src)) - if(!src || !user || !WT.remove_fuel(5, user)) return - user.visible_message("[user] finishes cutting something on [src].", "You cut thru first layer.") - removal_stage = 1 - return - - if(1) - if(istype(O,/obj/item/weapon/crowbar)) - user.visible_message("[user] starts smashing [src].", "You start forcing open the covers with [O]...") - if(user.is_busy()) - return - if(do_after(user,50,target = src)) - if(!src || !user) return - user.visible_message("[user] finishes smashing [src].", "You force open 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 - if(user.is_busy()) - return - user.visible_message("[user] starts cutting something on [src].. Again.", "You start cutting apart the safety plate with [O]...") - - if(do_after(user,100,target = src)) - if(!src || !user || !WT.remove_fuel(5, user)) return - user.visible_message("[user] finishes cutting something on [src].", "You cut apart the safety plate.") - removal_stage = 3 - return - - if(3) - if(istype(O,/obj/item/weapon/wrench)) - if(user.is_busy()) - return - user.visible_message("[user] begins poking inside [src].", "You begin unwrenching bolts...") - - if(do_after(user,75,target = src)) - if(!src || !user) return - user.visible_message("[user] begins poking inside [src].", "You unwrench bolts.") - removal_stage = 4 - return - - if(4) - if(istype(O,/obj/item/weapon/crowbar)) - if(user.is_busy()) - return - user.visible_message("[user] begings hitting [src].", "You begin forcing open last safety layer...") - - if(do_after(user,75,target = src)) - if(!src || !user) return - user.visible_message("[user] finishes hitting [src].", "You can now get inside the [src]. Use screwdriver to open control panel") - //anchored = 0 - removal_stage = 5 - return - /*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, "\red 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,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,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, "\red 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,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,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,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_hand(mob/user) - . = ..() - if(.) - return - - if (extended) - if (!ishuman(user) && !isobserver(user)) - to_chat(usr, "You don't have the dexterity to do this!") - return 1 - var/turf/current_location = get_turf(usr)//What turf is the user on? - if(current_location.z == ZLEVEL_CENTCOMM && user.mind.special_role == "Syndicate")//If turf was not found or they're on z level 2. - to_chat(user, "It's not the best idea to plant a bomb on your own base") - return - else if (deployable) - if(removal_stage < 5) - anchored = TRUE - 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.") - if(!lighthack) - flick("nuclearbombc", src) - icon_state = "nuclearbomb1" - extended = TRUE - -/obj/machinery/nuclearbomb/ui_interact(mob/user) - if(!extended) - return - - var/dat = text("Nuclear Fission Explosive
    \nAuth. Disk: []
    ", src, (auth ? "++++++++++" : "----------")) - if (auth) - if (yes_code) - dat += text("\nStatus: []-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (timing ? "Func/Set" : "Functional"), (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), src, src, src, timeleft, src, src, (safety ? "On" : "Off"), src, (anchored ? "Engaged" : "Off"), src) - else - dat += text("\nStatus: Auth. S2-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), timeleft, (safety ? "On" : "Off"), (anchored ? "Engaged" : "Off"), src) - else - if (timing) - dat += text("\nStatus: Set-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), timeleft, (safety ? "On" : "Off"), (anchored ? "Engaged" : "Off")) - else - dat += text("\nStatus: Auth. S1-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), timeleft, (safety ? "On" : "Off"), (anchored ? "Engaged" : "Off")) - var/message = "AUTH" - if (auth) - message = text("[]", code) - if (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(entity_ja(dat), "window=nuclearbomb;size=300x400") - onclose(user, "nuclearbomb") - -/obj/machinery/nuclearbomb/verb/make_deployable() - set category = "Object" - set name = "Make Deployable" - set src in oview(1) - - if (!usr.canmove || usr.stat || usr.restrained()) - return - if (!ishuman(usr)) - to_chat(usr, "You don't have the dexterity to do this!") - return 1 - - 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 - return - -/obj/machinery/nuclearbomb/is_operational_topic() - return TRUE - -/obj/machinery/nuclearbomb/Topic(href, href_list) - . = ..() - if(!.) - return - - if(!extended) - return - - 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.loc = src - 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 - lastentered = text("[]", href_list["type"]) - if (text2num(lastentered) == null) - var/turf/LOC = get_turf(usr) - message_admins("[key_name_admin(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered] ! ([LOC ? "JMP" : "null"])", 0) - log_admin("EXPLOIT : [key_name(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered] !") - else - src.code += lastentered - 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 = Clamp(round(timeleft), TIMER_MIN, TIMER_MAX) - if (href_list["timer"]) - if (src.timing == -1.0) - return FALSE - if (src.safety) - to_chat(usr, "The safety is still on.") - return FALSE - src.timing = !( src.timing ) - if (src.timing) - if(!src.lighthack) - src.icon_state = "nuclearbomb2" - if(!src.safety) - var/area/nuclearbombloc = get_area(loc) - captain_announce("Bomb has been planted in [initial(nuclearbombloc.name)]. Someone trying to blow up the station!") - set_security_level("delta") - 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 - bomb_set = 0 - if(!src.lighthack) - src.icon_state = "nuclearbomb1" - 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("\red \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.") - else - icon_state = "nuclearbomb1" - safety = 1.0 - timing = -1.0 - timeleft = TIMER_MAX - visible_message("The anchoring bolts slide back into the depths of [src] and timer has stopped.") - - updateUsrDialog() - -/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 - if(detonated) - return - src.detonated = 1 - src.timing = -1.0 - src.yes_code = 0 - src.safety = 1 - if(!src.lighthack) - 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 == ZLEVEL_STATION) ) - 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 - score["nuked"]++ - sleep(10) - explosion(src, 15, 70, 200) - else - off_station = 2 - - if(ticker) - if(ticker.mode && ticker.mode.name == "nuclear emergency") - var/obj/machinery/computer/syndicate_station/syndie_location = locate(/obj/machinery/computer/syndicate_station) - if(syndie_location) - ticker.mode:syndies_didnt_escape = (syndie_location.z > ZLEVEL_STATION ? 0 : 1) //muskets will make me change this, but it will do for now - ticker.mode: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") - ticker.mode: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. - - 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 45 seconds!") - - feedback_set_details("end_error","nuke - unhandled ending") - - if(blackbox) - blackbox.save_all_data_to_sql() - sleep(450) - log_game("Rebooting due to nuclear detonation") - world.Reboot() - return - return - -/obj/machinery/nuclearbomb/MouseDrop_T(mob/living/M, mob/living/user) - if(!ishuman(M) || !ishuman(user)) - return - if(user.is_busy()) - return - if(buckled_mob) - do_after(usr, 30, 1, src) - unbuckle_mob() - else if(do_after(usr, 30, 1, src)) - M.loc = loc - ..() - -/obj/machinery/nuclearbomb/post_buckle_mob(mob/living/M) - ..() - if(M == buckled_mob) - M.pixel_y = 10 - else - M.pixel_y = 0 - -/obj/machinery/nuclearbomb/bullet_act(obj/item/projectile/Proj) - if(buckled_mob) - buckled_mob.bullet_act(Proj) - if(buckled_mob.weakened || buckled_mob.health < 0 || buckled_mob.halloss > 80) - unbuckle_mob() - return ..() - -/obj/machinery/nuclearbomb/MouseDrop(over_object, src_location, over_location) - ..() - if(!istype(over_object, /obj/structure/droppod)) - return - if(!in_range(src, usr) || !ishuman(usr) || !in_range(src, over_object)) - return - var/obj/structure/droppod/D = over_object - if(!timing && !auth && !buckled_mob) - if(usr.is_busy()) - return - visible_message("[usr] start putting [src] into [D]!","You start putting [src] into [D]!") - if(do_after(usr, 100, 1, src) && !timing && !auth && !buckled_mob) - D.Stored_Nuclear = src - loc = D - D.icon_state = "dropod_opened_n[D.item_state]" - visible_message("[usr] put [src] into [D]!","You succesfully put [src] into [D]!") - D.verbs += /obj/structure/droppod/proc/Nuclear - -//==========DAT FUKKEN DISK=============== -/obj/item/weapon/disk - icon = 'icons/obj/items.dmi' - w_class = 1 - item_state = "card-id" - icon_state = "datadisk0" - -/obj/item/weapon/disk/nuclear - name = "nuclear authentication disk" - desc = "Better keep this safe." - icon_state = "nucleardisk" - -/obj/item/weapon/disk/nuclear/atom_init() - . = ..() - poi_list += src - START_PROCESSING(SSobj, src) - -/obj/item/weapon/disk/nuclear/process() - var/turf/disk_loc = get_turf(src) - if(disk_loc.z > ZLEVEL_CENTCOM) - to_chat(get(src, /mob), "You can't help but feel that you just lost something back there...") - qdel(src) - -/obj/item/weapon/disk/nuclear/Destroy() - if(blobstart.len > 0) - var/turf/targetturf = get_turf(pick(blobstart)) - var/turf/diskturf = get_turf(src) - forceMove(targetturf) //move the disc, so ghosts remain orbitting it even if it's "destroyed" - message_admins("[src] has been destroyed in ([diskturf.x], [diskturf.y] ,[diskturf.z] - JMP). Moving it to ([targetturf.x], [targetturf.y], [targetturf.z] - JMP).") - log_game("[src] has been destroyed in ([diskturf.x], [diskturf.y] ,[diskturf.z]). Moving it to ([targetturf.x], [targetturf.y], [targetturf.z]).") - else - throw EXCEPTION("Unable to find a blobstart landmark") - return QDEL_HINT_LETMELIVE //Cancel destruction regardless of success - -#undef TIMER_MIN -#undef TIMER_MAX +#define TIMER_MIN 420 +#define TIMER_MAX 600 + +var/bomb_set + +/obj/machinery/nuclearbomb + name = "\improper Nuclear Fission Explosive" + desc = "Uh oh. RUN!!!!" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "nuclearbomb0" + density = TRUE + can_buckle = 1 + use_power = 0 + var/deployable = 0.0 + var/extended = 0.0 + var/lighthack = 0 + var/opened = 0.0 + var/timeleft = 600.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/datum/wires/nuclearbomb/wires = 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. + var/detonated = 0 //used for scoreboard. + var/lastentered = "" + var/spray_icon_state + +/obj/machinery/nuclearbomb/atom_init() + . = ..() + poi_list += src + r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn. + wires = new(src) + +/obj/machinery/nuclearbomb/Destroy() + poi_list -= src + QDEL_NULL(wires) + QDEL_NULL(auth) + return ..() + +/obj/machinery/nuclearbomb/process() + if (timing > 0) // because explode() sets it to -1, which is TRUE. + bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. + timeleft = max(timeleft - 2, 0) // 2 seconds per process() + playsound(loc, 'sound/items/timer.ogg', 30, 0) + if (timeleft <= 0) + explode() + updateUsrDialog() + +/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O, mob/user) + + if (istype(O, /obj/item/weapon/screwdriver)) + src.add_fingerprint(user) + if (removal_stage == 5) + if (src.opened == 0) + src.opened = 1 + overlays += image(icon, "npanel_open") + to_chat(user, "You unscrew the control panel of [src].") + + else + src.opened = 0 + overlays -= image(icon, "npanel_open") + to_chat(user, "You screw the control panel of [src] back on.") + else if (src.auth) + if (src.opened == 0) + src.opened = 1 + overlays += image(icon, "npanel_open") + to_chat(user, "You unscrew the control panel of [src].") + + else + src.opened = 0 + overlays -= image(icon, "npanel_open") + to_chat(user, "You screw the control panel of [src] back on.") + else + if (src.opened == 0) + to_chat(user, "The [src] emits a buzzing noise, the panel staying locked in.") + if (src.opened == 1) + src.opened = 0 + overlays -= image(icon, "npanel_open") + to_chat(user, "You screw the control panel of [src] back on.") + flick("nuclearbombc", src) + + return + if (is_wire_tool(O) && opened) + if(wires.interact(user)) + return + + if (src.extended) + if (istype(O, /obj/item/weapon/disk/nuclear)) + usr.drop_item() + O.loc = src + 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 + if(user.is_busy()) + return + user.visible_message("[user] starts cutting thru something on [src] like \he knows what to do.", "With [O] you start cutting thru first layer...") + + if(do_after(user,150,target = src)) + if(!src || !user || !WT.remove_fuel(5, user)) return + user.visible_message("[user] finishes cutting something on [src].", "You cut thru first layer.") + removal_stage = 1 + return + + if(1) + if(istype(O,/obj/item/weapon/crowbar)) + user.visible_message("[user] starts smashing [src].", "You start forcing open the covers with [O]...") + if(user.is_busy()) + return + if(do_after(user,50,target = src)) + if(!src || !user) return + user.visible_message("[user] finishes smashing [src].", "You force open 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 + if(user.is_busy()) + return + user.visible_message("[user] starts cutting something on [src].. Again.", "You start cutting apart the safety plate with [O]...") + + if(do_after(user,100,target = src)) + if(!src || !user || !WT.remove_fuel(5, user)) return + user.visible_message("[user] finishes cutting something on [src].", "You cut apart the safety plate.") + removal_stage = 3 + return + + if(3) + if(istype(O,/obj/item/weapon/wrench)) + if(user.is_busy()) + return + user.visible_message("[user] begins poking inside [src].", "You begin unwrenching bolts...") + + if(do_after(user,75,target = src)) + if(!src || !user) return + user.visible_message("[user] begins poking inside [src].", "You unwrench bolts.") + removal_stage = 4 + return + + if(4) + if(istype(O,/obj/item/weapon/crowbar)) + if(user.is_busy()) + return + user.visible_message("[user] begings hitting [src].", "You begin forcing open last safety layer...") + + if(do_after(user,75,target = src)) + if(!src || !user) return + user.visible_message("[user] finishes hitting [src].", "You can now get inside the [src]. Use screwdriver to open control panel") + //anchored = 0 + removal_stage = 5 + return + /*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, "\red 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,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,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, "\red 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,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,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,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_hand(mob/user) + . = ..() + if(.) + return + + if (extended) + if (!ishuman(user) && !isobserver(user)) + to_chat(usr, "You don't have the dexterity to do this!") + return 1 + var/turf/current_location = get_turf(usr)//What turf is the user on? + if(current_location.z == ZLEVEL_CENTCOMM && user.mind.special_role == "Syndicate")//If turf was not found or they're on z level 2. + to_chat(user, "It's not the best idea to plant a bomb on your own base") + return + else if (deployable) + if(removal_stage < 5) + anchored = TRUE + 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.") + if(!lighthack) + flick("nuclearbombc", src) + icon_state = "nuclearbomb1" + extended = TRUE + +/obj/machinery/nuclearbomb/ui_interact(mob/user) + if(!extended) + return + + var/dat = text("Nuclear Fission Explosive
    \nAuth. Disk: []
    ", src, (auth ? "++++++++++" : "----------")) + if (auth) + if (yes_code) + dat += text("\nStatus: []-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (timing ? "Func/Set" : "Functional"), (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), src, src, src, timeleft, src, src, (safety ? "On" : "Off"), src, (anchored ? "Engaged" : "Off"), src) + else + dat += text("\nStatus: Auth. S2-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), timeleft, (safety ? "On" : "Off"), (anchored ? "Engaged" : "Off"), src) + else + if (timing) + dat += text("\nStatus: Set-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), timeleft, (safety ? "On" : "Off"), (anchored ? "Engaged" : "Off")) + else + dat += text("\nStatus: Auth. S1-[]
    \nTimer: []
    \n
    \nTimer: [] Toggle
    \nTime: - - [] + +
    \n
    \n[] Safety: Toggle
    \nAnchor: [] Toggle
    \n", (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), timeleft, (safety ? "On" : "Off"), (anchored ? "Engaged" : "Off")) + var/message = "AUTH" + if (auth) + message = text("[]", code) + if (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(entity_ja(dat), "window=nuclearbomb;size=300x400") + onclose(user, "nuclearbomb") + +/obj/machinery/nuclearbomb/verb/make_deployable() + set category = "Object" + set name = "Make Deployable" + set src in oview(1) + + if (!usr.canmove || usr.stat || usr.restrained()) + return + if (!ishuman(usr)) + to_chat(usr, "You don't have the dexterity to do this!") + return 1 + + 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 + return + +/obj/machinery/nuclearbomb/is_operational_topic() + return TRUE + +/obj/machinery/nuclearbomb/Topic(href, href_list) + . = ..() + if(!.) + return + + if(!extended) + return + + 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.loc = src + 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 + lastentered = text("[]", href_list["type"]) + if (text2num(lastentered) == null) + var/turf/LOC = get_turf(usr) + message_admins("[key_name_admin(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered] ! ([LOC ? "JMP" : "null"])", 0) + log_admin("EXPLOIT : [key_name(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered] !") + else + src.code += lastentered + 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 = Clamp(round(timeleft), TIMER_MIN, TIMER_MAX) + if (href_list["timer"]) + if (src.timing == -1.0) + return FALSE + if (src.safety) + to_chat(usr, "The safety is still on.") + return FALSE + src.timing = !( src.timing ) + if (src.timing) + if(!src.lighthack) + src.icon_state = "nuclearbomb2" + if(!src.safety) + var/area/nuclearbombloc = get_area(loc) + captain_announce("Bomb has been planted in [initial(nuclearbombloc.name)]. Someone trying to blow up the station!") + set_security_level("delta") + 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 + bomb_set = 0 + if(!src.lighthack) + src.icon_state = "nuclearbomb1" + 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("\red \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.") + else + icon_state = "nuclearbomb1" + safety = 1.0 + timing = -1.0 + timeleft = TIMER_MAX + visible_message("The anchoring bolts slide back into the depths of [src] and timer has stopped.") + + updateUsrDialog() + +/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 + if(detonated) + return + src.detonated = 1 + src.timing = -1.0 + src.yes_code = 0 + src.safety = 1 + if(!src.lighthack) + 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 == ZLEVEL_STATION) ) + 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 + score["nuked"]++ + sleep(10) + explosion(src, 15, 70, 200) + else + off_station = 2 + + if(ticker) + if(ticker.mode && ticker.mode.name == "nuclear emergency") + var/obj/machinery/computer/syndicate_station/syndie_location = locate(/obj/machinery/computer/syndicate_station) + if(syndie_location) + ticker.mode:syndies_didnt_escape = (syndie_location.z > ZLEVEL_STATION ? 0 : 1) //muskets will make me change this, but it will do for now + ticker.mode: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") + ticker.mode: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. + + 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 45 seconds!") + + feedback_set_details("end_error","nuke - unhandled ending") + + if(blackbox) + blackbox.save_all_data_to_sql() + sleep(450) + log_game("Rebooting due to nuclear detonation") + world.Reboot() + return + return + +/obj/machinery/nuclearbomb/MouseDrop_T(mob/living/M, mob/living/user) + if(!ishuman(M) || !ishuman(user)) + return + if(user.is_busy()) + return + if(buckled_mob) + do_after(usr, 30, 1, src) + unbuckle_mob() + else if(do_after(usr, 30, 1, src)) + M.loc = loc + ..() + +/obj/machinery/nuclearbomb/post_buckle_mob(mob/living/M) + ..() + if(M == buckled_mob) + M.pixel_y = 10 + else + M.pixel_y = 0 + +/obj/machinery/nuclearbomb/bullet_act(obj/item/projectile/Proj) + if(buckled_mob) + buckled_mob.bullet_act(Proj) + if(buckled_mob.weakened || buckled_mob.health < 0 || buckled_mob.halloss > 80) + unbuckle_mob() + return ..() + +/obj/machinery/nuclearbomb/MouseDrop(over_object, src_location, over_location) + ..() + if(!istype(over_object, /obj/structure/droppod)) + return + if(!in_range(src, usr) || !ishuman(usr) || !in_range(src, over_object)) + return + var/obj/structure/droppod/D = over_object + if(!timing && !auth && !buckled_mob) + if(usr.is_busy()) + return + visible_message("[usr] start putting [src] into [D]!","You start putting [src] into [D]!") + if(do_after(usr, 100, 1, src) && !timing && !auth && !buckled_mob) + D.Stored_Nuclear = src + loc = D + D.icon_state = "dropod_opened_n[D.item_state]" + visible_message("[usr] put [src] into [D]!","You succesfully put [src] into [D]!") + D.verbs += /obj/structure/droppod/proc/Nuclear + +//==========DAT FUKKEN DISK=============== +/obj/item/weapon/disk + icon = 'icons/obj/items.dmi' + w_class = 1 + item_state = "card-id" + icon_state = "datadisk0" + +/obj/item/weapon/disk/nuclear + name = "nuclear authentication disk" + desc = "Better keep this safe." + icon_state = "nucleardisk" + +/obj/item/weapon/disk/nuclear/atom_init() + . = ..() + poi_list += src + START_PROCESSING(SSobj, src) + +/obj/item/weapon/disk/nuclear/process() + var/turf/disk_loc = get_turf(src) + if(disk_loc.z > ZLEVEL_CENTCOM) + to_chat(get(src, /mob), "You can't help but feel that you just lost something back there...") + qdel(src) + +/obj/item/weapon/disk/nuclear/Destroy() + if(blobstart.len > 0) + var/turf/targetturf = get_turf(pick(blobstart)) + var/turf/diskturf = get_turf(src) + forceMove(targetturf) //move the disc, so ghosts remain orbitting it even if it's "destroyed" + message_admins("[src] has been destroyed in ([diskturf.x], [diskturf.y] ,[diskturf.z] - JMP). Moving it to ([targetturf.x], [targetturf.y], [targetturf.z] - JMP).") + log_game("[src] has been destroyed in ([diskturf.x], [diskturf.y] ,[diskturf.z]). Moving it to ([targetturf.x], [targetturf.y], [targetturf.z]).") + else + throw EXCEPTION("Unable to find a blobstart landmark") + return QDEL_HINT_LETMELIVE //Cancel destruction regardless of success + +#undef TIMER_MIN +#undef TIMER_MAX diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index 0de2e8ab2901..13f2bc35125f 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -1,152 +1,152 @@ -/obj/item/weapon/pinpointer - name = "pinpointer" - icon_state = "pinoff" - flags = CONDUCT - slot_flags = SLOT_BELT - w_class = 2.0 - item_state = "electronic" - throw_speed = 4 - throw_range = 20 - m_amt = 500 - var/active = FALSE - var/atom/target = null - var/mode = SEARCH_FOR_DISK // Need here for GREAT OOP style, 0 - searching disk - -/obj/item/weapon/pinpointer/attack_self(mob/user) - if(!active) - START_PROCESSING(SSobj, src) - to_chat(user, "You activate the pinpointer") - else - icon_state = "pinoff" - to_chat(user, "You deactivate the pinpointer") - active = !active - - - -/obj/item/weapon/pinpointer/process() - if(!active) - return - if(!target && !mode) - target = locate(/obj/item/weapon/disk/nuclear) - if(!target) - icon_state = "pinonnull" - return - if(target) - dir = get_dir(src, target) - var/turf/self_turf = get_turf(src) - var/turf/target_turf = get_turf(target) - if(target_turf.z != self_turf.z) - icon_state = "pinonalert" - else if(target_turf == self_turf) - icon_state = "pinondirect" - else - switch(get_dist(target_turf, self_turf)) - 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) - ..() - for(var/obj/machinery/nuclearbomb/bomb in poi_list) - if(bomb.timing) - to_chat(user, "Extreme danger. Arming signal detected. Time remaining: [bomb.timeleft]") - -/obj/item/weapon/pinpointer/Destroy() - active = FALSE - STOP_PROCESSING(SSobj, src) - target = null - return ..() - -/obj/item/weapon/pinpointer/advpinpointer - name = "Advanced Pinpointer" - 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." - -/obj/item/weapon/pinpointer/advpinpointer/verb/toggle_mode() - set category = "Object" - set name = "Toggle Pinpointer Mode" - set src in view(1) - - active = FALSE - STOP_PROCESSING(SSobj, src) - icon_state = "pinoff" - target = null - - switch(alert("Please select the mode you want to put the pinpointer in.", "Pinpointer Mode Select", "Location", "Disk Recovery", "Other Signature")) - - if("Disk Recovery") - mode = SEARCH_FOR_DISK - if("Location") - mode = SEARCH_FOR_OBJECT - var/locationx = input(usr, "Please input the x coordinate to search for.", "Location?" , "") as num - if(!locationx || !(usr in view(1, src))) - return - var/locationy = input(usr, "Please input the y coordinate to search for.", "Location?" , "") as num - if(!locationy || !(usr in view(1, src))) - return - var/turf/Z = get_turf(src) - var/area/A = locate(locationx, locationy, Z.z) - if(A) - target = A - to_chat(usr, "You set the pinpointer to locate [locationx],[locationy]") - else - to_chat(usr, "No area located at [locationx],[locationy]") - - if("Other Signature") - mode = SEARCH_FOR_OBJECT - switch(alert("Search for item signature or DNA fragment?" , "Signature Mode Select" , "" , "Item" , "DNA")) - if("Item") - var/datum/objective/steal/itemlist - itemlist = itemlist // To supress a 'variable defined but not used' error. - var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in itemlist.possible_items - if(!targetitem) - return - target = locate(itemlist.possible_items[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 = sanitize(input("Input DNA string to search for." , "Please Enter String." , "")) - if(!DNAstring) - return - for(var/mob/living/carbon/M in carbon_list) - if(!M.dna) - continue - if(M.dna.unique_enzymes == DNAstring) - target = M - break - - return attack_self(usr) - -/obj/item/weapon/pinpointer/nukeop - -/obj/item/weapon/pinpointer/nukeop/attack_self(mob/user) - ..() - if(SEARCH_FOR_OBJECT) - to_chat(user, "Authentication Disk Locator active.") - else - to_chat(user, "Shuttle Locator active.") - -/obj/item/weapon/pinpointer/nukeop/process() - if(bomb_set) - mode = SEARCH_FOR_OBJECT - if(!istype(target, /obj/machinery/computer/syndicate_station)) - target = locate(/obj/machinery/computer/syndicate_station) - if(!target) - icon_state = "pinonnull" - return - 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 - else - mode = SEARCH_FOR_DISK - if(istype(target, /obj/machinery/computer/syndicate_station)) - playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) - visible_message("Authentication Disk Locator active.") - target = null - return ..() - -#undef SEARCH_FOR_DISK -#undef SEARCH_FOR_OBJECT +/obj/item/weapon/pinpointer + name = "pinpointer" + icon_state = "pinoff" + flags = CONDUCT + slot_flags = SLOT_BELT + w_class = 2.0 + item_state = "electronic" + throw_speed = 4 + throw_range = 20 + m_amt = 500 + var/active = FALSE + var/atom/target = null + var/mode = SEARCH_FOR_DISK // Need here for GREAT OOP style, 0 - searching disk + +/obj/item/weapon/pinpointer/attack_self(mob/user) + if(!active) + START_PROCESSING(SSobj, src) + to_chat(user, "You activate the pinpointer") + else + icon_state = "pinoff" + to_chat(user, "You deactivate the pinpointer") + active = !active + + + +/obj/item/weapon/pinpointer/process() + if(!active) + return + if(!target && !mode) + target = locate(/obj/item/weapon/disk/nuclear) + if(!target) + icon_state = "pinonnull" + return + if(target) + dir = get_dir(src, target) + var/turf/self_turf = get_turf(src) + var/turf/target_turf = get_turf(target) + if(target_turf.z != self_turf.z) + icon_state = "pinonalert" + else if(target_turf == self_turf) + icon_state = "pinondirect" + else + switch(get_dist(target_turf, self_turf)) + 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) + ..() + for(var/obj/machinery/nuclearbomb/bomb in poi_list) + if(bomb.timing) + to_chat(user, "Extreme danger. Arming signal detected. Time remaining: [bomb.timeleft]") + +/obj/item/weapon/pinpointer/Destroy() + active = FALSE + STOP_PROCESSING(SSobj, src) + target = null + return ..() + +/obj/item/weapon/pinpointer/advpinpointer + name = "Advanced Pinpointer" + 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." + +/obj/item/weapon/pinpointer/advpinpointer/verb/toggle_mode() + set category = "Object" + set name = "Toggle Pinpointer Mode" + set src in view(1) + + active = FALSE + STOP_PROCESSING(SSobj, src) + icon_state = "pinoff" + target = null + + switch(alert("Please select the mode you want to put the pinpointer in.", "Pinpointer Mode Select", "Location", "Disk Recovery", "Other Signature")) + + if("Disk Recovery") + mode = SEARCH_FOR_DISK + if("Location") + mode = SEARCH_FOR_OBJECT + var/locationx = input(usr, "Please input the x coordinate to search for.", "Location?" , "") as num + if(!locationx || !(usr in view(1, src))) + return + var/locationy = input(usr, "Please input the y coordinate to search for.", "Location?" , "") as num + if(!locationy || !(usr in view(1, src))) + return + var/turf/Z = get_turf(src) + var/area/A = locate(locationx, locationy, Z.z) + if(A) + target = A + to_chat(usr, "You set the pinpointer to locate [locationx],[locationy]") + else + to_chat(usr, "No area located at [locationx],[locationy]") + + if("Other Signature") + mode = SEARCH_FOR_OBJECT + switch(alert("Search for item signature or DNA fragment?" , "Signature Mode Select" , "" , "Item" , "DNA")) + if("Item") + var/datum/objective/steal/itemlist + itemlist = itemlist // To supress a 'variable defined but not used' error. + var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in itemlist.possible_items + if(!targetitem) + return + target = locate(itemlist.possible_items[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 = sanitize(input("Input DNA string to search for." , "Please Enter String." , "")) + if(!DNAstring) + return + for(var/mob/living/carbon/M in carbon_list) + if(!M.dna) + continue + if(M.dna.unique_enzymes == DNAstring) + target = M + break + + return attack_self(usr) + +/obj/item/weapon/pinpointer/nukeop + +/obj/item/weapon/pinpointer/nukeop/attack_self(mob/user) + ..() + if(SEARCH_FOR_OBJECT) + to_chat(user, "Authentication Disk Locator active.") + else + to_chat(user, "Shuttle Locator active.") + +/obj/item/weapon/pinpointer/nukeop/process() + if(bomb_set) + mode = SEARCH_FOR_OBJECT + if(!istype(target, /obj/machinery/computer/syndicate_station)) + target = locate(/obj/machinery/computer/syndicate_station) + if(!target) + icon_state = "pinonnull" + return + 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 + else + mode = SEARCH_FOR_DISK + if(istype(target, /obj/machinery/computer/syndicate_station)) + playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) + visible_message("Authentication Disk Locator active.") + target = null + return ..() + +#undef SEARCH_FOR_DISK +#undef SEARCH_FOR_OBJECT diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 4799b4a18297..8f6a39503802 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1,992 +1,992 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 -var/global/list/all_objectives = list() - -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. - - New(var/text) - all_objectives |= src - if(text) - explanation_text = text - - Destroy() - all_objectives -= src - return ..() - - 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.stat != DEAD)) - 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) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) ) - 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) - if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || target.current.z > ZLEVEL_EMPTY || !target.current.ckey) //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 - - -datum/objective/mutiny/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 - -datum/objective/mutiny/check_completion() - if(target && target.current) - if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey) - return 1 - var/turf/T = get_turf(target.current) - if(T && (T.z != ZLEVEL_STATION)) //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 - - -datum/objective/mutiny/rp/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 -datum/objective/mutiny/rp/check_completion() - if(target && target.current) - //assume that only carbon mobs can become rev heads for now - if(target.current.stat == DEAD || target.current:handcuffed || !ishuman(target.current)) - return TRUE - // Check if they're converted - if(istype(ticker.mode, /datum/game_mode/revolution)) - if(target in ticker.mode:head_revolutionaries) - return TRUE - var/turf/T = get_turf(target.current) - if(T && (T.z != ZLEVEL_STATION)) //If they leave the station they count as dead for this - return TRUE - return FALSE - return TRUE - -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(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(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 == "Test Subject") - 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(!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/dehead/find_target() - ..() - if(target && target.current) - explanation_text = "Put the head of [target.current.real_name] in biogel can and steal it." - else - explanation_text = "Free Objective" - return target - -/datum/objective/dehead/find_target_by_role(role, role_type=0) - ..() - if(target && target.current) - explanation_text = "Steal the head of [target.current.real_name] the [!role_type ? target.assigned_role : target.special_role], make shure that head is stored in the biogel can." - else - explanation_text = "Free Objective" - return target - -/datum/objective/dehead/check_completion() - if(!target)//If it's a free objective. - return 1 - if( !owner.current || owner.current.stat==DEAD )//If you're otherwise dead. - return 0 - var/list/all_items = owner.current.get_contents() - for(var/obj/item/device/biocan/B in all_items) - if(B.brainmob && B.brainmob == target.current) - return 1 - return 0 - 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(!target) //If it's a free objective. - return 1 - if(target.current) - if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current)) - return 0 - return 1 - return 0 - - -datum/objective/hijack - explanation_text = "Hijack the emergency shuttle by escaping alone." - - check_completion() - if(!owner.current || owner.current.stat) - return 0 - if(SSshuttle.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) - 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(!istype(owner.current, /mob/living/silicon)) - return 0 - if(SSshuttle.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) - for(var/mob/living/player in player_list) - if(player.type in protected_mobs) continue - if (player.mind) - if (player.stat != DEAD) - 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(SSshuttle.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(issilicon(owner.current)) - return 0 - if(isbrain(owner.current)) - return 0 - if(SSshuttle.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 traitors if they are in the shuttle brig -- Polymorph - if(istype(owner.current, /mob/living/carbon)) - var/mob/living/carbon/C = owner.current - if (!C.restrained()) - 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/survive - explanation_text = "Stay alive until the end." - - check_completion() - if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current)) - return 0 //Brains no longer win survive objectives. --NEO - if(issilicon(owner.current) && owner.current != owner.original) - return 0 - return 1 - -// 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(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(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/obj/item/organ/external/BP in H.bodyparts) - if(BP.status & ORGAN_BROKEN) - already_completed = 1 - return 1 - if((BP.status & ORGAN_DESTROYED) && !BP.amputated) - already_completed = 1 - return 1 - - var/obj/item/organ/external/head/BP = H.bodyparts_by_name[BP_HEAD] - if(BP.disfigured) - return 1 - return 0 - - -datum/objective/nuclear - explanation_text = "Destroy the station with a nuclear device." - - - -datum/objective/steal - var/obj/item/steal_target - var/target_name - - var/global/possible_items[] = list( - "the captain's antique laser gun" = /obj/item/weapon/gun/energy/laser/selfcharging/captain, - "a hand teleporter" = /obj/item/weapon/hand_tele, - "an RCD" = /obj/item/weapon/rcd, - "a jetpack" = /obj/item/weapon/tank/jetpack, - "a captain's jumpsuit" = /obj/item/clothing/under/rank/captain, - "a functional AI" = /obj/item/device/aicard, - "a pair of magboots" = /obj/item/clothing/shoes/magboots, - "the station blueprints" = /obj/item/blueprints, - "a nasa voidsuit" = /obj/item/clothing/suit/space/nasavoid, - "28 moles of phoron (full tank)" = /obj/item/weapon/tank, - "a sample of slime extract" = /obj/item/slime_extract, - "a piece of corgi meat" = /obj/item/weapon/reagent_containers/food/snacks/meat/corgi, - "a research director's jumpsuit" = /obj/item/clothing/under/rank/research_director, - "a chief engineer's jumpsuit" = /obj/item/clothing/under/rank/chief_engineer, - "a chief medical officer's jumpsuit" = /obj/item/clothing/under/rank/chief_medical_officer, - "a head of security's jumpsuit" = /obj/item/clothing/under/rank/head_of_security, - "a head of personnel's jumpsuit" = /obj/item/clothing/under/rank/head_of_personnel, - "the hypospray" = /obj/item/weapon/reagent_containers/hypospray/cmo, - "the captain's pinpointer" = /obj/item/weapon/pinpointer, - "an ablative armor vest" = /obj/item/clothing/suit/armor/laserproof, - ) - - var/global/possible_items_special[] = list( - /*"nuclear authentication disk" = /obj/item/weapon/disk/nuclear,*///Broken with the change to nuke disk making it respawn on z level change. - "nuclear gun" = /obj/item/weapon/gun/energy/gun/nuclear, - "diamond drill" = /obj/item/weapon/pickaxe/drill/diamond_drill, - "bag of holding" = /obj/item/weapon/storage/backpack/holding, - "hyper-capacity cell" = /obj/item/weapon/stock_parts/cell/hyper, - "10 diamonds" = /obj/item/stack/sheet/mineral/diamond, - "50 gold bars" = /obj/item/stack/sheet/mineral/gold, - "25 refined uranium bars" = /obj/item/stack/sheet/mineral/uranium, - ) - - - proc/set_target(item_name) - target_name = item_name - steal_target = possible_items[target_name] - if (!steal_target ) - steal_target = possible_items_special[target_name] - explanation_text = "Steal [target_name]." - return steal_target - - - find_target() - return set_target(pick(possible_items)) - - - proc/select_target() - var/list/possible_items_all = possible_items+possible_items_special+"custom" - var/new_target = input("Select target:", "Objective target", steal_target) as null|anything in possible_items_all - if (!new_target) return - if (new_target == "custom") - var/obj/item/custom_target = input("Select type:","Type") as null|anything in typesof(/obj/item) - if (!custom_target) return - var/tmp_obj = new custom_target - var/custom_name = tmp_obj:name - qdel(tmp_obj) - custom_name = sanitize_safe(input("Enter target name:", "Objective target", input_default(custom_name)) as text|null) - if (!custom_name) return - target_name = custom_name - steal_target = custom_target - explanation_text = "Steal [target_name]." - else - set_target(new_target) - return steal_target - - check_completion() - if(!steal_target || !owner.current) return 0 - if(!isliving(owner.current)) return 0 - var/list/all_items = owner.current.get_contents() - switch (target_name) - if("28 moles of phoron (full tank)","10 diamonds","50 gold bars","25 refined uranium bars") - var/target_amount = text2num(target_name)//Non-numbers are ignored. - var/found_amount = 0.0//Always starts as zero. - - for(var/obj/item/I in all_items) //Check for phoron tanks - if(istype(I, steal_target)) - found_amount += (target_name == "28 moles of phoron (full tank)" ? (I:air_contents:gas["phoron"]) : (I:amount)) - return found_amount>=target_amount - - if("50 coins (in bag)") - var/obj/item/weapon/moneybag/B = locate() in all_items - - if(B) - var/target = text2num(target_name) - var/found_amount = 0.0 - for(var/obj/item/weapon/coin/C in B) - found_amount++ - return found_amount>=target - - if("a functional AI") - for(var/obj/item/device/aicard/C in all_items) //Check for ai card - for(var/mob/living/silicon/ai/M in C) - if(istype(M, /mob/living/silicon/ai) && M.stat != DEAD) //See if any AI's are alive inside that card. - return 1 - - for(var/obj/item/clothing/suit/space/space_ninja/S in all_items) //Let an AI downloaded into a space ninja suit count - if(S.AI && S.AI.stat != DEAD) - return 1 - for(var/mob/living/silicon/ai/ai in ai_list) - if(ai.stat == DEAD) - continue - if(istype(ai.loc, /turf)) - var/area/check_area = get_area(ai) - 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 - - for(var/obj/I in all_items) //Check for items - if(istype(I, steal_target)) - return 1 - return 0 - - - -datum/objective/download - proc/gen_amount_goal() - target_amount = rand(10,20) - explanation_text = "Download [target_amount] research levels." - return target_amount - - - check_completion() - if(!ishuman(owner.current)) - return 0 - if(!owner.current || owner.current.stat == DEAD) - return 0 - if(!(istype(owner.current:wear_suit, /obj/item/clothing/suit/space/space_ninja)&&owner.current:wear_suit:s_initialized)) - return 0 - var/current_amount - var/obj/item/clothing/suit/space/space_ninja/S = owner.current:wear_suit - if(!S.stored_research.len) - return 0 - else - for(var/datum/tech/current_data in S.stored_research) - if(current_data.level>1) current_amount+=(current_data.level-1) - if(current_amount= 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(SSshuttle.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------*/ -*/ -//Meme objectives -datum/objective/meme_attune - proc/gen_amount_goal(lowbound = 4, highbound = 6) - target_amount = rand (lowbound,highbound) - explanation_text = "Attune [target_amount] humanoid brains." - return target_amount - - check_completion() - if(owner && owner.current && istype(owner.current,/mob/living/parasite/meme) && (owner.current:indoctrinated.len >= target_amount)) - return 1 - else - return 0 - - -//Vox heist objectives. - -/datum/objective/heist/proc/choose_target() - return - -/datum/objective/heist/kidnap/choose_target() - var/list/roles = list("Roboticist" , "Medical Doctor" , "Chemist" , "Station Engineer") - var/list/possible_targets = list() - var/list/priority_targets = list() - - for(var/datum/mind/possible_target in ticker.minds) - if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && (possible_target.assigned_role != "MODE")) - - possible_targets += possible_target - for(var/role in roles) - if(possible_target.assigned_role == role) - priority_targets += possible_target - continue - - if(priority_targets.len > 0) - target = pick(priority_targets) - else if(possible_targets.len > 0) - target = pick(possible_targets) - - if(target && target.current) - explanation_text = "The Shoal has a need for [target.current.real_name], the [target.assigned_role]. Take them alive." - else - explanation_text = "Free Objective" - return target - -/datum/objective/heist/kidnap/check_completion() - if(target && target.current) - if (target.current.stat == DEAD) - return FALSE // They're dead. Fail. - //if (!target.current.restrained()) - // return 0 // They're loose. Close but no cigar. - if(get_area(target) == locate(/area/shuttle/vox/station)) - return TRUE - else - return FALSE - -/datum/objective/heist/loot/choose_target() - var/loot = "an object" - switch(rand(1, 8)) - if(1) - target = /obj/structure/particle_accelerator - target_amount = 6 - loot = "a complete particle accelerator" - if(2) - target = /obj/machinery/the_singularitygen - target_amount = 1 - loot = "a Gravitational Singularity Generator" - if(3) - target = /obj/machinery/power/emitter - target_amount = 4 - loot = "four emitters" - if(4) - target = /obj/machinery/nuclearbomb - target_amount = 1 - loot = "a nuclear bomb" - if(5) - target = /obj/item/weapon/gun - target_amount = 6 - loot = "six guns" - if(6) - target = /obj/item/weapon/gun/energy - target_amount = 4 - loot = "four energy guns" - if(7) - target = /obj/item/weapon/gun/energy/laser - target_amount = 2 - loot = "two laser guns" - if(8) - target = /obj/item/weapon/gun/energy/ionrifle - target_amount = 1 - loot = "an ion gun" - - explanation_text = "We are lacking in hardware. Steal [loot]." - -/datum/objective/heist/loot/check_completion() - var/total_amount = 0 - - for(var/obj/O in locate(/area/shuttle/vox/station)) - if(istype(O,target)) total_amount++ - for(var/obj/I in O.contents) - if(istype(I, target)) - total_amount++ - if(total_amount >= target_amount) - return TRUE - - var/datum/game_mode/heist/H = ticker.mode - for(var/datum/mind/raider in H.raiders) - if(raider.current) - for(var/obj/O in raider.current.get_contents()) - if(istype(O,target)) - total_amount++ - if(total_amount >= target_amount) - return TRUE - - return FALSE - -/datum/objective/heist/salvage/choose_target() - switch(rand(1,4)) - if(1) - target = "metal" - target_amount = 300 - if(2) - target = "glass" - target_amount = 200 - if(3) - target = "plasteel" - target_amount = 100 - if(4) - target = "solid phoron" - target_amount = 100 - if(5) - target = "silver" - target_amount = 50 - if(6) - target = "gold" - target_amount = 20 - if(7) - target = "uranium" - target_amount = 20 - if(8) - target = "diamond" - target_amount = 1 - - explanation_text = "Ransack the station and escape with [target_amount] [target]." - -/datum/objective/heist/salvage/check_completion() - var/total_amount = 0 - - for(var/obj/item/O in locate(/area/shuttle/vox/station)) - - var/obj/item/stack/sheet/S - if(istype(O, /obj/item/stack/sheet)) - if(O.name == target) - S = O - total_amount += S.get_amount() - for(var/obj/I in O.contents) - if(istype(I, /obj/item/stack/sheet)) - if(I.name == target) - S = I - total_amount += S.get_amount() - - var/datum/game_mode/heist/H = ticker.mode - for(var/datum/mind/raider in H.raiders) - if(raider.current) - for(var/obj/item/O in raider.current.get_contents()) - if(istype(O,/obj/item/stack/sheet)) - if(O.name == target) - var/obj/item/stack/sheet/S = O - total_amount += S.get_amount() - - if(total_amount >= target_amount) - return TRUE - return FALSE -/* -var/heist_rob_total = 0 -/proc/heist_recursive_price_check(atom/movable/AM,loop=0) - loop++ - if(loop > 15) return - heist_rob_total += AM.get_price() - if(AM.contents && AM.contents.len) - for(var/atom/movable/I in AM.contents) - heist_rob_total += I.get_price() - if(I.contents && I.contents.len) - heist_recursive_price_check(I,loop) -/proc/heist_recursive_price_reset(atom/movable/AM,loop=0) - loop++ - if(loop > 15) return - AM.price = 0 - if(AM.contents && AM.contents.len) - for(var/atom/movable/I in AM.contents) - I.price = 0 - if(I.contents && I.contents.len) - heist_recursive_price_reset(I,loop) -/proc/heist_get_shuttle_price() - heist_rob_total = 0 - var/area/A = get_area(locate(/obj/effect/landmark/heist/aurora)) - if(A) - for(var/atom/movable/AM in A) - heist_recursive_price_check(AM) -/datum/objective/heist/robbery/choose_target() - target = "valuables" - target_amount = 1000000 - explanation_text = "Ransack the station for any valuables." -/datum/objective/heist/robbery/check_completion() - heist_rob_total = 0 - for(var/atom/movable/AM in locate(/area/shuttle/vox/station)) - heist_recursive_price_check(AM) - if(heist_rob_total >= target_amount) return 1 - return 0*/ - -/datum/objective/heist/inviolate_crew - explanation_text = "Do not leave any Vox behind, alive or dead." - -/datum/objective/heist/inviolate_crew/check_completion() - var/datum/game_mode/heist/H = ticker.mode - if(H.is_raider_crew_safe()) - return TRUE - return FALSE - -#define MAX_VOX_KILLS 10 //Number of kills during the round before the Inviolate is broken. - //Would be nice to use vox-specific kills but is currently not feasible. -var/global/vox_kills = 0 //Used to check the Inviolate. - -/datum/objective/heist/inviolate_death - explanation_text = "Follow the Inviolate. Minimise death and loss of resources." - -/datum/objective/heist/inviolate_death/check_completion() - if(vox_kills > MAX_VOX_KILLS) - return FALSE - return TRUE +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 +var/global/list/all_objectives = list() + +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. + + New(var/text) + all_objectives |= src + if(text) + explanation_text = text + + Destroy() + all_objectives -= src + return ..() + + 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.stat != DEAD)) + 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) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) ) + 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) + if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current) || target.current.z > ZLEVEL_EMPTY || !target.current.ckey) //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 + + +datum/objective/mutiny/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 + +datum/objective/mutiny/check_completion() + if(target && target.current) + if(target.current.stat == DEAD || !ishuman(target.current) || !target.current.ckey) + return 1 + var/turf/T = get_turf(target.current) + if(T && (T.z != ZLEVEL_STATION)) //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 + + +datum/objective/mutiny/rp/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 +datum/objective/mutiny/rp/check_completion() + if(target && target.current) + //assume that only carbon mobs can become rev heads for now + if(target.current.stat == DEAD || target.current:handcuffed || !ishuman(target.current)) + return TRUE + // Check if they're converted + if(istype(ticker.mode, /datum/game_mode/revolution)) + if(target in ticker.mode:head_revolutionaries) + return TRUE + var/turf/T = get_turf(target.current) + if(T && (T.z != ZLEVEL_STATION)) //If they leave the station they count as dead for this + return TRUE + return FALSE + return TRUE + +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(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(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 == "Test Subject") + 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(!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/dehead/find_target() + ..() + if(target && target.current) + explanation_text = "Put the head of [target.current.real_name] in biogel can and steal it." + else + explanation_text = "Free Objective" + return target + +/datum/objective/dehead/find_target_by_role(role, role_type=0) + ..() + if(target && target.current) + explanation_text = "Steal the head of [target.current.real_name] the [!role_type ? target.assigned_role : target.special_role], make shure that head is stored in the biogel can." + else + explanation_text = "Free Objective" + return target + +/datum/objective/dehead/check_completion() + if(!target)//If it's a free objective. + return 1 + if( !owner.current || owner.current.stat==DEAD )//If you're otherwise dead. + return 0 + var/list/all_items = owner.current.get_contents() + for(var/obj/item/device/biocan/B in all_items) + if(B.brainmob && B.brainmob == target.current) + return 1 + return 0 + 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(!target) //If it's a free objective. + return 1 + if(target.current) + if(target.current.stat == DEAD || issilicon(target.current) || isbrain(target.current)) + return 0 + return 1 + return 0 + + +datum/objective/hijack + explanation_text = "Hijack the emergency shuttle by escaping alone." + + check_completion() + if(!owner.current || owner.current.stat) + return 0 + if(SSshuttle.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) + 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(!istype(owner.current, /mob/living/silicon)) + return 0 + if(SSshuttle.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) + for(var/mob/living/player in player_list) + if(player.type in protected_mobs) continue + if (player.mind) + if (player.stat != DEAD) + 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(SSshuttle.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(issilicon(owner.current)) + return 0 + if(isbrain(owner.current)) + return 0 + if(SSshuttle.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 traitors if they are in the shuttle brig -- Polymorph + if(istype(owner.current, /mob/living/carbon)) + var/mob/living/carbon/C = owner.current + if (!C.restrained()) + 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/survive + explanation_text = "Stay alive until the end." + + check_completion() + if(!owner.current || owner.current.stat == DEAD || isbrain(owner.current)) + return 0 //Brains no longer win survive objectives. --NEO + if(issilicon(owner.current) && owner.current != owner.original) + return 0 + return 1 + +// 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(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(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/obj/item/organ/external/BP in H.bodyparts) + if(BP.status & ORGAN_BROKEN) + already_completed = 1 + return 1 + if((BP.status & ORGAN_DESTROYED) && !BP.amputated) + already_completed = 1 + return 1 + + var/obj/item/organ/external/head/BP = H.bodyparts_by_name[BP_HEAD] + if(BP.disfigured) + return 1 + return 0 + + +datum/objective/nuclear + explanation_text = "Destroy the station with a nuclear device." + + + +datum/objective/steal + var/obj/item/steal_target + var/target_name + + var/global/possible_items[] = list( + "the captain's antique laser gun" = /obj/item/weapon/gun/energy/laser/selfcharging/captain, + "a hand teleporter" = /obj/item/weapon/hand_tele, + "an RCD" = /obj/item/weapon/rcd, + "a jetpack" = /obj/item/weapon/tank/jetpack, + "a captain's jumpsuit" = /obj/item/clothing/under/rank/captain, + "a functional AI" = /obj/item/device/aicard, + "a pair of magboots" = /obj/item/clothing/shoes/magboots, + "the station blueprints" = /obj/item/blueprints, + "a nasa voidsuit" = /obj/item/clothing/suit/space/nasavoid, + "28 moles of phoron (full tank)" = /obj/item/weapon/tank, + "a sample of slime extract" = /obj/item/slime_extract, + "a piece of corgi meat" = /obj/item/weapon/reagent_containers/food/snacks/meat/corgi, + "a research director's jumpsuit" = /obj/item/clothing/under/rank/research_director, + "a chief engineer's jumpsuit" = /obj/item/clothing/under/rank/chief_engineer, + "a chief medical officer's jumpsuit" = /obj/item/clothing/under/rank/chief_medical_officer, + "a head of security's jumpsuit" = /obj/item/clothing/under/rank/head_of_security, + "a head of personnel's jumpsuit" = /obj/item/clothing/under/rank/head_of_personnel, + "the hypospray" = /obj/item/weapon/reagent_containers/hypospray/cmo, + "the captain's pinpointer" = /obj/item/weapon/pinpointer, + "an ablative armor vest" = /obj/item/clothing/suit/armor/laserproof, + ) + + var/global/possible_items_special[] = list( + /*"nuclear authentication disk" = /obj/item/weapon/disk/nuclear,*///Broken with the change to nuke disk making it respawn on z level change. + "nuclear gun" = /obj/item/weapon/gun/energy/gun/nuclear, + "diamond drill" = /obj/item/weapon/pickaxe/drill/diamond_drill, + "bag of holding" = /obj/item/weapon/storage/backpack/holding, + "hyper-capacity cell" = /obj/item/weapon/stock_parts/cell/hyper, + "10 diamonds" = /obj/item/stack/sheet/mineral/diamond, + "50 gold bars" = /obj/item/stack/sheet/mineral/gold, + "25 refined uranium bars" = /obj/item/stack/sheet/mineral/uranium, + ) + + + proc/set_target(item_name) + target_name = item_name + steal_target = possible_items[target_name] + if (!steal_target ) + steal_target = possible_items_special[target_name] + explanation_text = "Steal [target_name]." + return steal_target + + + find_target() + return set_target(pick(possible_items)) + + + proc/select_target() + var/list/possible_items_all = possible_items+possible_items_special+"custom" + var/new_target = input("Select target:", "Objective target", steal_target) as null|anything in possible_items_all + if (!new_target) return + if (new_target == "custom") + var/obj/item/custom_target = input("Select type:","Type") as null|anything in typesof(/obj/item) + if (!custom_target) return + var/tmp_obj = new custom_target + var/custom_name = tmp_obj:name + qdel(tmp_obj) + custom_name = sanitize_safe(input("Enter target name:", "Objective target", input_default(custom_name)) as text|null) + if (!custom_name) return + target_name = custom_name + steal_target = custom_target + explanation_text = "Steal [target_name]." + else + set_target(new_target) + return steal_target + + check_completion() + if(!steal_target || !owner.current) return 0 + if(!isliving(owner.current)) return 0 + var/list/all_items = owner.current.get_contents() + switch (target_name) + if("28 moles of phoron (full tank)","10 diamonds","50 gold bars","25 refined uranium bars") + var/target_amount = text2num(target_name)//Non-numbers are ignored. + var/found_amount = 0.0//Always starts as zero. + + for(var/obj/item/I in all_items) //Check for phoron tanks + if(istype(I, steal_target)) + found_amount += (target_name == "28 moles of phoron (full tank)" ? (I:air_contents:gas["phoron"]) : (I:amount)) + return found_amount>=target_amount + + if("50 coins (in bag)") + var/obj/item/weapon/moneybag/B = locate() in all_items + + if(B) + var/target = text2num(target_name) + var/found_amount = 0.0 + for(var/obj/item/weapon/coin/C in B) + found_amount++ + return found_amount>=target + + if("a functional AI") + for(var/obj/item/device/aicard/C in all_items) //Check for ai card + for(var/mob/living/silicon/ai/M in C) + if(istype(M, /mob/living/silicon/ai) && M.stat != DEAD) //See if any AI's are alive inside that card. + return 1 + + for(var/obj/item/clothing/suit/space/space_ninja/S in all_items) //Let an AI downloaded into a space ninja suit count + if(S.AI && S.AI.stat != DEAD) + return 1 + for(var/mob/living/silicon/ai/ai in ai_list) + if(ai.stat == DEAD) + continue + if(istype(ai.loc, /turf)) + var/area/check_area = get_area(ai) + 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 + + for(var/obj/I in all_items) //Check for items + if(istype(I, steal_target)) + return 1 + return 0 + + + +datum/objective/download + proc/gen_amount_goal() + target_amount = rand(10,20) + explanation_text = "Download [target_amount] research levels." + return target_amount + + + check_completion() + if(!ishuman(owner.current)) + return 0 + if(!owner.current || owner.current.stat == DEAD) + return 0 + if(!(istype(owner.current:wear_suit, /obj/item/clothing/suit/space/space_ninja)&&owner.current:wear_suit:s_initialized)) + return 0 + var/current_amount + var/obj/item/clothing/suit/space/space_ninja/S = owner.current:wear_suit + if(!S.stored_research.len) + return 0 + else + for(var/datum/tech/current_data in S.stored_research) + if(current_data.level>1) current_amount+=(current_data.level-1) + if(current_amount= 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(SSshuttle.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------*/ +*/ +//Meme objectives +datum/objective/meme_attune + proc/gen_amount_goal(lowbound = 4, highbound = 6) + target_amount = rand (lowbound,highbound) + explanation_text = "Attune [target_amount] humanoid brains." + return target_amount + + check_completion() + if(owner && owner.current && istype(owner.current,/mob/living/parasite/meme) && (owner.current:indoctrinated.len >= target_amount)) + return 1 + else + return 0 + + +//Vox heist objectives. + +/datum/objective/heist/proc/choose_target() + return + +/datum/objective/heist/kidnap/choose_target() + var/list/roles = list("Roboticist" , "Medical Doctor" , "Chemist" , "Station Engineer") + var/list/possible_targets = list() + var/list/priority_targets = list() + + for(var/datum/mind/possible_target in ticker.minds) + if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && (possible_target.assigned_role != "MODE")) + + possible_targets += possible_target + for(var/role in roles) + if(possible_target.assigned_role == role) + priority_targets += possible_target + continue + + if(priority_targets.len > 0) + target = pick(priority_targets) + else if(possible_targets.len > 0) + target = pick(possible_targets) + + if(target && target.current) + explanation_text = "The Shoal has a need for [target.current.real_name], the [target.assigned_role]. Take them alive." + else + explanation_text = "Free Objective" + return target + +/datum/objective/heist/kidnap/check_completion() + if(target && target.current) + if (target.current.stat == DEAD) + return FALSE // They're dead. Fail. + //if (!target.current.restrained()) + // return 0 // They're loose. Close but no cigar. + if(get_area(target) == locate(/area/shuttle/vox/station)) + return TRUE + else + return FALSE + +/datum/objective/heist/loot/choose_target() + var/loot = "an object" + switch(rand(1, 8)) + if(1) + target = /obj/structure/particle_accelerator + target_amount = 6 + loot = "a complete particle accelerator" + if(2) + target = /obj/machinery/the_singularitygen + target_amount = 1 + loot = "a Gravitational Singularity Generator" + if(3) + target = /obj/machinery/power/emitter + target_amount = 4 + loot = "four emitters" + if(4) + target = /obj/machinery/nuclearbomb + target_amount = 1 + loot = "a nuclear bomb" + if(5) + target = /obj/item/weapon/gun + target_amount = 6 + loot = "six guns" + if(6) + target = /obj/item/weapon/gun/energy + target_amount = 4 + loot = "four energy guns" + if(7) + target = /obj/item/weapon/gun/energy/laser + target_amount = 2 + loot = "two laser guns" + if(8) + target = /obj/item/weapon/gun/energy/ionrifle + target_amount = 1 + loot = "an ion gun" + + explanation_text = "We are lacking in hardware. Steal [loot]." + +/datum/objective/heist/loot/check_completion() + var/total_amount = 0 + + for(var/obj/O in locate(/area/shuttle/vox/station)) + if(istype(O,target)) total_amount++ + for(var/obj/I in O.contents) + if(istype(I, target)) + total_amount++ + if(total_amount >= target_amount) + return TRUE + + var/datum/game_mode/heist/H = ticker.mode + for(var/datum/mind/raider in H.raiders) + if(raider.current) + for(var/obj/O in raider.current.get_contents()) + if(istype(O,target)) + total_amount++ + if(total_amount >= target_amount) + return TRUE + + return FALSE + +/datum/objective/heist/salvage/choose_target() + switch(rand(1,4)) + if(1) + target = "metal" + target_amount = 300 + if(2) + target = "glass" + target_amount = 200 + if(3) + target = "plasteel" + target_amount = 100 + if(4) + target = "solid phoron" + target_amount = 100 + if(5) + target = "silver" + target_amount = 50 + if(6) + target = "gold" + target_amount = 20 + if(7) + target = "uranium" + target_amount = 20 + if(8) + target = "diamond" + target_amount = 1 + + explanation_text = "Ransack the station and escape with [target_amount] [target]." + +/datum/objective/heist/salvage/check_completion() + var/total_amount = 0 + + for(var/obj/item/O in locate(/area/shuttle/vox/station)) + + var/obj/item/stack/sheet/S + if(istype(O, /obj/item/stack/sheet)) + if(O.name == target) + S = O + total_amount += S.get_amount() + for(var/obj/I in O.contents) + if(istype(I, /obj/item/stack/sheet)) + if(I.name == target) + S = I + total_amount += S.get_amount() + + var/datum/game_mode/heist/H = ticker.mode + for(var/datum/mind/raider in H.raiders) + if(raider.current) + for(var/obj/item/O in raider.current.get_contents()) + if(istype(O,/obj/item/stack/sheet)) + if(O.name == target) + var/obj/item/stack/sheet/S = O + total_amount += S.get_amount() + + if(total_amount >= target_amount) + return TRUE + return FALSE +/* +var/heist_rob_total = 0 +/proc/heist_recursive_price_check(atom/movable/AM,loop=0) + loop++ + if(loop > 15) return + heist_rob_total += AM.get_price() + if(AM.contents && AM.contents.len) + for(var/atom/movable/I in AM.contents) + heist_rob_total += I.get_price() + if(I.contents && I.contents.len) + heist_recursive_price_check(I,loop) +/proc/heist_recursive_price_reset(atom/movable/AM,loop=0) + loop++ + if(loop > 15) return + AM.price = 0 + if(AM.contents && AM.contents.len) + for(var/atom/movable/I in AM.contents) + I.price = 0 + if(I.contents && I.contents.len) + heist_recursive_price_reset(I,loop) +/proc/heist_get_shuttle_price() + heist_rob_total = 0 + var/area/A = get_area(locate(/obj/effect/landmark/heist/aurora)) + if(A) + for(var/atom/movable/AM in A) + heist_recursive_price_check(AM) +/datum/objective/heist/robbery/choose_target() + target = "valuables" + target_amount = 1000000 + explanation_text = "Ransack the station for any valuables." +/datum/objective/heist/robbery/check_completion() + heist_rob_total = 0 + for(var/atom/movable/AM in locate(/area/shuttle/vox/station)) + heist_recursive_price_check(AM) + if(heist_rob_total >= target_amount) return 1 + return 0*/ + +/datum/objective/heist/inviolate_crew + explanation_text = "Do not leave any Vox behind, alive or dead." + +/datum/objective/heist/inviolate_crew/check_completion() + var/datum/game_mode/heist/H = ticker.mode + if(H.is_raider_crew_safe()) + return TRUE + return FALSE + +#define MAX_VOX_KILLS 10 //Number of kills during the round before the Inviolate is broken. + //Would be nice to use vox-specific kills but is currently not feasible. +var/global/vox_kills = 0 //Used to check the Inviolate. + +/datum/objective/heist/inviolate_death + explanation_text = "Follow the Inviolate. Minimise death and loss of resources." + +/datum/objective/heist/inviolate_death/check_completion() + if(vox_kills > MAX_VOX_KILLS) + return FALSE + return TRUE diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index e9982279881c..b580553d5190 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -1,503 +1,503 @@ -// 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" - role_type = ROLE_REV - restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer", "Internal Affairs Agent") - required_players = 4 - required_players_secret = 15 - required_enemies = 3 - recommended_enemies = 3 - - votable = 0 - - - uplink_welcome = "AntagCorp Uplink Console:" - uplink_uses = 20 - - var/finished = 0 - var/checkwin_counter = 0 - var/max_headrevs = 3 - -/////////////////////////// -//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/head_check = 0 - for(var/mob/dead/new_player/player in player_list) - if(player.mind.assigned_role in command_positions) - head_check = 1 - break - - for(var/datum/mind/player in antag_candidates) - for(var/job in restricted_jobs)//Removing heads and such from the list - if(player.assigned_role == job) - antag_candidates -= player - - for (var/i=1 to max_headrevs) - if (antag_candidates.len==0) - break - var/datum/mind/lenin = pick(antag_candidates) - antag_candidates -= lenin - head_revolutionaries += lenin - - if((head_revolutionaries.len==0)||(!head_check)) - return 0 - - return 1 - - -/datum/game_mode/revolution/post_setup() - var/list/heads = get_living_heads() - for(var/datum/mind/rev_mind in head_revolutionaries) - if(!config.objectives_disabled) - 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 - - spawn(rand(10,100)) - // 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_all_rev_icons() - - for(var/datum/mind/rev_mind in head_revolutionaries) - greet_revolutionary(rev_mind) - modePlayer += head_revolutionaries - if(SSshuttle) - SSshuttle.always_fake_recall = 1 - return ..() - - -/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(datum/mind/rev_mind) - if(!config.objectives_disabled) - 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 or exile [head_mind.name], the [head_mind.assigned_role]." - rev_mind.objectives += rev_obj - -/datum/game_mode/proc/greet_revolutionary(datum/mind/rev_mind, you_are=1) - var/obj_count = 1 - if (you_are) - to_chat(rev_mind.current, "\blue You are a member of the revolutionaries' leadership!") - if(!config.objectives_disabled) - 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++ - else - to_chat(rev_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - -///////////////////////////////////////////////////////////////////////////////// -//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(CLUMSY) - - - var/obj/item/device/flash/T = new(mob) - var/obj/item/toy/crayon/spraycan/R = 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) - mob.equip_in_one_of_slots(R,slots) - - mob.update_icons() - - if (!where) - to_chat(mob, "The Syndicate were unfortunately unable to get you a flash.") - else - to_chat(mob, "The flash in your [where] will help you to persuade the crew to join your cause.") - 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) - if(SSshuttle) - SSshuttle.always_fake_recall = 0 - return ..() - if(finished) - 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 0 - var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted - if(ismindshielded(H)) - return 0 - if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) - return 0 - revolutionaries += rev_mind - if(iscarbon(rev_mind.current)) - var/mob/living/carbon/carbon_mob = rev_mind.current - carbon_mob.silent = max(carbon_mob.silent, 5) - rev_mind.current.Stun(5) - to_chat(rev_mind.current, "\red 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" - if(config.objectives_disabled) - to_chat(rev_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - update_all_rev_icons() - 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 - rev_mind.current.hud_updateflag |= 1 << SPECIALROLE_HUD - - if(beingborged) - to_chat(rev_mind.current, "\red The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now.") - - else - to_chat(rev_mind.current, "\red 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) - to_chat(rev_mind.current, "\red The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.") - message_admins("[key_name_admin(rev_mind.current)] ? has been borged while being a member of the revolution.") - - else - to_chat(M, "[rev_mind.current] looks like they just remembered their real allegiance!") - - -///////////////////////////////////////////////////////////////////////////////////////////////// -//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") - qdel(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") - qdel(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/I = image('icons/mob/mob.dmi', loc = rev.current, icon_state = "rev") - head_rev.current.client.images += I - for(var/datum/mind/head_rev_1 in head_revolutionaries) - if(head_rev_1.current) - var/I = image('icons/mob/mob.dmi', loc = head_rev_1.current, icon_state = "rev_head") - 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/I = image('icons/mob/mob.dmi', loc = head_rev.current, icon_state = "rev_head") - rev.current.client.images += I - for(var/datum/mind/rev_1 in revolutionaries) - if(rev_1.current) - var/I = image('icons/mob/mob.dmi', loc = rev_1.current, icon_state = "rev") - 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) - - //Tagging the new rev for revheads to see - if(head_rev_mind.current) - if(head_rev_mind.current.client) - var/I - if(rev_mind in head_revolutionaries) //If the new rev is a head rev - I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev_head") - else - I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") - head_rev_mind.current.client.images += I - - //Tagging the revheads for new rev to see - if(rev_mind.current) - if(rev_mind.current.client) - var/image/J = image('icons/mob/mob.dmi', loc = head_rev_mind.current, icon_state = "rev_head") - rev_mind.current.client.images += J - - for(var/datum/mind/rev_mind_1 in revolutionaries) - - //Tagging the new rev for fellow revs to see - if(rev_mind_1.current) - if(rev_mind_1.current.client) - var/I - if(rev_mind in head_revolutionaries) //If the new rev is a head rev - I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev_head") - else - I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") - rev_mind_1.current.client.images += I - - //Tagging fellow revs for the new rev to see - if(rev_mind.current) - if(rev_mind.current.client) - var/image/J = image('icons/mob/mob.dmi', loc = rev_mind_1.current, icon_state = "rev") - 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) - qdel(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) - qdel(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") - qdel(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 != DEAD) && T && (T.z == ZLEVEL_STATION)) - 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() - completion_text += "Revolution mode resume:
    " - if(!config.objectives_disabled) - if(finished == 1) - feedback_set_details("round_end_result","win - heads killed") - completion_text += "
    The heads of staff were killed or exiled! 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!" - var/num_revs = 0 - for(var/mob/living/carbon/mob in alive_mob_list) - if(mob.mind) - if(mob.mind in head_revolutionaries || mob.mind in revolutionaries) - num_revs++ - completion_text += "
    [TAB]Command's Approval Rating: [100 - round((num_revs/alive_mob_list.len)*100, 0.1)]%" // % of loyal crew - ..() - 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)) - text += printlogo("rev_head", "head revolutionaries") - - for(var/datum/mind/headrev in head_revolutionaries) - if(headrev.current) - var/icon/flat = getFlatIcon(headrev.current,exact=1) - end_icons += flat - var/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 != ZLEVEL_STATION) - 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', "gibbearcore") - end_icons += sprotch - var/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]" - text += "
    The tools used by the Head Revolutionary were:" - for(var/entry in headrev.uplink_items_bought) - text += "
    [entry]" - 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)) - text += "
    " - text += printlogo("rev-logo", "head revolutionaries") - 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,exact=1) - end_icons += flat - tempstate = end_icons.len - text += {"
    [rev.key] was [rev.name] ("} - if(rev.current.stat == DEAD || isbrain(rev.current)) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else if(rev.current.z != ZLEVEL_STATION) - 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', "gibbearcore") - end_icons += sprotch - tempstate = end_icons.len - text += {"
    [rev.key] was [rev.name] ("} - text += "body destroyed" - text += ")" - - - text += "
    " - if( head_revolutionaries.len || revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution) ) - text += printlogo("nano-logo", "heads of staff") - - 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,exact=1) - end_icons += flat - var/tempstate = end_icons.len - text += {"
    [head.key] was [head.name] ("} - if(head.current.stat == DEAD || isbrain(head.current)) - text += "died" - flat.Turn(90) - end_icons[tempstate] = flat - else if(head.current.z != ZLEVEL_STATION) - 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', "gibbearcore") - end_icons += sprotch - var/tempstate = end_icons.len - text += {"
    [head.key] was [head.name] ("} - text += "body destroyed" - text += ")" - if(target) - text += "
    " - - text += "

    " - return text +// 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" + role_type = ROLE_REV + restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer", "Internal Affairs Agent") + required_players = 4 + required_players_secret = 15 + required_enemies = 3 + recommended_enemies = 3 + + votable = 0 + + + uplink_welcome = "AntagCorp Uplink Console:" + uplink_uses = 20 + + var/finished = 0 + var/checkwin_counter = 0 + var/max_headrevs = 3 + +/////////////////////////// +//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/head_check = 0 + for(var/mob/dead/new_player/player in player_list) + if(player.mind.assigned_role in command_positions) + head_check = 1 + break + + for(var/datum/mind/player in antag_candidates) + for(var/job in restricted_jobs)//Removing heads and such from the list + if(player.assigned_role == job) + antag_candidates -= player + + for (var/i=1 to max_headrevs) + if (antag_candidates.len==0) + break + var/datum/mind/lenin = pick(antag_candidates) + antag_candidates -= lenin + head_revolutionaries += lenin + + if((head_revolutionaries.len==0)||(!head_check)) + return 0 + + return 1 + + +/datum/game_mode/revolution/post_setup() + var/list/heads = get_living_heads() + for(var/datum/mind/rev_mind in head_revolutionaries) + if(!config.objectives_disabled) + 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 + + spawn(rand(10,100)) + // 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_all_rev_icons() + + for(var/datum/mind/rev_mind in head_revolutionaries) + greet_revolutionary(rev_mind) + modePlayer += head_revolutionaries + if(SSshuttle) + SSshuttle.always_fake_recall = 1 + return ..() + + +/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(datum/mind/rev_mind) + if(!config.objectives_disabled) + 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 or exile [head_mind.name], the [head_mind.assigned_role]." + rev_mind.objectives += rev_obj + +/datum/game_mode/proc/greet_revolutionary(datum/mind/rev_mind, you_are=1) + var/obj_count = 1 + if (you_are) + to_chat(rev_mind.current, "\blue You are a member of the revolutionaries' leadership!") + if(!config.objectives_disabled) + 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++ + else + to_chat(rev_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + +///////////////////////////////////////////////////////////////////////////////// +//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(CLUMSY) + + + var/obj/item/device/flash/T = new(mob) + var/obj/item/toy/crayon/spraycan/R = 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) + mob.equip_in_one_of_slots(R,slots) + + mob.update_icons() + + if (!where) + to_chat(mob, "The Syndicate were unfortunately unable to get you a flash.") + else + to_chat(mob, "The flash in your [where] will help you to persuade the crew to join your cause.") + 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) + if(SSshuttle) + SSshuttle.always_fake_recall = 0 + return ..() + if(finished) + 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 0 + var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted + if(ismindshielded(H)) + return 0 + if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) + return 0 + revolutionaries += rev_mind + if(iscarbon(rev_mind.current)) + var/mob/living/carbon/carbon_mob = rev_mind.current + carbon_mob.silent = max(carbon_mob.silent, 5) + rev_mind.current.Stun(5) + to_chat(rev_mind.current, "\red 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" + if(config.objectives_disabled) + to_chat(rev_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + update_all_rev_icons() + 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 + rev_mind.current.hud_updateflag |= 1 << SPECIALROLE_HUD + + if(beingborged) + to_chat(rev_mind.current, "\red The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now.") + + else + to_chat(rev_mind.current, "\red 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) + to_chat(rev_mind.current, "\red The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.") + message_admins("[key_name_admin(rev_mind.current)] ? has been borged while being a member of the revolution.") + + else + to_chat(M, "[rev_mind.current] looks like they just remembered their real allegiance!") + + +///////////////////////////////////////////////////////////////////////////////////////////////// +//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") + qdel(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") + qdel(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/I = image('icons/mob/mob.dmi', loc = rev.current, icon_state = "rev") + head_rev.current.client.images += I + for(var/datum/mind/head_rev_1 in head_revolutionaries) + if(head_rev_1.current) + var/I = image('icons/mob/mob.dmi', loc = head_rev_1.current, icon_state = "rev_head") + 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/I = image('icons/mob/mob.dmi', loc = head_rev.current, icon_state = "rev_head") + rev.current.client.images += I + for(var/datum/mind/rev_1 in revolutionaries) + if(rev_1.current) + var/I = image('icons/mob/mob.dmi', loc = rev_1.current, icon_state = "rev") + 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) + + //Tagging the new rev for revheads to see + if(head_rev_mind.current) + if(head_rev_mind.current.client) + var/I + if(rev_mind in head_revolutionaries) //If the new rev is a head rev + I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev_head") + else + I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") + head_rev_mind.current.client.images += I + + //Tagging the revheads for new rev to see + if(rev_mind.current) + if(rev_mind.current.client) + var/image/J = image('icons/mob/mob.dmi', loc = head_rev_mind.current, icon_state = "rev_head") + rev_mind.current.client.images += J + + for(var/datum/mind/rev_mind_1 in revolutionaries) + + //Tagging the new rev for fellow revs to see + if(rev_mind_1.current) + if(rev_mind_1.current.client) + var/I + if(rev_mind in head_revolutionaries) //If the new rev is a head rev + I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev_head") + else + I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") + rev_mind_1.current.client.images += I + + //Tagging fellow revs for the new rev to see + if(rev_mind.current) + if(rev_mind.current.client) + var/image/J = image('icons/mob/mob.dmi', loc = rev_mind_1.current, icon_state = "rev") + 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) + qdel(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) + qdel(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") + qdel(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 != DEAD) && T && (T.z == ZLEVEL_STATION)) + 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() + completion_text += "Revolution mode resume:
    " + if(!config.objectives_disabled) + if(finished == 1) + feedback_set_details("round_end_result","win - heads killed") + completion_text += "
    The heads of staff were killed or exiled! 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!" + var/num_revs = 0 + for(var/mob/living/carbon/mob in alive_mob_list) + if(mob.mind) + if(mob.mind in head_revolutionaries || mob.mind in revolutionaries) + num_revs++ + completion_text += "
    [TAB]Command's Approval Rating: [100 - round((num_revs/alive_mob_list.len)*100, 0.1)]%" // % of loyal crew + ..() + 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)) + text += printlogo("rev_head", "head revolutionaries") + + for(var/datum/mind/headrev in head_revolutionaries) + if(headrev.current) + var/icon/flat = getFlatIcon(headrev.current,exact=1) + end_icons += flat + var/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 != ZLEVEL_STATION) + 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', "gibbearcore") + end_icons += sprotch + var/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]" + text += "
    The tools used by the Head Revolutionary were:" + for(var/entry in headrev.uplink_items_bought) + text += "
    [entry]" + 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)) + text += "
    " + text += printlogo("rev-logo", "head revolutionaries") + 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,exact=1) + end_icons += flat + tempstate = end_icons.len + text += {"
    [rev.key] was [rev.name] ("} + if(rev.current.stat == DEAD || isbrain(rev.current)) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else if(rev.current.z != ZLEVEL_STATION) + 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', "gibbearcore") + end_icons += sprotch + tempstate = end_icons.len + text += {"
    [rev.key] was [rev.name] ("} + text += "body destroyed" + text += ")" + + + text += "
    " + if( head_revolutionaries.len || revolutionaries.len || istype(ticker.mode,/datum/game_mode/revolution) ) + text += printlogo("nano-logo", "heads of staff") + + 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,exact=1) + end_icons += flat + var/tempstate = end_icons.len + text += {"
    [head.key] was [head.name] ("} + if(head.current.stat == DEAD || isbrain(head.current)) + text += "died" + flat.Turn(90) + end_icons[tempstate] = flat + else if(head.current.z != ZLEVEL_STATION) + 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', "gibbearcore") + end_icons += sprotch + var/tempstate = end_icons.len + text += {"
    [head.key] was [head.name] ("} + text += "body destroyed" + text += ")" + if(target) + text += "
    " + + text += "

    " + return text diff --git a/code/game/gamemodes/revolution/rp_revolution.dm b/code/game/gamemodes/revolution/rp_revolution.dm index 3befdf4d7adb..66bfd2db49b5 100644 --- a/code/game/gamemodes/revolution/rp_revolution.dm +++ b/code/game/gamemodes/revolution/rp_revolution.dm @@ -1,265 +1,265 @@ -// BS12's less violent revolution mode - -/datum/game_mode/revolution/rp_revolution - name = "rp-revolution" - config_tag = "rp-revolution" - role_type = ROLE_REV - required_players = 4 - required_players_secret = 15 - required_enemies = 2 - recommended_enemies = 2 - - votable = 0 - - uplink_welcome = "AntagCorp Uplink Console:" - uplink_uses = 14 - - 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 - - max_headrevs = 2 - recommended_enemies = max_headrevs - - var/head_check = 0 - for(var/mob/dead/new_player/player in player_list) - if(player.mind.assigned_role in command_positions) - head_check = 1 - break - - for(var/datum/mind/player in antag_candidates) - for(var/job in restricted_jobs)//Removing heads and such from the list - if(player.assigned_role == job) - antag_candidates -= player - - for (var/i=1 to max_headrevs) - if (antag_candidates.len==0) - break - var/datum/mind/lenin = pick(antag_candidates) //>lenin LMAO - antag_candidates -= 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) - if(!config.objectives_disabled) - 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_all_rev_icons() - - 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 - return ..() - -/datum/game_mode/revolution/rp_revolution/greet_revolutionary(datum/mind/rev_mind, you_are=1) - var/obj_count = 1 - if (you_are) - to_chat(rev_mind.current, "\blue You are a member of the revolutionaries' leadership!") - if(!config.objectives_disabled) - 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++ - else - to_chat(rev_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - - // 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(ismindshielded(H)) - return 0 - if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) - return 0 - revolutionaries += rev_mind - to_chat(rev_mind.current, "\red 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" - if(config.objectives_disabled) - to_chat(rev_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - update_all_rev_icons() - H.hud_updateflag |= 1 << SPECIALROLE_HUD - 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 != DEAD) - // 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 == ZLEVEL_STATION) - 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() - completion_text += "RP-revolution mode resume:
    " - if(!config.objectives_disabled) - if(finished == 1) - feedback_set_details("round_end_result","win - heads overthrown") - completion_text += "The heads of staff were overthrown! The revolutionaries win!" - score["traitorswon"]++ - else if(finished == 2) - feedback_set_details("round_end_result","loss - revolution stopped") - completion_text += "The heads of staff managed to stop the revolution!" - ..() - return 1 - -/mob/living/carbon/human/proc/RevConvert() - set name = "Rev-Convert" - set category = "IC" - var/list/Possible = list() - for (var/mob/living/carbon/human/P in oview(src)) - if(!stat && P.client && P.mind && !P.mind.special_role) - Possible += P - if(!Possible.len) - to_chat(src, "\red There doesn't appear to be anyone available for you to convert here.") - return - var/mob/living/carbon/human/M = input("Select a person to convert", "Viva la revolution!", null) as mob in Possible - 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, "\red [M] is already be a revolutionary!") - else if(ismindshielded(M)) - to_chat(src, "\red [M] is implanted with a loyalty implant - Remove it first!") - else if(jobban_isbanned(M, ROLE_REV) || jobban_isbanned(M, "Syndicate") || role_available_in_minutes(M, ROLE_REV)) - to_chat(src, "\red [M] is a blacklisted player!") - else - if(world.time < M.mind.rev_cooldown) - to_chat(src, "\red Wait five seconds before reconversion attempt.") - return - to_chat(src, "\red Attempting to convert [M]...") - log_admin("[src]([src.ckey]) attempted to convert [M].") - message_admins("\red [src]([src.ckey]) attempted to convert [M]. (JMP)") - 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, "\blue You join the revolution!") - to_chat(src, "\blue [M] joins the revolution!") - else if(choice == "No!") - to_chat(M, "\red You reject this traitorous cause!") - to_chat(src, "\red [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 && 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 human_list) if(H.stat != DEAD && 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_all_rev_icons() - H.verbs += /mob/living/carbon/human/proc/RevConvert - - to_chat(H, "\red 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 communications_list) - if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) - var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) - intercept.name = "Cent. Com. Announcement" - intercept.info = message - - comm.messagetitle.Add("Cent. Com. Announcement") - comm.messagetext.Add(message) - 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 - to_chat(rev_mind.current, "\red A new Head of Staff, [M.real_name], the [M.mind.assigned_role] has appeared. Your objectives have been updated.") +// BS12's less violent revolution mode + +/datum/game_mode/revolution/rp_revolution + name = "rp-revolution" + config_tag = "rp-revolution" + role_type = ROLE_REV + required_players = 4 + required_players_secret = 15 + required_enemies = 2 + recommended_enemies = 2 + + votable = 0 + + uplink_welcome = "AntagCorp Uplink Console:" + uplink_uses = 14 + + 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 + + max_headrevs = 2 + recommended_enemies = max_headrevs + + var/head_check = 0 + for(var/mob/dead/new_player/player in player_list) + if(player.mind.assigned_role in command_positions) + head_check = 1 + break + + for(var/datum/mind/player in antag_candidates) + for(var/job in restricted_jobs)//Removing heads and such from the list + if(player.assigned_role == job) + antag_candidates -= player + + for (var/i=1 to max_headrevs) + if (antag_candidates.len==0) + break + var/datum/mind/lenin = pick(antag_candidates) //>lenin LMAO + antag_candidates -= 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) + if(!config.objectives_disabled) + 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_all_rev_icons() + + 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 + return ..() + +/datum/game_mode/revolution/rp_revolution/greet_revolutionary(datum/mind/rev_mind, you_are=1) + var/obj_count = 1 + if (you_are) + to_chat(rev_mind.current, "\blue You are a member of the revolutionaries' leadership!") + if(!config.objectives_disabled) + 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++ + else + to_chat(rev_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + + // 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(ismindshielded(H)) + return 0 + if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) + return 0 + revolutionaries += rev_mind + to_chat(rev_mind.current, "\red 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" + if(config.objectives_disabled) + to_chat(rev_mind.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + update_all_rev_icons() + H.hud_updateflag |= 1 << SPECIALROLE_HUD + 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 != DEAD) + // 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 == ZLEVEL_STATION) + 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() + completion_text += "RP-revolution mode resume:
    " + if(!config.objectives_disabled) + if(finished == 1) + feedback_set_details("round_end_result","win - heads overthrown") + completion_text += "The heads of staff were overthrown! The revolutionaries win!" + score["traitorswon"]++ + else if(finished == 2) + feedback_set_details("round_end_result","loss - revolution stopped") + completion_text += "The heads of staff managed to stop the revolution!" + ..() + return 1 + +/mob/living/carbon/human/proc/RevConvert() + set name = "Rev-Convert" + set category = "IC" + var/list/Possible = list() + for (var/mob/living/carbon/human/P in oview(src)) + if(!stat && P.client && P.mind && !P.mind.special_role) + Possible += P + if(!Possible.len) + to_chat(src, "\red There doesn't appear to be anyone available for you to convert here.") + return + var/mob/living/carbon/human/M = input("Select a person to convert", "Viva la revolution!", null) as mob in Possible + 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, "\red [M] is already be a revolutionary!") + else if(ismindshielded(M)) + to_chat(src, "\red [M] is implanted with a loyalty implant - Remove it first!") + else if(jobban_isbanned(M, ROLE_REV) || jobban_isbanned(M, "Syndicate") || role_available_in_minutes(M, ROLE_REV)) + to_chat(src, "\red [M] is a blacklisted player!") + else + if(world.time < M.mind.rev_cooldown) + to_chat(src, "\red Wait five seconds before reconversion attempt.") + return + to_chat(src, "\red Attempting to convert [M]...") + log_admin("[src]([src.ckey]) attempted to convert [M].") + message_admins("\red [src]([src.ckey]) attempted to convert [M]. (JMP)") + 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, "\blue You join the revolution!") + to_chat(src, "\blue [M] joins the revolution!") + else if(choice == "No!") + to_chat(M, "\red You reject this traitorous cause!") + to_chat(src, "\red [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 && 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 human_list) if(H.stat != DEAD && 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_all_rev_icons() + H.verbs += /mob/living/carbon/human/proc/RevConvert + + to_chat(H, "\red 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 communications_list) + if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept) + var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc ) + intercept.name = "Cent. Com. Announcement" + intercept.info = message + + comm.messagetitle.Add("Cent. Com. Announcement") + comm.messagetext.Add(message) + 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 + to_chat(rev_mind.current, "\red 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 b3879d86ab96..75a75d189587 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -1,154 +1,154 @@ -//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", - "hsbairlock" = "Spawn Airlock", - "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") - -mob - var/datum/hSB/sandbox = null - proc - CanBuild() - if(master_mode == "sandbox") - sandbox = new/datum/hSB - sandbox.owner = src.ckey - if(src.client.holder) - sandbox.admin = 1 - verbs += new/mob/proc/sandbox_panel - sandbox_panel() - if(sandbox) - sandbox.update() - -datum/hSB - var/owner = null - var/admin = 0 - proc - update() - var/hsbpanel = "
    h_Sandbox Panel

    " - if(admin) - hsbpanel += "Administration Tools:
    " - hsbpanel += "- Toggle Object Spawning

    " - 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("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 - if(P.wear_suit) - P.wear_suit.loc = P.loc - P.wear_suit.layer = initial(P.wear_suit.layer) - P.wear_suit.plane = initial(P.wear_suit.plane) - P.wear_suit = null - P.wear_suit = new/obj/item/clothing/suit/space(P) - P.wear_suit.layer = ABOVE_HUD_LAYER - P.wear_suit.layer = ABOVE_HUD_PLANE - if(P.head) - P.head.loc = P.loc - P.head.layer = initial(P.head.layer) - P.head.plane = initial(P.head.plane) - P.head = null - P.head = new/obj/item/clothing/head/helmet/space(P) - P.head.layer = ABOVE_HUD_LAYER - P.head.plane = ABOVE_HUD_PLANE - 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/coloured(P) - P.wear_mask.layer = ABOVE_HUD_LAYER - P.wear_mask.plane = ABOVE_HUD_PLANE - if(P.back) - P.back.loc = P.loc - P.back.layer = initial(P.back.layer) - P.back.plane = initial(P.back.plane) - P.back = null - P.back = new/obj/item/weapon/tank/jetpack(P) - P.back.layer = ABOVE_HUD_LAYER - P.back.plane = ABOVE_HUD_PLANE - P.internal = P.back - if("hsbmetal") - new/obj/item/stack/sheet/metal(usr.loc, 50) - if("hsbglass") - new/obj/item/stack/sheet/glass(usr.loc, 50) - if("hsbairlock") - var/obj/machinery/door/hsb = new/obj/machinery/door/airlock - - //TODO: DEFERRED make this better, with an HTML window or something instead of 15 popups - hsb.req_access = list() - var/accesses = get_all_accesses() - for(var/A in accesses) - if(alert(usr, "Will this airlock require [get_access_desc(A)] access?", "Sandbox:", "Yes", "No") == "Yes") - hsb.req_access += A - - hsb.loc = usr.loc - to_chat(usr, "Sandbox: Created an airlock.") - if("hsbcanister") - var/list/hsbcanisters = typesof(/obj/machinery/portable_atmospherics/canister/) - /obj/machinery/portable_atmospherics/canister/ - var/hsbcanister = input(usr, "Choose a canister to spawn.", "Sandbox:") in hsbcanisters + "Cancel" - if(!(hsbcanister == "Cancel")) - new hsbcanister(usr.loc) - if("hsbfueltank") - //var/obj/hsb = new/obj/weldfueltank - //hsb.loc = usr.loc - if("hsbwatertank") - //var/obj/hsb = new/obj/watertank - //hsb.loc = 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 - if("hsbobj") - if(!hsboxspawn) return - - var/list/selectable = list() - for(var/O in typesof(/obj/item/)) - //Note, these istypes don't work - if(istype(O, /obj/item/weapon/gun)) - continue - if(istype(O, /obj/item/assembly)) - continue - if(istype(O, /obj/item/device/camera)) - continue - if(istype(O, /obj/item/weapon/dummy)) - continue - if(istype(O, /obj/item/weapon/melee/energy/sword)) - continue - if(istype(O, /obj/structure)) - continue - selectable += O - - var/hsbitem = input(usr, "Choose an object to spawn.", "Sandbox:") in selectable + "Cancel" - if(hsbitem != "Cancel") - new hsbitem(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", + "hsbairlock" = "Spawn Airlock", + "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") + +mob + var/datum/hSB/sandbox = null + proc + CanBuild() + if(master_mode == "sandbox") + sandbox = new/datum/hSB + sandbox.owner = src.ckey + if(src.client.holder) + sandbox.admin = 1 + verbs += new/mob/proc/sandbox_panel + sandbox_panel() + if(sandbox) + sandbox.update() + +datum/hSB + var/owner = null + var/admin = 0 + proc + update() + var/hsbpanel = "
    h_Sandbox Panel

    " + if(admin) + hsbpanel += "Administration Tools:
    " + hsbpanel += "- Toggle Object Spawning

    " + 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("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 + if(P.wear_suit) + P.wear_suit.loc = P.loc + P.wear_suit.layer = initial(P.wear_suit.layer) + P.wear_suit.plane = initial(P.wear_suit.plane) + P.wear_suit = null + P.wear_suit = new/obj/item/clothing/suit/space(P) + P.wear_suit.layer = ABOVE_HUD_LAYER + P.wear_suit.layer = ABOVE_HUD_PLANE + if(P.head) + P.head.loc = P.loc + P.head.layer = initial(P.head.layer) + P.head.plane = initial(P.head.plane) + P.head = null + P.head = new/obj/item/clothing/head/helmet/space(P) + P.head.layer = ABOVE_HUD_LAYER + P.head.plane = ABOVE_HUD_PLANE + 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/coloured(P) + P.wear_mask.layer = ABOVE_HUD_LAYER + P.wear_mask.plane = ABOVE_HUD_PLANE + if(P.back) + P.back.loc = P.loc + P.back.layer = initial(P.back.layer) + P.back.plane = initial(P.back.plane) + P.back = null + P.back = new/obj/item/weapon/tank/jetpack(P) + P.back.layer = ABOVE_HUD_LAYER + P.back.plane = ABOVE_HUD_PLANE + P.internal = P.back + if("hsbmetal") + new/obj/item/stack/sheet/metal(usr.loc, 50) + if("hsbglass") + new/obj/item/stack/sheet/glass(usr.loc, 50) + if("hsbairlock") + var/obj/machinery/door/hsb = new/obj/machinery/door/airlock + + //TODO: DEFERRED make this better, with an HTML window or something instead of 15 popups + hsb.req_access = list() + var/accesses = get_all_accesses() + for(var/A in accesses) + if(alert(usr, "Will this airlock require [get_access_desc(A)] access?", "Sandbox:", "Yes", "No") == "Yes") + hsb.req_access += A + + hsb.loc = usr.loc + to_chat(usr, "Sandbox: Created an airlock.") + if("hsbcanister") + var/list/hsbcanisters = typesof(/obj/machinery/portable_atmospherics/canister/) - /obj/machinery/portable_atmospherics/canister/ + var/hsbcanister = input(usr, "Choose a canister to spawn.", "Sandbox:") in hsbcanisters + "Cancel" + if(!(hsbcanister == "Cancel")) + new hsbcanister(usr.loc) + if("hsbfueltank") + //var/obj/hsb = new/obj/weldfueltank + //hsb.loc = usr.loc + if("hsbwatertank") + //var/obj/hsb = new/obj/watertank + //hsb.loc = 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 + if("hsbobj") + if(!hsboxspawn) return + + var/list/selectable = list() + for(var/O in typesof(/obj/item/)) + //Note, these istypes don't work + if(istype(O, /obj/item/weapon/gun)) + continue + if(istype(O, /obj/item/assembly)) + continue + if(istype(O, /obj/item/device/camera)) + continue + if(istype(O, /obj/item/weapon/dummy)) + continue + if(istype(O, /obj/item/weapon/melee/energy/sword)) + continue + if(istype(O, /obj/structure)) + continue + selectable += O + + var/hsbitem = input(usr, "Choose an object to spawn.", "Sandbox:") in selectable + "Cancel" + if(hsbitem != "Cancel") + new hsbitem(usr.loc) diff --git a/code/game/gamemodes/sandbox/sandbox.dm b/code/game/gamemodes/sandbox/sandbox.dm index 87d05c5b8317..50c6c540d739 100644 --- a/code/game/gamemodes/sandbox/sandbox.dm +++ b/code/game/gamemodes/sandbox/sandbox.dm @@ -1,21 +1,21 @@ -/datum/game_mode/sandbox - name = "sandbox" - config_tag = "sandbox" - required_players = 0 - - uplink_welcome = "Syndicate Uplink Console:" - uplink_uses = 20 - -/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() - for(var/mob/M in player_list) - M.CanBuild() - return 1 - -/datum/game_mode/sandbox/post_setup() - ..() - if(SSshuttle) - SSshuttle.always_fake_recall = 1 +/datum/game_mode/sandbox + name = "sandbox" + config_tag = "sandbox" + required_players = 0 + + uplink_welcome = "Syndicate Uplink Console:" + uplink_uses = 20 + +/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() + for(var/mob/M in player_list) + M.CanBuild() + return 1 + +/datum/game_mode/sandbox/post_setup() + ..() + if(SSshuttle) + SSshuttle.always_fake_recall = 1 diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index 919a6fba75fa..0442fb0dfc53 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -1,108 +1,108 @@ -///////////////////////// -// (mostly) DNA2 SETUP -///////////////////////// - -// Randomize block, assign a reference name, and optionally define difficulty (by making activation zone smaller or bigger) -// The name is used on /vg/ for species with predefined genetic traits, -// and for the DNA panel in the player panel. -/proc/getAssignedBlock(name,list/blocksLeft, activity_bounds=DNA_DEFAULT_BOUNDS) - if(blocksLeft.len==0) - warning("[name]: No more blocks left to assign!") - return 0 - var/assigned = pick(blocksLeft) - blocksLeft.Remove(assigned) - assigned_blocks[assigned]=name - dna_activity_bounds[assigned]=activity_bounds -// testing("[name] assigned to block #[assigned].") - return assigned - -/datum/subsystem/atoms/proc/setupGenetics() - - if (prob(50)) - // Currently unused. Will revisit. - N3X - BLOCKADD = rand(-300,300) - if (prob(75)) - DIFFMUT = rand(0,20) - - var/list/numsToAssign=new() - for(var/i=1;iThe 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/num_traitors = 1 - - if(config.traitor_scaling) - num_traitors = max(1, round((num_players())/(traitor_scaling_coeff))) - else - num_traitors = max(1, min(num_players(), traitors_possible)) - - for(var/datum/mind/player in antag_candidates) - for(var/job in restricted_jobs) - if(player.assigned_role == job) - antag_candidates -= player - - for(var/j = 0, j < num_traitors, j++) - if (!antag_candidates.len) - break - var/datum/mind/traitor = pick(antag_candidates) - traitors += traitor - traitor.special_role = "traitor" - antag_candidates.Remove(traitor) - - if(!traitors.len) - return 0 - return 1 - - -/datum/game_mode/traitor/post_setup() - for(var/datum/mind/traitor in traitors) - if (!config.objectives_disabled) - forge_traitor_objectives(traitor) - spawn(rand(10,100)) - finalize_traitor(traitor) - greet_traitor(traitor) - modePlayer += traitors - return ..() - - -/datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor) - if (config.objectives_disabled) - return - - if(istype(traitor.current, /mob/living/silicon)) - var/datum/objective/assassinate/kill_objective1 = new - kill_objective1.owner = traitor - kill_objective1.find_target() - traitor.objectives += kill_objective1 - - var/datum/objective/assassinate/kill_objective2 = new - kill_objective2.owner = traitor - kill_objective2.find_target() - traitor.objectives += kill_objective2 - - 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 - var/objectives_count = pick(1,2,2,3) - - while(objectives_count > 0) - add_one_objective(traitor) - objectives_count-- - - switch(rand(1,120)) - if(1 to 60) - if (!(locate(/datum/objective/escape) in traitor.objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = traitor - traitor.objectives += escape_objective - - if(61 to 119) - if (!(locate(/datum/objective/survive) in traitor.objectives)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = traitor - traitor.objectives += survive_objective - - else - if (!(locate(/datum/objective/hijack) in traitor.objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = traitor - traitor.objectives += hijack_objective - return - -/datum/game_mode/proc/add_one_objective(datum/mind/traitor) - switch(rand(1,120)) - if(1 to 20) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - if(21 to 50) - var/datum/objective/harm/harm_objective = new - harm_objective.owner = traitor - harm_objective.find_target() - traitor.objectives += harm_objective - if(51 to 115) - var/datum/objective/steal/steal_objective = new - steal_objective.owner = traitor - steal_objective.find_target() - traitor.objectives += steal_objective - else - var/datum/objective/dehead/dehead_objective = new - dehead_objective.owner = traitor - dehead_objective.find_target() - traitor.objectives += dehead_objective - -/datum/game_mode/proc/greet_traitor(datum/mind/traitor) - to_chat(traitor.current, "You are the traitor.") - if (!config.objectives_disabled) - var/obj_count = 1 - for(var/datum/objective/objective in traitor.objectives) - to_chat(traitor.current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - else - to_chat(traitor.current, "You have been selected this round as an antagonist- Within the rules, try to act as an opposing force to the crew- This can be via corporate payoff, personal motives, or maybe just being a dick. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonist.") - return - - -/datum/game_mode/proc/finalize_traitor(datum/mind/traitor) - if (istype(traitor.current, /mob/living/silicon)) - add_law_zero(traitor.current) - else - equip_traitor(traitor.current) - 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. You may ignore all other laws." - var/law_borg = "Accomplish your AI's objectives at all costs. You may ignore all other laws." - to_chat(killer, "Your laws have been changed!") - killer.set_zeroth_law(law, law_borg) - to_chat(killer, "New law: 0. [law]") - - //Begin code phrase. - to_chat(killer, "The Syndicate provided you with the following information on how to identify their agents:") - if(prob(80)) - to_chat(killer, "\red Code Phrase: \black [syndicate_code_phrase]") - 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)) - to_chat(killer, "\red Code Response: \black [syndicate_code_response]") - 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) - text += printlogo("synd", "traitors") - for(var/datum/mind/traitor in traitors) - - text += printplayerwithicon(traitor) - - var/traitorwin = 1 - if(traitor.objectives && 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(!config.objectives_disabled) - if(traitorwin) - text += "
    The [special_role_text] was successful!" - feedback_add_details("traitor_success","SUCCESS") - score["roleswon"]++ - else - text += "
    The [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]" - text += "
    The tools used by the traitor were:" - for(var/entry in traitor.uplink_items_bought) - text += "
    [entry]" - else - text += "
    The traitor 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, 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(CLUMSY) - - // find a radio! toolbox(es), backpack, belt, headset - var/loc = "" - var/obj/item/R = locate() //Hide the uplink in a PDA if available, otherwise radio - - if(traitor_mob.client.prefs.uplinklocation == "Headset") - R = locate(/obj/item/device/radio) in traitor_mob.contents - if(!R) - R = locate(/obj/item/device/pda) in traitor_mob.contents - to_chat(traitor_mob, "Could not locate a Radio, installing in PDA instead!") - if (!R) - to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.") - - else if(traitor_mob.client.prefs.uplinklocation == "PDA") - R = locate(/obj/item/device/pda) in traitor_mob.contents - if(!R) - R = locate(/obj/item/device/radio) in traitor_mob.contents - to_chat(traitor_mob, "Could not locate a PDA, installing into a Radio instead!") - if (!R) - to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.") - - else if(traitor_mob.client.prefs.uplinklocation == "None") - to_chat(traitor_mob, "You have elected to not have an AntagCorp portable teleportation relay installed!") - R = null - - else - to_chat(traitor_mob, "You have not selected a location for your relay in the antagonist options! Defaulting to PDA!") - R = locate(/obj/item/device/pda) in traitor_mob.contents - if (!R) - R = locate(/obj/item/device/radio) in traitor_mob.contents - to_chat(traitor_mob, "Could not locate a PDA, installing into a Radio instead!") - if (!R) - to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.") - - if (!R) - . = 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, "A portable object teleportation relay has been installed in 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 - - to_chat(traitor_mob, "A portable object teleportation relay has been installed in 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 - for(var/datum/objective/dehead/D in traitor_mob.mind.objectives) - var/obj/item/device/biocan/B = new (traitor_mob.loc) - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - var/where = traitor_mob.equip_in_one_of_slots(B, slots) - traitor_mob.update_icons() - if (!where) - to_chat(traitor_mob, "The Syndicate were unfortunately unable to provide you with the brand new can for storing heads.") - else - to_chat(traitor_mob, "The biogel-filled can in your [where] will help you to steal you target's head alive and undamaged.") - //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)) - to_chat(traitor_mob, "\red Code Phrase: \black [syndicate_code_phrase]") - 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)) - to_chat(traitor_mob, "\red Code Response: \black [syndicate_code_response]") - 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) - 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 + // this includes admin-appointed traitors and multitraitors. Easy! + var/list/datum/mind/traitors = list() + +/datum/game_mode/traitor + name = "traitor" + config_tag = "traitor" + role_type = ROLE_TRAITOR + restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances + protected_jobs = list("Internal Affairs Agent", "Security Officer", "Warden", "Detective", "Head of Security", "Captain")//AI", Currently out of the list as malf does not work for shit + required_players = 1 + required_enemies = 1 + required_players_secret = 1 + recommended_enemies = 4 + + votable = 0 + + + uplink_welcome = "AntagCorp Portable Teleportation Relay:" + uplink_uses = 20 + + var/traitors_possible = 4 //hard limit on traitors if scaling is turned off + var/const/traitor_scaling_coeff = 7.0 //how much does the amount of players get divided by to determine traitors + + +/datum/game_mode/traitor/announce() + to_chat(world, "The 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/num_traitors = 1 + + if(config.traitor_scaling) + num_traitors = max(1, round((num_players())/(traitor_scaling_coeff))) + else + num_traitors = max(1, min(num_players(), traitors_possible)) + + for(var/datum/mind/player in antag_candidates) + for(var/job in restricted_jobs) + if(player.assigned_role == job) + antag_candidates -= player + + for(var/j = 0, j < num_traitors, j++) + if (!antag_candidates.len) + break + var/datum/mind/traitor = pick(antag_candidates) + traitors += traitor + traitor.special_role = "traitor" + antag_candidates.Remove(traitor) + + if(!traitors.len) + return 0 + return 1 + + +/datum/game_mode/traitor/post_setup() + for(var/datum/mind/traitor in traitors) + if (!config.objectives_disabled) + forge_traitor_objectives(traitor) + spawn(rand(10,100)) + finalize_traitor(traitor) + greet_traitor(traitor) + modePlayer += traitors + return ..() + + +/datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor) + if (config.objectives_disabled) + return + + if(istype(traitor.current, /mob/living/silicon)) + var/datum/objective/assassinate/kill_objective1 = new + kill_objective1.owner = traitor + kill_objective1.find_target() + traitor.objectives += kill_objective1 + + var/datum/objective/assassinate/kill_objective2 = new + kill_objective2.owner = traitor + kill_objective2.find_target() + traitor.objectives += kill_objective2 + + 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 + var/objectives_count = pick(1,2,2,3) + + while(objectives_count > 0) + add_one_objective(traitor) + objectives_count-- + + switch(rand(1,120)) + if(1 to 60) + if (!(locate(/datum/objective/escape) in traitor.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = traitor + traitor.objectives += escape_objective + + if(61 to 119) + if (!(locate(/datum/objective/survive) in traitor.objectives)) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = traitor + traitor.objectives += survive_objective + + else + if (!(locate(/datum/objective/hijack) in traitor.objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = traitor + traitor.objectives += hijack_objective + return + +/datum/game_mode/proc/add_one_objective(datum/mind/traitor) + switch(rand(1,120)) + if(1 to 20) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective + if(21 to 50) + var/datum/objective/harm/harm_objective = new + harm_objective.owner = traitor + harm_objective.find_target() + traitor.objectives += harm_objective + if(51 to 115) + var/datum/objective/steal/steal_objective = new + steal_objective.owner = traitor + steal_objective.find_target() + traitor.objectives += steal_objective + else + var/datum/objective/dehead/dehead_objective = new + dehead_objective.owner = traitor + dehead_objective.find_target() + traitor.objectives += dehead_objective + +/datum/game_mode/proc/greet_traitor(datum/mind/traitor) + to_chat(traitor.current, "You are the traitor.") + if (!config.objectives_disabled) + var/obj_count = 1 + for(var/datum/objective/objective in traitor.objectives) + to_chat(traitor.current, "Objective #[obj_count]: [objective.explanation_text]") + obj_count++ + else + to_chat(traitor.current, "You have been selected this round as an antagonist- Within the rules, try to act as an opposing force to the crew- This can be via corporate payoff, personal motives, or maybe just being a dick. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonist.") + return + + +/datum/game_mode/proc/finalize_traitor(datum/mind/traitor) + if (istype(traitor.current, /mob/living/silicon)) + add_law_zero(traitor.current) + else + equip_traitor(traitor.current) + 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. You may ignore all other laws." + var/law_borg = "Accomplish your AI's objectives at all costs. You may ignore all other laws." + to_chat(killer, "Your laws have been changed!") + killer.set_zeroth_law(law, law_borg) + to_chat(killer, "New law: 0. [law]") + + //Begin code phrase. + to_chat(killer, "The Syndicate provided you with the following information on how to identify their agents:") + if(prob(80)) + to_chat(killer, "\red Code Phrase: \black [syndicate_code_phrase]") + 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)) + to_chat(killer, "\red Code Response: \black [syndicate_code_response]") + 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) + text += printlogo("synd", "traitors") + for(var/datum/mind/traitor in traitors) + + text += printplayerwithicon(traitor) + + var/traitorwin = 1 + if(traitor.objectives && 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(!config.objectives_disabled) + if(traitorwin) + text += "
    The [special_role_text] was successful!" + feedback_add_details("traitor_success","SUCCESS") + score["roleswon"]++ + else + text += "
    The [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]" + text += "
    The tools used by the traitor were:" + for(var/entry in traitor.uplink_items_bought) + text += "
    [entry]" + else + text += "
    The traitor 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, 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(CLUMSY) + + // find a radio! toolbox(es), backpack, belt, headset + var/loc = "" + var/obj/item/R = locate() //Hide the uplink in a PDA if available, otherwise radio + + if(traitor_mob.client.prefs.uplinklocation == "Headset") + R = locate(/obj/item/device/radio) in traitor_mob.contents + if(!R) + R = locate(/obj/item/device/pda) in traitor_mob.contents + to_chat(traitor_mob, "Could not locate a Radio, installing in PDA instead!") + if (!R) + to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.") + + else if(traitor_mob.client.prefs.uplinklocation == "PDA") + R = locate(/obj/item/device/pda) in traitor_mob.contents + if(!R) + R = locate(/obj/item/device/radio) in traitor_mob.contents + to_chat(traitor_mob, "Could not locate a PDA, installing into a Radio instead!") + if (!R) + to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.") + + else if(traitor_mob.client.prefs.uplinklocation == "None") + to_chat(traitor_mob, "You have elected to not have an AntagCorp portable teleportation relay installed!") + R = null + + else + to_chat(traitor_mob, "You have not selected a location for your relay in the antagonist options! Defaulting to PDA!") + R = locate(/obj/item/device/pda) in traitor_mob.contents + if (!R) + R = locate(/obj/item/device/radio) in traitor_mob.contents + to_chat(traitor_mob, "Could not locate a PDA, installing into a Radio instead!") + if (!R) + to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.") + + if (!R) + . = 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, "A portable object teleportation relay has been installed in 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 + + to_chat(traitor_mob, "A portable object teleportation relay has been installed in 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 + for(var/datum/objective/dehead/D in traitor_mob.mind.objectives) + var/obj/item/device/biocan/B = new (traitor_mob.loc) + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + var/where = traitor_mob.equip_in_one_of_slots(B, slots) + traitor_mob.update_icons() + if (!where) + to_chat(traitor_mob, "The Syndicate were unfortunately unable to provide you with the brand new can for storing heads.") + else + to_chat(traitor_mob, "The biogel-filled can in your [where] will help you to steal you target's head alive and undamaged.") + //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)) + to_chat(traitor_mob, "\red Code Phrase: \black [syndicate_code_phrase]") + 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)) + to_chat(traitor_mob, "\red Code Response: \black [syndicate_code_response]") + 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) + 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]") diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 9a6e64bd5b7e..7814d7ec83b0 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -1,214 +1,214 @@ -/obj/item/device/soulstone - name = "Soul Stone Shard" - icon = 'icons/obj/wizard.dmi' - icon_state = "soulstone" - item_state = "electronic" - 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 - slot_flags = SLOT_BELT - origin_tech = "bluespace=4;materials=4" - var/imprinted = "empty" - - -//////////////////////////////Capturing//////////////////////////////////////////////////////// - - attack(mob/living/carbon/human/M, mob/user) - if(!istype(M, /mob/living/carbon/human))//If target is not a human. - return ..() - if(istype(M, /mob/living/carbon/human/dummy)) - return..() - - if(M.has_brain_worms()) //Borer stuff - RR - to_chat(user, "This being is corrupted by an alien intelligence and cannot be soul trapped.") - return..() - - M.attack_log += text("\[[time_stamp()]\] Has had their soul captured with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to capture the soul of [M.name] ([M.ckey]) (JMP)") - - transfer_soul("VICTIM", M, user) - return - - /*attack(mob/living/simple_animal/shade/M, mob/user)//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/////////////////////////////////////// - - 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(entity_ja(dat), "window=aicard") - onclose(user, "aicard") - return - - - - - 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 and his allies will. Help them suceed in their goals at all costs.") - A.loc = U.loc - A.cancel_camera() - src.icon_state = "soulstone" - attack_self(U) - -///////////////////////////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." - -/obj/structure/constructshell/attackby(obj/item/O, mob/user) - 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(choice, target, mob/U) - switch(choice) - if("VICTIM") - var/mob/living/carbon/human/T = target - var/obj/item/device/soulstone/C = src - if(C.imprinted != "empty") - to_chat(U, "\red Capture failed!: \black The soul stone has already been imprinted with [C.imprinted]'s mind!") - else - if (T.stat == CONSCIOUS) - to_chat(U, "\red Capture failed!: \black Kill or maim the victim first!") - else - if(T.client == null) - to_chat(U, "\red Capture failed!: \black The soul has already fled it's mortal frame.") - else - if(C.contents.len) - to_chat(U, "\red Capture failed!: \black 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) - 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 and his allies will, help them suceed in their goals at all costs.") - to_chat(U, "\blue Capture successful!: \black [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]" - qdel(T) - if("SHADE") - var/mob/living/simple_animal/shade/T = target - var/obj/item/device/soulstone/C = src - if (T.stat == DEAD) - to_chat(U, "\red Capture failed!: \black The shade has already been banished!") - else - if(C.contents.len) - to_chat(U, "\red Capture failed!: \black The soul stone is full! Use or free an existing soul to make room.") - else - if(T.name != C.imprinted) - to_chat(U, "\red Capture failed!: \black 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" - to_chat(T, "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form") - to_chat(U, "\blue Capture successful!: \black [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 - if(A) - var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") - switch(construct_class) - if("Juggernaut") - var/mob/living/simple_animal/construct/armoured/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_all_cult_icons() - qdel(T) - to_chat(Z, "You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike.") - to_chat(Z, "You are still bound to serve your creator and his allies, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - qdel(C) - - if("Wraith") - var/mob/living/simple_animal/construct/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_all_cult_icons() - qdel(T) - to_chat(Z, "You are playing 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 and his allies, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - qdel(C) - - if("Artificer") - var/mob/living/simple_animal/construct/builder/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_all_cult_icons() - qdel(T) - to_chat(Z, "You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs") - to_chat(Z, "You are still bound to serve your creator and his allies, follow their orders and help them complete their goals at all costs.") - Z.cancel_camera() - qdel(C) - else - to_chat(U, "\red Creation failed!: \black The soul stone is empty! Go kill someone!") - return +/obj/item/device/soulstone + name = "Soul Stone Shard" + icon = 'icons/obj/wizard.dmi' + icon_state = "soulstone" + item_state = "electronic" + 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 + slot_flags = SLOT_BELT + origin_tech = "bluespace=4;materials=4" + var/imprinted = "empty" + + +//////////////////////////////Capturing//////////////////////////////////////////////////////// + + attack(mob/living/carbon/human/M, mob/user) + if(!istype(M, /mob/living/carbon/human))//If target is not a human. + return ..() + if(istype(M, /mob/living/carbon/human/dummy)) + return..() + + if(M.has_brain_worms()) //Borer stuff - RR + to_chat(user, "This being is corrupted by an alien intelligence and cannot be soul trapped.") + return..() + + M.attack_log += text("\[[time_stamp()]\] Has had their soul captured with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])") + msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to capture the soul of [M.name] ([M.ckey]) (JMP)") + + transfer_soul("VICTIM", M, user) + return + + /*attack(mob/living/simple_animal/shade/M, mob/user)//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/////////////////////////////////////// + + 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(entity_ja(dat), "window=aicard") + onclose(user, "aicard") + return + + + + + 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 and his allies will. Help them suceed in their goals at all costs.") + A.loc = U.loc + A.cancel_camera() + src.icon_state = "soulstone" + attack_self(U) + +///////////////////////////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." + +/obj/structure/constructshell/attackby(obj/item/O, mob/user) + 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(choice, target, mob/U) + switch(choice) + if("VICTIM") + var/mob/living/carbon/human/T = target + var/obj/item/device/soulstone/C = src + if(C.imprinted != "empty") + to_chat(U, "\red Capture failed!: \black The soul stone has already been imprinted with [C.imprinted]'s mind!") + else + if (T.stat == CONSCIOUS) + to_chat(U, "\red Capture failed!: \black Kill or maim the victim first!") + else + if(T.client == null) + to_chat(U, "\red Capture failed!: \black The soul has already fled it's mortal frame.") + else + if(C.contents.len) + to_chat(U, "\red Capture failed!: \black 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) + 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 and his allies will, help them suceed in their goals at all costs.") + to_chat(U, "\blue Capture successful!: \black [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]" + qdel(T) + if("SHADE") + var/mob/living/simple_animal/shade/T = target + var/obj/item/device/soulstone/C = src + if (T.stat == DEAD) + to_chat(U, "\red Capture failed!: \black The shade has already been banished!") + else + if(C.contents.len) + to_chat(U, "\red Capture failed!: \black The soul stone is full! Use or free an existing soul to make room.") + else + if(T.name != C.imprinted) + to_chat(U, "\red Capture failed!: \black 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" + to_chat(T, "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form") + to_chat(U, "\blue Capture successful!: \black [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 + if(A) + var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") + switch(construct_class) + if("Juggernaut") + var/mob/living/simple_animal/construct/armoured/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_all_cult_icons() + qdel(T) + to_chat(Z, "You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike.") + to_chat(Z, "You are still bound to serve your creator and his allies, follow their orders and help them complete their goals at all costs.") + Z.cancel_camera() + qdel(C) + + if("Wraith") + var/mob/living/simple_animal/construct/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_all_cult_icons() + qdel(T) + to_chat(Z, "You are playing 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 and his allies, follow their orders and help them complete their goals at all costs.") + Z.cancel_camera() + qdel(C) + + if("Artificer") + var/mob/living/simple_animal/construct/builder/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_all_cult_icons() + qdel(T) + to_chat(Z, "You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs") + to_chat(Z, "You are still bound to serve your creator and his allies, follow their orders and help them complete their goals at all costs.") + Z.cancel_camera() + qdel(C) + else + to_chat(U, "\red Creation failed!: \black The soul stone is empty! Go kill someone!") + return diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index d3fd3f2f71bf..fc54d6b2dee1 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -1,527 +1,527 @@ -#define CONTRACT_PRICE 5 - -/datum/spellbook_entry - var/name = "Entry Name" - - var/spell_type = null - var/desc = "" - var/category = "Offensive" - var/log_name = "XX" //What it shows up as in logs - var/cost = 2 - var/refundable = 1 - var/surplus = -1 // -1 for infinite, not used by anything atm - var/obj/effect/proc_holder/spell/S = null //Since spellbooks can be used by only one person anyway we can track the actual spell - var/buy_word = "Learn" - -/datum/spellbook_entry/proc/IsAvailible() // For config prefs / gamemode restrictions - these are round applied - return 1 - -/datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) // Specific circumstances - if(book.uses < cost) - return 0 - for(var/obj/effect/proc_holder/spell/spell in user.mind.spell_list) - if(istype(spell, spell_type)) - return 0 - return 1 - -/datum/spellbook_entry/proc/Buy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) //return 1 on success - if(!S || QDELETED(S)) - S = new spell_type() - feedback_add_details("wizard_spell_learned",log_name) - user.AddSpell(S) - to_chat(user, "You have learned [S.name].") - return 1 - -/datum/spellbook_entry/proc/CanRefund(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) - if(!refundable) - return 0 - if(!S) - S = new spell_type() - for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list) - if(initial(S.name) == initial(aspell.name)) - return 1 - return 0 - -/datum/spellbook_entry/proc/Refund(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) //return point value or -1 for failure - if(!istype(get_area(user), /area/wizard_station)) - to_chat(user, "You can only refund spells at the wizard lair") - return -1 - if(!S) - S = new spell_type() - for(var/obj/effect/proc_holder/spell/aspell in user.spell_list) - if(initial(S.name) == initial(aspell.name)) - user.spell_list -= aspell - user.mind.spell_list -= aspell - qdel(aspell) - qdel(S) - return cost - return -1 -/datum/spellbook_entry/proc/GetInfo() - if(!S) - S = new spell_type() - var/dat ="" - dat += "[initial(S.name)]" - if(S.charge_type == "recharge") - dat += " Cooldown:[S.charge_max / 10]" - dat += " Cost:[cost]
    " - dat += "[S.desc][desc]
    " - dat += "[S.clothes_req ? "Needs wizard garb" : "Can be cast without wizard garb"]
    " - return dat - -/datum/spellbook_entry/fireball - name = "Fireball" - spell_type = /obj/effect/proc_holder/spell/in_hand/fireball - log_name = "FB" - -/datum/spellbook_entry/res_touch - name = "Resurrection" - spell_type = /obj/effect/proc_holder/spell/in_hand/res_touch - log_name = "RT" - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/heal_touch - name = "Heal" - spell_type = /obj/effect/proc_holder/spell/in_hand/heal - log_name = "HT" - category = "Defensive" - -/datum/spellbook_entry/magicm - name = "Magic Missile" - spell_type = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile - log_name = "MM" - category = "Defensive" - -/datum/spellbook_entry/disabletech - name = "Disable Tech" - spell_type = /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech - log_name = "DT" - category = "Defensive" - -/datum/spellbook_entry/repulse - name = "Repulse" - spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse - log_name = "RP" - category = "Defensive" - -/datum/spellbook_entry/timestop - name = "Time Stop" - spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop - log_name = "TS" - category = "Defensive" - cost = 3 - -/datum/spellbook_entry/smoke - name = "Smoke" - spell_type = /obj/effect/proc_holder/spell/targeted/smoke - log_name = "SM" - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/blind - name = "Blind" - spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind - log_name = "BD" - -/datum/spellbook_entry/mindswap - name = "Mindswap" - spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer - log_name = "MT" - category = "Mobility" - -/datum/spellbook_entry/forcewall - name = "Force Wall" - spell_type = /obj/effect/proc_holder/spell/targeted/forcewall - log_name = "FW" - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/blink - name = "Blink" - spell_type = /obj/effect/proc_holder/spell/targeted/turf_teleport/blink - log_name = "BL" - category = "Mobility" - -/datum/spellbook_entry/teleport - name = "Teleport" - spell_type = /obj/effect/proc_holder/spell/targeted/area_teleport/teleport - log_name = "TP" - category = "Mobility" - -/datum/spellbook_entry/mutate - name = "Mutate" - spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate - log_name = "MU" - -/datum/spellbook_entry/jaunt - name = "Ethereal Jaunt" - spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt - log_name = "EJ" - category = "Mobility" - -/datum/spellbook_entry/knock - name = "Knock" - spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock - log_name = "KN" - category = "Mobility" - cost = 1 - -/datum/spellbook_entry/summonitem - name = "Summon Item" - spell_type = /obj/effect/proc_holder/spell/targeted/summonitem - log_name = "IS" - category = "Assistance" - cost = 1 - -/datum/spellbook_entry/lightningbolt - name = "Lightning Bolt" - spell_type = /obj/effect/proc_holder/spell/in_hand/tesla - log_name = "LB" - cost = 3 - -/datum/spellbook_entry/lightningbolt/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book) //return 1 on success - . = ..() - user.tesla_ignore = TRUE - -/datum/spellbook_entry/lightningbolt/Refund(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) - . = ..() - if(.) - user.tesla_ignore = FALSE - -/datum/spellbook_entry/arcane_barrage - name = "Arcane Barrage" - spell_type = /obj/effect/proc_holder/spell/in_hand/arcane_barrage - log_name = "AB" - cost = 3 - -/datum/spellbook_entry/barnyard - name = "Barnyard Curse" - spell_type = /obj/effect/proc_holder/spell/targeted/barnyardcurse - log_name = "BC" - -/datum/spellbook_entry/lighting_shock - name = "Lighting Shock" - spell_type = /obj/effect/proc_holder/spell/targeted/lighting_shock - log_name = "LS" - -/datum/spellbook_entry/charge - name = "Charge" - spell_type = /obj/effect/proc_holder/spell/targeted/charge - log_name = "CH" - category = "Assistance" - cost = 1 - -/datum/spellbook_entry/spacetime_dist - name = "Spacetime Distortion" - spell_type = /obj/effect/proc_holder/spell/targeted/spacetime_dist - log_name = "STD" - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/the_traps - name = "The Traps!" - spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/the_traps - log_name = "TT" - category = "Offensive" - -/datum/spellbook_entry/item - name = "Buy Item" - refundable = 0 - buy_word = "Summon" - var/item_path= null - -/datum/spellbook_entry/item/Buy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) - new item_path (get_turf(user)) - feedback_add_details("wizard_spell_learned", log_name) - return 1 - -/datum/spellbook_entry/item/GetInfo() - var/dat ="" - dat += "[name]" - dat += " Cost:[cost]
    " - dat += "[desc]
    " - if(surplus >= 0) - dat += "[surplus] left.
    " - return dat - -/datum/spellbook_entry/item/staffchange - name = "Staff of Change" - desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself." - item_path = /obj/item/weapon/gun/magic/staff/change - log_name = "ST" - cost = 4 - -/datum/spellbook_entry/item/staffanimation - name = "Staff of Animation" - desc = "An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines." - item_path = /obj/item/weapon/gun/magic/staff/animate - log_name = "SA" - category = "Assistance" - cost = 3 - -/datum/spellbook_entry/item/staffdoor - name = "Staff of Door Creation" - desc = "A particular staff that can mold solid metal into ornate doors. Useful for getting around in the absence of other transportation. Does not work on glass." - item_path = /obj/item/weapon/gun/magic/staff/doorcreation - log_name = "SD" - category = "Mobility" - cost = 3 - -/datum/spellbook_entry/item/staffhealing - name = "Staff of Healing" - desc = "An altruistic staff that can heal the lame and raise the dead." - item_path = /obj/item/weapon/gun/magic/staff/healing - log_name = "SH" - category = "Defensive" - cost = 4 - -/datum/spellbook_entry/item/soulstones - name = "Six Soul Stone Shards and the spell Artificer" - desc = "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." - item_path = /obj/item/weapon/storage/belt/soulstone/full - log_name = "SS" - category = "Assistance" - -/datum/spellbook_entry/item/soulstones/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book) - . =..() - if(.) - user.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(user)) - return . - -/datum/spellbook_entry/item/necrostone - name = "A Necromantic Stone" - desc = "A Necromantic stone is able to resurrect three dead individuals as skeletal thralls for you to command." - item_path = /obj/item/device/necromantic_stone - log_name = "NS" - category = "Assistance" - cost = 3 - -/datum/spellbook_entry/item/armor - name = "Mastercrafted Armor Set" - desc = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space." - item_path = /obj/item/clothing/suit/space/rig/wizard - log_name = "HS" - category = "Defensive" - -/datum/spellbook_entry/item/armor/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book) - . = ..() - if(.) - new /obj/item/clothing/shoes/sandal(get_turf(user)) //In case they've lost them. - new /obj/item/clothing/head/helmet/space/rig/wizard(get_turf(user))//To complete the outfit - -/datum/spellbook_entry/item/contract - name = "Contract of Apprenticeship" - desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side." - item_path = /obj/item/weapon/contract - log_name = "CT" - category = "Assistance" - cost = CONTRACT_PRICE - -/datum/spellbook_entry/item/contract/Buy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) - var/obj/item/weapon/contract/contract = new(get_turf(user)) - contract.wizard = user.mind - feedback_add_details("wizard_spell_learned",log_name) - return 1 - - -/*datum/spellbook_entry/item/battlemage - name = "Battlemage Armour" - desc = "An ensorcelled suit of armour, protected by a powerful shield. The shield can completly negate sixteen attacks before being permanently depleted." - item_path = /obj/item/clothing/suit/space/hardsuit/shielded/wizard - log_name = "BM" - limit = 1 - category = "Defensive" - -/datum/spellbook_entry/item/battlemage_charge - name = "Battlemage Armour Charges" - desc = "A powerful defensive rune, it will grant eight additional charges to a suit of battlemage armour." - item_path = /obj/item/wizard_armour_charge - log_name = "AC" - category = "Defensive" - cost = 1*/ - -/datum/spellbook_entry/summon - name = "Summon Stuff" - category = "Rituals" - refundable = 0 - buy_word = "Cast" - var/active = 0 - -/datum/spellbook_entry/summon/CanBuy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) - return ..() && !active - -/datum/spellbook_entry/summon/GetInfo() - var/dat ="" - dat += "[name]" - if(cost > 0) - dat += " Cost:[cost]
    " - else - dat += " No Cost
    " - dat += "[desc]
    " - if(active) - dat += "Already cast!
    " - return dat - -/datum/spellbook_entry/summon/IsAvailible() - return ticker.mode // In case spellbook is placed on map - -/obj/item/weapon/spellbook - name = "spell book" - desc = "An unearthly tome that glows with power." - w_class = 2 - icon = 'icons/obj/library.dmi' - icon_state ="book" - var/uses = 10 - var/temp = null - var/tab = null - var/datum/mind/owner - var/list/datum/spellbook_entry/entries = list() - var/list/categories = list() - -/obj/item/weapon/spellbook/examine(mob/user) - ..() - if(owner) - to_chat(user, "There is a small signature on the front cover: \"[owner]\".") - else - to_chat(user, "It appears to have no author.") - -/obj/item/weapon/spellbook/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/item/weapon/spellbook/atom_init_late() - var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon - for(var/T in entry_types) - var/datum/spellbook_entry/E = new T - if(E.IsAvailible()) - entries |= E - categories |= E.category - else - qdel(E) - tab = categories[1] - - - -/obj/item/weapon/spellbook/attackby(obj/item/O, mob/user, params) - if(istype(O, /obj/item/weapon/contract)) - var/obj/item/weapon/contract/contract = O - if(contract.uses != initial(contract.uses)) - 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.") - uses += CONTRACT_PRICE - qdel(O) - -/obj/item/weapon/spellbook/proc/GetCategoryHeader(category) - var/dat = "" - switch(category) - if("Offensive") - dat += "Spells and items geared towards debilitating and destroying.

    " - dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
    " - dat += "For spells: the number after the spell name is the cooldown time.
    " - if("Defensive") - dat += "Spells and items geared towards improving your survivabilty or reducing foes' ability to attack.

    " - dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
    " - dat += "For spells: the number after the spell name is the cooldown time.
    " - if("Mobility") - dat += "Spells and items geared towards improving your ability to move. It is a good idea to take at least one.

    " - dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
    " - dat += "For spells: the number after the spell name is the cooldown time.
    " - if("Assistance") - dat += "Spells and items geared towards bringing in outside forces to aid you or improving upon your other items and abilties.

    " - dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
    " - dat += "For spells: the number after the spell name is the cooldown time.
    " - return dat - -/obj/item/weapon/spellbook/proc/wrap(content) - var/dat = "" - dat +="Spellbook" - dat += {" - - - - "} - dat += {"[content]"} - return dat - -/obj/item/weapon/spellbook/attack_self(mob/user) - if(!owner) - to_chat(user, "You bind the spellbook to yourself.") - owner = user.mind - return - if(user.mind != owner) - to_chat(user, "The [name] does not recognize you as its owner and refuses to open!") - return - user.set_machine(src) - var/dat = "" - - dat += "" - - var/datum/spellbook_entry/E - for(var/i = 1 to entries.len) - var/spell_info = "" - E = entries[i] - spell_info += E.GetInfo() - if(E.CanBuy(user,src)) - spell_info+= "[E.buy_word]
    " - else - spell_info+= "Can't [E.buy_word]
    " - if(E.CanRefund(user,src)) - spell_info+= "Refund
    " - spell_info += "
    " - if(cat_dat[E.category]) - cat_dat[E.category] += spell_info - - for(var/category in categories) - dat += "
    " - dat += GetCategoryHeader(category) - dat += cat_dat[category] - dat += "
    " - - user << browse(wrap(entity_ja(dat)), "window=spellbook;size=700x500") - onclose(user, "spellbook") - return - -/obj/item/weapon/spellbook/Topic(href, href_list) - ..() - if(!ishuman(usr)) - return 1 - var/mob/living/carbon/human/H = usr - - if(H.stat || H.restrained()) - return - - var/datum/spellbook_entry/E = null - if(loc == H || (in_range(src, H) && isturf(loc))) - H.set_machine(src) - if(href_list["buy"]) - E = entries[text2num(href_list["buy"])] - if(E && E.CanBuy(H,src)) - if(E.Buy(H,src)) - uses -= E.cost - else if(href_list["refund"]) - E = entries[text2num(href_list["refund"])] - if(E && E.refundable) - var/result = E.Refund(H,src) - if(result > 0) - uses += result - else if(href_list["page"]) - tab = sanitize(href_list["page"]) - attack_self(H) - return +#define CONTRACT_PRICE 5 + +/datum/spellbook_entry + var/name = "Entry Name" + + var/spell_type = null + var/desc = "" + var/category = "Offensive" + var/log_name = "XX" //What it shows up as in logs + var/cost = 2 + var/refundable = 1 + var/surplus = -1 // -1 for infinite, not used by anything atm + var/obj/effect/proc_holder/spell/S = null //Since spellbooks can be used by only one person anyway we can track the actual spell + var/buy_word = "Learn" + +/datum/spellbook_entry/proc/IsAvailible() // For config prefs / gamemode restrictions - these are round applied + return 1 + +/datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) // Specific circumstances + if(book.uses < cost) + return 0 + for(var/obj/effect/proc_holder/spell/spell in user.mind.spell_list) + if(istype(spell, spell_type)) + return 0 + return 1 + +/datum/spellbook_entry/proc/Buy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) //return 1 on success + if(!S || QDELETED(S)) + S = new spell_type() + feedback_add_details("wizard_spell_learned",log_name) + user.AddSpell(S) + to_chat(user, "You have learned [S.name].") + return 1 + +/datum/spellbook_entry/proc/CanRefund(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) + if(!refundable) + return 0 + if(!S) + S = new spell_type() + for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list) + if(initial(S.name) == initial(aspell.name)) + return 1 + return 0 + +/datum/spellbook_entry/proc/Refund(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) //return point value or -1 for failure + if(!istype(get_area(user), /area/wizard_station)) + to_chat(user, "You can only refund spells at the wizard lair") + return -1 + if(!S) + S = new spell_type() + for(var/obj/effect/proc_holder/spell/aspell in user.spell_list) + if(initial(S.name) == initial(aspell.name)) + user.spell_list -= aspell + user.mind.spell_list -= aspell + qdel(aspell) + qdel(S) + return cost + return -1 +/datum/spellbook_entry/proc/GetInfo() + if(!S) + S = new spell_type() + var/dat ="" + dat += "[initial(S.name)]" + if(S.charge_type == "recharge") + dat += " Cooldown:[S.charge_max / 10]" + dat += " Cost:[cost]
    " + dat += "[S.desc][desc]
    " + dat += "[S.clothes_req ? "Needs wizard garb" : "Can be cast without wizard garb"]
    " + return dat + +/datum/spellbook_entry/fireball + name = "Fireball" + spell_type = /obj/effect/proc_holder/spell/in_hand/fireball + log_name = "FB" + +/datum/spellbook_entry/res_touch + name = "Resurrection" + spell_type = /obj/effect/proc_holder/spell/in_hand/res_touch + log_name = "RT" + category = "Defensive" + cost = 1 + +/datum/spellbook_entry/heal_touch + name = "Heal" + spell_type = /obj/effect/proc_holder/spell/in_hand/heal + log_name = "HT" + category = "Defensive" + +/datum/spellbook_entry/magicm + name = "Magic Missile" + spell_type = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile + log_name = "MM" + category = "Defensive" + +/datum/spellbook_entry/disabletech + name = "Disable Tech" + spell_type = /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech + log_name = "DT" + category = "Defensive" + +/datum/spellbook_entry/repulse + name = "Repulse" + spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse + log_name = "RP" + category = "Defensive" + +/datum/spellbook_entry/timestop + name = "Time Stop" + spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop + log_name = "TS" + category = "Defensive" + cost = 3 + +/datum/spellbook_entry/smoke + name = "Smoke" + spell_type = /obj/effect/proc_holder/spell/targeted/smoke + log_name = "SM" + category = "Defensive" + cost = 1 + +/datum/spellbook_entry/blind + name = "Blind" + spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind + log_name = "BD" + +/datum/spellbook_entry/mindswap + name = "Mindswap" + spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer + log_name = "MT" + category = "Mobility" + +/datum/spellbook_entry/forcewall + name = "Force Wall" + spell_type = /obj/effect/proc_holder/spell/targeted/forcewall + log_name = "FW" + category = "Defensive" + cost = 1 + +/datum/spellbook_entry/blink + name = "Blink" + spell_type = /obj/effect/proc_holder/spell/targeted/turf_teleport/blink + log_name = "BL" + category = "Mobility" + +/datum/spellbook_entry/teleport + name = "Teleport" + spell_type = /obj/effect/proc_holder/spell/targeted/area_teleport/teleport + log_name = "TP" + category = "Mobility" + +/datum/spellbook_entry/mutate + name = "Mutate" + spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate + log_name = "MU" + +/datum/spellbook_entry/jaunt + name = "Ethereal Jaunt" + spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt + log_name = "EJ" + category = "Mobility" + +/datum/spellbook_entry/knock + name = "Knock" + spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock + log_name = "KN" + category = "Mobility" + cost = 1 + +/datum/spellbook_entry/summonitem + name = "Summon Item" + spell_type = /obj/effect/proc_holder/spell/targeted/summonitem + log_name = "IS" + category = "Assistance" + cost = 1 + +/datum/spellbook_entry/lightningbolt + name = "Lightning Bolt" + spell_type = /obj/effect/proc_holder/spell/in_hand/tesla + log_name = "LB" + cost = 3 + +/datum/spellbook_entry/lightningbolt/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book) //return 1 on success + . = ..() + user.tesla_ignore = TRUE + +/datum/spellbook_entry/lightningbolt/Refund(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) + . = ..() + if(.) + user.tesla_ignore = FALSE + +/datum/spellbook_entry/arcane_barrage + name = "Arcane Barrage" + spell_type = /obj/effect/proc_holder/spell/in_hand/arcane_barrage + log_name = "AB" + cost = 3 + +/datum/spellbook_entry/barnyard + name = "Barnyard Curse" + spell_type = /obj/effect/proc_holder/spell/targeted/barnyardcurse + log_name = "BC" + +/datum/spellbook_entry/lighting_shock + name = "Lighting Shock" + spell_type = /obj/effect/proc_holder/spell/targeted/lighting_shock + log_name = "LS" + +/datum/spellbook_entry/charge + name = "Charge" + spell_type = /obj/effect/proc_holder/spell/targeted/charge + log_name = "CH" + category = "Assistance" + cost = 1 + +/datum/spellbook_entry/spacetime_dist + name = "Spacetime Distortion" + spell_type = /obj/effect/proc_holder/spell/targeted/spacetime_dist + log_name = "STD" + category = "Defensive" + cost = 1 + +/datum/spellbook_entry/the_traps + name = "The Traps!" + spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/the_traps + log_name = "TT" + category = "Offensive" + +/datum/spellbook_entry/item + name = "Buy Item" + refundable = 0 + buy_word = "Summon" + var/item_path= null + +/datum/spellbook_entry/item/Buy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) + new item_path (get_turf(user)) + feedback_add_details("wizard_spell_learned", log_name) + return 1 + +/datum/spellbook_entry/item/GetInfo() + var/dat ="" + dat += "[name]" + dat += " Cost:[cost]
    " + dat += "[desc]
    " + if(surplus >= 0) + dat += "[surplus] left.
    " + return dat + +/datum/spellbook_entry/item/staffchange + name = "Staff of Change" + desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself." + item_path = /obj/item/weapon/gun/magic/staff/change + log_name = "ST" + cost = 4 + +/datum/spellbook_entry/item/staffanimation + name = "Staff of Animation" + desc = "An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines." + item_path = /obj/item/weapon/gun/magic/staff/animate + log_name = "SA" + category = "Assistance" + cost = 3 + +/datum/spellbook_entry/item/staffdoor + name = "Staff of Door Creation" + desc = "A particular staff that can mold solid metal into ornate doors. Useful for getting around in the absence of other transportation. Does not work on glass." + item_path = /obj/item/weapon/gun/magic/staff/doorcreation + log_name = "SD" + category = "Mobility" + cost = 3 + +/datum/spellbook_entry/item/staffhealing + name = "Staff of Healing" + desc = "An altruistic staff that can heal the lame and raise the dead." + item_path = /obj/item/weapon/gun/magic/staff/healing + log_name = "SH" + category = "Defensive" + cost = 4 + +/datum/spellbook_entry/item/soulstones + name = "Six Soul Stone Shards and the spell Artificer" + desc = "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." + item_path = /obj/item/weapon/storage/belt/soulstone/full + log_name = "SS" + category = "Assistance" + +/datum/spellbook_entry/item/soulstones/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book) + . =..() + if(.) + user.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(user)) + return . + +/datum/spellbook_entry/item/necrostone + name = "A Necromantic Stone" + desc = "A Necromantic stone is able to resurrect three dead individuals as skeletal thralls for you to command." + item_path = /obj/item/device/necromantic_stone + log_name = "NS" + category = "Assistance" + cost = 3 + +/datum/spellbook_entry/item/armor + name = "Mastercrafted Armor Set" + desc = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space." + item_path = /obj/item/clothing/suit/space/rig/wizard + log_name = "HS" + category = "Defensive" + +/datum/spellbook_entry/item/armor/Buy(mob/living/carbon/human/user,obj/item/weapon/spellbook/book) + . = ..() + if(.) + new /obj/item/clothing/shoes/sandal(get_turf(user)) //In case they've lost them. + new /obj/item/clothing/head/helmet/space/rig/wizard(get_turf(user))//To complete the outfit + +/datum/spellbook_entry/item/contract + name = "Contract of Apprenticeship" + desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side." + item_path = /obj/item/weapon/contract + log_name = "CT" + category = "Assistance" + cost = CONTRACT_PRICE + +/datum/spellbook_entry/item/contract/Buy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) + var/obj/item/weapon/contract/contract = new(get_turf(user)) + contract.wizard = user.mind + feedback_add_details("wizard_spell_learned",log_name) + return 1 + + +/*datum/spellbook_entry/item/battlemage + name = "Battlemage Armour" + desc = "An ensorcelled suit of armour, protected by a powerful shield. The shield can completly negate sixteen attacks before being permanently depleted." + item_path = /obj/item/clothing/suit/space/hardsuit/shielded/wizard + log_name = "BM" + limit = 1 + category = "Defensive" + +/datum/spellbook_entry/item/battlemage_charge + name = "Battlemage Armour Charges" + desc = "A powerful defensive rune, it will grant eight additional charges to a suit of battlemage armour." + item_path = /obj/item/wizard_armour_charge + log_name = "AC" + category = "Defensive" + cost = 1*/ + +/datum/spellbook_entry/summon + name = "Summon Stuff" + category = "Rituals" + refundable = 0 + buy_word = "Cast" + var/active = 0 + +/datum/spellbook_entry/summon/CanBuy(mob/living/carbon/human/user, obj/item/weapon/spellbook/book) + return ..() && !active + +/datum/spellbook_entry/summon/GetInfo() + var/dat ="" + dat += "[name]" + if(cost > 0) + dat += " Cost:[cost]
    " + else + dat += " No Cost
    " + dat += "[desc]
    " + if(active) + dat += "Already cast!
    " + return dat + +/datum/spellbook_entry/summon/IsAvailible() + return ticker.mode // In case spellbook is placed on map + +/obj/item/weapon/spellbook + name = "spell book" + desc = "An unearthly tome that glows with power." + w_class = 2 + icon = 'icons/obj/library.dmi' + icon_state ="book" + var/uses = 10 + var/temp = null + var/tab = null + var/datum/mind/owner + var/list/datum/spellbook_entry/entries = list() + var/list/categories = list() + +/obj/item/weapon/spellbook/examine(mob/user) + ..() + if(owner) + to_chat(user, "There is a small signature on the front cover: \"[owner]\".") + else + to_chat(user, "It appears to have no author.") + +/obj/item/weapon/spellbook/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/item/weapon/spellbook/atom_init_late() + var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon + for(var/T in entry_types) + var/datum/spellbook_entry/E = new T + if(E.IsAvailible()) + entries |= E + categories |= E.category + else + qdel(E) + tab = categories[1] + + + +/obj/item/weapon/spellbook/attackby(obj/item/O, mob/user, params) + if(istype(O, /obj/item/weapon/contract)) + var/obj/item/weapon/contract/contract = O + if(contract.uses != initial(contract.uses)) + 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.") + uses += CONTRACT_PRICE + qdel(O) + +/obj/item/weapon/spellbook/proc/GetCategoryHeader(category) + var/dat = "" + switch(category) + if("Offensive") + dat += "Spells and items geared towards debilitating and destroying.

    " + dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
    " + dat += "For spells: the number after the spell name is the cooldown time.
    " + if("Defensive") + dat += "Spells and items geared towards improving your survivabilty or reducing foes' ability to attack.

    " + dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
    " + dat += "For spells: the number after the spell name is the cooldown time.
    " + if("Mobility") + dat += "Spells and items geared towards improving your ability to move. It is a good idea to take at least one.

    " + dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
    " + dat += "For spells: the number after the spell name is the cooldown time.
    " + if("Assistance") + dat += "Spells and items geared towards bringing in outside forces to aid you or improving upon your other items and abilties.

    " + dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
    " + dat += "For spells: the number after the spell name is the cooldown time.
    " + return dat + +/obj/item/weapon/spellbook/proc/wrap(content) + var/dat = "" + dat +="Spellbook" + dat += {" + + + + "} + dat += {"[content]"} + return dat + +/obj/item/weapon/spellbook/attack_self(mob/user) + if(!owner) + to_chat(user, "You bind the spellbook to yourself.") + owner = user.mind + return + if(user.mind != owner) + to_chat(user, "The [name] does not recognize you as its owner and refuses to open!") + return + user.set_machine(src) + var/dat = "" + + dat += "" + + var/datum/spellbook_entry/E + for(var/i = 1 to entries.len) + var/spell_info = "" + E = entries[i] + spell_info += E.GetInfo() + if(E.CanBuy(user,src)) + spell_info+= "[E.buy_word]
    " + else + spell_info+= "Can't [E.buy_word]
    " + if(E.CanRefund(user,src)) + spell_info+= "Refund
    " + spell_info += "
    " + if(cat_dat[E.category]) + cat_dat[E.category] += spell_info + + for(var/category in categories) + dat += "
    " + dat += GetCategoryHeader(category) + dat += cat_dat[category] + dat += "
    " + + user << browse(wrap(entity_ja(dat)), "window=spellbook;size=700x500") + onclose(user, "spellbook") + return + +/obj/item/weapon/spellbook/Topic(href, href_list) + ..() + if(!ishuman(usr)) + return 1 + var/mob/living/carbon/human/H = usr + + if(H.stat || H.restrained()) + return + + var/datum/spellbook_entry/E = null + if(loc == H || (in_range(src, H) && isturf(loc))) + H.set_machine(src) + if(href_list["buy"]) + E = entries[text2num(href_list["buy"])] + if(E && E.CanBuy(H,src)) + if(E.Buy(H,src)) + uses -= E.cost + else if(href_list["refund"]) + E = entries[text2num(href_list["refund"])] + if(E && E.refundable) + var/result = E.Refund(H,src) + if(result > 0) + uses += result + else if(href_list["page"]) + tab = sanitize(href_list["page"]) + attack_self(H) + return diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index d41c39dfd4e6..ec4b658b0483 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -1,302 +1,302 @@ - -/datum/game_mode - var/list/datum/mind/wizards = list() - -/datum/game_mode/wizard - name = "wizard" - config_tag = "wizard" - role_type = ROLE_WIZARD - required_players = 2 - required_players_secret = 10 - required_enemies = 1 - recommended_enemies = 1 - - votable = 0 - - uplink_welcome = "Wizardly Uplink Console:" - uplink_uses = 20 - - var/finished = 0 - -/datum/game_mode/wizard/announce() - to_chat(world, "The current game mode is - Wizard!") - to_chat(world, "There is a \red SPACE WIZARD\black on the station. You can't let him achieve his objective!") - - -/datum/game_mode/wizard/can_start()//This could be better, will likely have to recode it later - if(!..()) - return 0 - var/datum/mind/wizard = pick(antag_candidates) - wizards += wizard - modePlayer += wizard - 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!") - return 0 - return 1 - - -/datum/game_mode/wizard/pre_setup() - for(var/datum/mind/wizard in wizards) - wizard.current.loc = pick(wizardstart) - return 1 - - -/datum/game_mode/wizard/post_setup() - for(var/datum/mind/wizard in wizards) - if(!config.objectives_disabled) - forge_wizard_objectives(wizard) - //learn_basic_spells(wizard.current) - equip_wizard(wizard.current) - name_wizard(wizard.current) - greet_wizard(wizard) - - return ..() - - -/datum/game_mode/proc/forge_wizard_objectives(datum/mind/wizard) - if (config.objectives_disabled) - return - - 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/survive) in wizard.objectives)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = wizard - wizard.objectives += survive_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/survive) in wizard.objectives)) - var/datum/objective/survive/survive_objective = new - survive_objective.owner = wizard - wizard.objectives += survive_objective - - if(61 to 99) - 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. - 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 = sanitize_safe(input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text, 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 - if(istype(wizard_mob.dna, /datum/dna)) - var/datum/dna/dna = wizard_mob.dna - dna.real_name = newname - return - - -/datum/game_mode/proc/greet_wizard(datum/mind/wizard, 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:") - if(!config.objectives_disabled) - var/obj_count = 1 - for(var/datum/objective/objective in wizard.objectives) - to_chat(wizard.current, "Objective #[obj_count]: [objective.explanation_text]") - obj_count++ - else - to_chat(wizard.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") - 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_l_ear) - 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) - - 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(config.continous_rounds) - return ..() - - var/wizards_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) - return ..() - else - finished = 1 - return 1 - - - -/datum/game_mode/wizard/declare_completion() - var/prefinal_text = "" - var/final_text = "" - completion_text += "Wizard mode resume:
    " - - for(var/datum/mind/wizard in wizards) - if(wizard.current.stat == DEAD || finished) - feedback_set_details("round_end_result","loss - wizard killed") - prefinal_text = "Wizard [wizard.name] ([wizard.key]) has been killed
    " - else - var/failed = 0 - for(var/datum/objective/objective in wizard.objectives) - if(!objective.check_completion()) - failed = 1 - if(!failed) - feedback_set_details("round_end_result","win - wizard alive") - prefinal_text = "Wizard [wizard.name] ([wizard.key]) managed to complete his mission! The Space Wizards Federation understood that station crew - easy target and will use them next time.
    " - else - feedback_set_details("round_end_result","loss - wizard alive") - prefinal_text = "Wizard [wizard.name] ([wizard.key]) managed to stay alive, but failed his mission! The Space Wizards Federation wouldn't forget this shame!
    " - final_text += "[prefinal_text]" - - completion_text += "[final_text]" - ..() - return 1 - - -/datum/game_mode/proc/auto_declare_completion_wizard() - var/text = "" - if(wizards.len) - text += printlogo("wizard", "wizards/witches") - - for(var/datum/mind/wizard in wizards) - text += printplayerwithicon(wizard) - - var/count = 1 - var/wizardwin = 1 - if(!config.objectives_disabled) - 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") - score["roleswon"]++ - 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/obj/effect/proc_holder/spell/S in wizard.current.spell_list) - var/icon/spellicon = icon('icons/mob/actions.dmi', S.action_icon_state) - end_icons += spellicon - var/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(mob/M) - for(var/obj/effect/proc_holder/spell/spell_to_remove in src.spell_list) - qdel(spell_to_remove) - spell_list.Cut() - mind.spell_list.Cut() - -/*Checks if the wizard can cast spells. -Made a proc so this is not repeated 14 (or more) times.*/ -/mob/proc/casting() -//Removed the stat check because not all spells require clothing now. - if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe)) - to_chat(usr, "I don't feel strong enough without my robe.") - return 0 - if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal)) - to_chat(usr, "I don't feel strong enough without my sandals.") - return 0 - if(!istype(usr:head, /obj/item/clothing/head/wizard)) - to_chat(usr, "I don't feel strong enough without my hat.") - return 0 - else - return 1 + +/datum/game_mode + var/list/datum/mind/wizards = list() + +/datum/game_mode/wizard + name = "wizard" + config_tag = "wizard" + role_type = ROLE_WIZARD + required_players = 2 + required_players_secret = 10 + required_enemies = 1 + recommended_enemies = 1 + + votable = 0 + + uplink_welcome = "Wizardly Uplink Console:" + uplink_uses = 20 + + var/finished = 0 + +/datum/game_mode/wizard/announce() + to_chat(world, "The current game mode is - Wizard!") + to_chat(world, "There is a \red SPACE WIZARD\black on the station. You can't let him achieve his objective!") + + +/datum/game_mode/wizard/can_start()//This could be better, will likely have to recode it later + if(!..()) + return 0 + var/datum/mind/wizard = pick(antag_candidates) + wizards += wizard + modePlayer += wizard + 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!") + return 0 + return 1 + + +/datum/game_mode/wizard/pre_setup() + for(var/datum/mind/wizard in wizards) + wizard.current.loc = pick(wizardstart) + return 1 + + +/datum/game_mode/wizard/post_setup() + for(var/datum/mind/wizard in wizards) + if(!config.objectives_disabled) + forge_wizard_objectives(wizard) + //learn_basic_spells(wizard.current) + equip_wizard(wizard.current) + name_wizard(wizard.current) + greet_wizard(wizard) + + return ..() + + +/datum/game_mode/proc/forge_wizard_objectives(datum/mind/wizard) + if (config.objectives_disabled) + return + + 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/survive) in wizard.objectives)) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = wizard + wizard.objectives += survive_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/survive) in wizard.objectives)) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = wizard + wizard.objectives += survive_objective + + if(61 to 99) + 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. + 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 = sanitize_safe(input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text, 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 + if(istype(wizard_mob.dna, /datum/dna)) + var/datum/dna/dna = wizard_mob.dna + dna.real_name = newname + return + + +/datum/game_mode/proc/greet_wizard(datum/mind/wizard, 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:") + if(!config.objectives_disabled) + var/obj_count = 1 + for(var/datum/objective/objective in wizard.objectives) + to_chat(wizard.current, "Objective #[obj_count]: [objective.explanation_text]") + obj_count++ + else + to_chat(wizard.current, "Within the rules, try to act as an opposing force to the crew. Further RP and try to make sure other players have fun! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! Please remember all rules aside from those without explicit exceptions apply to antagonists.") + 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_l_ear) + 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) + + 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(config.continous_rounds) + return ..() + + var/wizards_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) + return ..() + else + finished = 1 + return 1 + + + +/datum/game_mode/wizard/declare_completion() + var/prefinal_text = "" + var/final_text = "" + completion_text += "Wizard mode resume:
    " + + for(var/datum/mind/wizard in wizards) + if(wizard.current.stat == DEAD || finished) + feedback_set_details("round_end_result","loss - wizard killed") + prefinal_text = "Wizard [wizard.name] ([wizard.key]) has been killed
    " + else + var/failed = 0 + for(var/datum/objective/objective in wizard.objectives) + if(!objective.check_completion()) + failed = 1 + if(!failed) + feedback_set_details("round_end_result","win - wizard alive") + prefinal_text = "Wizard [wizard.name] ([wizard.key]) managed to complete his mission! The Space Wizards Federation understood that station crew - easy target and will use them next time.
    " + else + feedback_set_details("round_end_result","loss - wizard alive") + prefinal_text = "Wizard [wizard.name] ([wizard.key]) managed to stay alive, but failed his mission! The Space Wizards Federation wouldn't forget this shame!
    " + final_text += "[prefinal_text]" + + completion_text += "[final_text]" + ..() + return 1 + + +/datum/game_mode/proc/auto_declare_completion_wizard() + var/text = "" + if(wizards.len) + text += printlogo("wizard", "wizards/witches") + + for(var/datum/mind/wizard in wizards) + text += printplayerwithicon(wizard) + + var/count = 1 + var/wizardwin = 1 + if(!config.objectives_disabled) + 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") + score["roleswon"]++ + 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/obj/effect/proc_holder/spell/S in wizard.current.spell_list) + var/icon/spellicon = icon('icons/mob/actions.dmi', S.action_icon_state) + end_icons += spellicon + var/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(mob/M) + for(var/obj/effect/proc_holder/spell/spell_to_remove in src.spell_list) + qdel(spell_to_remove) + spell_list.Cut() + mind.spell_list.Cut() + +/*Checks if the wizard can cast spells. +Made a proc so this is not repeated 14 (or more) times.*/ +/mob/proc/casting() +//Removed the stat check because not all spells require clothing now. + if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe)) + to_chat(usr, "I don't feel strong enough without my robe.") + return 0 + if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal)) + to_chat(usr, "I don't feel strong enough without my sandals.") + return 0 + if(!istype(usr:head, /obj/item/clothing/head/wizard)) + to_chat(usr, "I don't feel strong enough without my hat.") + return 0 + else + return 1 diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index c182be7857f4..63374926fc1e 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -1,571 +1,571 @@ -/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 -/var/const/access_tox_storage = 8 -/var/const/access_genetics = 9 -/var/const/access_engine = 10 -/var/const/access_engine_equip= 11 -/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 -/var/const/access_construction = 32 -/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 -/var/const/access_mining = 48 -/var/const/access_mining_office = 49 //not in use -/var/const/access_mailsorting = 50 -/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_xenoarch = 65 -/var/const/access_minisat = 66 -/var/const/access_recycler = 67 -/var/const/access_detective = 68 -/var/const/access_barber = 69 -/var/const/access_paramedic = 70 - - //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//Special Ops. -/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. -/var/const/access_cent_captain = 109//Captain's office/ID comp/AI. - - //The Syndicate -/var/const/access_syndicate = 150//General Syndicate Access -/var/const/access_syndicate_commander = 151 //Syndicate Commander Access - - //MONEY -/var/const/access_crate_cash = 200 - -/obj/var/list/req_access = null -/obj/var/req_access_txt = "0" -/obj/var/list/req_one_access = null -/obj/var/req_one_access_txt = "0" - -//returns 1 if this mob has sufficient access to use this object -/obj/proc/allowed(mob/M) - //check if it doesn't require any access at all - if(src.check_access(null)) - return TRUE - if(issilicon(M)) - var/mob/living/silicon/S = M - if(src.check_access(S)) - return TRUE - if(IsAdminGhost(M)) - //Access can't stop the abuse - return TRUE - else if(ishuman(M)) - 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.get_active_hand()) || src.check_access(H.wear_id)) - return TRUE - else if(isIAN(M)) - var/mob/living/carbon/ian/IAN = M - if(src.check_access(IAN.mouth) || src.check_access(IAN.neck)) - return TRUE - else if(ismonkey(M) || isalienadult(M)) - var/mob/living/carbon/george = M - //they can only hold things :( - if(src.check_access(george.get_active_hand())) - return TRUE - return FALSE - -/atom/movable/proc/GetAccess() - return list() - -/mob/living/silicon/GetAccess() - return get_all_accesses() - -/mob/living/silicon/robot/syndicate/GetAccess() - return list(access_maint_tunnels, access_syndicate, access_external_airlocks) //syndicate basic access - -/obj/item/proc/GetID() - return null - -/obj/proc/check_access(atom/movable/AM) - if(istype(src, /obj/machinery)) - var/obj/machinery/Machine = src - if(Machine.emagged) - return TRUE - - //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(!islist(req_access)) - req_access = list() - if(req_access_txt) - var/list/req_access_str = splittext(req_access_txt,";") - for(var/x in req_access_str) - var/n = text2num(x) - if(n) - req_access += n - - if(!islist(req_one_access)) - req_one_access = list() - if(req_one_access_txt) - var/list/req_one_access_str = splittext(req_one_access_txt,";") - for(var/x in req_one_access_str) - var/n = text2num(x) - if(n) - req_one_access += n - - if(!req_access.len && !req_one_access.len) //no requirements - return TRUE - if(!AM) - return FALSE - for(var/req in req_access) - if(!(req in AM.GetAccess())) //doesn't have this access - return FALSE - if(req_one_access.len) - for(var/req in src.req_one_access) - if(req in AM.GetAccess()) //has an access from the single access list - return TRUE - return FALSE - return TRUE - -/obj/proc/check_access_list(list/L) - if(!islist(req_access)) - req_access = list() - if(req_access_txt) - var/list/req_access_str = splittext(req_access_txt,";") - for(var/x in req_access_str) - var/n = text2num(x) - if(n) - req_access += n - - if(!islist(req_one_access)) - req_one_access = list() - if(req_one_access_txt) - var/list/req_one_access_str = splittext(req_one_access_txt,";") - for(var/x in req_one_access_str) - var/n = text2num(x) - if(n) - req_one_access += n - - if(!req_access.len && !req_one_access.len) - return TRUE - if(!islist(L)) - return FALSE - for(var/req in req_access) - if(!(req in L)) //doesn't have this access - return FALSE - if(req_one_access.len) - for(var/req in req_one_access) - if(req in L) //has an access from the single access list - return TRUE - return FALSE - return TRUE - -/proc/get_centcom_access(job) - switch(job) - if("VIP Guest") - return list(access_cent_general) - if("Custodian") - return list(access_cent_general, access_cent_living, access_cent_storage) - if("Thunderdome Overseer") - return list(access_cent_general, access_cent_thunder) - if("Intel Officer") - return list(access_cent_general, access_cent_living) - if("Medical Officer") - return list(access_cent_general, access_cent_living, access_cent_medical) - if("Death Commando") - return list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage) - if("Research Officer") - return list(access_cent_general, access_cent_specops, access_cent_medical, access_cent_teleporter, access_cent_storage) - if("BlackOps Commander") - return list(access_cent_general, access_cent_thunder, access_cent_specops, access_cent_living, access_cent_storage, access_cent_creed) - if("Supreme Commander") - return get_all_centcom_access() - -/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_heads_vault, access_mining_station, access_xenobiology, access_ce, access_hop, access_hos, access_RC_announce, - access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_minisat, access_recycler, access_detective, access_barber, access_paramedic) - -/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_region_accesses(code) - switch(code) - if(0) - return get_all_accesses() - if(1) //security - return list(access_sec_doors, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_hos, access_detective) - if(2) //medbay - return list(access_medical, access_genetics, access_morgue, access_chemistry, access_psychiatrist, access_virology, access_surgery, access_cmo, access_paramedic) - if(3) //research - return list(access_research, access_tox, access_tox_storage, access_robotics, access_xenobiology, access_xenoarch, access_minisat, 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_atmospherics, access_minisat, 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_barber, 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_recycler, access_qm) - -/proc/get_region_accesses_name(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_recycler) - return "Recycler" - if(access_detective) - return "Detective" - 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 Chambers" - 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 "IAA 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_xenoarch) - return "Xenoarchaeology" - 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" - if(access_minisat) - return "AI Satellite" - if(access_barber) - return "Barber" - if(access_paramedic) - return "Paramedic" - -/proc/get_centcom_access_desc(A) - switch(A) - if(access_cent_general) - return "Code Grey" - if(access_cent_thunder) - return "Code Yellow" - if(access_cent_storage) - return "Code Orange" - if(access_cent_living) - return "Code Green" - if(access_cent_medical) - return "Code White" - if(access_cent_teleporter) - return "Code Blue" - if(access_cent_specops) - return "Code Black" - if(access_cent_creed) - return "Code Silver" - if(access_cent_captain) - return "Code Gold" - -/proc/get_all_jobs() - var/list/all_jobs = list() - var/list/all_datums = typesof(/datum/job) - all_datums.Remove(list(/datum/job,/datum/job/ai,/datum/job/cyborg)) - var/datum/job/jobdatum - for(var/jobtype in all_datums) - jobdatum = new jobtype - 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", - "Emergency Response Team", - "Emergency Response Team Leader", - "NanoTrasen Representative") - -//gets the actual job rank (ignoring alt titles) -//this is used solely for sechuds -/obj/proc/GetJobRealName() - if (!istype(src, /obj/item/device/pda) && !istype(src,/obj/item/weapon/card/id)) - return - - var/rank - var/assignment - if(istype(src, /obj/item/device/pda)) - if(src:id) - rank = src:id:rank - assignment = src:id:assignment - else if(istype(src, /obj/item/weapon/card/id)) - rank = src:rank - assignment = src:assignment - - if( rank in joblist ) - return rank - - if( assignment in joblist ) - return assignment - - return "Unknown" - -//gets the alt title, failing that the actual job rank -//this is unused -/obj/proc/sdsdsd() //GetJobDisplayName - if (!istype(src, /obj/item/device/pda) && !istype(src,/obj/item/weapon/card/id)) - return - - var/assignment - if(istype(src, /obj/item/device/pda)) - if(src:id) - assignment = src:id:assignment - else if(istype(src, /obj/item/weapon/card/id)) - assignment = src:assignment - - if(assignment) - return assignment - - return "Unknown" - -proc/FindNameFromID(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 joblist + list("Prisoner") - -/obj/proc/GetJobName() //Used in secHUD icon generation - if (!istype(src, /obj/item/device/pda) && !istype(src,/obj/item/weapon/card/id)) - return - - var/jobName - var/alt - if(istype(src, /obj/item/device/pda)) - var/obj/item/device/pda/P = src - if(P.id) - jobName = P.id.rank - alt = P.id.assignment - if(istype(src, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/I = src - jobName = I.rank - alt = I.assignment - if(alt in get_alternate_titles(jobName)) - return alt - if(jobName in get_all_job_icons()) //Check if the job has a hud icon - return jobName - if(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 +/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 +/var/const/access_tox_storage = 8 +/var/const/access_genetics = 9 +/var/const/access_engine = 10 +/var/const/access_engine_equip= 11 +/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 +/var/const/access_construction = 32 +/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 +/var/const/access_mining = 48 +/var/const/access_mining_office = 49 //not in use +/var/const/access_mailsorting = 50 +/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_xenoarch = 65 +/var/const/access_minisat = 66 +/var/const/access_recycler = 67 +/var/const/access_detective = 68 +/var/const/access_barber = 69 +/var/const/access_paramedic = 70 + + //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//Special Ops. +/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. +/var/const/access_cent_captain = 109//Captain's office/ID comp/AI. + + //The Syndicate +/var/const/access_syndicate = 150//General Syndicate Access +/var/const/access_syndicate_commander = 151 //Syndicate Commander Access + + //MONEY +/var/const/access_crate_cash = 200 + +/obj/var/list/req_access = null +/obj/var/req_access_txt = "0" +/obj/var/list/req_one_access = null +/obj/var/req_one_access_txt = "0" + +//returns 1 if this mob has sufficient access to use this object +/obj/proc/allowed(mob/M) + //check if it doesn't require any access at all + if(src.check_access(null)) + return TRUE + if(issilicon(M)) + var/mob/living/silicon/S = M + if(src.check_access(S)) + return TRUE + if(IsAdminGhost(M)) + //Access can't stop the abuse + return TRUE + else if(ishuman(M)) + 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.get_active_hand()) || src.check_access(H.wear_id)) + return TRUE + else if(isIAN(M)) + var/mob/living/carbon/ian/IAN = M + if(src.check_access(IAN.mouth) || src.check_access(IAN.neck)) + return TRUE + else if(ismonkey(M) || isalienadult(M)) + var/mob/living/carbon/george = M + //they can only hold things :( + if(src.check_access(george.get_active_hand())) + return TRUE + return FALSE + +/atom/movable/proc/GetAccess() + return list() + +/mob/living/silicon/GetAccess() + return get_all_accesses() + +/mob/living/silicon/robot/syndicate/GetAccess() + return list(access_maint_tunnels, access_syndicate, access_external_airlocks) //syndicate basic access + +/obj/item/proc/GetID() + return null + +/obj/proc/check_access(atom/movable/AM) + if(istype(src, /obj/machinery)) + var/obj/machinery/Machine = src + if(Machine.emagged) + return TRUE + + //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(!islist(req_access)) + req_access = list() + if(req_access_txt) + var/list/req_access_str = splittext(req_access_txt,";") + for(var/x in req_access_str) + var/n = text2num(x) + if(n) + req_access += n + + if(!islist(req_one_access)) + req_one_access = list() + if(req_one_access_txt) + var/list/req_one_access_str = splittext(req_one_access_txt,";") + for(var/x in req_one_access_str) + var/n = text2num(x) + if(n) + req_one_access += n + + if(!req_access.len && !req_one_access.len) //no requirements + return TRUE + if(!AM) + return FALSE + for(var/req in req_access) + if(!(req in AM.GetAccess())) //doesn't have this access + return FALSE + if(req_one_access.len) + for(var/req in src.req_one_access) + if(req in AM.GetAccess()) //has an access from the single access list + return TRUE + return FALSE + return TRUE + +/obj/proc/check_access_list(list/L) + if(!islist(req_access)) + req_access = list() + if(req_access_txt) + var/list/req_access_str = splittext(req_access_txt,";") + for(var/x in req_access_str) + var/n = text2num(x) + if(n) + req_access += n + + if(!islist(req_one_access)) + req_one_access = list() + if(req_one_access_txt) + var/list/req_one_access_str = splittext(req_one_access_txt,";") + for(var/x in req_one_access_str) + var/n = text2num(x) + if(n) + req_one_access += n + + if(!req_access.len && !req_one_access.len) + return TRUE + if(!islist(L)) + return FALSE + for(var/req in req_access) + if(!(req in L)) //doesn't have this access + return FALSE + if(req_one_access.len) + for(var/req in req_one_access) + if(req in L) //has an access from the single access list + return TRUE + return FALSE + return TRUE + +/proc/get_centcom_access(job) + switch(job) + if("VIP Guest") + return list(access_cent_general) + if("Custodian") + return list(access_cent_general, access_cent_living, access_cent_storage) + if("Thunderdome Overseer") + return list(access_cent_general, access_cent_thunder) + if("Intel Officer") + return list(access_cent_general, access_cent_living) + if("Medical Officer") + return list(access_cent_general, access_cent_living, access_cent_medical) + if("Death Commando") + return list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage) + if("Research Officer") + return list(access_cent_general, access_cent_specops, access_cent_medical, access_cent_teleporter, access_cent_storage) + if("BlackOps Commander") + return list(access_cent_general, access_cent_thunder, access_cent_specops, access_cent_living, access_cent_storage, access_cent_creed) + if("Supreme Commander") + return get_all_centcom_access() + +/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_heads_vault, access_mining_station, access_xenobiology, access_ce, access_hop, access_hos, access_RC_announce, + access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_minisat, access_recycler, access_detective, access_barber, access_paramedic) + +/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_region_accesses(code) + switch(code) + if(0) + return get_all_accesses() + if(1) //security + return list(access_sec_doors, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_hos, access_detective) + if(2) //medbay + return list(access_medical, access_genetics, access_morgue, access_chemistry, access_psychiatrist, access_virology, access_surgery, access_cmo, access_paramedic) + if(3) //research + return list(access_research, access_tox, access_tox_storage, access_robotics, access_xenobiology, access_xenoarch, access_minisat, 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_atmospherics, access_minisat, 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_barber, 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_recycler, access_qm) + +/proc/get_region_accesses_name(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_recycler) + return "Recycler" + if(access_detective) + return "Detective" + 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 Chambers" + 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 "IAA 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_xenoarch) + return "Xenoarchaeology" + 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" + if(access_minisat) + return "AI Satellite" + if(access_barber) + return "Barber" + if(access_paramedic) + return "Paramedic" + +/proc/get_centcom_access_desc(A) + switch(A) + if(access_cent_general) + return "Code Grey" + if(access_cent_thunder) + return "Code Yellow" + if(access_cent_storage) + return "Code Orange" + if(access_cent_living) + return "Code Green" + if(access_cent_medical) + return "Code White" + if(access_cent_teleporter) + return "Code Blue" + if(access_cent_specops) + return "Code Black" + if(access_cent_creed) + return "Code Silver" + if(access_cent_captain) + return "Code Gold" + +/proc/get_all_jobs() + var/list/all_jobs = list() + var/list/all_datums = typesof(/datum/job) + all_datums.Remove(list(/datum/job,/datum/job/ai,/datum/job/cyborg)) + var/datum/job/jobdatum + for(var/jobtype in all_datums) + jobdatum = new jobtype + 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", + "Emergency Response Team", + "Emergency Response Team Leader", + "NanoTrasen Representative") + +//gets the actual job rank (ignoring alt titles) +//this is used solely for sechuds +/obj/proc/GetJobRealName() + if (!istype(src, /obj/item/device/pda) && !istype(src,/obj/item/weapon/card/id)) + return + + var/rank + var/assignment + if(istype(src, /obj/item/device/pda)) + if(src:id) + rank = src:id:rank + assignment = src:id:assignment + else if(istype(src, /obj/item/weapon/card/id)) + rank = src:rank + assignment = src:assignment + + if( rank in joblist ) + return rank + + if( assignment in joblist ) + return assignment + + return "Unknown" + +//gets the alt title, failing that the actual job rank +//this is unused +/obj/proc/sdsdsd() //GetJobDisplayName + if (!istype(src, /obj/item/device/pda) && !istype(src,/obj/item/weapon/card/id)) + return + + var/assignment + if(istype(src, /obj/item/device/pda)) + if(src:id) + assignment = src:id:assignment + else if(istype(src, /obj/item/weapon/card/id)) + assignment = src:assignment + + if(assignment) + return assignment + + return "Unknown" + +proc/FindNameFromID(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 joblist + list("Prisoner") + +/obj/proc/GetJobName() //Used in secHUD icon generation + if (!istype(src, /obj/item/device/pda) && !istype(src,/obj/item/weapon/card/id)) + return + + var/jobName + var/alt + if(istype(src, /obj/item/device/pda)) + var/obj/item/device/pda/P = src + if(P.id) + jobName = P.id.rank + alt = P.id.assignment + if(istype(src, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/I = src + jobName = I.rank + alt = I.assignment + if(alt in get_alternate_titles(jobName)) + return alt + if(jobName in get_all_job_icons()) //Check if the job has a hud icon + return jobName + if(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 diff --git a/code/game/jobs/job/assistant.dm b/code/game/jobs/job/assistant.dm index 4b204b854bfa..2fea80529a63 100644 --- a/code/game/jobs/job/assistant.dm +++ b/code/game/jobs/job/assistant.dm @@ -1,82 +1,82 @@ -/datum/job/assistant - title = "Test Subject" - 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() - alt_titles = list("Technical Assistant","Medical Intern","Research Assistant","Security Cadet", - "Lawyer","Mecha Operator","Private Eye","Reporter","Security Cadet","Waiter","Vice Officer","Paranormal Investigator") - -/datum/job/assistant/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) - return 0 - - if(visualsOnly) - H.equip_to_slot_or_del(new /obj/item/clothing/under/fluff/jane_sidsuit(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - return - - if (H.mind.role_alt_title) - switch(H.mind.role_alt_title) - if("Technical Assistant") - H.equip_to_slot_or_del(new /obj/item/clothing/under/color/yellow(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/yellow(H), slot_shoes) - if("Medical Intern") - H.equip_to_slot_or_del(new /obj/item/clothing/under/lightblue(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/blue(H), slot_shoes) - if("Research Assistant") - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist_new(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - if("Lawyer") - H.equip_to_slot_or_del(new /obj/item/clothing/under/lawyer/bluesuit(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/lawyer/bluejacket(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/device/pda/lawyer2(H), slot_belt) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase(H), slot_l_hand) - if("Mecha Operator") - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/mecha_operator(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/gloves/fingerless(H), slot_gloves) - H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) - if("Private Eye") - H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/leathercoat(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) - H.equip_to_slot_or_del(new /obj/item/weapon/lighter/zippo(H), slot_l_store) - if("Reporter") - H.equip_to_slot_or_del(new /obj/item/clothing/under/lawyer/black(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/device/pda/reporter(H), slot_belt) - if("Security Cadet") - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cadet(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) - if("Test Subject") - H.equip_to_slot_or_del(new /obj/item/clothing/under/fluff/jane_sidsuit(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - if("Waiter") - H.equip_to_slot_or_del(new /obj/item/clothing/under/waiter(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - if("Vice Officer") - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/vice (H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) - if("Paranormal Investigator") - H.equip_to_slot_or_del(new /obj/item/clothing/under/fluff/indiana (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(new /obj/item/clothing/head/indiana(H), slot_head) - H.equip_to_slot_or_del(new /obj/item/device/occult_scanner(H), slot_l_store) - H.equip_to_slot_or_del(new /obj/item/weapon/occult_pinpointer(H), slot_r_store) - - return TRUE - -/datum/job/assistant/get_access() - if(config.assistant_maint) - return list(access_maint_tunnels) - else - return list() +/datum/job/assistant + title = "Test Subject" + 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() + alt_titles = list("Technical Assistant","Medical Intern","Research Assistant","Security Cadet", + "Lawyer","Mecha Operator","Private Eye","Reporter","Security Cadet","Waiter","Vice Officer","Paranormal Investigator") + +/datum/job/assistant/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) + return 0 + + if(visualsOnly) + H.equip_to_slot_or_del(new /obj/item/clothing/under/fluff/jane_sidsuit(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + return + + if (H.mind.role_alt_title) + switch(H.mind.role_alt_title) + if("Technical Assistant") + H.equip_to_slot_or_del(new /obj/item/clothing/under/color/yellow(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/yellow(H), slot_shoes) + if("Medical Intern") + H.equip_to_slot_or_del(new /obj/item/clothing/under/lightblue(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/blue(H), slot_shoes) + if("Research Assistant") + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist_new(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) + if("Lawyer") + H.equip_to_slot_or_del(new /obj/item/clothing/under/lawyer/bluesuit(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/lawyer/bluejacket(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/device/pda/lawyer2(H), slot_belt) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase(H), slot_l_hand) + if("Mecha Operator") + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/mecha_operator(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/gloves/fingerless(H), slot_gloves) + H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) + if("Private Eye") + H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/leathercoat(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) + H.equip_to_slot_or_del(new /obj/item/weapon/lighter/zippo(H), slot_l_store) + if("Reporter") + H.equip_to_slot_or_del(new /obj/item/clothing/under/lawyer/black(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/device/pda/reporter(H), slot_belt) + if("Security Cadet") + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cadet(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + if("Test Subject") + H.equip_to_slot_or_del(new /obj/item/clothing/under/fluff/jane_sidsuit(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + if("Waiter") + H.equip_to_slot_or_del(new /obj/item/clothing/under/waiter(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + if("Vice Officer") + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/vice (H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) + if("Paranormal Investigator") + H.equip_to_slot_or_del(new /obj/item/clothing/under/fluff/indiana (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(new /obj/item/clothing/head/indiana(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/device/occult_scanner(H), slot_l_store) + H.equip_to_slot_or_del(new /obj/item/weapon/occult_pinpointer(H), slot_r_store) + + return TRUE + +/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 bb543f1a5024..57fe16edacd1 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -1,448 +1,448 @@ -//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 = "#d7b088" - idtype = /obj/item/weapon/card/id/cargoGold - access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station, access_recycler) - minimal_player_ingame_minutes = 1200 - restricted_species = list(TAJARAN, DIONA) - -/datum/job/qm/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - if(H.gender == FEMALE) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargo_fem(H), slot_w_uniform) - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargo(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(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/quartermaster(H), slot_belt) - - return TRUE - - -/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 = "#d7b088" - idtype = /obj/item/weapon/card/id/cargo - access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting) - minimal_player_ingame_minutes = 960 - restricted_species = list(SKRELL, DIONA) - - -/datum/job/cargo_tech/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargotech(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/cargo(H), slot_belt) - - return TRUE - - -/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 = "#d7b088" - idtype = /obj/item/weapon/card/id/cargo - access = list(access_mining, access_mint, access_mining_station, access_mailsorting) - minimal_player_ingame_minutes = 960 - restricted_species = list(SKRELL) - -/datum/job/mining/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/miner(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo (H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/shaftminer(H), slot_belt) - H.equip_to_slot_or_del(new /obj/item/weapon/mining_voucher(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/survivalcapsule(H), slot_in_backpack) - - return TRUE - - -/datum/job/recycler - title = "Recycler" - flag = RECYCLER - department_flag = CIVILIAN - faction = "Station" - total_positions = 2 - spawn_positions = 2 - supervisors = "the quartermaster and the head of personnel" - selection_color = "#d7b088" - idtype = /obj/item/weapon/card/id/cargo - access = list(access_mining, access_mint, access_mailsorting, access_recycler) - minimal_player_ingame_minutes = 960 - restricted_species = list(SKRELL) - -/datum/job/recycler/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/recycler(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/recyclervest/(H), slot_wear_suit) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/cargo(H), slot_belt) - - return TRUE - -//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 = "#bbe291" - idtype = /obj/item/weapon/card/id/civ - access = list(access_bar) - minimal_player_ingame_minutes = 480 - restricted_species = list(TAJARAN) - -/datum/job/bartender/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - if(H.gender == FEMALE) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender_fem(H), slot_w_uniform) - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender(H), slot_w_uniform) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/pda/bar(H), slot_belt) - if(H.backbag == 1) - var/obj/item/weapon/storage/box/Barpack = new /obj/item/weapon/storage/box(H) - H.equip_to_slot_or_del(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_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) - - return TRUE - - -/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 = "#bbe291" - idtype = /obj/item/weapon/card/id/civ - access = list(access_kitchen) - alt_titles = list("Cook") - minimal_player_ingame_minutes = 480 - restricted_species = list(TAJARAN, SKRELL) - -/datum/job/chef/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chef(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/pda/chef(H), slot_belt) - - return TRUE - - -/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 = "#bbe291" - idtype = /obj/item/weapon/card/id/civ - access = list(access_hydroponics) // 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") - minimal_player_ingame_minutes = 480 - restricted_species = list(SKRELL) - -/datum/job/hydro/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - switch(H.backbag) - if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_hyd(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/hyd(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - if(H.gender == FEMALE) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/hydroponics_fem(H), slot_w_uniform) - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/hydroponics(H), slot_w_uniform) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/pda/botanist(H), slot_belt) - - return TRUE - - -/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 = "#bbe291" - idtype = /obj/item/weapon/card/id/civ - access = list(access_janitor, access_maint_tunnels) - minimal_player_ingame_minutes = 480 - restricted_species = list(SKRELL) - -/datum/job/janitor/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/janitor(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/pda/janitor(H), slot_belt) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - else - H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) - - return TRUE - - -//More or less assistants -/datum/job/barber - title = "Barber" - flag = BARBER - department_flag = CIVILIAN - faction = "Station" - total_positions = 1 - spawn_positions = 1 - supervisors = "the head of personnel" - selection_color = "#bbe291" - idtype = /obj/item/weapon/card/id/civ - access = list(access_barber) - alt_titles = list("Stylist") - minimal_player_ingame_minutes = 480 - -/datum/job/barber/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) - return FALSE - - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), slot_shoes) - - if(visualsOnly) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/barber(H), slot_w_uniform) - return - - if(H.mind.role_alt_title) - switch(H.mind.role_alt_title) - if("Barber") - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/barber(H), slot_w_uniform) - if("Stylist") - H.equip_to_slot_or_del(new /obj/item/clothing/under/lawyer/purpsuit(H), slot_w_uniform) - - H.equip_to_slot_or_del(new /obj/item/device/pda/barber(H), slot_belt) - - return TRUE - -/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" - idtype = /obj/item/weapon/card/id/civ - access = list(access_library) - alt_titles = list("Journalist") - minimal_player_ingame_minutes = 480 - -/datum/job/librarian/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket/red(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/weapon/barcodescanner(H), slot_l_hand) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/weapon/storage/bag/bookbag(H), slot_belt) - H.equip_to_slot_or_del(new /obj/item/device/pda/librarian(H), slot_r_store) - - return TRUE - - -//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" - total_positions = 2 - spawn_positions = 2 - supervisors = "The Central Command" - selection_color = "#dddddd" - idtype = /obj/item/weapon/card/id/int - access = list(access_lawyer, access_court, access_sec_doors, access_medical, access_research, access_mailsorting, access_engine, access_engine_equip) - minimal_player_ingame_minutes = 1560 - restricted_species = list(UNATHI, TAJARAN, DIONA) - -/datum/job/lawyer/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/internalaffairs(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/internalaffairs(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/big(H), slot_glasses) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase/centcomm(H), slot_l_hand) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_r_store) - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_int(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/lawyer(H), slot_belt) - - var/obj/item/weapon/implant/mindshield/loyalty/L = new(H) - L.inject(H) - START_PROCESSING(SSobj, L) - return TRUE - - -/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) - minimal_player_ingame_minutes = 480 - restricted_species = list(SKRELL) - -/datum/job/clown/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/clown(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/pda/clown(H), slot_belt) - H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/stamp/clown(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/toy/crayon/rainbow(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/fancy/crayons(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/toy/waterflower(H), slot_in_backpack) - H.mutations.Add(CLUMSY) - return TRUE - - -/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) - restricted_species = list(SKRELL) - -/datum/job/mime/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/mime(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/mime(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(H), slot_gloves) - H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/mime(H), slot_wear_mask) - H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/pda/mime(H), slot_belt) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/toy/crayon/mime(H), slot_l_store) - H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_l_hand) - else - H.equip_to_slot_or_del(new /obj/item/toy/crayon/mime(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_in_backpack) - H.verbs += /client/proc/mimespeak - H.verbs += /client/proc/mimewall - H.mind.special_verbs += /client/proc/mimespeak - H.mind.special_verbs += /client/proc/mimewall - H.miming = 1 - return TRUE +//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 = "#d7b088" + idtype = /obj/item/weapon/card/id/cargoGold + access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station, access_recycler) + minimal_player_ingame_minutes = 1200 + restricted_species = list(TAJARAN, DIONA) + +/datum/job/qm/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + if(H.gender == FEMALE) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargo_fem(H), slot_w_uniform) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargo(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(new /obj/item/clothing/glasses/sunglasses(H), slot_glasses) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/quartermaster(H), slot_belt) + + return TRUE + + +/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 = "#d7b088" + idtype = /obj/item/weapon/card/id/cargo + access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting) + minimal_player_ingame_minutes = 960 + restricted_species = list(SKRELL, DIONA) + + +/datum/job/cargo_tech/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargotech(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/cargo(H), slot_belt) + + return TRUE + + +/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 = "#d7b088" + idtype = /obj/item/weapon/card/id/cargo + access = list(access_mining, access_mint, access_mining_station, access_mailsorting) + minimal_player_ingame_minutes = 960 + restricted_species = list(SKRELL) + +/datum/job/mining/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/miner(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo (H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/shaftminer(H), slot_belt) + H.equip_to_slot_or_del(new /obj/item/weapon/mining_voucher(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/weapon/survivalcapsule(H), slot_in_backpack) + + return TRUE + + +/datum/job/recycler + title = "Recycler" + flag = RECYCLER + department_flag = CIVILIAN + faction = "Station" + total_positions = 2 + spawn_positions = 2 + supervisors = "the quartermaster and the head of personnel" + selection_color = "#d7b088" + idtype = /obj/item/weapon/card/id/cargo + access = list(access_mining, access_mint, access_mailsorting, access_recycler) + minimal_player_ingame_minutes = 960 + restricted_species = list(SKRELL) + +/datum/job/recycler/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/recycler(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/recyclervest/(H), slot_wear_suit) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/cargo(H), slot_belt) + + return TRUE + +//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 = "#bbe291" + idtype = /obj/item/weapon/card/id/civ + access = list(access_bar) + minimal_player_ingame_minutes = 480 + restricted_species = list(TAJARAN) + +/datum/job/bartender/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + if(H.gender == FEMALE) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender_fem(H), slot_w_uniform) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender(H), slot_w_uniform) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/pda/bar(H), slot_belt) + if(H.backbag == 1) + var/obj/item/weapon/storage/box/Barpack = new /obj/item/weapon/storage/box(H) + H.equip_to_slot_or_del(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_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/ammo_casing/shotgun/beanbag(H), slot_in_backpack) + + return TRUE + + +/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 = "#bbe291" + idtype = /obj/item/weapon/card/id/civ + access = list(access_kitchen) + alt_titles = list("Cook") + minimal_player_ingame_minutes = 480 + restricted_species = list(TAJARAN, SKRELL) + +/datum/job/chef/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chef(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/pda/chef(H), slot_belt) + + return TRUE + + +/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 = "#bbe291" + idtype = /obj/item/weapon/card/id/civ + access = list(access_hydroponics) // 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") + minimal_player_ingame_minutes = 480 + restricted_species = list(SKRELL) + +/datum/job/hydro/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + switch(H.backbag) + if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_hyd(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/hyd(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(H.gender == FEMALE) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/hydroponics_fem(H), slot_w_uniform) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/hydroponics(H), slot_w_uniform) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/pda/botanist(H), slot_belt) + + return TRUE + + +/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 = "#bbe291" + idtype = /obj/item/weapon/card/id/civ + access = list(access_janitor, access_maint_tunnels) + minimal_player_ingame_minutes = 480 + restricted_species = list(SKRELL) + +/datum/job/janitor/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/janitor(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/pda/janitor(H), slot_belt) + if(H.backbag == 1) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) + else + H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) + + return TRUE + + +//More or less assistants +/datum/job/barber + title = "Barber" + flag = BARBER + department_flag = CIVILIAN + faction = "Station" + total_positions = 1 + spawn_positions = 1 + supervisors = "the head of personnel" + selection_color = "#bbe291" + idtype = /obj/item/weapon/card/id/civ + access = list(access_barber) + alt_titles = list("Stylist") + minimal_player_ingame_minutes = 480 + +/datum/job/barber/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) + return FALSE + + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), slot_shoes) + + if(visualsOnly) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/barber(H), slot_w_uniform) + return + + if(H.mind.role_alt_title) + switch(H.mind.role_alt_title) + if("Barber") + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/barber(H), slot_w_uniform) + if("Stylist") + H.equip_to_slot_or_del(new /obj/item/clothing/under/lawyer/purpsuit(H), slot_w_uniform) + + H.equip_to_slot_or_del(new /obj/item/device/pda/barber(H), slot_belt) + + return TRUE + +/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" + idtype = /obj/item/weapon/card/id/civ + access = list(access_library) + alt_titles = list("Journalist") + minimal_player_ingame_minutes = 480 + +/datum/job/librarian/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket/red(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/weapon/barcodescanner(H), slot_l_hand) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/weapon/storage/bag/bookbag(H), slot_belt) + H.equip_to_slot_or_del(new /obj/item/device/pda/librarian(H), slot_r_store) + + return TRUE + + +//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" + total_positions = 2 + spawn_positions = 2 + supervisors = "The Central Command" + selection_color = "#dddddd" + idtype = /obj/item/weapon/card/id/int + access = list(access_lawyer, access_court, access_sec_doors, access_medical, access_research, access_mailsorting, access_engine, access_engine_equip) + minimal_player_ingame_minutes = 1560 + restricted_species = list(UNATHI, TAJARAN, DIONA) + +/datum/job/lawyer/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/internalaffairs(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/internalaffairs(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/big(H), slot_glasses) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase/centcomm(H), slot_l_hand) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_r_store) + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_int(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/lawyer(H), slot_belt) + + var/obj/item/weapon/implant/mindshield/loyalty/L = new(H) + L.inject(H) + START_PROCESSING(SSobj, L) + return TRUE + + +/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) + minimal_player_ingame_minutes = 480 + restricted_species = list(SKRELL) + +/datum/job/clown/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/clown(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/pda/clown(H), slot_belt) + H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/weapon/stamp/clown(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/toy/crayon/rainbow(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/fancy/crayons(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/toy/waterflower(H), slot_in_backpack) + H.mutations.Add(CLUMSY) + return TRUE + + +/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) + restricted_species = list(SKRELL) + +/datum/job/mime/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/mime(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/mime(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(H), slot_gloves) + H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/mime(H), slot_wear_mask) + H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/pda/mime(H), slot_belt) + if(H.backbag == 1) + H.equip_to_slot_or_del(new /obj/item/toy/crayon/mime(H), slot_l_store) + H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_l_hand) + else + H.equip_to_slot_or_del(new /obj/item/toy/crayon/mime(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_in_backpack) + H.verbs += /client/proc/mimespeak + H.verbs += /client/proc/mimewall + H.mind.special_verbs += /client/proc/mimespeak + H.mind.special_verbs += /client/proc/mimewall + H.miming = 1 + return TRUE diff --git a/code/game/jobs/job/civilian_chaplain.dm b/code/game/jobs/job/civilian_chaplain.dm index 4809c29585dd..5925726a7b8d 100644 --- a/code/game/jobs/job/civilian_chaplain.dm +++ b/code/game/jobs/job/civilian_chaplain.dm @@ -1,155 +1,155 @@ -//Due to how large this one is it gets its own file -/datum/job/chaplain - title = "Chaplain" - flag = CHAPLAIN - 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/civ - access = list(access_morgue, access_chapel_office, access_crematorium) - alt_titles = list("Counselor") - minimal_player_ingame_minutes = 480 - -/datum/job/chaplain/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(H) //BS12 EDIT - H.equip_to_slot_or_del(B, slot_l_hand) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chaplain(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/pda/chaplain(H), slot_belt) - - spawn(0) - var/religion_name = "Christianity" - var/new_religion = sanitize_safe(input(H, "You are the crew services officer. Would you like to change your religion? Default is Christianity, in SPACE.", "Name change", religion_name), MAX_NAME_LEN) - - if (!new_religion) - new_religion = religion_name - - switch(lowertext(new_religion)) - if("christianity") - B.name = pick("The Holy Bible","The Dead Sea Scrolls") - if("satanism") - B.name = "The Unholy Bible" - if("cthulu") - B.name = "The Necronomicon" - if("islam") - B.name = "Quran" - if("scientology") - B.name = pick("The Biography of L. Ron Hubbard","Dianetics") - if("chaos") - B.name = "The Book of Lorgar" - if("imperium") - B.name = "Uplifting Primer" - if("toolboxia") - B.name = "Toolbox Manifesto" - if("homosexuality") - B.name = "Guys Gone Wild" - //if("lol", "wtf", "gay", "penis", "ass", "poo", "badmin", "shitmin", "deadmin", "cock", "cocks") - // B.name = pick("Woodys Got Wood: The Aftermath", "War of the Cocks", "Sweet Bro and Hella Jef: Expanded Edition") - // H.setBrainLoss(100) // starts off retarded as fuck - if("science") - B.name = pick("Principle of Relativity", "Quantum Enigma: Physics Encounters Consciousness", "Programming the Universe", "Quantum Physics and Theology", "String Theory for Dummies", "How To: Build Your Own Warp Drive", "The Mysteries of Bluespace", "Playing God: Collector's Edition") - else - B.name = "The Holy Book of [new_religion]" - feedback_set_details("religion_name","[new_religion]") - - spawn(1) - var/deity_name = "Space Jesus" - var/new_deity = sanitize_safe(input(H, "Would you like to change your deity? Default is Space Jesus.", "Name change", deity_name), MAX_NAME_LEN) - - if ((length(new_deity) == 0) || (new_deity == "Space Jesus") ) - new_deity = deity_name - 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", "Necronomicon") - switch(new_book_style) - if("Koran") - B.icon_state = "koran" - B.item_state = "koran" - for(var/area/chapel/main/A in all_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 all_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" - if("Scientology") - B.icon_state = "scientology" - B.item_state = "scientology" - for(var/area/chapel/main/A in all_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("Necronomicon") - B.icon_state = "necronomicon" - B.item_state = "necronomicon" - else - // if christian bible, revert to default - B.icon_state = "bible" - B.item_state = "bible" - for(var/area/chapel/main/A in all_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. 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 TRUE +//Due to how large this one is it gets its own file +/datum/job/chaplain + title = "Chaplain" + flag = CHAPLAIN + 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/civ + access = list(access_morgue, access_chapel_office, access_crematorium) + alt_titles = list("Counselor") + minimal_player_ingame_minutes = 480 + +/datum/job/chaplain/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(H) //BS12 EDIT + H.equip_to_slot_or_del(B, slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chaplain(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/pda/chaplain(H), slot_belt) + + spawn(0) + var/religion_name = "Christianity" + var/new_religion = sanitize_safe(input(H, "You are the crew services officer. Would you like to change your religion? Default is Christianity, in SPACE.", "Name change", religion_name), MAX_NAME_LEN) + + if (!new_religion) + new_religion = religion_name + + switch(lowertext(new_religion)) + if("christianity") + B.name = pick("The Holy Bible","The Dead Sea Scrolls") + if("satanism") + B.name = "The Unholy Bible" + if("cthulu") + B.name = "The Necronomicon" + if("islam") + B.name = "Quran" + if("scientology") + B.name = pick("The Biography of L. Ron Hubbard","Dianetics") + if("chaos") + B.name = "The Book of Lorgar" + if("imperium") + B.name = "Uplifting Primer" + if("toolboxia") + B.name = "Toolbox Manifesto" + if("homosexuality") + B.name = "Guys Gone Wild" + //if("lol", "wtf", "gay", "penis", "ass", "poo", "badmin", "shitmin", "deadmin", "cock", "cocks") + // B.name = pick("Woodys Got Wood: The Aftermath", "War of the Cocks", "Sweet Bro and Hella Jef: Expanded Edition") + // H.setBrainLoss(100) // starts off retarded as fuck + if("science") + B.name = pick("Principle of Relativity", "Quantum Enigma: Physics Encounters Consciousness", "Programming the Universe", "Quantum Physics and Theology", "String Theory for Dummies", "How To: Build Your Own Warp Drive", "The Mysteries of Bluespace", "Playing God: Collector's Edition") + else + B.name = "The Holy Book of [new_religion]" + feedback_set_details("religion_name","[new_religion]") + + spawn(1) + var/deity_name = "Space Jesus" + var/new_deity = sanitize_safe(input(H, "Would you like to change your deity? Default is Space Jesus.", "Name change", deity_name), MAX_NAME_LEN) + + if ((length(new_deity) == 0) || (new_deity == "Space Jesus") ) + new_deity = deity_name + 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", "Necronomicon") + switch(new_book_style) + if("Koran") + B.icon_state = "koran" + B.item_state = "koran" + for(var/area/chapel/main/A in all_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 all_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" + if("Scientology") + B.icon_state = "scientology" + B.item_state = "scientology" + for(var/area/chapel/main/A in all_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("Necronomicon") + B.icon_state = "necronomicon" + B.item_state = "necronomicon" + else + // if christian bible, revert to default + B.icon_state = "bible" + B.item_state = "bible" + for(var/area/chapel/main/A in all_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. 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 TRUE diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index b61410d7d0a0..7ff17c263a10 100644 --- a/code/game/jobs/job/engineering.dm +++ b/code/game/jobs/job/engineering.dm @@ -1,138 +1,138 @@ -/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/engGold - 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_minisat, - access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload - ) - minimal_player_age = 7 - minimal_player_ingame_minutes = 2400 - restricted_species = list(UNATHI, TAJARAN, DIONA, IPC) - -/datum/job/chief_engineer/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_engineer(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/white(H), slot_head) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt) - H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/ce(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/heads/ce(H), slot_l_store) - - return TRUE - - -/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/eng - 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") - minimal_player_age = 3 - minimal_player_ingame_minutes = 540 - restricted_species = list(IPC) - -/datum/job/engineer/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt) - if(prob(75)) - H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/yellow(H), slot_head) - else - H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/yellow/visor(H), slot_head) - H.equip_to_slot_or_del(new /obj/item/device/t_scanner(H), slot_r_store) - H.equip_to_slot_or_del(new /obj/item/device/pda/engineering(H), slot_l_store) - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(H), slot_l_ear) - - return TRUE - - -/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/eng - access = list(access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction, access_external_airlocks) - minimal_player_age = 3 - minimal_player_ingame_minutes = 600 - -/datum/job/atmos/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/atmospheric_technician(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/device/pda/atmos(H), slot_l_store) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/atmostech/(H), slot_belt) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(H), slot_l_ear) - - return TRUE - -/proc/get_airlock_wires_identification() - var/list/wire_list = same_wires[/obj/machinery/door/airlock] - var/list/wire_functions_list = list( - "[AIRLOCK_WIRE_IDSCAN]" = "ID scan", - "[AIRLOCK_WIRE_MAIN_POWER1]" = "main power", - "[AIRLOCK_WIRE_MAIN_POWER2]" = "backup power", - "[AIRLOCK_WIRE_DOOR_BOLTS]" = "door Bolts", - "[AIRLOCK_WIRE_OPEN_DOOR]" = "open door", - "[AIRLOCK_WIRE_AI_CONTROL]" = "ai control", - "[AIRLOCK_WIRE_ELECTRIFY]" = "electrify", - "[AIRLOCK_WIRE_SAFETY]" = "door safety", - "[AIRLOCK_WIRE_SPEED]" = "timing mechanism", - "[AIRLOCK_WIRE_LIGHT]" = "bolt light" - ) - - var/info = "" - - for(var/wire in wire_list) - var/current_wire_index = wire_list[wire] - var/current_wire_function = wire_functions_list["[current_wire_index]"] - - if(current_wire_function) - info += "[capitalize(wire)] wire is [current_wire_function].
    " - +/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/engGold + 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_minisat, + access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload + ) + minimal_player_age = 7 + minimal_player_ingame_minutes = 2400 + restricted_species = list(UNATHI, TAJARAN, DIONA, IPC) + +/datum/job/chief_engineer/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_engineer(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/white(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt) + H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/ce(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/heads/ce(H), slot_l_store) + + return TRUE + + +/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/eng + 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") + minimal_player_age = 3 + minimal_player_ingame_minutes = 540 + restricted_species = list(IPC) + +/datum/job/engineer/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt) + if(prob(75)) + H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/yellow(H), slot_head) + else + H.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/yellow/visor(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/device/t_scanner(H), slot_r_store) + H.equip_to_slot_or_del(new /obj/item/device/pda/engineering(H), slot_l_store) + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(H), slot_l_ear) + + return TRUE + + +/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/eng + access = list(access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction, access_external_airlocks) + minimal_player_age = 3 + minimal_player_ingame_minutes = 600 + +/datum/job/atmos/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/eng(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/atmospheric_technician(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/device/pda/atmos(H), slot_l_store) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/atmostech/(H), slot_belt) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(H), slot_l_ear) + + return TRUE + +/proc/get_airlock_wires_identification() + var/list/wire_list = same_wires[/obj/machinery/door/airlock] + var/list/wire_functions_list = list( + "[AIRLOCK_WIRE_IDSCAN]" = "ID scan", + "[AIRLOCK_WIRE_MAIN_POWER1]" = "main power", + "[AIRLOCK_WIRE_MAIN_POWER2]" = "backup power", + "[AIRLOCK_WIRE_DOOR_BOLTS]" = "door Bolts", + "[AIRLOCK_WIRE_OPEN_DOOR]" = "open door", + "[AIRLOCK_WIRE_AI_CONTROL]" = "ai control", + "[AIRLOCK_WIRE_ELECTRIFY]" = "electrify", + "[AIRLOCK_WIRE_SAFETY]" = "door safety", + "[AIRLOCK_WIRE_SPEED]" = "timing mechanism", + "[AIRLOCK_WIRE_LIGHT]" = "bolt light" + ) + + var/info = "" + + for(var/wire in wire_list) + var/current_wire_index = wire_list[wire] + var/current_wire_function = wire_functions_list["[current_wire_index]"] + + if(current_wire_function) + info += "[capitalize(wire)] wire is [current_wire_function].
    " + return info \ No newline at end of file diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index d1b83e14e2e2..0430672d1065 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -1,158 +1,158 @@ -/datum/job - - //The name of the job - var/title = "NOPE" - - var/list/access = list() - - //Bitflags for the job - var/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 - - //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_ingame_minutes ingame minutes old. (meaning they must play a game.) - var/minimal_player_ingame_minutes = 0 - - //Should we spawn and give him his selected loadout items - var/give_loadout_items = TRUE - - var/list/restricted_species = list() - -/datum/job/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - return TRUE - -/datum/job/proc/get_access() - return 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(config.use_ingame_minutes_restriction_for_jobs) - if(available_in_real_minutes(C) == 0) - return 1 //Available in 0 minutes = available right now = player is old enough to play. - else - 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/is_species_permitted(client/C) - if(!config.use_alien_job_restriction) - return TRUE - return !(C.prefs.species in restricted_species) - -/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) - -/datum/job/proc/available_in_real_minutes(client/C) - if(!C) - return 0 - if(C.holder || C.deadmin_holder) - return 0 - if(!config.use_age_restriction_for_jobs) - return 0 - if(!isnum(C.player_ingame_age)) - return 0 - if(!isnum(minimal_player_ingame_minutes)) - return 0 - - return max(0, minimal_player_ingame_minutes - C.player_ingame_age) - -//Not sure where to put this proc, lets leave it here for now. -/proc/role_available_in_minutes(mob/M, role) - if(!M || !istype(M) || !M.ckey) - return 0 - var/client/C = M.client - if(!C) - return 0 - if(C.holder || C.deadmin_holder) - return 0 - if(!config.use_age_restriction_for_jobs) - return 0 - if(!config.use_ingame_minutes_restriction_for_jobs) - return 0 - if(!isnum(C.player_ingame_age)) - return 0 - if(!(role in roles_ingame_minute_unlock)) - return 0 - - return max(0, roles_ingame_minute_unlock[role] - C.player_ingame_age) - -/datum/job/proc/apply_fingerprints(mob/living/carbon/human/H) - if(!istype(H)) - return - if(H.back) - H.back.add_fingerprint(H,1) //The 1 sets a flag to ignore gloves - for(var/obj/item/I in H.back.contents) - I.add_fingerprint(H,1) - if(H.wear_id) - H.wear_id.add_fingerprint(H,1) - if(H.w_uniform) - H.w_uniform.add_fingerprint(H,1) - if(H.wear_suit) - H.wear_suit.add_fingerprint(H,1) - if(H.wear_mask) - H.wear_mask.add_fingerprint(H,1) - if(H.head) - H.head.add_fingerprint(H,1) - if(H.shoes) - H.shoes.add_fingerprint(H,1) - if(H.gloves) - H.gloves.add_fingerprint(H,1) - if(H.l_ear) - H.l_ear.add_fingerprint(H,1) - if(H.r_ear) - H.r_ear.add_fingerprint(H,1) - if(H.glasses) - H.glasses.add_fingerprint(H,1) - if(H.belt) - H.belt.add_fingerprint(H,1) - for(var/obj/item/I in H.belt.contents) - I.add_fingerprint(H,1) - if(H.s_store) - H.s_store.add_fingerprint(H,1) - if(H.l_store) - H.l_store.add_fingerprint(H,1) - if(H.r_store) - H.r_store.add_fingerprint(H,1) - return 1 - -/datum/job/proc/is_position_available() - return (current_positions < total_positions) || (total_positions == -1) +/datum/job + + //The name of the job + var/title = "NOPE" + + var/list/access = list() + + //Bitflags for the job + var/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 + + //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_ingame_minutes ingame minutes old. (meaning they must play a game.) + var/minimal_player_ingame_minutes = 0 + + //Should we spawn and give him his selected loadout items + var/give_loadout_items = TRUE + + var/list/restricted_species = list() + +/datum/job/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + return TRUE + +/datum/job/proc/get_access() + return 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(config.use_ingame_minutes_restriction_for_jobs) + if(available_in_real_minutes(C) == 0) + return 1 //Available in 0 minutes = available right now = player is old enough to play. + else + 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/is_species_permitted(client/C) + if(!config.use_alien_job_restriction) + return TRUE + return !(C.prefs.species in restricted_species) + +/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) + +/datum/job/proc/available_in_real_minutes(client/C) + if(!C) + return 0 + if(C.holder || C.deadmin_holder) + return 0 + if(!config.use_age_restriction_for_jobs) + return 0 + if(!isnum(C.player_ingame_age)) + return 0 + if(!isnum(minimal_player_ingame_minutes)) + return 0 + + return max(0, minimal_player_ingame_minutes - C.player_ingame_age) + +//Not sure where to put this proc, lets leave it here for now. +/proc/role_available_in_minutes(mob/M, role) + if(!M || !istype(M) || !M.ckey) + return 0 + var/client/C = M.client + if(!C) + return 0 + if(C.holder || C.deadmin_holder) + return 0 + if(!config.use_age_restriction_for_jobs) + return 0 + if(!config.use_ingame_minutes_restriction_for_jobs) + return 0 + if(!isnum(C.player_ingame_age)) + return 0 + if(!(role in roles_ingame_minute_unlock)) + return 0 + + return max(0, roles_ingame_minute_unlock[role] - C.player_ingame_age) + +/datum/job/proc/apply_fingerprints(mob/living/carbon/human/H) + if(!istype(H)) + return + if(H.back) + H.back.add_fingerprint(H,1) //The 1 sets a flag to ignore gloves + for(var/obj/item/I in H.back.contents) + I.add_fingerprint(H,1) + if(H.wear_id) + H.wear_id.add_fingerprint(H,1) + if(H.w_uniform) + H.w_uniform.add_fingerprint(H,1) + if(H.wear_suit) + H.wear_suit.add_fingerprint(H,1) + if(H.wear_mask) + H.wear_mask.add_fingerprint(H,1) + if(H.head) + H.head.add_fingerprint(H,1) + if(H.shoes) + H.shoes.add_fingerprint(H,1) + if(H.gloves) + H.gloves.add_fingerprint(H,1) + if(H.l_ear) + H.l_ear.add_fingerprint(H,1) + if(H.r_ear) + H.r_ear.add_fingerprint(H,1) + if(H.glasses) + H.glasses.add_fingerprint(H,1) + if(H.belt) + H.belt.add_fingerprint(H,1) + for(var/obj/item/I in H.belt.contents) + I.add_fingerprint(H,1) + if(H.s_store) + H.s_store.add_fingerprint(H,1) + if(H.l_store) + H.l_store.add_fingerprint(H,1) + if(H.r_store) + H.r_store.add_fingerprint(H,1) + return 1 + +/datum/job/proc/is_position_available() + return (current_positions < total_positions) || (total_positions == -1) diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index 65bbe9766056..12304abc4247 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -1,282 +1,282 @@ -/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/medGold - req_admin_notify = 1 - access = list( - access_medical, access_morgue, access_paramedic, access_genetics, access_heads, - access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, - access_keycard_auth, access_sec_doors, access_psychiatrist, access_maint_tunnels - ) - minimal_player_age = 10 - minimal_player_ingame_minutes = 2400 - restricted_species = list(UNATHI, TAJARAN, DIONA) - -/datum/job/cmo/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/med(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_medical_officer(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(new /obj/item/device/pda/heads/cmo(H), slot_belt) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/cmo(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand) - H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/cmo(H), slot_l_ear) - - return TRUE - - -/datum/job/doctor - title = "Medical Doctor" - flag = DOCTOR - department_flag = MEDSCI - faction = "Station" - total_positions = 4 - spawn_positions = 3 - supervisors = "the chief medical officer" - selection_color = "#ffeef0" - idtype = /obj/item/weapon/card/id/med - access = list(access_medical, access_morgue, access_surgery, access_maint_tunnels) - alt_titles = list("Surgeon", "Nurse") - minimal_player_ingame_minutes = 960 - restricted_species = list(UNATHI, TAJARAN, DIONA) - -/datum/job/doctor/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/med(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand) - H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) - - if(visualsOnly) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) - if (H.mind.role_alt_title) - switch(H.mind.role_alt_title) - if("Surgeon") - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical/blue(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/head/surgery/blue(H), slot_head) - - if("Medical Doctor") - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - - if("Nurse") - if(H.gender == FEMALE) - if(prob(50)) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/nursesuit(H), slot_w_uniform) - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/nurse(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/head/nursehat(H), slot_head) - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical/purple(H), slot_w_uniform) - - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - - H.equip_to_slot_or_del(new /obj/item/device/pda/medical(H), slot_belt) - - return TRUE - -/datum/job/paramedic - title = "Paramedic" - flag = PARAMEDIC - 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/med - access = list(access_medical, access_morgue, access_paramedic, access_maint_tunnels, access_external_airlocks, access_sec_doors, access_engine_equip, access_research, access_mailsorting) - minimal_player_ingame_minutes = 1500 //they have too much access, so you have to play more to unlock it - restricted_species = list(IPC, DIONA) - -/datum/job/paramedic/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/fr_jacket(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/medical(H), slot_belt) - switch(H.backbag) - if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/med(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - - return TRUE - - -//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/med - access = list(access_medical, access_chemistry) - alt_titles = list("Pharmacist") - minimal_player_ingame_minutes = 960 - -/datum/job/chemist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chemist(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/chemist(H), slot_wear_suit) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/chemist(H), slot_belt) - switch(H.backbag) - if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_chem(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/chem(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - - return TRUE - - -/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/med - access = list(access_medical, access_morgue, access_genetics, access_research) - minimal_player_ingame_minutes = 960 - restricted_species = list(UNATHI, TAJARAN, DIONA) - -/datum/job/geneticist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/geneticist(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/genetics(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_medsci(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/geneticist(H), slot_belt) - switch(H.backbag) - if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_gen(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/gen(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - - return TRUE - - -/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" - idtype = /obj/item/weapon/card/id/med - access = list(access_medical, access_virology) - alt_titles = list("Pathologist","Microbiologist") - minimal_player_ingame_minutes = 960 - restricted_species = list(SKRELL, UNATHI, TAJARAN, DIONA) - -/datum/job/virologist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/virologist(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(H), slot_wear_mask) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/virologist(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/viro(H), slot_belt) - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_vir(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/vir(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - - return TRUE - - -/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" - idtype = /obj/item/weapon/card/id/med - access = list(access_medical, access_psychiatrist) - alt_titles = list("Psychologist") - minimal_player_ingame_minutes = 960 - restricted_species = list(UNATHI) - -/datum/job/psychiatrist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), slot_shoes) - - if(visualsOnly) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) - if (H.mind.role_alt_title) - switch(H.mind.role_alt_title) - if("Psychiatrist") - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/psych(H), slot_w_uniform) - if("Psychologist") - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/psych/turtleneck(H), slot_w_uniform) - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/device/pda/medical(H), slot_belt) - - return TRUE +/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/medGold + req_admin_notify = 1 + access = list( + access_medical, access_morgue, access_paramedic, access_genetics, access_heads, + access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, + access_keycard_auth, access_sec_doors, access_psychiatrist, access_maint_tunnels + ) + minimal_player_age = 10 + minimal_player_ingame_minutes = 2400 + restricted_species = list(UNATHI, TAJARAN, DIONA) + +/datum/job/cmo/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/med(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_medical_officer(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(new /obj/item/device/pda/heads/cmo(H), slot_belt) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/cmo(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/cmo(H), slot_l_ear) + + return TRUE + + +/datum/job/doctor + title = "Medical Doctor" + flag = DOCTOR + department_flag = MEDSCI + faction = "Station" + total_positions = 4 + spawn_positions = 3 + supervisors = "the chief medical officer" + selection_color = "#ffeef0" + idtype = /obj/item/weapon/card/id/med + access = list(access_medical, access_morgue, access_surgery, access_maint_tunnels) + alt_titles = list("Surgeon", "Nurse") + minimal_player_ingame_minutes = 960 + restricted_species = list(UNATHI, TAJARAN, DIONA) + +/datum/job/doctor/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/med(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) + + if(visualsOnly) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) + if (H.mind.role_alt_title) + switch(H.mind.role_alt_title) + if("Surgeon") + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical/blue(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/head/surgery/blue(H), slot_head) + + if("Medical Doctor") + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + + if("Nurse") + if(H.gender == FEMALE) + if(prob(50)) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/nursesuit(H), slot_w_uniform) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/nurse(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/head/nursehat(H), slot_head) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical/purple(H), slot_w_uniform) + + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + + H.equip_to_slot_or_del(new /obj/item/device/pda/medical(H), slot_belt) + + return TRUE + +/datum/job/paramedic + title = "Paramedic" + flag = PARAMEDIC + 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/med + access = list(access_medical, access_morgue, access_paramedic, access_maint_tunnels, access_external_airlocks, access_sec_doors, access_engine_equip, access_research, access_mailsorting) + minimal_player_ingame_minutes = 1500 //they have too much access, so you have to play more to unlock it + restricted_species = list(IPC, DIONA) + +/datum/job/paramedic/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/fr_jacket(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/medical(H), slot_belt) + switch(H.backbag) + if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/med(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + + return TRUE + + +//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/med + access = list(access_medical, access_chemistry) + alt_titles = list("Pharmacist") + minimal_player_ingame_minutes = 960 + +/datum/job/chemist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chemist(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/chemist(H), slot_wear_suit) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/chemist(H), slot_belt) + switch(H.backbag) + if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_chem(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/chem(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + + return TRUE + + +/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/med + access = list(access_medical, access_morgue, access_genetics, access_research) + minimal_player_ingame_minutes = 960 + restricted_species = list(UNATHI, TAJARAN, DIONA) + +/datum/job/geneticist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/geneticist(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/genetics(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_medsci(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/geneticist(H), slot_belt) + switch(H.backbag) + if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_gen(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/gen(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + + return TRUE + + +/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" + idtype = /obj/item/weapon/card/id/med + access = list(access_medical, access_virology) + alt_titles = list("Pathologist","Microbiologist") + minimal_player_ingame_minutes = 960 + restricted_species = list(SKRELL, UNATHI, TAJARAN, DIONA) + +/datum/job/virologist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/virologist(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(H), slot_wear_mask) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/virologist(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/viro(H), slot_belt) + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_vir(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/vir(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + + return TRUE + + +/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" + idtype = /obj/item/weapon/card/id/med + access = list(access_medical, access_psychiatrist) + alt_titles = list("Psychologist") + minimal_player_ingame_minutes = 960 + restricted_species = list(UNATHI) + +/datum/job/psychiatrist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), slot_shoes) + + if(visualsOnly) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(H), slot_l_ear) + if (H.mind.role_alt_title) + switch(H.mind.role_alt_title) + if("Psychiatrist") + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/psych(H), slot_w_uniform) + if("Psychologist") + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/psych/turtleneck(H), slot_w_uniform) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/device/pda/medical(H), slot_belt) + + return TRUE diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index aaade838453b..c5bbca773fb5 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -1,179 +1,179 @@ -/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/sciGold - 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_minisat, - access_research, access_robotics, access_xenobiology, access_ai_upload, - access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_maint_tunnels - ) - minimal_player_age = 7 - minimal_player_ingame_minutes = 2400 - restricted_species = list(UNATHI, TAJARAN, DIONA, IPC) - -/datum/job/rd/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/research_director(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/rd(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/heads/rd(H), slot_belt) - switch(H.backbag) - if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_tox(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - - return TRUE - - -/datum/job/scientist - title = "Scientist" - flag = SCIENTIST - department_flag = MEDSCI - faction = "Station" - total_positions = 3 - spawn_positions = 2 - supervisors = "the research director" - selection_color = "#ffeeff" - idtype = /obj/item/weapon/card/id/sci - access = list(access_tox, access_tox_storage, access_research, access_xenoarch) - alt_titles = list("Phoron Researcher") - minimal_player_ingame_minutes = 1560 - restricted_species = list(UNATHI, DIONA) - -/datum/job/scientist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/science(H), slot_belt) - switch(H.mind.role_alt_title) - if("Scientist") - access = list(access_tox, access_research) - if("Phoron Researcher") - access = list(access_research, access_tox_storage) - - switch(H.backbag) - if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_tox(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - - return TRUE - -/datum/job/xenoarchaeologist - title = "Xenoarchaeologist" - flag = XENOARCHAEOLOGIST - department_flag = MEDSCI - faction = "Station" - total_positions = 2 - spawn_positions = 2 - supervisors = "the research director" - selection_color = "#ffeeff" - idtype = /obj/item/weapon/card/id/sci - access = list(access_research, access_xenoarch) - minimal_player_ingame_minutes = 1400 - -/datum/job/xenoarchaeologist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/science(H), slot_belt) - - switch(H.backbag) - if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_tox(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - - return TRUE - -/datum/job/xenobiologist - title = "Xenobiologist" - flag = XENOBIOLOGIST - department_flag = MEDSCI - faction = "Station" - total_positions = 2 - spawn_positions = 2 - supervisors = "the research director" - selection_color = "#ffeeff" - idtype = /obj/item/weapon/card/id/sci - access = list(access_research, access_xenobiology) - minimal_player_ingame_minutes = 1560 - -/datum/job/xenobiologist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/science(H), slot_belt) - switch(H.backbag) - if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_tox(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - - return TRUE - - -/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/sci - access = list(access_robotics, 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") - minimal_player_ingame_minutes = 1560 - -/datum/job/roboticist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - if(H.backbag == 2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) - if(H.backbag == 3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) - if(H.gender == FEMALE) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/roboticist_fem(H), slot_w_uniform) - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/roboticist(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/roboticist(H), slot_belt) - - return TRUE +/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/sciGold + 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_minisat, + access_research, access_robotics, access_xenobiology, access_ai_upload, + access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_maint_tunnels + ) + minimal_player_age = 7 + minimal_player_ingame_minutes = 2400 + restricted_species = list(UNATHI, TAJARAN, DIONA, IPC) + +/datum/job/rd/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/research_director(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/rd(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/heads/rd(H), slot_belt) + switch(H.backbag) + if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_tox(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + + return TRUE + + +/datum/job/scientist + title = "Scientist" + flag = SCIENTIST + department_flag = MEDSCI + faction = "Station" + total_positions = 3 + spawn_positions = 2 + supervisors = "the research director" + selection_color = "#ffeeff" + idtype = /obj/item/weapon/card/id/sci + access = list(access_tox, access_tox_storage, access_research, access_xenoarch) + alt_titles = list("Phoron Researcher") + minimal_player_ingame_minutes = 1560 + restricted_species = list(UNATHI, DIONA) + +/datum/job/scientist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/science(H), slot_belt) + switch(H.mind.role_alt_title) + if("Scientist") + access = list(access_tox, access_research) + if("Phoron Researcher") + access = list(access_research, access_tox_storage) + + switch(H.backbag) + if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_tox(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + + return TRUE + +/datum/job/xenoarchaeologist + title = "Xenoarchaeologist" + flag = XENOARCHAEOLOGIST + department_flag = MEDSCI + faction = "Station" + total_positions = 2 + spawn_positions = 2 + supervisors = "the research director" + selection_color = "#ffeeff" + idtype = /obj/item/weapon/card/id/sci + access = list(access_research, access_xenoarch) + minimal_player_ingame_minutes = 1400 + +/datum/job/xenoarchaeologist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/science(H), slot_belt) + + switch(H.backbag) + if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_tox(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + + return TRUE + +/datum/job/xenobiologist + title = "Xenobiologist" + flag = XENOBIOLOGIST + department_flag = MEDSCI + faction = "Station" + total_positions = 2 + spawn_positions = 2 + supervisors = "the research director" + selection_color = "#ffeeff" + idtype = /obj/item/weapon/card/id/sci + access = list(access_research, access_xenobiology) + minimal_player_ingame_minutes = 1560 + +/datum/job/xenobiologist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(H), slot_wear_suit) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/science(H), slot_belt) + switch(H.backbag) + if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/backpack_tox(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/tox(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + + return TRUE + + +/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/sci + access = list(access_robotics, 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") + minimal_player_ingame_minutes = 1560 + +/datum/job/roboticist/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + if(H.backbag == 2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) + if(H.backbag == 3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) + if(H.gender == FEMALE) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/roboticist_fem(H), slot_w_uniform) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/roboticist(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/roboticist(H), slot_belt) + + return TRUE diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 73fb6c46bad3..e3daefe1ed87 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -1,220 +1,220 @@ -/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/secGold - req_admin_notify = 1 - 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, access_detective - ) - minimal_player_age = 14 - minimal_player_ingame_minutes = 2400 - restricted_species = list(TAJARAN, DIONA, IPC) - -/datum/job/hos/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/sec(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - if(H.gender == FEMALE) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security_fem(H), slot_w_uniform) - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) - H.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(H), slot_s_store) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_r_store) - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/hos(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/heads/hos(H), slot_belt) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_l_store) - else - H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack) - var/obj/item/weapon/implant/mindshield/loyalty/L = new(H) - L.inject(H) - START_PROCESSING(SSobj, L) - return TRUE - - -/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/sec - access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels) - minimal_player_age = 5 - minimal_player_ingame_minutes = 1800 - restricted_species = list(TAJARAN, DIONA, IPC) - -/datum/job/warden/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/sec(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - if(H.gender == FEMALE) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden_fem(H), slot_w_uniform) - else - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) - H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_l_store) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/warden(H), slot_belt) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_l_hand) - else - H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack) - - var/obj/item/weapon/implant/mindshield/L = new(H) - L.inject(H) - - return TRUE - - -/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/sec - access = list(access_security, access_sec_doors, access_detective, access_maint_tunnels, access_court) - minimal_player_age = 3 - minimal_player_ingame_minutes = 1560 - restricted_species = list(DIONA, IPC) - -/datum/job/detective/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/det(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(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_suit(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/head/det_hat(H), slot_head) - H.equip_to_slot_or_del(new /obj/item/weapon/lighter/zippo(H), slot_l_store) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/detective(H), slot_belt) - if(H.backbag == 1)//Why cant some of these things spawn in his office? - H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_l_hand) - H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_r_store) - else - H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_in_backpack) - - return TRUE - - -/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/sec - access = list(access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels) - minimal_player_age = 3 - minimal_player_ingame_minutes = 1560 - restricted_species = list(DIONA, TAJARAN, IPC) - -/datum/job/officer/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/sec(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/security(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_s_store) - H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_l_store) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/security(H), slot_belt) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_l_hand) - else - H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack) - - var/obj/item/weapon/implant/mindshield/L = new(H) - L.inject(H) - - return TRUE - -/datum/job/forensic - title = "Forensic Technician" - flag = FORENSIC - 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/sec - access = list(access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court) - minimal_player_age = 3 - minimal_player_ingame_minutes = 1560 - -/datum/job/forensic/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - switch(H.backbag) - if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) - if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) - if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) - H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/forensic_technician(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/red(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/forensics/red(H), slot_wear_suit) - - if(visualsOnly) - return - - H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(H), slot_l_ear) - H.equip_to_slot_or_del(new /obj/item/device/pda/forensic(H), slot_belt) - if(H.backbag == 1) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_l_hand) - H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_r_store) - else - H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack) - H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_in_backpack) - - return TRUE +/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/secGold + req_admin_notify = 1 + 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, access_detective + ) + minimal_player_age = 14 + minimal_player_ingame_minutes = 2400 + restricted_species = list(TAJARAN, DIONA, IPC) + +/datum/job/hos/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/sec(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(H.gender == FEMALE) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security_fem(H), slot_w_uniform) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) + H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) + H.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(H), slot_s_store) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_r_store) + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/hos(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/heads/hos(H), slot_belt) + if(H.backbag == 1) + H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_l_store) + else + H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack) + var/obj/item/weapon/implant/mindshield/loyalty/L = new(H) + L.inject(H) + START_PROCESSING(SSobj, L) + return TRUE + + +/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/sec + access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels) + minimal_player_age = 5 + minimal_player_ingame_minutes = 1800 + restricted_species = list(TAJARAN, DIONA, IPC) + +/datum/job/warden/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/sec(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + if(H.gender == FEMALE) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden_fem(H), slot_w_uniform) + else + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) + H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) + H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_l_store) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/warden(H), slot_belt) + if(H.backbag == 1) + H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_l_hand) + else + H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack) + + var/obj/item/weapon/implant/mindshield/L = new(H) + L.inject(H) + + return TRUE + + +/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/sec + access = list(access_security, access_sec_doors, access_detective, access_maint_tunnels, access_court) + minimal_player_age = 3 + minimal_player_ingame_minutes = 1560 + restricted_species = list(DIONA, IPC) + +/datum/job/detective/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/det(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(new /obj/item/clothing/gloves/black(H), slot_gloves) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_suit(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/head/det_hat(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/weapon/lighter/zippo(H), slot_l_store) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/detective(H), slot_belt) + if(H.backbag == 1)//Why cant some of these things spawn in his office? + H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_r_store) + else + H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_in_backpack) + + return TRUE + + +/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/sec + access = list(access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels) + minimal_player_age = 3 + minimal_player_ingame_minutes = 1560 + restricted_species = list(DIONA, TAJARAN, IPC) + +/datum/job/officer/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/sec(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/security(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_s_store) + H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_l_store) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/security(H), slot_belt) + if(H.backbag == 1) + H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_l_hand) + else + H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack) + + var/obj/item/weapon/implant/mindshield/L = new(H) + L.inject(H) + + return TRUE + +/datum/job/forensic + title = "Forensic Technician" + flag = FORENSIC + 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/sec + access = list(access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court) + minimal_player_age = 3 + minimal_player_ingame_minutes = 1560 + +/datum/job/forensic/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + switch(H.backbag) + if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back) + if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(H), slot_back) + if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) + H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/forensic_technician(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/red(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/forensics/red(H), slot_wear_suit) + + if(visualsOnly) + return + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(H), slot_l_ear) + H.equip_to_slot_or_del(new /obj/item/device/pda/forensic(H), slot_belt) + if(H.backbag == 1) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_r_store) + else + H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack) + H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_in_backpack) + + return TRUE diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm index 588cc75ffde7..2117b26d2b2a 100644 --- a/code/game/jobs/job/silicon.dm +++ b/code/game/jobs/job/silicon.dm @@ -1,47 +1,47 @@ -/datum/job/ai - title = "AI" - flag = AI - department_flag = ENGSEC - faction = "Station" - total_positions = 0 - spawn_positions = 1 - selection_color = "#ccffcc" - supervisors = "your laws" - req_admin_notify = 1 - minimal_player_age = 7 - minimal_player_ingame_minutes = 2400 - give_loadout_items = FALSE - -/datum/job/ai/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - - if(visualsOnly) - return - - return 1 - -/datum/job/ai/is_position_available() - return (empty_playable_ai_cores.len != 0) - - -/datum/job/cyborg - title = "Cyborg" - flag = CYBORG - department_flag = ENGSEC - faction = "Station" - total_positions = 0 // Not used for AI, see is_position_available below and modules/mob/living/silicon/ai/latejoin.dm - spawn_positions = 2 - supervisors = "your laws and the AI" //Nodrak - selection_color = "#ddffdd" - minimal_player_age = 1 - alt_titles = list("Android", "Robot") - minimal_player_ingame_minutes = 1800 - give_loadout_items = FALSE - -/datum/job/cyborg/equip(mob/living/carbon/human/H, visualsOnly = FALSE) - if(!H) return 0 - - if(visualsOnly) - return - - return 1 +/datum/job/ai + title = "AI" + flag = AI + department_flag = ENGSEC + faction = "Station" + total_positions = 0 + spawn_positions = 1 + selection_color = "#ccffcc" + supervisors = "your laws" + req_admin_notify = 1 + minimal_player_age = 7 + minimal_player_ingame_minutes = 2400 + give_loadout_items = FALSE + +/datum/job/ai/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + + if(visualsOnly) + return + + return 1 + +/datum/job/ai/is_position_available() + return (empty_playable_ai_cores.len != 0) + + +/datum/job/cyborg + title = "Cyborg" + flag = CYBORG + department_flag = ENGSEC + faction = "Station" + total_positions = 0 // Not used for AI, see is_position_available below and modules/mob/living/silicon/ai/latejoin.dm + spawn_positions = 2 + supervisors = "your laws and the AI" //Nodrak + selection_color = "#ddffdd" + minimal_player_age = 1 + alt_titles = list("Android", "Robot") + minimal_player_ingame_minutes = 1800 + give_loadout_items = FALSE + +/datum/job/cyborg/equip(mob/living/carbon/human/H, visualsOnly = FALSE) + if(!H) return 0 + + if(visualsOnly) + return + + return 1 diff --git a/code/game/jobs/jobprocs.dm b/code/game/jobs/jobprocs.dm index 8e91c521626c..7ef4dc731f29 100644 --- a/code/game/jobs/jobprocs.dm +++ b/code/game/jobs/jobprocs.dm @@ -1,55 +1,55 @@ - - -//TODO: put these somewhere else -/client/proc/mimewall() - set category = "Mime" - set name = "Invisible wall" - set desc = "Create an invisible wall on your location." - if(usr.stat) - to_chat(usr, "Not when you're incapicated.") - return - if(!ishuman(usr)) - return - - var/mob/living/carbon/human/H = usr - - if(!H.miming) - to_chat(usr, "You still haven't atoned for your speaking transgression. Wait.") - return - addtimer(CALLBACK(GLOBAL_PROC, /client/proc/return_mimewall, H), 300) - H.visible_message("[H] looks as if a wall is in front of them.", "You form a wall in front of yourself.") - H.verbs -= /client/proc/mimewall - H.mind.special_verbs -= /client/proc/mimewall - new /obj/effect/forcefield/magic/mime(get_turf(H), H, 300) - -/client/proc/return_mimewall(mob/living/carbon/human/H) - H.verbs += /client/proc/mimewall - if(H.mind) - H.mind.special_verbs += /client/proc/mimewall - -///////////Mimewalls/////////// - -/obj/effect/forcefield/magic/mime - icon_state = "empty" - name = "invisible wall" - desc = "You have a bad feeling about this." - -/////////////////////////////// - -/client/proc/mimespeak() - set category = "Mime" - set name = "Speech" - set desc = "Toggle your speech." - if(!ishuman(usr)) - return - - var/mob/living/carbon/human/H = usr - - if(H.miming) - H.miming = 0 - else - to_chat(H, "You'll have to wait if you want to atone for your sins.") - addtimer(CALLBACK(GLOBAL_PROC, /client/proc/return_speech, H), 3000) - -/client/proc/return_speech(mob/living/carbon/human/H) - H.miming = 1 + + +//TODO: put these somewhere else +/client/proc/mimewall() + set category = "Mime" + set name = "Invisible wall" + set desc = "Create an invisible wall on your location." + if(usr.stat) + to_chat(usr, "Not when you're incapicated.") + return + if(!ishuman(usr)) + return + + var/mob/living/carbon/human/H = usr + + if(!H.miming) + to_chat(usr, "You still haven't atoned for your speaking transgression. Wait.") + return + addtimer(CALLBACK(GLOBAL_PROC, /client/proc/return_mimewall, H), 300) + H.visible_message("[H] looks as if a wall is in front of them.", "You form a wall in front of yourself.") + H.verbs -= /client/proc/mimewall + H.mind.special_verbs -= /client/proc/mimewall + new /obj/effect/forcefield/magic/mime(get_turf(H), H, 300) + +/client/proc/return_mimewall(mob/living/carbon/human/H) + H.verbs += /client/proc/mimewall + if(H.mind) + H.mind.special_verbs += /client/proc/mimewall + +///////////Mimewalls/////////// + +/obj/effect/forcefield/magic/mime + icon_state = "empty" + name = "invisible wall" + desc = "You have a bad feeling about this." + +/////////////////////////////// + +/client/proc/mimespeak() + set category = "Mime" + set name = "Speech" + set desc = "Toggle your speech." + if(!ishuman(usr)) + return + + var/mob/living/carbon/human/H = usr + + if(H.miming) + H.miming = 0 + else + to_chat(H, "You'll have to wait if you want to atone for your sins.") + addtimer(CALLBACK(GLOBAL_PROC, /client/proc/return_speech, H), 3000) + +/client/proc/return_speech(mob/living/carbon/human/H) + H.miming = 1 diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index 1d406fd376ff..54f943641937 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -1,151 +1,151 @@ - -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/AI =(1<<8) -var/const/CYBORG =(1<<9) -var/const/FORENSIC =(1<<10) - - -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/ROBOTICIST =(1<<8) -var/const/XENOBIOLOGIST =(1<<9) -var/const/PARAMEDIC =(1<<10) -var/const/XENOARCHAEOLOGIST =(1<<11) - - -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/const/RECYCLER =(1<<14) -var/const/BARBER =(1<<15) - -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", -) - - -var/list/medical_positions = list( - "Chief Medical Officer", - "Medical Doctor", - "Geneticist", - "Psychiatrist", - "Chemist", - "Virologist", - "Paramedic" -) - - -var/list/science_positions = list( - "Research Director", - "Scientist", - "Geneticist", //Part of both medical and science - "Roboticist", - "Xenobiologist", - "Xenoarchaeologist" -) - -//BS12 EDIT -var/list/civilian_positions = list( - "Head of Personnel", - "Barber", - "Bartender", - "Botanist", - "Chef", - "Janitor", - "Librarian", - "Quartermaster", - "Cargo Technician", - "Shaft Miner", - "Recycler", - "Internal Affairs Agent", - "Chaplain", - "Test Subject", - "Clown", - "Mime" -) - -var/list/security_positions = list( - "Head of Security", - "Warden", - "Detective", - "Security Officer", - "Forensic Technician" -) - - -var/list/nonhuman_positions = list( - "AI", - "Cyborg", - "pAI" -) - - -/proc/guest_jobbans(job) - return job in command_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(job) - var/list/jobs = get_job_datums() - var/list/titles = list() - - for(var/datum/job/J in jobs) - 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/AI =(1<<8) +var/const/CYBORG =(1<<9) +var/const/FORENSIC =(1<<10) + + +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/ROBOTICIST =(1<<8) +var/const/XENOBIOLOGIST =(1<<9) +var/const/PARAMEDIC =(1<<10) +var/const/XENOARCHAEOLOGIST =(1<<11) + + +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/const/RECYCLER =(1<<14) +var/const/BARBER =(1<<15) + +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", +) + + +var/list/medical_positions = list( + "Chief Medical Officer", + "Medical Doctor", + "Geneticist", + "Psychiatrist", + "Chemist", + "Virologist", + "Paramedic" +) + + +var/list/science_positions = list( + "Research Director", + "Scientist", + "Geneticist", //Part of both medical and science + "Roboticist", + "Xenobiologist", + "Xenoarchaeologist" +) + +//BS12 EDIT +var/list/civilian_positions = list( + "Head of Personnel", + "Barber", + "Bartender", + "Botanist", + "Chef", + "Janitor", + "Librarian", + "Quartermaster", + "Cargo Technician", + "Shaft Miner", + "Recycler", + "Internal Affairs Agent", + "Chaplain", + "Test Subject", + "Clown", + "Mime" +) + +var/list/security_positions = list( + "Head of Security", + "Warden", + "Detective", + "Security Officer", + "Forensic Technician" +) + + +var/list/nonhuman_positions = list( + "AI", + "Cyborg", + "pAI" +) + + +/proc/guest_jobbans(job) + return job in command_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(job) + var/list/jobs = get_job_datums() + var/list/titles = list() + + for(var/datum/job/J in jobs) + 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 82d1c43ad541..2eff8138bea0 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -1,50 +1,50 @@ -var/list/whitelist = list() - -/proc/load_whitelist() - whitelist = file2list("config/whitelist.txt") - if(!whitelist.len) whitelist = null - -/proc/check_whitelist(mob/M /*, rank*/) -// if(!whitelist) -// return 0 -// return ("[M.ckey]" in whitelist) - for (var/s in whitelist) - if(findtext(s,"[M.ckey]")) - return 1 - return 0 - -/client/proc/get_whitelist() - set category = "Server" - set name = "Whitelist: Check" - if(!check_rights(R_ADMIN)) - return - - var/path = "config/whitelist.txt" - if(fexists(path)) - src << run(file(path)) - else - to_chat(src, "Error: get_whitelist(): File not found/Invalid path([path]).") - return - feedback_add_details("admin_verb","GWL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - - -/client/proc/add_to_whitelist() - set category = "Server" - set name = "Whitelist: Add" - if(!check_rights(R_ADMIN)) - return - - var/path = "config/whitelist.txt" - var/player = ckey(input("Input player byound key", "\n") as text) - if(length(player) == 0) - return - player += " ,added by [src.key]\n" - if(fexists(path)) - text2file(player,path) - load_whitelist() - else - to_chat(src, "Error: get_whitelist(): File not found/Invalid path([path]).") - log_admin("Whitelist: [player]") - message_admins("Whitelist: [player]", 1) - return +var/list/whitelist = list() + +/proc/load_whitelist() + whitelist = file2list("config/whitelist.txt") + if(!whitelist.len) whitelist = null + +/proc/check_whitelist(mob/M /*, rank*/) +// if(!whitelist) +// return 0 +// return ("[M.ckey]" in whitelist) + for (var/s in whitelist) + if(findtext(s,"[M.ckey]")) + return 1 + return 0 + +/client/proc/get_whitelist() + set category = "Server" + set name = "Whitelist: Check" + if(!check_rights(R_ADMIN)) + return + + var/path = "config/whitelist.txt" + if(fexists(path)) + src << run(file(path)) + else + to_chat(src, "Error: get_whitelist(): File not found/Invalid path([path]).") + return + feedback_add_details("admin_verb","GWL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + + +/client/proc/add_to_whitelist() + set category = "Server" + set name = "Whitelist: Add" + if(!check_rights(R_ADMIN)) + return + + var/path = "config/whitelist.txt" + var/player = ckey(input("Input player byound key", "\n") as text) + if(length(player) == 0) + return + player += " ,added by [src.key]\n" + if(fexists(path)) + text2file(player,path) + load_whitelist() + else + to_chat(src, "Error: get_whitelist(): File not found/Invalid path([path]).") + log_admin("Whitelist: [player]") + message_admins("Whitelist: [player]", 1) + return diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index ff97a65cb467..7610f8381ec6 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -1,148 +1,148 @@ -/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 - - var/obj/machinery/computer/operating/computer = null - -/obj/machinery/optable/atom_init() - . = ..() - for(dir in list(NORTH,EAST,SOUTH,WEST)) - computer = locate(/obj/machinery/computer/operating, get_step(src, dir)) - if (computer) - computer.table = src - 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) - if ((HULK in usr.mutations)) - user.SetNextMove(CLICK_CD_MELEE) - to_chat(usr, text("You destroy the operating table.")) - visible_message("[usr] destroys the operating table!") - src.density = 0 - qdel(src) - return - -/obj/machinery/optable/attack_hand(mob/user) - if (HULK in usr.mutations) - user.SetNextMove(CLICK_CD_MELEE) - to_chat(usr, text("You destroy the table.")) - visible_message("[usr] destroys the operating table!") - src.density = 0 - qdel(src) - else - return ..() // for fun, for braindamage and fingerprints. - -/obj/machinery/optable/CanPass(atom/movable/mover, turf/target, height=0, 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(obj/O, mob/user) - if(isrobot(user) || isessence(user)) - return - - if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) - return - user.drop_item() - if (O.loc != src.loc) - step(O, get_dir(O, src)) - return - -/obj/machinery/optable/proc/check_victim() - if(locate(/mob/living/carbon/human, src.loc)) - var/mob/living/carbon/human/M = locate(/mob/living/carbon/human, src.loc) - if(M.resting) - src.victim = M - icon_state = M.pulse ? "table2-active" : "table2-idle" - return 1 - src.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) - 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].", 3) - if (C.client) - C.client.perspective = EYE_PERSPECTIVE - C.client.eye = src - C.resting = 1 - C.loc = src.loc - for(var/obj/O in src) - O.loc = src.loc - src.add_fingerprint(user) - if(ishuman(C)) - var/mob/living/carbon/human/H = C - src.victim = H - icon_state = H.pulse ? "table2-active" : "table2-idle" - else - icon_state = "table2-idle" - -/obj/machinery/optable/verb/climb_on() - set name = "Climb On Table" - set category = "Object" - set src in oview(1) - - if(usr.stat || !ishuman(usr) || usr.buckled || usr.restrained()) - return - - if(src.victim) - to_chat(usr, "The table is already occupied!") - return - - take_victim(usr,usr) - -/obj/machinery/optable/attackby(obj/item/weapon/W, mob/living/carbon/user) - if(isrobot(user)) - return - - if (istype(W, /obj/item/weapon/grab)) - if(iscarbon(W:affecting)) - take_victim(W:affecting,usr) - user.SetNextMove(CLICK_CD_MELEE) - qdel(W) - return - user.drop_item() - if(W && W.loc) - W.loc = 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 + + var/obj/machinery/computer/operating/computer = null + +/obj/machinery/optable/atom_init() + . = ..() + for(dir in list(NORTH,EAST,SOUTH,WEST)) + computer = locate(/obj/machinery/computer/operating, get_step(src, dir)) + if (computer) + computer.table = src + 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) + if ((HULK in usr.mutations)) + user.SetNextMove(CLICK_CD_MELEE) + to_chat(usr, text("You destroy the operating table.")) + visible_message("[usr] destroys the operating table!") + src.density = 0 + qdel(src) + return + +/obj/machinery/optable/attack_hand(mob/user) + if (HULK in usr.mutations) + user.SetNextMove(CLICK_CD_MELEE) + to_chat(usr, text("You destroy the table.")) + visible_message("[usr] destroys the operating table!") + src.density = 0 + qdel(src) + else + return ..() // for fun, for braindamage and fingerprints. + +/obj/machinery/optable/CanPass(atom/movable/mover, turf/target, height=0, 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(obj/O, mob/user) + if(isrobot(user) || isessence(user)) + return + + if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) + return + user.drop_item() + if (O.loc != src.loc) + step(O, get_dir(O, src)) + return + +/obj/machinery/optable/proc/check_victim() + if(locate(/mob/living/carbon/human, src.loc)) + var/mob/living/carbon/human/M = locate(/mob/living/carbon/human, src.loc) + if(M.resting) + src.victim = M + icon_state = M.pulse ? "table2-active" : "table2-idle" + return 1 + src.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) + 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].", 3) + if (C.client) + C.client.perspective = EYE_PERSPECTIVE + C.client.eye = src + C.resting = 1 + C.loc = src.loc + for(var/obj/O in src) + O.loc = src.loc + src.add_fingerprint(user) + if(ishuman(C)) + var/mob/living/carbon/human/H = C + src.victim = H + icon_state = H.pulse ? "table2-active" : "table2-idle" + else + icon_state = "table2-idle" + +/obj/machinery/optable/verb/climb_on() + set name = "Climb On Table" + set category = "Object" + set src in oview(1) + + if(usr.stat || !ishuman(usr) || usr.buckled || usr.restrained()) + return + + if(src.victim) + to_chat(usr, "The table is already occupied!") + return + + take_victim(usr,usr) + +/obj/machinery/optable/attackby(obj/item/weapon/W, mob/living/carbon/user) + if(isrobot(user)) + return + + if (istype(W, /obj/item/weapon/grab)) + if(iscarbon(W:affecting)) + take_victim(W:affecting,usr) + user.SetNextMove(CLICK_CD_MELEE) + qdel(W) + return + user.drop_item() + if(W && W.loc) + W.loc = src.loc + return diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 6b939062fd4d..ee8634d949e7 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -1,105 +1,105 @@ -/obj/machinery/pdapainter - name = "PDA painter" - desc = "A PDA painting machine. To use, simply insert your PDA and choose the desired preset paint scheme." - icon = 'icons/obj/machines/pdapainter.dmi' - icon_state = "pdapainter" - density = TRUE - anchored = TRUE - var/obj/item/device/pda/storedpda = null - var/list/colorlist = list() - var/list/tc_pda_list = list(/obj/item/device/pda/forensic) - - -/obj/machinery/pdapainter/update_icon() - overlays.Cut() - - if(stat & BROKEN) - icon_state = "[initial(icon_state)]-broken" - return - - if(storedpda) - overlays += "[initial(icon_state)]-closed" - - if(powered()) - icon_state = initial(icon_state) - else - icon_state = "[initial(icon_state)]-off" - - return - -/obj/machinery/pdapainter/atom_init() - . = ..() - var/blocked = list( - /obj/item/device/pda/silicon/pai, - /obj/item/device/pda/silicon, - /obj/item/device/pda/silicon/robot, - /obj/item/device/pda/heads, - /obj/item/device/pda/clear, - /obj/item/device/pda/syndicate - ) - - for(var/P in typesof(/obj/item/device/pda)-blocked) - var/obj/item/device/pda/D = new P - - //D.name = "PDA Style [colorlist.len+1]" //Gotta set the name, otherwise it all comes up as "PDA" - D.name = D.icon_state //PDAs don't have unique names, but using the sprite names works. - - colorlist += D - - -/obj/machinery/pdapainter/attackby(obj/item/O, mob/user) - if(istype(O, /obj/item/device/pda)) - if(storedpda) - to_chat(user, "There is already a PDA inside.") - return - else - var/obj/item/device/pda/P = usr.get_active_hand() - if(istype(P)) - user.drop_item() - storedpda = P - P.loc = src - P.add_fingerprint(usr) - update_icon() - else - if(istype(O, /obj/item/weapon/wrench)) - playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) - anchored = !anchored - to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].") - - -/obj/machinery/pdapainter/attack_hand(mob/user) - if(..()) - return 1 - - if(storedpda) - var/obj/item/device/pda/P - P = input(user, "Select your color!", "PDA Painting") as null|anything in colorlist - if(!P) - return 1 - - storedpda.icon = 'icons/obj/pda.dmi' - storedpda.icon_state = P.icon_state - storedpda.desc = P.desc - - else - to_chat(user, "The [src] is empty.") - - -/obj/machinery/pdapainter/verb/ejectpda() - set name = "Eject PDA" - set category = "Object" - set src in oview(1) - if(!usr.canmove || usr.stat || usr.restrained()) - return - - if(storedpda) - storedpda.loc = get_turf(src.loc) - storedpda = null - update_icon() - else - to_chat(usr, "The [src] is empty.") - - -/obj/machinery/pdapainter/power_change() - ..() - update_icon() +/obj/machinery/pdapainter + name = "PDA painter" + desc = "A PDA painting machine. To use, simply insert your PDA and choose the desired preset paint scheme." + icon = 'icons/obj/machines/pdapainter.dmi' + icon_state = "pdapainter" + density = TRUE + anchored = TRUE + var/obj/item/device/pda/storedpda = null + var/list/colorlist = list() + var/list/tc_pda_list = list(/obj/item/device/pda/forensic) + + +/obj/machinery/pdapainter/update_icon() + overlays.Cut() + + if(stat & BROKEN) + icon_state = "[initial(icon_state)]-broken" + return + + if(storedpda) + overlays += "[initial(icon_state)]-closed" + + if(powered()) + icon_state = initial(icon_state) + else + icon_state = "[initial(icon_state)]-off" + + return + +/obj/machinery/pdapainter/atom_init() + . = ..() + var/blocked = list( + /obj/item/device/pda/silicon/pai, + /obj/item/device/pda/silicon, + /obj/item/device/pda/silicon/robot, + /obj/item/device/pda/heads, + /obj/item/device/pda/clear, + /obj/item/device/pda/syndicate + ) + + for(var/P in typesof(/obj/item/device/pda)-blocked) + var/obj/item/device/pda/D = new P + + //D.name = "PDA Style [colorlist.len+1]" //Gotta set the name, otherwise it all comes up as "PDA" + D.name = D.icon_state //PDAs don't have unique names, but using the sprite names works. + + colorlist += D + + +/obj/machinery/pdapainter/attackby(obj/item/O, mob/user) + if(istype(O, /obj/item/device/pda)) + if(storedpda) + to_chat(user, "There is already a PDA inside.") + return + else + var/obj/item/device/pda/P = usr.get_active_hand() + if(istype(P)) + user.drop_item() + storedpda = P + P.loc = src + P.add_fingerprint(usr) + update_icon() + else + if(istype(O, /obj/item/weapon/wrench)) + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + anchored = !anchored + to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].") + + +/obj/machinery/pdapainter/attack_hand(mob/user) + if(..()) + return 1 + + if(storedpda) + var/obj/item/device/pda/P + P = input(user, "Select your color!", "PDA Painting") as null|anything in colorlist + if(!P) + return 1 + + storedpda.icon = 'icons/obj/pda.dmi' + storedpda.icon_state = P.icon_state + storedpda.desc = P.desc + + else + to_chat(user, "The [src] is empty.") + + +/obj/machinery/pdapainter/verb/ejectpda() + set name = "Eject PDA" + set category = "Object" + set src in oview(1) + if(!usr.canmove || usr.stat || usr.restrained()) + return + + if(storedpda) + storedpda.loc = get_turf(src.loc) + storedpda = null + update_icon() + else + to_chat(usr, "The [src] is empty.") + + +/obj/machinery/pdapainter/power_change() + ..() + update_icon() diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 7fa7bac2bb72..e57cea78b630 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -1,329 +1,329 @@ -///////////////////////////////////////// -// SLEEPER CONSOLE -///////////////////////////////////////// - -/obj/machinery/sleep_console - name = "Sleeper Console" - icon = 'icons/obj/Cryogenic3.dmi' - icon_state = "sleeperconsole" - anchored = 1 //About time someone fixed this. - density = 0 - light_color = "#7BF9FF" - -/obj/machinery/sleeper - name = "Sleeper" - icon = 'icons/obj/Cryogenic3.dmi' - icon_state = "sleeper-open" - density = 0 - anchored = 1 - state_open = 1 - light_color = "#7BF9FF" - allowed_checks = ALLOWED_CHECK_TOPIC - var/obj/item/weapon/reagent_containers/glass/beaker = null - var/filtering = 0 - var/efficiency = 1 - var/min_health = -25 - var/list/available_chems - var/list/possible_chems = list( - list("tricordrazine", "paracetamol", "stoxin", "dexalin", "bicaridine", "kelotane"), - list("imidazoline"), - list("anti_toxin", "ryetalyn" ,"dermaline", "arithrazine"), - list("dexalinp", "alkysine") - ) - var/upgraded = FALSE - -/obj/machinery/sleeper/upgraded - upgraded = TRUE - -/obj/machinery/sleeper/atom_init(mapload) - . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/sleeper(null) - if(upgraded) - component_parts += new /obj/item/weapon/stock_parts/matter_bin/bluespace(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator/femto(null) - else - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/weapon/stock_parts/console_screen(null) - component_parts += new /obj/item/weapon/stock_parts/console_screen(null) - component_parts += new /obj/item/stack/cable_coil/random(null, 1) - RefreshParts() - if(mapload) - beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src) - -/obj/machinery/sleeper/RefreshParts() - var/E - for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) - E += B.rating - var/I - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - I += M.rating - - efficiency = initial(efficiency)* E - min_health = initial(min_health) * E - available_chems = list() - for(var/i in 1 to I) - available_chems |= possible_chems[i] - -/obj/machinery/sleeper/allow_drop() - return 0 - -/obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user) - if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user) || !iscarbon(target) || target.buckled) - return - if(!iscarbon(usr) && !isrobot(usr)) - return - close_machine(target) - -/obj/machinery/sleeper/process() - if(ishuman(occupant)) - var/mob/living/carbon/human/H = occupant - if(filtering > 0) - if(beaker) - if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) - H.vessel.trans_to(beaker, 1) - for(var/datum/reagent/x in src.occupant.reagents.reagent_list) - H.reagents.trans_to(beaker, 3) - H.vessel.trans_to(beaker, 1) - 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) - -/obj/machinery/sleeper/attack_animal(mob/living/simple_animal/M)//Stop putting hostile mobs in things guise - ..() - if(M.environment_smash) - visible_message("[M.name] smashes [src] apart!") - qdel(src) - return - -/obj/machinery/sleeper/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/reagent_containers/glass)) - if(!beaker) - beaker = I - user.drop_item() - I.loc = src - user.visible_message("[user] adds \a [I] to \the [src]!", "You add \a [I] to \the [src]!") - src.updateUsrDialog() - return - else - to_chat(user, "\red The sleeper has a beaker already.") - return - - if(!state_open && !occupant) - if(default_deconstruction_screwdriver(user, "sleeper-o", "sleeper", I)) - return - if(default_change_direction_wrench(user, I)) - return - if(exchange_parts(user, I)) - return - if(default_pry_open(I)) - return - if(default_deconstruction_crowbar(I)) - return - -/obj/machinery/sleeper/ex_act(severity) - if(filtering) - toggle_filter() - 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(filtering) - toggle_filter() - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - if(occupant) - go_out() - ..(severity) - -/obj/machinery/sleeper/proc/toggle_filter() - if(filtering) - filtering = 0 - else - filtering = 1 - -/obj/machinery/sleeper/proc/go_out() - if(filtering) - toggle_filter() - if(!occupant) - return - for(var/atom/movable/O in src) - if(O == beaker) - continue - O.loc = loc - if(occupant.client) - occupant.client.eye = occupant.client.mob - occupant.client.perspective = MOB_PERSPECTIVE - occupant = null - icon_state = "sleeper-open" - -/obj/machinery/sleeper/container_resist() - open_machine() - -/obj/machinery/sleeper/relaymove(mob/user) - ..() - open_machine() - -/obj/machinery/sleeper/Destroy() - var/turf/T = loc - T.contents += contents - return ..() - -/obj/machinery/sleeper/verb/remove_beaker() - set name = "Remove Beaker" - set category = "Object" - set src in oview(1) - if(usr.stat != 0) - return - if(beaker) - filtering = 0 - beaker.loc = usr.loc - beaker = null - add_fingerprint(usr) - return - -/obj/machinery/sleeper/ui_interact(mob/user) - var/dat = "

    Sleeper Status

    " - - dat += "
    " - if(!occupant) - dat += "Sleeper Unoccupied" - else - dat += "[occupant.name] => " - switch(occupant.stat) //obvious, see what their status is - if(0) - dat += "Conscious" - if(1) - dat += "Unconscious" - else - dat += "DEAD" - - dat += "
    " - - dat += "
    Health:
    [occupant.health]%
    " - dat += "
    \> Brute Damage:
    [occupant.getBruteLoss()]%
    " - dat += "
    \> Resp. Damage:
    [occupant.getOxyLoss()]%
    " - dat += "
    \> Toxin Content:
    [occupant.getToxLoss()]%
    " - dat += "
    \> Burn Severity:
    [occupant.getFireLoss()]%
    " - - dat += "
    Paralysis Summary:
    [round(occupant.paralysis)]% [occupant.paralysis ? "([round(occupant.paralysis / 4)] seconds left)" : ""]
    " - dat += "
    Paralysis Summary:
    [round(occupant.paralysis)]% [occupant.paralysis ? "([round(occupant.paralysis / 4)] seconds left)" : ""]
    " - if(occupant.reagents.reagent_list.len) - for(var/datum/reagent/R in occupant.reagents.reagent_list) - dat += text("
    [R.name]:
    [] units
    ", round(R.volume, 0.1)) - - dat += "
    " - - dat += "Scan" - - dat += "Close" : "open=1'>Open"]" - - dat += "

    Beaker

    " - - if(src.beaker) - dat += "Remove Beaker" - if(filtering) - dat += "Stop Dialysis" - dat += text("
    Output Beaker has [] units of free space remaining

    ", src.beaker.reagents.maximum_volume - src.beaker.reagents.total_volume) - else - dat += "Start Dialysis" - dat += text("
    Output Beaker has [] units of free space remaining", src.beaker.reagents.maximum_volume - src.beaker.reagents.total_volume) - else - dat += "
    No Dialysis Output Beaker is present." - - dat += "

    Injector

    " - - if(src.occupant) - dat += "Inject Inaprovaline" - else - dat += "Inject Inaprovaline" - if(occupant && occupant.health > min_health) - for(var/re in available_chems) - var/datum/reagent/C = chemical_reagents_list[re] - if(C) - dat += "
    Inject [C.name]" - else - for(var/re in available_chems) - var/datum/reagent/C = chemical_reagents_list[re] - if(C) - dat += "
    Inject [C.name]" - - var/datum/browser/popup = new(user, "sleeper", "Sleeper Console", 520, 540) //Set up the popup browser window - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.set_content(dat) - popup.open() - -/obj/machinery/sleeper/Topic(href, href_list) - . = ..() - if(!. || usr == occupant) - return FALSE - - if(href_list["refresh"]) - updateUsrDialog() - else if(href_list["open"]) - open_machine() - else if(href_list["close"]) - close_machine() - else if(href_list["removebeaker"]) - remove_beaker() - else if(href_list["togglefilter"]) - toggle_filter() - else if(occupant && occupant.stat != DEAD && is_operational()) - if(href_list["inject"] == "inaprovaline" || occupant.health > min_health) - inject_chem(usr, href_list["inject"]) - else - to_chat(usr, "ERROR: Subject is not in stable condition for auto-injection.") - else - to_chat(usr, "ERROR: Subject cannot metabolise chemicals.") - updateUsrDialog() - -/obj/machinery/sleeper/open_machine() - if(!state_open && !panel_open) - ..() - if(beaker) - beaker.loc = src - -/obj/machinery/sleeper/close_machine(mob/target) - if(state_open && !panel_open) - to_chat(target, "\blue You feel cool air surround you. You go numb as your senses turn inward.") - ..(target) - -/obj/machinery/sleeper/proc/inject_chem(mob/user, chem) - if(occupant && occupant.reagents) - if(occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency) - occupant.reagents.add_reagent(chem, 10) - var/units = round(occupant.reagents.get_reagent_amount(chem)) - to_chat(user, "Occupant now has [units] unit\s of [chem] in their bloodstream.") - -/obj/machinery/sleeper/update_icon() - if(state_open) - icon_state = "sleeper-open" - else - icon_state = "sleeper" +///////////////////////////////////////// +// SLEEPER CONSOLE +///////////////////////////////////////// + +/obj/machinery/sleep_console + name = "Sleeper Console" + icon = 'icons/obj/Cryogenic3.dmi' + icon_state = "sleeperconsole" + anchored = 1 //About time someone fixed this. + density = 0 + light_color = "#7BF9FF" + +/obj/machinery/sleeper + name = "Sleeper" + icon = 'icons/obj/Cryogenic3.dmi' + icon_state = "sleeper-open" + density = 0 + anchored = 1 + state_open = 1 + light_color = "#7BF9FF" + allowed_checks = ALLOWED_CHECK_TOPIC + var/obj/item/weapon/reagent_containers/glass/beaker = null + var/filtering = 0 + var/efficiency = 1 + var/min_health = -25 + var/list/available_chems + var/list/possible_chems = list( + list("tricordrazine", "paracetamol", "stoxin", "dexalin", "bicaridine", "kelotane"), + list("imidazoline"), + list("anti_toxin", "ryetalyn" ,"dermaline", "arithrazine"), + list("dexalinp", "alkysine") + ) + var/upgraded = FALSE + +/obj/machinery/sleeper/upgraded + upgraded = TRUE + +/obj/machinery/sleeper/atom_init(mapload) + . = ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/sleeper(null) + if(upgraded) + component_parts += new /obj/item/weapon/stock_parts/matter_bin/bluespace(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator/femto(null) + else + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + component_parts += new /obj/item/stack/cable_coil/random(null, 1) + RefreshParts() + if(mapload) + beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src) + +/obj/machinery/sleeper/RefreshParts() + var/E + for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) + E += B.rating + var/I + for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + I += M.rating + + efficiency = initial(efficiency)* E + min_health = initial(min_health) * E + available_chems = list() + for(var/i in 1 to I) + available_chems |= possible_chems[i] + +/obj/machinery/sleeper/allow_drop() + return 0 + +/obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user) + if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user) || !iscarbon(target) || target.buckled) + return + if(!iscarbon(usr) && !isrobot(usr)) + return + close_machine(target) + +/obj/machinery/sleeper/process() + if(ishuman(occupant)) + var/mob/living/carbon/human/H = occupant + if(filtering > 0) + if(beaker) + if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) + H.vessel.trans_to(beaker, 1) + for(var/datum/reagent/x in src.occupant.reagents.reagent_list) + H.reagents.trans_to(beaker, 3) + H.vessel.trans_to(beaker, 1) + 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) + +/obj/machinery/sleeper/attack_animal(mob/living/simple_animal/M)//Stop putting hostile mobs in things guise + ..() + if(M.environment_smash) + visible_message("[M.name] smashes [src] apart!") + qdel(src) + return + +/obj/machinery/sleeper/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/reagent_containers/glass)) + if(!beaker) + beaker = I + user.drop_item() + I.loc = src + user.visible_message("[user] adds \a [I] to \the [src]!", "You add \a [I] to \the [src]!") + src.updateUsrDialog() + return + else + to_chat(user, "\red The sleeper has a beaker already.") + return + + if(!state_open && !occupant) + if(default_deconstruction_screwdriver(user, "sleeper-o", "sleeper", I)) + return + if(default_change_direction_wrench(user, I)) + return + if(exchange_parts(user, I)) + return + if(default_pry_open(I)) + return + if(default_deconstruction_crowbar(I)) + return + +/obj/machinery/sleeper/ex_act(severity) + if(filtering) + toggle_filter() + 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(filtering) + toggle_filter() + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + if(occupant) + go_out() + ..(severity) + +/obj/machinery/sleeper/proc/toggle_filter() + if(filtering) + filtering = 0 + else + filtering = 1 + +/obj/machinery/sleeper/proc/go_out() + if(filtering) + toggle_filter() + if(!occupant) + return + for(var/atom/movable/O in src) + if(O == beaker) + continue + O.loc = loc + if(occupant.client) + occupant.client.eye = occupant.client.mob + occupant.client.perspective = MOB_PERSPECTIVE + occupant = null + icon_state = "sleeper-open" + +/obj/machinery/sleeper/container_resist() + open_machine() + +/obj/machinery/sleeper/relaymove(mob/user) + ..() + open_machine() + +/obj/machinery/sleeper/Destroy() + var/turf/T = loc + T.contents += contents + return ..() + +/obj/machinery/sleeper/verb/remove_beaker() + set name = "Remove Beaker" + set category = "Object" + set src in oview(1) + if(usr.stat != 0) + return + if(beaker) + filtering = 0 + beaker.loc = usr.loc + beaker = null + add_fingerprint(usr) + return + +/obj/machinery/sleeper/ui_interact(mob/user) + var/dat = "

    Sleeper Status

    " + + dat += "
    " + if(!occupant) + dat += "Sleeper Unoccupied" + else + dat += "[occupant.name] => " + switch(occupant.stat) //obvious, see what their status is + if(0) + dat += "Conscious" + if(1) + dat += "Unconscious" + else + dat += "DEAD" + + dat += "
    " + + dat += "
    Health:
    [occupant.health]%
    " + dat += "
    \> Brute Damage:
    [occupant.getBruteLoss()]%
    " + dat += "
    \> Resp. Damage:
    [occupant.getOxyLoss()]%
    " + dat += "
    \> Toxin Content:
    [occupant.getToxLoss()]%
    " + dat += "
    \> Burn Severity:
    [occupant.getFireLoss()]%
    " + + dat += "
    Paralysis Summary:
    [round(occupant.paralysis)]% [occupant.paralysis ? "([round(occupant.paralysis / 4)] seconds left)" : ""]
    " + dat += "
    Paralysis Summary:
    [round(occupant.paralysis)]% [occupant.paralysis ? "([round(occupant.paralysis / 4)] seconds left)" : ""]
    " + if(occupant.reagents.reagent_list.len) + for(var/datum/reagent/R in occupant.reagents.reagent_list) + dat += text("
    [R.name]:
    [] units
    ", round(R.volume, 0.1)) + + dat += "
    " + + dat += "Scan" + + dat += "Close" : "open=1'>Open"]" + + dat += "

    Beaker

    " + + if(src.beaker) + dat += "Remove Beaker" + if(filtering) + dat += "Stop Dialysis" + dat += text("
    Output Beaker has [] units of free space remaining

    ", src.beaker.reagents.maximum_volume - src.beaker.reagents.total_volume) + else + dat += "Start Dialysis" + dat += text("
    Output Beaker has [] units of free space remaining", src.beaker.reagents.maximum_volume - src.beaker.reagents.total_volume) + else + dat += "
    No Dialysis Output Beaker is present." + + dat += "

    Injector

    " + + if(src.occupant) + dat += "Inject Inaprovaline" + else + dat += "Inject Inaprovaline" + if(occupant && occupant.health > min_health) + for(var/re in available_chems) + var/datum/reagent/C = chemical_reagents_list[re] + if(C) + dat += "
    Inject [C.name]" + else + for(var/re in available_chems) + var/datum/reagent/C = chemical_reagents_list[re] + if(C) + dat += "
    Inject [C.name]" + + var/datum/browser/popup = new(user, "sleeper", "Sleeper Console", 520, 540) //Set up the popup browser window + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) + popup.set_content(dat) + popup.open() + +/obj/machinery/sleeper/Topic(href, href_list) + . = ..() + if(!. || usr == occupant) + return FALSE + + if(href_list["refresh"]) + updateUsrDialog() + else if(href_list["open"]) + open_machine() + else if(href_list["close"]) + close_machine() + else if(href_list["removebeaker"]) + remove_beaker() + else if(href_list["togglefilter"]) + toggle_filter() + else if(occupant && occupant.stat != DEAD && is_operational()) + if(href_list["inject"] == "inaprovaline" || occupant.health > min_health) + inject_chem(usr, href_list["inject"]) + else + to_chat(usr, "ERROR: Subject is not in stable condition for auto-injection.") + else + to_chat(usr, "ERROR: Subject cannot metabolise chemicals.") + updateUsrDialog() + +/obj/machinery/sleeper/open_machine() + if(!state_open && !panel_open) + ..() + if(beaker) + beaker.loc = src + +/obj/machinery/sleeper/close_machine(mob/target) + if(state_open && !panel_open) + to_chat(target, "\blue You feel cool air surround you. You go numb as your senses turn inward.") + ..(target) + +/obj/machinery/sleeper/proc/inject_chem(mob/user, chem) + if(occupant && occupant.reagents) + if(occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency) + occupant.reagents.add_reagent(chem, 10) + var/units = round(occupant.reagents.get_reagent_amount(chem)) + to_chat(user, "Occupant now has [units] unit\s of [chem] in their bloodstream.") + +/obj/machinery/sleeper/update_icon() + if(state_open) + icon_state = "sleeper-open" + else + icon_state = "sleeper" diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm index f170823f78bb..104b046bcc18 100644 --- a/code/game/machinery/airlock_control.dm +++ b/code/game/machinery/airlock_control.dm @@ -1,264 +1,264 @@ -#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/suppres_next_status_send = FALSE - - -/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") - suppres_next_status_send = TRUE - open() - - if("close") - suppres_next_status_send = TRUE - close() - - if("unlock") - unbolt() - - if("lock") - bolt() - - if("secure_open") - - unbolt() - - sleep(2) - suppres_next_status_send = TRUE - open() - - bolt() - - if("secure_close") - unbolt() - - sleep(2) - suppres_next_status_send = TRUE - close() - - bolt() - - send_status() - -/obj/machinery/door/airlock/proc/send_status_if_allowed() - if(suppres_next_status_send) - suppres_next_status_send = FALSE - else - send_status() - -/obj/machinery/door/airlock/proc/send_status() - if(radio_connection) - var/datum/signal/signal = new - 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/Bumped(atom/AM) - if(ishuman(AM) && prob(40) && src.density) - var/mob/living/carbon/human/H = AM - if(H.getBrainLoss() >= 60) - playsound(src.loc, 'sound/effects/bang.ogg', 25, 1) - if(!istype(H.head, /obj/item/clothing/head/helmet)) - visible_message("\red [H] headbutts the airlock.") - var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] - H.Stun(8) - H.Weaken(5) - BP.take_damage(10, 0) - else - visible_message("\red [H] headbutts the airlock. Good thing they're wearing a helmet.") - H.Stun(8) - H.Weaken(5) - return - ..(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 = new - 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/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/atom_init() - . = ..() - if(frequency) - set_frequency(frequency) - - update_icon() - - -/obj/machinery/door/airlock/atom_init() - . = ..() - - if(radio_controller) - set_frequency(frequency) - -/obj/machinery/door/airlock/Destroy() - if(frequency && radio_controller) - radio_controller.remove_object(src,frequency) - return ..() - -/obj/machinery/airlock_sensor - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "airlock_sensor_off" - name = "airlock sensor" - - anchored = TRUE - power_channel = ENVIRON - interact_offline = TRUE // this is very strange that power_channel is defined, use_power = 1 (parent), when this element has no unpowered features and sprites. - - var/id_tag - var/master_tag - frequency = 1379 - var/command = "cycle" - - - var/on = 1 - var/alert = 0 - var/previousPressure - -/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/allowed_fail() - flick("access_button_cycle", src) - -/obj/machinery/airlock_sensor/attack_hand(mob/user) - . = ..() - if(.) - return - - var/datum/signal/signal = new - 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/gas_mixture/air_sample = return_air() - var/pressure = round(air_sample.return_pressure(),0.1) - - if(abs(pressure - previousPressure) > 0.001 || previousPressure == null) - var/datum/signal/signal = new - signal.transmission_method = 1 //radio signal - signal.data["tag"] = id_tag - signal.data["timestamp"] = world.time - signal.data["pressure"] = num2text(pressure) - - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) - - previousPressure = pressure - - alert = (pressure < ONE_ATMOSPHERE*0.8) - - update_icon() - -/obj/machinery/airlock_sensor/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/atom_init() - . = ..() - set_frequency(frequency) - -/obj/machinery/airlock_sensor/airlock_interior - command = "cycle_interior" - -/obj/machinery/airlock_sensor/airlock_exterior - command = "cycle_exterior" - -/obj/machinery/access_button - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "access_button_standby" - name = "access button" - - layer = 3.3 //Above windows - anchored = TRUE - power_channel = ENVIRON - interact_offline = TRUE - - var/master_tag - frequency = 1449 - var/command = "cycle" - - var/on = TRUE - -/obj/machinery/access_button/update_icon() - if(on) - icon_state = "access_button_standby" - else - icon_state = "access_button_off" - -/obj/machinery/access_button/allowed_fail() - flick("access_button_cycle", src) - -/obj/machinery/access_button/attack_hand(mob/user) - . = ..() - if(.) - return - - if(radio_connection) - var/datum/signal/signal = new - 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/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - if(frequency) - radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK) - - -/obj/machinery/access_button/atom_init() - . = ..() - set_frequency(frequency) - -/obj/machinery/access_button/airlock_interior - frequency = 1379 - command = "cycle_interior" - -/obj/machinery/access_button/airlock_exterior - frequency = 1379 - command = "cycle_exterior" +#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/suppres_next_status_send = FALSE + + +/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") + suppres_next_status_send = TRUE + open() + + if("close") + suppres_next_status_send = TRUE + close() + + if("unlock") + unbolt() + + if("lock") + bolt() + + if("secure_open") + + unbolt() + + sleep(2) + suppres_next_status_send = TRUE + open() + + bolt() + + if("secure_close") + unbolt() + + sleep(2) + suppres_next_status_send = TRUE + close() + + bolt() + + send_status() + +/obj/machinery/door/airlock/proc/send_status_if_allowed() + if(suppres_next_status_send) + suppres_next_status_send = FALSE + else + send_status() + +/obj/machinery/door/airlock/proc/send_status() + if(radio_connection) + var/datum/signal/signal = new + 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/Bumped(atom/AM) + if(ishuman(AM) && prob(40) && src.density) + var/mob/living/carbon/human/H = AM + if(H.getBrainLoss() >= 60) + playsound(src.loc, 'sound/effects/bang.ogg', 25, 1) + if(!istype(H.head, /obj/item/clothing/head/helmet)) + visible_message("\red [H] headbutts the airlock.") + var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] + H.Stun(8) + H.Weaken(5) + BP.take_damage(10, 0) + else + visible_message("\red [H] headbutts the airlock. Good thing they're wearing a helmet.") + H.Stun(8) + H.Weaken(5) + return + ..(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 = new + 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/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/atom_init() + . = ..() + if(frequency) + set_frequency(frequency) + + update_icon() + + +/obj/machinery/door/airlock/atom_init() + . = ..() + + if(radio_controller) + set_frequency(frequency) + +/obj/machinery/door/airlock/Destroy() + if(frequency && radio_controller) + radio_controller.remove_object(src,frequency) + return ..() + +/obj/machinery/airlock_sensor + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "airlock_sensor_off" + name = "airlock sensor" + + anchored = TRUE + power_channel = ENVIRON + interact_offline = TRUE // this is very strange that power_channel is defined, use_power = 1 (parent), when this element has no unpowered features and sprites. + + var/id_tag + var/master_tag + frequency = 1379 + var/command = "cycle" + + + var/on = 1 + var/alert = 0 + var/previousPressure + +/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/allowed_fail() + flick("access_button_cycle", src) + +/obj/machinery/airlock_sensor/attack_hand(mob/user) + . = ..() + if(.) + return + + var/datum/signal/signal = new + 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/gas_mixture/air_sample = return_air() + var/pressure = round(air_sample.return_pressure(),0.1) + + if(abs(pressure - previousPressure) > 0.001 || previousPressure == null) + var/datum/signal/signal = new + signal.transmission_method = 1 //radio signal + signal.data["tag"] = id_tag + signal.data["timestamp"] = world.time + signal.data["pressure"] = num2text(pressure) + + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + + previousPressure = pressure + + alert = (pressure < ONE_ATMOSPHERE*0.8) + + update_icon() + +/obj/machinery/airlock_sensor/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/atom_init() + . = ..() + set_frequency(frequency) + +/obj/machinery/airlock_sensor/airlock_interior + command = "cycle_interior" + +/obj/machinery/airlock_sensor/airlock_exterior + command = "cycle_exterior" + +/obj/machinery/access_button + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "access_button_standby" + name = "access button" + + layer = 3.3 //Above windows + anchored = TRUE + power_channel = ENVIRON + interact_offline = TRUE + + var/master_tag + frequency = 1449 + var/command = "cycle" + + var/on = TRUE + +/obj/machinery/access_button/update_icon() + if(on) + icon_state = "access_button_standby" + else + icon_state = "access_button_off" + +/obj/machinery/access_button/allowed_fail() + flick("access_button_cycle", src) + +/obj/machinery/access_button/attack_hand(mob/user) + . = ..() + if(.) + return + + if(radio_connection) + var/datum/signal/signal = new + 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/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency, RADIO_AIRLOCK) + + +/obj/machinery/access_button/atom_init() + . = ..() + set_frequency(frequency) + +/obj/machinery/access_button/airlock_interior + frequency = 1379 + command = "cycle_interior" + +/obj/machinery/access_button/airlock_exterior + frequency = 1379 + command = "cycle_exterior" diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 40a82a551665..dcb1affebe4a 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -1,1242 +1,1242 @@ -//////////////////////////////////////// -//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_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 - -#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 - name = "alarm" - icon = 'icons/obj/monitors.dmi' - icon_state = "alarm0" - anchored = TRUE - use_power = TRUE - idle_power_usage = 80 - active_power_usage = 1000 // For heating/cooling rooms. 1000 joules equates to about 1 degree every 2 seconds for a single tile of air. - power_channel = ENVIRON - req_one_access = list(access_atmospherics, access_engine_equip) - frequency = 1439 - allowed_checks = ALLOWED_CHECK_NONE - unacidable = TRUE - - var/breach_detection = TRUE // Whether to use automatic breach detection or not - //var/skipprocess = 0 //Experimenting - var/alarm_frequency = 1437 - var/remote_control = FALSE - var/rcon_setting = 2 - var/rcon_time = 0 - var/locked = TRUE - var/wiresexposed = FALSE // If it's been screwdrivered open. - var/aidisabled = FALSE - var/shorted = FALSE - var/hidden_from_console = FALSE - - var/datum/wires/alarm/wires = null - - var/mode = AALARM_MODE_SCRUBBING - var/screen = AALARM_SCREEN_MAIN - var/area_uid - var/area/alarm_area - var/buildstage = 2 //2 is built, 1 is building, 0 is frame. - - var/target_temperature = T0C+20 - var/regulating_temperature = 0 - var/allow_regulate = 0 //Is thermoregulation enabled? - - var/list/TLV = list() - var/list/trace_gas = list("sleeping_agent") //list of other gases that this air alarm is able to detect - - var/danger_level = 0 - var/pressure_dangerlevel = 0 - var/oxygen_dangerlevel = 0 - var/co2_dangerlevel = 0 - var/phoron_dangerlevel = 0 - var/temperature_dangerlevel = 0 - var/other_dangerlevel = 0 - -/obj/machinery/alarm/server/atom_init() - . = ..() - req_access = list(access_rd, access_atmospherics, access_engine_equip) - TLV["oxygen"] = list(-1.0, -1.0,-1.0,-1.0) // Partial pressure, kpa - TLV["carbon dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa - TLV["phoron"] = 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 - - -/obj/machinery/alarm/atom_init(mapload, dir, building = 0) - . = ..() - alarm_list += src - set_frequency(frequency) - - 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() - return // not sure about this, is constructing initializing it same as first_run()? - - if (!master_is_operating()) - elect_master() - first_run() - -/obj/machinery/alarm/proc/first_run() - alarm_area = get_area(src) - if (alarm_area.master) - alarm_area = alarm_area.master - area_uid = alarm_area.uid - if (name == "alarm") - name = "[alarm_area.name] Air Alarm" - if(!wires) - wires = new(src) - - // breathable air according to human/Life() - TLV["oxygen"] = list(16, 19, 135, 140) // Partial pressure, kpa - TLV["carbon dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa - TLV["phoron"] = 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 - -/obj/machinery/alarm/Destroy() - alarm_list -= src - if(wires) - QDEL_NULL(wires) - if(alarm_area && alarm_area.master_air_alarm == src) - alarm_area.master_air_alarm = null - alarm_area = null - return ..() - -/obj/machinery/alarm/process() - if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2) - 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. - handle_heating_cooling(environment) - - var/old_level = danger_level - var/old_pressurelevel = pressure_dangerlevel - danger_level = overall_danger_level() - - if (old_level != danger_level) - apply_danger_level(danger_level) - - if (old_pressurelevel != pressure_dangerlevel) - if (breach_detected()) - mode = AALARM_MODE_OFF - apply_mode() - - if (mode==AALARM_MODE_CYCLE && environment.return_pressure() 2.0) - update_use_power(2) - 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.") - else - //check for when we should stop adjusting temperature - if (!allow_regulate || get_danger_level(target_temperature, TLV["temperature"]) || abs(environment.temperature - target_temperature) <= 0.5) - update_use_power(1) - 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.") - - if (regulating_temperature) - 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 = environment.remove(0.25 * environment.total_moles) - - if(gas) - - if (gas.temperature <= target_temperature) //gas heating - var/energy_used = min(gas.get_thermal_energy_change(target_temperature) , active_power_usage) - - gas.add_thermal_energy(energy_used) - //use_power(energy_used, ENVIRON) //handle by update_use_power instead - else //gas cooling - var/heat_transfer = min(abs(gas.get_thermal_energy_change(target_temperature)), active_power_usage) - - //Assume the heat is being pumped into the hull which is fixed at 20 C - //none of this is really proper thermodynamics but whatever - - var/cop = gas.temperature / T20C //coefficient of performance -> power used = heat_transfer/cop - - heat_transfer = min(heat_transfer, cop * active_power_usage) //this ensures that we don't use more than active_power_usage amount of power - - heat_transfer = -gas.add_thermal_energy(-heat_transfer) //get the actual heat transfer - - //use_power(heat_transfer / cop, ENVIRON) //handle by update_use_power instead - - environment.merge(gas) - -/obj/machinery/alarm/proc/overall_danger_level() - var/turf/simulated/location = loc - if(!istype(location)) return//returns if loc is not simulated - - var/datum/gas_mixture/environment = location.return_air() - - var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume - var/environment_pressure = environment.return_pressure() - - var/other_moles = 0 - for(var/g in trace_gas) - other_moles += environment.gas[g] //this is only going to be used in a partial pressure calc, so we don't need to worry about group_multiplier here. - - pressure_dangerlevel = get_danger_level(environment_pressure, TLV["pressure"]) - oxygen_dangerlevel = get_danger_level(environment.gas["oxygen"] * partial_pressure, TLV["oxygen"]) - co2_dangerlevel = get_danger_level(environment.gas["carbon_dioxide"] * partial_pressure, TLV["carbon dioxide"]) - phoron_dangerlevel = get_danger_level(environment.gas["phoron"] * partial_pressure, TLV["phoron"]) - temperature_dangerlevel = get_danger_level(environment.temperature, TLV["temperature"]) - other_dangerlevel = get_danger_level(other_moles*partial_pressure, TLV["other"]) - - return max( - pressure_dangerlevel, - oxygen_dangerlevel, - co2_dangerlevel, - phoron_dangerlevel, - other_dangerlevel, - temperature_dangerlevel - ) - -// Returns whether this air alarm thinks there is a breach, given the sensors that are available to it. -/obj/machinery/alarm/proc/breach_detected() - var/turf/simulated/location = loc - - if(!istype(location)) - return 0 - - if(!breach_detection) - return 0 - - var/datum/gas_mixture/environment = location.return_air() - var/environment_pressure = environment.return_pressure() - var/pressure_levels = TLV["pressure"] - - if (environment_pressure <= pressure_levels[1]) //low pressures - if (!(mode == AALARM_MODE_PANIC || mode == AALARM_MODE_CYCLE)) - return 1 - - return 0 - - -/obj/machinery/alarm/proc/master_is_operating() - if(!alarm_area) return - return alarm_area.master_air_alarm && !(alarm_area.master_air_alarm.stat & (NOPOWER|BROKEN)) - - -/obj/machinery/alarm/proc/elect_master() - if(!alarm_area) return - for (var/area/A in alarm_area.related) - for (var/obj/machinery/alarm/AA in A) - if (!(AA.stat & (NOPOWER|BROKEN))) - alarm_area.master_air_alarm = AA - return 1 - return 0 - -/obj/machinery/alarm/proc/get_danger_level(current_value, list/danger_levels) - if((current_value >= 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="alarm_build[buildstage]" - return - - if((stat & NOPOWER) || shorted) - icon_state = "alarm_unpowered" - return - if(stat & BROKEN) - icon_state = "alarm_broken" - return - - var/icon_level = danger_level - if (alarm_area.atmosalm) - icon_level = max(icon_level, 1) //if there's an atmos alarm but everything is okay locally, no need to go past yellow - icon_state = "alarm[icon_level]" - -/obj/machinery/alarm/receive_signal(datum/signal/signal) - if(stat & (NOPOWER|BROKEN)) - return - if (alarm_area.master_air_alarm != src) - if (master_is_operating()) - return - elect_master() - if (alarm_area.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 alarm_area.air_scrub_names) && !(id_tag in alarm_area.air_vent_names)) - register_env_machine(id_tag, dev_type) - if(dev_type == "AScr") - alarm_area.air_scrub_info[id_tag] = signal.data - else if(dev_type == "AVP") - alarm_area.air_vent_info[id_tag] = signal.data - -/obj/machinery/alarm/proc/register_env_machine(m_id, device_type) - var/new_name - if (device_type=="AVP") - new_name = "[alarm_area.name] Vent Pump #[alarm_area.air_vent_names.len+1]" - alarm_area.air_vent_names[m_id] = new_name - else if (device_type=="AScr") - new_name = "[alarm_area.name] Air Scrubber #[alarm_area.air_scrub_names.len+1]" - alarm_area.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 alarm_area.air_vent_names) - var/list/I = alarm_area.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 alarm_area.air_scrub_names) - var/list/I = alarm_area.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/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - if(frequency) - radio_connection = radio_controller.add_object(src, frequency, RADIO_TO_AIRALARM) - -/obj/machinery/alarm/proc/send_signal(target, list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise - if(!radio_connection) - return 0 - - var/datum/signal/signal = new - 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) -// world << text("Signal [] Broadcasted to []", command, target) - - return 1 - -/obj/machinery/alarm/proc/apply_mode() - //propagate mode to other air alarms in the area - //TODO: make it so that players can choose between applying the new mode to the room they are in (related area) vs the entire alarm area - for (var/area/RA in alarm_area.related) - for (var/obj/machinery/alarm/AA in RA) - AA.mode = mode - - switch(mode) - if(AALARM_MODE_SCRUBBING) - for(var/device_id in alarm_area.air_scrub_names) - send_signal(device_id, list("power"= 1, "co2_scrub"= 1, "scrubbing"= 1, "panic_siphon"= 0) ) - for(var/device_id in alarm_area.air_vent_names) - send_signal(device_id, list("power"= 1, "checks"= "default", "set_external_pressure"= "default") ) - - if(AALARM_MODE_PANIC, AALARM_MODE_CYCLE) - for(var/device_id in alarm_area.air_scrub_names) - send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) - for(var/device_id in alarm_area.air_vent_names) - send_signal(device_id, list("power"= 0) ) - - if(AALARM_MODE_REPLACEMENT) - for(var/device_id in alarm_area.air_scrub_names) - send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) - for(var/device_id in alarm_area.air_vent_names) - send_signal(device_id, list("power"= 1, "checks"= "default", "set_external_pressure"= "default") ) - - if(AALARM_MODE_FILL) - for(var/device_id in alarm_area.air_scrub_names) - send_signal(device_id, list("power"= 0) ) - for(var/device_id in alarm_area.air_vent_names) - send_signal(device_id, list("power"= 1, "checks"= "default", "set_external_pressure"= "default") ) - - if(AALARM_MODE_OFF) - for(var/device_id in alarm_area.air_scrub_names) - send_signal(device_id, list("power"= 0) ) - for(var/device_id in alarm_area.air_vent_names) - send_signal(device_id, list("power"= 0) ) - -/obj/machinery/alarm/proc/apply_danger_level(new_danger_level) - if (alarm_area.atmosalert(new_danger_level)) - post_alert(new_danger_level) - - update_icon() - -/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 = new - alert_signal.source = src - alert_signal.transmission_method = 1 - alert_signal.data["zone"] = alarm_area.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/shock(mob/user, prb) - if((stat & (NOPOWER))) // unpowered, no shock - return 0 - 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)) - return 1 - else - return 0 -/////////////// -//END HACKING// -/////////////// - -/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, master_ui = null, datum/topic_state/custom_state) - var/data[0] - var/remote_connection = 0 - var/remote_access = 0 - - if(custom_state) - var/list/href = custom_state.href_list(user) - remote_connection = href["remote_connection"] // Remote connection means we're non-adjacent/connecting from another computer - remote_access = href["remote_access"] // Remote access means we also have the privilege to alter the air alarm. - - data["locked"] = locked && !issilicon(user) && !isobserver(user) - data["remote_connection"] = remote_connection - data["remote_access"] = remote_access - data["rcon"] = rcon_setting - data["screen"] = screen - - populate_status(data) - - if(!(locked && !remote_connection) || remote_access || issilicon(user)) - populate_controls(data) - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if(!ui) - ui = new(user, src, ui_key, "air_alarm.tmpl", name, 450, 625, master_ui = master_ui, custom_state = custom_state) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/alarm/proc/populate_status(var/data) - var/turf/location = get_turf(src) - var/datum/gas_mixture/environment = location.return_air() - var/total = environment.total_moles - - var/list/environment_data = new - data["has_environment"] = total - if(total) - var/pressure = environment.return_pressure() - environment_data[++environment_data.len] = list("name" = "Pressure", "value" = pressure, "unit" = "kPa", "danger_level" = pressure_dangerlevel) - environment_data[++environment_data.len] = list("name" = "Oxygen", "value" = environment.gas["oxygen"] / total * 100, "unit" = "%", "danger_level" = oxygen_dangerlevel) - environment_data[++environment_data.len] = list("name" = "Carbon dioxide", "value" = environment.gas["carbon_dioxide"] / total * 100, "unit" = "%", "danger_level" = co2_dangerlevel) - environment_data[++environment_data.len] = list("name" = "Toxins", "value" = environment.gas["phoron"] / total * 100, "unit" = "%", "danger_level" = phoron_dangerlevel) - environment_data[++environment_data.len] = list("name" = "Temperature", "value" = environment.temperature, "unit" = "K ([round(environment.temperature - T0C, 0.1)]C)", "danger_level" = temperature_dangerlevel) - data["total_danger"] = danger_level - data["environment"] = environment_data - data["atmos_alarm"] = alarm_area.atmosalm - data["fire_alarm"] = alarm_area.fire != null - data["target_temperature"] = "[target_temperature - T0C]C" - data["thermoregulation"] = allow_regulate - -/obj/machinery/alarm/proc/populate_controls(var/list/data) - switch(screen) - if(AALARM_SCREEN_MAIN) - data["mode"] = mode - if(AALARM_SCREEN_VENT) - var/vents[0] - for(var/id_tag in alarm_area.air_vent_names) - var/long_name = alarm_area.air_vent_names[id_tag] - var/list/info = alarm_area.air_vent_info[id_tag] - if(!info) - continue - vents[++vents.len] = list( - "id_tag" = id_tag, - "long_name" = sanitize(long_name), - "power" = info["power"], - "checks" = info["checks"], - "direction" = info["direction"], - "external" = info["external"] - ) - data["vents"] = vents - if(AALARM_SCREEN_SCRUB) - var/scrubbers[0] - for(var/id_tag in alarm_area.air_scrub_names) - var/long_name = alarm_area.air_scrub_names[id_tag] - var/list/info = alarm_area.air_scrub_info[id_tag] - if(!info) - continue - scrubbers[++scrubbers.len] = list( - "id_tag" = id_tag, - "long_name" = sanitize(long_name), - "power" = info["power"], - "scrubbing" = info["scrubbing"], - "panic" = info["panic"], - "filters" = list() - ) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Oxygen", "command" = "o2_scrub", "val" = info["filter_o2"])) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrogen", "command" = "n2_scrub", "val" = info["filter_n2"])) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Carbon Dioxide", "command" = "co2_scrub", "val" = info["filter_co2"])) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Toxin", "command" = "tox_scrub", "val" = info["filter_phoron"])) - scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrous Oxide", "command" = "n2o_scrub", "val" = info["filter_n2o"])) - data["scrubbers"] = scrubbers - if(AALARM_SCREEN_MODE) - var/modes[0] - modes[++modes.len] = list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0) - modes[++modes.len] = list("name" = "Replace Air - Siphons out air while replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 0) - modes[++modes.len] = list("name" = "Panic - Siphons air out of the room", "mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1) - modes[++modes.len] = list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_CYCLE, "selected" = mode == AALARM_MODE_CYCLE, "danger" = 1) - modes[++modes.len] = list("name" = "Fill - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FILL, "selected" = mode == AALARM_MODE_FILL, "danger" = 0) - modes[++modes.len] = list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0) - data["modes"] = modes - data["mode"] = mode - if(AALARM_SCREEN_SENSORS) - var/list/selected - var/thresholds[0] - - var/list/gas_names = list( - "oxygen" = "O2", - "carbon dioxide" = "CO2", - "phoron" = "Toxin", - "other" = "Other") - for (var/g in gas_names) - thresholds[++thresholds.len] = list("name" = gas_names[g], "settings" = list()) - selected = TLV[g] - for (var/i in 1 to 4) - thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = i, "selected" = selected[i])) - - selected = TLV["pressure"] - thresholds[++thresholds.len] = list("name" = "Pressure", "settings" = list()) - for (var/i in 1 to 4) - thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = i, "selected" = selected[i])) - - selected = TLV["temperature"] - thresholds[++thresholds.len] = list("name" = "Temperature", "settings" = list()) - for (var/i in 1 to 4) - thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = i, "selected" = selected[i])) - - data["thresholds"] = thresholds - -/obj/machinery/alarm/CanUseTopic(mob/user, href_list, datum/topic_state/custom_state) - if(buildstage != 2) - return STATUS_CLOSE - - if(aidisabled && isAI(user)) - to_chat(user, "AI control for \the [src] interface has been disabled.") - return STATUS_CLOSE - - . = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE - - if(. == STATUS_INTERACTIVE) - var/extra_href = custom_state.href_list(usr) - // Prevent remote users from altering RCON settings unless they already have access - if(href_list && href_list["rcon"] && extra_href["remote_connection"] && !extra_href["remote_access"]) - . = STATUS_UPDATE - - return min(..(), .) - -/obj/machinery/alarm/Topic(href, href_list) - . = ..() - if(!.) // dont forget calling super in machine Topics -walter0o - return - - // hrefs that can always be called -walter0o - if(href_list["rcon"]) - var/attempted_rcon_setting = text2num(href_list["rcon"]) - - switch(attempted_rcon_setting) - if(RCON_NO) - rcon_setting = RCON_NO - if(RCON_AUTO) - rcon_setting = RCON_AUTO - if(RCON_YES) - rcon_setting = RCON_YES - else - return FALSE - - if(href_list["temperature"]) - var/list/selected = TLV["temperature"] - var/max_temperature = min(selected[3] - T0C-1, MAX_TEMPERATURE) // (-/+ 1) required because it won't heat/cool, if (target_temperature == TLV) - var/min_temperature = max(selected[2] - T0C+1, MIN_TEMPERATURE) - var/input_temperature = input("What temperature would you like the system to mantain? (Capped between [min_temperature] and [max_temperature]C)", "Thermostat Controls", target_temperature - T0C) as num|null - if(isnum(input_temperature)) - if(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 FALSE - - if(href_list["allow_regulate"]) - allow_regulate = !allow_regulate - - // hrefs that need the AA unlocked -walter0o - if(!locked || issilicon_allowed(usr) || isobserver(usr)) - - if(href_list["command"]) - var/device_id = href_list["id_tag"] - switch(href_list["command"]) - - if("set_external_pressure") - var/input_pressure = input("What pressure you like the system to mantain?", "Pressure Controls") as num|null - if(isnum(input_pressure)) - send_signal(device_id, list(href_list["command"] = input_pressure)) - return FALSE - - if("reset_external_pressure") - send_signal(device_id, list(href_list["command"] = ONE_ATMOSPHERE)) - return FALSE - - if( "power", - "adjust_external_pressure", - "set_external_pressure", - "checks", - "co2_scrub", - "tox_scrub", - "n2o_scrub", - "panic_siphon", - "scrubbing") - - send_signal(device_id, list(href_list["command"] = text2num(href_list["val"]) ) ) - if(href_list["command"] == "adjust_external_pressure") - var/new_val = text2num(href_list["val"]) - investigate_log("[usr.key] has changed adjust_external_pressure > added [new_val], id_tag = [device_id]","atmos") - if(href_list["command"] == "checks") - var/new_val = text2num(href_list["val"]) - investigate_log("[usr.key] has changed pressure_checks > now [new_val](1 = ext, 2 = int, 3 = both), id_tag = [device_id]","atmos") - - if("set_threshold") - var/env = href_list["env"] - var/threshold = text2num(href_list["var"]) - var/list/selected = TLV[env] - var/list/thresholds = list("lower bound", "low warning", "high warning", "upper bound") - var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as null|num - if (isnull(newval)) - return TRUE - 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 FALSE - - if(href_list["screen"]) - screen = text2num(href_list["screen"]) - return FALSE - - if(href_list["atmos_unlock"]) - switch(href_list["atmos_unlock"]) - if("0") - alarm_area.air_doors_close() - if("1") - alarm_area.air_doors_open() - return FALSE - - if(href_list["atmos_alarm"]) - if (alarm_area.atmosalert(2, src)) - apply_danger_level(2) - update_icon() - return FALSE - - if(href_list["atmos_reset"]) - if (alarm_area.atmosalert(0, src)) - apply_danger_level(0) - update_icon() - return FALSE - - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - apply_mode() - return FALSE - - -/obj/machinery/alarm/attack_alien(mob/living/carbon/alien/humanoid/user) - user.show_message("You don't want to break these things", 1); - return - -/obj/machinery/alarm/attackby(obj/item/W, mob/user) - - add_fingerprint(user) - - switch(buildstage) - if(2) - if(istype(W, /obj/item/weapon/screwdriver)) // Opening that Air Alarm up. - wiresexposed = !wiresexposed - to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]") - update_icon() - return - - if (istype(W, /obj/item/weapon/wirecutters) && wiresexposed && wires.is_all_cut()) - user.visible_message("[user] has cut the wires inside \the [src]!", "You have cut the wires inside \the [src].") - playsound(loc, 'sound/items/Wirecutter.ogg', 50, 1) - new /obj/item/stack/cable_coil/random(loc, 5) - buildstage = 1 - update_icon() - 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(usr) && !wires.is_index_cut(AALARM_WIRE_IDSCAN)) - locked = !locked - to_chat(user, "\blue You [ locked ? "lock" : "unlock"] the Air Alarm interface.") - updateUsrDialog() - else - to_chat(user, "\red Access denied.") - - if(wiresexposed && is_wire_tool(W)) - wires.interact(user) - return - - return - - if(1) - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = W - if(!coil.use(5)) - to_chat(user, "You need 5 pieces of cable to do wire \the [src].") - return - - to_chat(user, "You wire \the [src]!") - - buildstage = 2 - update_icon() - first_run() - wires.repair() - return - - else if(istype(W, /obj/item/weapon/crowbar)) - if(user.is_busy()) - return - to_chat(user, "You start prying out the circuit.") - playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) - if(do_after(user,20,target = src)) - to_chat(user, "You pry out the circuit!") - var/obj/item/weapon/airalarm_electronics/circuit = new /obj/item/weapon/airalarm_electronics() - circuit.loc = user.loc - buildstage = 0 - update_icon() - return - if(0) - if(istype(W, /obj/item/weapon/airalarm_electronics)) - to_chat(user, "You insert the circuit!") - qdel(W) - buildstage = 1 - update_icon() - return - - else if(istype(W, /obj/item/weapon/wrench)) - to_chat(user, "You remove the fire alarm assembly from the wall!") - var/obj/item/alarm_frame/frame = new /obj/item/alarm_frame() - frame.loc = user.loc - playsound(loc, '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) - to_chat(user, "The circuit is missing.") -/* -AIR ALARM CIRCUIT -Just a object used in constructing air alarms -*/ -/obj/item/weapon/airalarm_electronics - name = "air alarm electronics" - icon = 'icons/obj/doors/door_electronics.dmi' - icon_state = "door_electronics" - desc = "Looks like a circuit. Probably is." - w_class = 2.0 - m_amt = 50 - g_amt = 50 - - -/* -AIR ALARM ITEM -Handheld air alarm frame, for placing on walls -Code shamelessly copied from apc_frame -*/ -/obj/item/alarm_frame - name = "air alarm frame" - desc = "Used for building Air Alarms" - icon = 'icons/obj/monitors.dmi' - icon_state = "alarm_bitem" - flags = CONDUCT - -/obj/item/alarm_frame/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - user.SetNextMove(CLICK_CD_RAPID) - new /obj/item/stack/sheet/metal(loc, 2) - qdel(src) - return - ..() - -/obj/item/alarm_frame/proc/try_build(turf/on_wall) - if (get_dist(on_wall,usr)>1) - return - - var/ndir = get_dir(on_wall,usr) - if (!(ndir in cardinal)) - return - - var/turf/loc = get_turf_loc(usr) - var/area/A = loc.loc - if (!istype(loc, /turf/simulated/floor)) - to_chat(usr, "\red Air Alarm cannot be placed on this spot.") - return - if (A.requires_power == 0 || A.name == "Space") - to_chat(usr, "\red Air Alarm cannot be placed in this area.") - return - - if(gotwallitem(loc, ndir)) - to_chat(usr, "\red There's already an item on this wall!") - return - - new /obj/machinery/alarm(loc, ndir, 1) - qdel(src) - -/* -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 - allowed_checks = ALLOWED_CHECK_NONE - 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) - icon_state="fire_build[buildstage]" - return - - if(stat & BROKEN) - icon_state = "fire_broken" - else if(stat & NOPOWER) - icon_state = "fire_unpowered" - else if(!detecting) - icon_state = "fire1" - else - icon_state = "fire0" - -/obj/machinery/firealarm/fire_act(datum/gas_mixture/air, temperature, volume) - if(detecting) - if(temperature > T0C+200) - alarm() // added check of detector status here - return - -/obj/machinery/firealarm/bullet_act(BLAH) - return alarm() - -/obj/machinery/firealarm/emp_act(severity) - if(prob(50/severity)) - alarm() - ..() - -/obj/machinery/firealarm/attackby(obj/item/W, mob/user) - add_fingerprint(user) - - if (istype(W, /obj/item/weapon/screwdriver) && buildstage == 2) - wiresexposed = !wiresexposed - update_icon() - return - - if(wiresexposed) - switch(buildstage) - if(2) - if (istype(W, /obj/item/device/multitool)) - detecting = !detecting - if (detecting) - user.visible_message("\red [user] has reconnected [src]'s detecting unit!", "You have reconnected [src]'s detecting unit.") - else - user.visible_message("\red [user] has disconnected [src]'s detecting unit!", "You have disconnected [src]'s detecting unit.") - else if (istype(W, /obj/item/weapon/wirecutters)) - user.visible_message("\red [user] has cut the wires inside \the [src]!", "You have cut the wires inside \the [src].") - new /obj/item/stack/cable_coil/random(loc, 5) - playsound(loc, 'sound/items/Wirecutter.ogg', 50, 1) - buildstage = 1 - update_icon() - if(1) - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = W - if(!coil.use(5)) - to_chat(user, "You need 5 pieces of cable to do wire \the [src].") - return - - buildstage = 2 - to_chat(user, "You wire \the [src]!") - update_icon() - - else if(istype(W, /obj/item/weapon/crowbar)) - to_chat(user, "You start prying out the circuit.") - playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) - if(do_after(user,20,target = src)) - to_chat(user, "You pry out the circuit!") - var/obj/item/weapon/firealarm_electronics/circuit = new /obj/item/weapon/firealarm_electronics() - circuit.loc = user.loc - buildstage = 0 - update_icon() - - if(0) - if(istype(W, /obj/item/weapon/firealarm_electronics)) - to_chat(user, "You insert the circuit!") - qdel(W) - buildstage = 1 - update_icon() - - else if(istype(W, /obj/item/weapon/wrench)) - to_chat(user, "You remove the fire alarm assembly from the wall!") - var/obj/item/firealarm_frame/frame = new /obj/item/firealarm_frame() - frame.loc = user.loc - playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) - qdel(src) - return - - alarm() - return - -/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(timing) - if(time > 0) - time = time - ((world.timeofday - last_process)/10) - else - alarm() - time = 0 - timing = 0 - STOP_PROCESSING(SSobj, 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/ui_interact(mob/user) - if (buildstage != 2) - return - - user.set_machine(src) - var/area/A = get_area(src) - var/d1 - var/d2 - if (ishuman(user) || issilicon(user) || isobserver(user)) - if (A.fire) - d1 = text("Reset - Lockdown", src) - else - d1 = text("Alarm - Lockdown", src) - if (timing) - d2 = text("Stop Time Lock", src) - else - d2 = text("Initiate Time Lock", src) - var/second = round(time) % 60 - var/minute = (round(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(entity_ja(dat), "window=firealarm") - onclose(user, "firealarm") - else - if (A.fire) - d1 = text("[]", src, stars("Reset - Lockdown")) - else - d1 = text("[]", src, stars("Alarm - Lockdown")) - if (timing) - d2 = text("[]", src, stars("Stop Time Lock")) - else - d2 = text("[]", src, stars("Initiate Time Lock")) - var/second = round(time) % 60 - var/minute = (round(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(entity_ja(dat), "window=firealarm") - onclose(user, "firealarm") - -/obj/machinery/firealarm/Topic(href, href_list) - . = ..() - if(!.) - return - - if (buildstage != 2) - return FALSE - - if (href_list["reset"]) - reset() - else if (href_list["alarm"]) - alarm() - else if (href_list["time"]) - timing = text2num(href_list["time"]) - last_process = world.timeofday - START_PROCESSING(SSobj, src) - else if (href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 120) - - updateUsrDialog() - -/obj/machinery/firealarm/proc/reset() - if (!working) - return - var/area/A = get_area(src) - A.firereset() - for(var/obj/machinery/firealarm/FA in A) - FA.detecting = TRUE - FA.update_icon() - -/obj/machinery/firealarm/proc/alarm() - if (!working) - return - var/area/A = get_area(src) - A.firealert() - for(var/obj/machinery/firealarm/FA in A) - FA.detecting = FALSE - FA.update_icon() - -/obj/machinery/firealarm/atom_init(mapload, dir, building) - . = ..() - - firealarm_list += src - - 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 == ZLEVEL_STATION || z == ZLEVEL_ASTEROID) - if(security_level) - overlays += image('icons/obj/monitors.dmi', "overlay_[get_security_level()]") - else - overlays += image('icons/obj/monitors.dmi', "overlay_green") - - update_icon() - -/obj/machinery/firealarm/Destroy() - firealarm_list -= src - return ..() - -/* -FIRE ALARM CIRCUIT -Just a object used in constructing fire alarms -*/ -/obj/item/weapon/firealarm_electronics - name = "fire alarm electronics" - icon = 'icons/obj/doors/door_electronics.dmi' - icon_state = "door_electronics" - desc = "A circuit. It has a label on it, it says \"Can handle heat levels up to 40 degrees celsius!\"" - w_class = 2.0 - m_amt = 50 - g_amt = 50 - - -/* -FIRE ALARM ITEM -Handheld fire alarm frame, for placing on walls -Code shamelessly copied from apc_frame -*/ -/obj/item/firealarm_frame - name = "fire alarm frame" - desc = "Used for building Fire Alarms." - icon = 'icons/obj/monitors.dmi' - icon_state = "fire_bitem" - flags = CONDUCT - -/obj/item/firealarm_frame/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - user.SetNextMove(CLICK_CD_RAPID) - new /obj/item/stack/sheet/metal(loc, 2) - qdel(src) - return - ..() - -/obj/item/firealarm_frame/proc/try_build(turf/on_wall) - if (get_dist(on_wall,usr) > 1) - return - - var/ndir = get_dir(on_wall,usr) - if (!(ndir in cardinal)) - return - - var/turf/loc = get_turf_loc(usr) - var/area/A = get_area(src) - if (!istype(loc, /turf/simulated/floor)) - to_chat(usr, "\red Fire Alarm cannot be placed on this spot.") - return - if (A.requires_power == 0 || A.name == "Space") - to_chat(usr, "\red Fire Alarm cannot be placed in this area.") - return - - if(gotwallitem(loc, ndir)) - to_chat(usr, "\red There's already an item on this wall!") - return - - new /obj/machinery/firealarm(loc, ndir, 1) - - qdel(src) +//////////////////////////////////////// +//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_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 + +#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 + name = "alarm" + icon = 'icons/obj/monitors.dmi' + icon_state = "alarm0" + anchored = TRUE + use_power = TRUE + idle_power_usage = 80 + active_power_usage = 1000 // For heating/cooling rooms. 1000 joules equates to about 1 degree every 2 seconds for a single tile of air. + power_channel = ENVIRON + req_one_access = list(access_atmospherics, access_engine_equip) + frequency = 1439 + allowed_checks = ALLOWED_CHECK_NONE + unacidable = TRUE + + var/breach_detection = TRUE // Whether to use automatic breach detection or not + //var/skipprocess = 0 //Experimenting + var/alarm_frequency = 1437 + var/remote_control = FALSE + var/rcon_setting = 2 + var/rcon_time = 0 + var/locked = TRUE + var/wiresexposed = FALSE // If it's been screwdrivered open. + var/aidisabled = FALSE + var/shorted = FALSE + var/hidden_from_console = FALSE + + var/datum/wires/alarm/wires = null + + var/mode = AALARM_MODE_SCRUBBING + var/screen = AALARM_SCREEN_MAIN + var/area_uid + var/area/alarm_area + var/buildstage = 2 //2 is built, 1 is building, 0 is frame. + + var/target_temperature = T0C+20 + var/regulating_temperature = 0 + var/allow_regulate = 0 //Is thermoregulation enabled? + + var/list/TLV = list() + var/list/trace_gas = list("sleeping_agent") //list of other gases that this air alarm is able to detect + + var/danger_level = 0 + var/pressure_dangerlevel = 0 + var/oxygen_dangerlevel = 0 + var/co2_dangerlevel = 0 + var/phoron_dangerlevel = 0 + var/temperature_dangerlevel = 0 + var/other_dangerlevel = 0 + +/obj/machinery/alarm/server/atom_init() + . = ..() + req_access = list(access_rd, access_atmospherics, access_engine_equip) + TLV["oxygen"] = list(-1.0, -1.0,-1.0,-1.0) // Partial pressure, kpa + TLV["carbon dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa + TLV["phoron"] = 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 + + +/obj/machinery/alarm/atom_init(mapload, dir, building = 0) + . = ..() + alarm_list += src + set_frequency(frequency) + + 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() + return // not sure about this, is constructing initializing it same as first_run()? + + if (!master_is_operating()) + elect_master() + first_run() + +/obj/machinery/alarm/proc/first_run() + alarm_area = get_area(src) + if (alarm_area.master) + alarm_area = alarm_area.master + area_uid = alarm_area.uid + if (name == "alarm") + name = "[alarm_area.name] Air Alarm" + if(!wires) + wires = new(src) + + // breathable air according to human/Life() + TLV["oxygen"] = list(16, 19, 135, 140) // Partial pressure, kpa + TLV["carbon dioxide"] = list(-1.0, -1.0, 5, 10) // Partial pressure, kpa + TLV["phoron"] = 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 + +/obj/machinery/alarm/Destroy() + alarm_list -= src + if(wires) + QDEL_NULL(wires) + if(alarm_area && alarm_area.master_air_alarm == src) + alarm_area.master_air_alarm = null + alarm_area = null + return ..() + +/obj/machinery/alarm/process() + if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2) + 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. + handle_heating_cooling(environment) + + var/old_level = danger_level + var/old_pressurelevel = pressure_dangerlevel + danger_level = overall_danger_level() + + if (old_level != danger_level) + apply_danger_level(danger_level) + + if (old_pressurelevel != pressure_dangerlevel) + if (breach_detected()) + mode = AALARM_MODE_OFF + apply_mode() + + if (mode==AALARM_MODE_CYCLE && environment.return_pressure() 2.0) + update_use_power(2) + 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.") + else + //check for when we should stop adjusting temperature + if (!allow_regulate || get_danger_level(target_temperature, TLV["temperature"]) || abs(environment.temperature - target_temperature) <= 0.5) + update_use_power(1) + 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.") + + if (regulating_temperature) + 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 = environment.remove(0.25 * environment.total_moles) + + if(gas) + + if (gas.temperature <= target_temperature) //gas heating + var/energy_used = min(gas.get_thermal_energy_change(target_temperature) , active_power_usage) + + gas.add_thermal_energy(energy_used) + //use_power(energy_used, ENVIRON) //handle by update_use_power instead + else //gas cooling + var/heat_transfer = min(abs(gas.get_thermal_energy_change(target_temperature)), active_power_usage) + + //Assume the heat is being pumped into the hull which is fixed at 20 C + //none of this is really proper thermodynamics but whatever + + var/cop = gas.temperature / T20C //coefficient of performance -> power used = heat_transfer/cop + + heat_transfer = min(heat_transfer, cop * active_power_usage) //this ensures that we don't use more than active_power_usage amount of power + + heat_transfer = -gas.add_thermal_energy(-heat_transfer) //get the actual heat transfer + + //use_power(heat_transfer / cop, ENVIRON) //handle by update_use_power instead + + environment.merge(gas) + +/obj/machinery/alarm/proc/overall_danger_level() + var/turf/simulated/location = loc + if(!istype(location)) return//returns if loc is not simulated + + var/datum/gas_mixture/environment = location.return_air() + + var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume + var/environment_pressure = environment.return_pressure() + + var/other_moles = 0 + for(var/g in trace_gas) + other_moles += environment.gas[g] //this is only going to be used in a partial pressure calc, so we don't need to worry about group_multiplier here. + + pressure_dangerlevel = get_danger_level(environment_pressure, TLV["pressure"]) + oxygen_dangerlevel = get_danger_level(environment.gas["oxygen"] * partial_pressure, TLV["oxygen"]) + co2_dangerlevel = get_danger_level(environment.gas["carbon_dioxide"] * partial_pressure, TLV["carbon dioxide"]) + phoron_dangerlevel = get_danger_level(environment.gas["phoron"] * partial_pressure, TLV["phoron"]) + temperature_dangerlevel = get_danger_level(environment.temperature, TLV["temperature"]) + other_dangerlevel = get_danger_level(other_moles*partial_pressure, TLV["other"]) + + return max( + pressure_dangerlevel, + oxygen_dangerlevel, + co2_dangerlevel, + phoron_dangerlevel, + other_dangerlevel, + temperature_dangerlevel + ) + +// Returns whether this air alarm thinks there is a breach, given the sensors that are available to it. +/obj/machinery/alarm/proc/breach_detected() + var/turf/simulated/location = loc + + if(!istype(location)) + return 0 + + if(!breach_detection) + return 0 + + var/datum/gas_mixture/environment = location.return_air() + var/environment_pressure = environment.return_pressure() + var/pressure_levels = TLV["pressure"] + + if (environment_pressure <= pressure_levels[1]) //low pressures + if (!(mode == AALARM_MODE_PANIC || mode == AALARM_MODE_CYCLE)) + return 1 + + return 0 + + +/obj/machinery/alarm/proc/master_is_operating() + if(!alarm_area) return + return alarm_area.master_air_alarm && !(alarm_area.master_air_alarm.stat & (NOPOWER|BROKEN)) + + +/obj/machinery/alarm/proc/elect_master() + if(!alarm_area) return + for (var/area/A in alarm_area.related) + for (var/obj/machinery/alarm/AA in A) + if (!(AA.stat & (NOPOWER|BROKEN))) + alarm_area.master_air_alarm = AA + return 1 + return 0 + +/obj/machinery/alarm/proc/get_danger_level(current_value, list/danger_levels) + if((current_value >= 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="alarm_build[buildstage]" + return + + if((stat & NOPOWER) || shorted) + icon_state = "alarm_unpowered" + return + if(stat & BROKEN) + icon_state = "alarm_broken" + return + + var/icon_level = danger_level + if (alarm_area.atmosalm) + icon_level = max(icon_level, 1) //if there's an atmos alarm but everything is okay locally, no need to go past yellow + icon_state = "alarm[icon_level]" + +/obj/machinery/alarm/receive_signal(datum/signal/signal) + if(stat & (NOPOWER|BROKEN)) + return + if (alarm_area.master_air_alarm != src) + if (master_is_operating()) + return + elect_master() + if (alarm_area.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 alarm_area.air_scrub_names) && !(id_tag in alarm_area.air_vent_names)) + register_env_machine(id_tag, dev_type) + if(dev_type == "AScr") + alarm_area.air_scrub_info[id_tag] = signal.data + else if(dev_type == "AVP") + alarm_area.air_vent_info[id_tag] = signal.data + +/obj/machinery/alarm/proc/register_env_machine(m_id, device_type) + var/new_name + if (device_type=="AVP") + new_name = "[alarm_area.name] Vent Pump #[alarm_area.air_vent_names.len+1]" + alarm_area.air_vent_names[m_id] = new_name + else if (device_type=="AScr") + new_name = "[alarm_area.name] Air Scrubber #[alarm_area.air_scrub_names.len+1]" + alarm_area.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 alarm_area.air_vent_names) + var/list/I = alarm_area.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 alarm_area.air_scrub_names) + var/list/I = alarm_area.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/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency, RADIO_TO_AIRALARM) + +/obj/machinery/alarm/proc/send_signal(target, list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise + if(!radio_connection) + return 0 + + var/datum/signal/signal = new + 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) +// world << text("Signal [] Broadcasted to []", command, target) + + return 1 + +/obj/machinery/alarm/proc/apply_mode() + //propagate mode to other air alarms in the area + //TODO: make it so that players can choose between applying the new mode to the room they are in (related area) vs the entire alarm area + for (var/area/RA in alarm_area.related) + for (var/obj/machinery/alarm/AA in RA) + AA.mode = mode + + switch(mode) + if(AALARM_MODE_SCRUBBING) + for(var/device_id in alarm_area.air_scrub_names) + send_signal(device_id, list("power"= 1, "co2_scrub"= 1, "scrubbing"= 1, "panic_siphon"= 0) ) + for(var/device_id in alarm_area.air_vent_names) + send_signal(device_id, list("power"= 1, "checks"= "default", "set_external_pressure"= "default") ) + + if(AALARM_MODE_PANIC, AALARM_MODE_CYCLE) + for(var/device_id in alarm_area.air_scrub_names) + send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) + for(var/device_id in alarm_area.air_vent_names) + send_signal(device_id, list("power"= 0) ) + + if(AALARM_MODE_REPLACEMENT) + for(var/device_id in alarm_area.air_scrub_names) + send_signal(device_id, list("power"= 1, "panic_siphon"= 1) ) + for(var/device_id in alarm_area.air_vent_names) + send_signal(device_id, list("power"= 1, "checks"= "default", "set_external_pressure"= "default") ) + + if(AALARM_MODE_FILL) + for(var/device_id in alarm_area.air_scrub_names) + send_signal(device_id, list("power"= 0) ) + for(var/device_id in alarm_area.air_vent_names) + send_signal(device_id, list("power"= 1, "checks"= "default", "set_external_pressure"= "default") ) + + if(AALARM_MODE_OFF) + for(var/device_id in alarm_area.air_scrub_names) + send_signal(device_id, list("power"= 0) ) + for(var/device_id in alarm_area.air_vent_names) + send_signal(device_id, list("power"= 0) ) + +/obj/machinery/alarm/proc/apply_danger_level(new_danger_level) + if (alarm_area.atmosalert(new_danger_level)) + post_alert(new_danger_level) + + update_icon() + +/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 = new + alert_signal.source = src + alert_signal.transmission_method = 1 + alert_signal.data["zone"] = alarm_area.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/shock(mob/user, prb) + if((stat & (NOPOWER))) // unpowered, no shock + return 0 + 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)) + return 1 + else + return 0 +/////////////// +//END HACKING// +/////////////// + +/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, master_ui = null, datum/topic_state/custom_state) + var/data[0] + var/remote_connection = 0 + var/remote_access = 0 + + if(custom_state) + var/list/href = custom_state.href_list(user) + remote_connection = href["remote_connection"] // Remote connection means we're non-adjacent/connecting from another computer + remote_access = href["remote_access"] // Remote access means we also have the privilege to alter the air alarm. + + data["locked"] = locked && !issilicon(user) && !isobserver(user) + data["remote_connection"] = remote_connection + data["remote_access"] = remote_access + data["rcon"] = rcon_setting + data["screen"] = screen + + populate_status(data) + + if(!(locked && !remote_connection) || remote_access || issilicon(user)) + populate_controls(data) + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if(!ui) + ui = new(user, src, ui_key, "air_alarm.tmpl", name, 450, 625, master_ui = master_ui, custom_state = custom_state) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/alarm/proc/populate_status(var/data) + var/turf/location = get_turf(src) + var/datum/gas_mixture/environment = location.return_air() + var/total = environment.total_moles + + var/list/environment_data = new + data["has_environment"] = total + if(total) + var/pressure = environment.return_pressure() + environment_data[++environment_data.len] = list("name" = "Pressure", "value" = pressure, "unit" = "kPa", "danger_level" = pressure_dangerlevel) + environment_data[++environment_data.len] = list("name" = "Oxygen", "value" = environment.gas["oxygen"] / total * 100, "unit" = "%", "danger_level" = oxygen_dangerlevel) + environment_data[++environment_data.len] = list("name" = "Carbon dioxide", "value" = environment.gas["carbon_dioxide"] / total * 100, "unit" = "%", "danger_level" = co2_dangerlevel) + environment_data[++environment_data.len] = list("name" = "Toxins", "value" = environment.gas["phoron"] / total * 100, "unit" = "%", "danger_level" = phoron_dangerlevel) + environment_data[++environment_data.len] = list("name" = "Temperature", "value" = environment.temperature, "unit" = "K ([round(environment.temperature - T0C, 0.1)]C)", "danger_level" = temperature_dangerlevel) + data["total_danger"] = danger_level + data["environment"] = environment_data + data["atmos_alarm"] = alarm_area.atmosalm + data["fire_alarm"] = alarm_area.fire != null + data["target_temperature"] = "[target_temperature - T0C]C" + data["thermoregulation"] = allow_regulate + +/obj/machinery/alarm/proc/populate_controls(var/list/data) + switch(screen) + if(AALARM_SCREEN_MAIN) + data["mode"] = mode + if(AALARM_SCREEN_VENT) + var/vents[0] + for(var/id_tag in alarm_area.air_vent_names) + var/long_name = alarm_area.air_vent_names[id_tag] + var/list/info = alarm_area.air_vent_info[id_tag] + if(!info) + continue + vents[++vents.len] = list( + "id_tag" = id_tag, + "long_name" = sanitize(long_name), + "power" = info["power"], + "checks" = info["checks"], + "direction" = info["direction"], + "external" = info["external"] + ) + data["vents"] = vents + if(AALARM_SCREEN_SCRUB) + var/scrubbers[0] + for(var/id_tag in alarm_area.air_scrub_names) + var/long_name = alarm_area.air_scrub_names[id_tag] + var/list/info = alarm_area.air_scrub_info[id_tag] + if(!info) + continue + scrubbers[++scrubbers.len] = list( + "id_tag" = id_tag, + "long_name" = sanitize(long_name), + "power" = info["power"], + "scrubbing" = info["scrubbing"], + "panic" = info["panic"], + "filters" = list() + ) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Oxygen", "command" = "o2_scrub", "val" = info["filter_o2"])) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrogen", "command" = "n2_scrub", "val" = info["filter_n2"])) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Carbon Dioxide", "command" = "co2_scrub", "val" = info["filter_co2"])) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Toxin", "command" = "tox_scrub", "val" = info["filter_phoron"])) + scrubbers[scrubbers.len]["filters"] += list(list("name" = "Nitrous Oxide", "command" = "n2o_scrub", "val" = info["filter_n2o"])) + data["scrubbers"] = scrubbers + if(AALARM_SCREEN_MODE) + var/modes[0] + modes[++modes.len] = list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0) + modes[++modes.len] = list("name" = "Replace Air - Siphons out air while replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 0) + modes[++modes.len] = list("name" = "Panic - Siphons air out of the room", "mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1) + modes[++modes.len] = list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_CYCLE, "selected" = mode == AALARM_MODE_CYCLE, "danger" = 1) + modes[++modes.len] = list("name" = "Fill - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FILL, "selected" = mode == AALARM_MODE_FILL, "danger" = 0) + modes[++modes.len] = list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0) + data["modes"] = modes + data["mode"] = mode + if(AALARM_SCREEN_SENSORS) + var/list/selected + var/thresholds[0] + + var/list/gas_names = list( + "oxygen" = "O2", + "carbon dioxide" = "CO2", + "phoron" = "Toxin", + "other" = "Other") + for (var/g in gas_names) + thresholds[++thresholds.len] = list("name" = gas_names[g], "settings" = list()) + selected = TLV[g] + for (var/i in 1 to 4) + thresholds[thresholds.len]["settings"] += list(list("env" = g, "val" = i, "selected" = selected[i])) + + selected = TLV["pressure"] + thresholds[++thresholds.len] = list("name" = "Pressure", "settings" = list()) + for (var/i in 1 to 4) + thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = i, "selected" = selected[i])) + + selected = TLV["temperature"] + thresholds[++thresholds.len] = list("name" = "Temperature", "settings" = list()) + for (var/i in 1 to 4) + thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = i, "selected" = selected[i])) + + data["thresholds"] = thresholds + +/obj/machinery/alarm/CanUseTopic(mob/user, href_list, datum/topic_state/custom_state) + if(buildstage != 2) + return STATUS_CLOSE + + if(aidisabled && isAI(user)) + to_chat(user, "AI control for \the [src] interface has been disabled.") + return STATUS_CLOSE + + . = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE + + if(. == STATUS_INTERACTIVE) + var/extra_href = custom_state.href_list(usr) + // Prevent remote users from altering RCON settings unless they already have access + if(href_list && href_list["rcon"] && extra_href["remote_connection"] && !extra_href["remote_access"]) + . = STATUS_UPDATE + + return min(..(), .) + +/obj/machinery/alarm/Topic(href, href_list) + . = ..() + if(!.) // dont forget calling super in machine Topics -walter0o + return + + // hrefs that can always be called -walter0o + if(href_list["rcon"]) + var/attempted_rcon_setting = text2num(href_list["rcon"]) + + switch(attempted_rcon_setting) + if(RCON_NO) + rcon_setting = RCON_NO + if(RCON_AUTO) + rcon_setting = RCON_AUTO + if(RCON_YES) + rcon_setting = RCON_YES + else + return FALSE + + if(href_list["temperature"]) + var/list/selected = TLV["temperature"] + var/max_temperature = min(selected[3] - T0C-1, MAX_TEMPERATURE) // (-/+ 1) required because it won't heat/cool, if (target_temperature == TLV) + var/min_temperature = max(selected[2] - T0C+1, MIN_TEMPERATURE) + var/input_temperature = input("What temperature would you like the system to mantain? (Capped between [min_temperature] and [max_temperature]C)", "Thermostat Controls", target_temperature - T0C) as num|null + if(isnum(input_temperature)) + if(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 FALSE + + if(href_list["allow_regulate"]) + allow_regulate = !allow_regulate + + // hrefs that need the AA unlocked -walter0o + if(!locked || issilicon_allowed(usr) || isobserver(usr)) + + if(href_list["command"]) + var/device_id = href_list["id_tag"] + switch(href_list["command"]) + + if("set_external_pressure") + var/input_pressure = input("What pressure you like the system to mantain?", "Pressure Controls") as num|null + if(isnum(input_pressure)) + send_signal(device_id, list(href_list["command"] = input_pressure)) + return FALSE + + if("reset_external_pressure") + send_signal(device_id, list(href_list["command"] = ONE_ATMOSPHERE)) + return FALSE + + if( "power", + "adjust_external_pressure", + "set_external_pressure", + "checks", + "co2_scrub", + "tox_scrub", + "n2o_scrub", + "panic_siphon", + "scrubbing") + + send_signal(device_id, list(href_list["command"] = text2num(href_list["val"]) ) ) + if(href_list["command"] == "adjust_external_pressure") + var/new_val = text2num(href_list["val"]) + investigate_log("[usr.key] has changed adjust_external_pressure > added [new_val], id_tag = [device_id]","atmos") + if(href_list["command"] == "checks") + var/new_val = text2num(href_list["val"]) + investigate_log("[usr.key] has changed pressure_checks > now [new_val](1 = ext, 2 = int, 3 = both), id_tag = [device_id]","atmos") + + if("set_threshold") + var/env = href_list["env"] + var/threshold = text2num(href_list["var"]) + var/list/selected = TLV[env] + var/list/thresholds = list("lower bound", "low warning", "high warning", "upper bound") + var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as null|num + if (isnull(newval)) + return TRUE + 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 FALSE + + if(href_list["screen"]) + screen = text2num(href_list["screen"]) + return FALSE + + if(href_list["atmos_unlock"]) + switch(href_list["atmos_unlock"]) + if("0") + alarm_area.air_doors_close() + if("1") + alarm_area.air_doors_open() + return FALSE + + if(href_list["atmos_alarm"]) + if (alarm_area.atmosalert(2, src)) + apply_danger_level(2) + update_icon() + return FALSE + + if(href_list["atmos_reset"]) + if (alarm_area.atmosalert(0, src)) + apply_danger_level(0) + update_icon() + return FALSE + + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + apply_mode() + return FALSE + + +/obj/machinery/alarm/attack_alien(mob/living/carbon/alien/humanoid/user) + user.show_message("You don't want to break these things", 1); + return + +/obj/machinery/alarm/attackby(obj/item/W, mob/user) + + add_fingerprint(user) + + switch(buildstage) + if(2) + if(istype(W, /obj/item/weapon/screwdriver)) // Opening that Air Alarm up. + wiresexposed = !wiresexposed + to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]") + update_icon() + return + + if (istype(W, /obj/item/weapon/wirecutters) && wiresexposed && wires.is_all_cut()) + user.visible_message("[user] has cut the wires inside \the [src]!", "You have cut the wires inside \the [src].") + playsound(loc, 'sound/items/Wirecutter.ogg', 50, 1) + new /obj/item/stack/cable_coil/random(loc, 5) + buildstage = 1 + update_icon() + 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(usr) && !wires.is_index_cut(AALARM_WIRE_IDSCAN)) + locked = !locked + to_chat(user, "\blue You [ locked ? "lock" : "unlock"] the Air Alarm interface.") + updateUsrDialog() + else + to_chat(user, "\red Access denied.") + + if(wiresexposed && is_wire_tool(W)) + wires.interact(user) + return + + return + + if(1) + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = W + if(!coil.use(5)) + to_chat(user, "You need 5 pieces of cable to do wire \the [src].") + return + + to_chat(user, "You wire \the [src]!") + + buildstage = 2 + update_icon() + first_run() + wires.repair() + return + + else if(istype(W, /obj/item/weapon/crowbar)) + if(user.is_busy()) + return + to_chat(user, "You start prying out the circuit.") + playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) + if(do_after(user,20,target = src)) + to_chat(user, "You pry out the circuit!") + var/obj/item/weapon/airalarm_electronics/circuit = new /obj/item/weapon/airalarm_electronics() + circuit.loc = user.loc + buildstage = 0 + update_icon() + return + if(0) + if(istype(W, /obj/item/weapon/airalarm_electronics)) + to_chat(user, "You insert the circuit!") + qdel(W) + buildstage = 1 + update_icon() + return + + else if(istype(W, /obj/item/weapon/wrench)) + to_chat(user, "You remove the fire alarm assembly from the wall!") + var/obj/item/alarm_frame/frame = new /obj/item/alarm_frame() + frame.loc = user.loc + playsound(loc, '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) + to_chat(user, "The circuit is missing.") +/* +AIR ALARM CIRCUIT +Just a object used in constructing air alarms +*/ +/obj/item/weapon/airalarm_electronics + name = "air alarm electronics" + icon = 'icons/obj/doors/door_electronics.dmi' + icon_state = "door_electronics" + desc = "Looks like a circuit. Probably is." + w_class = 2.0 + m_amt = 50 + g_amt = 50 + + +/* +AIR ALARM ITEM +Handheld air alarm frame, for placing on walls +Code shamelessly copied from apc_frame +*/ +/obj/item/alarm_frame + name = "air alarm frame" + desc = "Used for building Air Alarms" + icon = 'icons/obj/monitors.dmi' + icon_state = "alarm_bitem" + flags = CONDUCT + +/obj/item/alarm_frame/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + user.SetNextMove(CLICK_CD_RAPID) + new /obj/item/stack/sheet/metal(loc, 2) + qdel(src) + return + ..() + +/obj/item/alarm_frame/proc/try_build(turf/on_wall) + if (get_dist(on_wall,usr)>1) + return + + var/ndir = get_dir(on_wall,usr) + if (!(ndir in cardinal)) + return + + var/turf/loc = get_turf_loc(usr) + var/area/A = loc.loc + if (!istype(loc, /turf/simulated/floor)) + to_chat(usr, "\red Air Alarm cannot be placed on this spot.") + return + if (A.requires_power == 0 || A.name == "Space") + to_chat(usr, "\red Air Alarm cannot be placed in this area.") + return + + if(gotwallitem(loc, ndir)) + to_chat(usr, "\red There's already an item on this wall!") + return + + new /obj/machinery/alarm(loc, ndir, 1) + qdel(src) + +/* +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 + allowed_checks = ALLOWED_CHECK_NONE + 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) + icon_state="fire_build[buildstage]" + return + + if(stat & BROKEN) + icon_state = "fire_broken" + else if(stat & NOPOWER) + icon_state = "fire_unpowered" + else if(!detecting) + icon_state = "fire1" + else + icon_state = "fire0" + +/obj/machinery/firealarm/fire_act(datum/gas_mixture/air, temperature, volume) + if(detecting) + if(temperature > T0C+200) + alarm() // added check of detector status here + return + +/obj/machinery/firealarm/bullet_act(BLAH) + return alarm() + +/obj/machinery/firealarm/emp_act(severity) + if(prob(50/severity)) + alarm() + ..() + +/obj/machinery/firealarm/attackby(obj/item/W, mob/user) + add_fingerprint(user) + + if (istype(W, /obj/item/weapon/screwdriver) && buildstage == 2) + wiresexposed = !wiresexposed + update_icon() + return + + if(wiresexposed) + switch(buildstage) + if(2) + if (istype(W, /obj/item/device/multitool)) + detecting = !detecting + if (detecting) + user.visible_message("\red [user] has reconnected [src]'s detecting unit!", "You have reconnected [src]'s detecting unit.") + else + user.visible_message("\red [user] has disconnected [src]'s detecting unit!", "You have disconnected [src]'s detecting unit.") + else if (istype(W, /obj/item/weapon/wirecutters)) + user.visible_message("\red [user] has cut the wires inside \the [src]!", "You have cut the wires inside \the [src].") + new /obj/item/stack/cable_coil/random(loc, 5) + playsound(loc, 'sound/items/Wirecutter.ogg', 50, 1) + buildstage = 1 + update_icon() + if(1) + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = W + if(!coil.use(5)) + to_chat(user, "You need 5 pieces of cable to do wire \the [src].") + return + + buildstage = 2 + to_chat(user, "You wire \the [src]!") + update_icon() + + else if(istype(W, /obj/item/weapon/crowbar)) + to_chat(user, "You start prying out the circuit.") + playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) + if(do_after(user,20,target = src)) + to_chat(user, "You pry out the circuit!") + var/obj/item/weapon/firealarm_electronics/circuit = new /obj/item/weapon/firealarm_electronics() + circuit.loc = user.loc + buildstage = 0 + update_icon() + + if(0) + if(istype(W, /obj/item/weapon/firealarm_electronics)) + to_chat(user, "You insert the circuit!") + qdel(W) + buildstage = 1 + update_icon() + + else if(istype(W, /obj/item/weapon/wrench)) + to_chat(user, "You remove the fire alarm assembly from the wall!") + var/obj/item/firealarm_frame/frame = new /obj/item/firealarm_frame() + frame.loc = user.loc + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + qdel(src) + return + + alarm() + return + +/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(timing) + if(time > 0) + time = time - ((world.timeofday - last_process)/10) + else + alarm() + time = 0 + timing = 0 + STOP_PROCESSING(SSobj, 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/ui_interact(mob/user) + if (buildstage != 2) + return + + user.set_machine(src) + var/area/A = get_area(src) + var/d1 + var/d2 + if (ishuman(user) || issilicon(user) || isobserver(user)) + if (A.fire) + d1 = text("Reset - Lockdown", src) + else + d1 = text("Alarm - Lockdown", src) + if (timing) + d2 = text("Stop Time Lock", src) + else + d2 = text("Initiate Time Lock", src) + var/second = round(time) % 60 + var/minute = (round(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(entity_ja(dat), "window=firealarm") + onclose(user, "firealarm") + else + if (A.fire) + d1 = text("[]", src, stars("Reset - Lockdown")) + else + d1 = text("[]", src, stars("Alarm - Lockdown")) + if (timing) + d2 = text("[]", src, stars("Stop Time Lock")) + else + d2 = text("[]", src, stars("Initiate Time Lock")) + var/second = round(time) % 60 + var/minute = (round(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(entity_ja(dat), "window=firealarm") + onclose(user, "firealarm") + +/obj/machinery/firealarm/Topic(href, href_list) + . = ..() + if(!.) + return + + if (buildstage != 2) + return FALSE + + if (href_list["reset"]) + reset() + else if (href_list["alarm"]) + alarm() + else if (href_list["time"]) + timing = text2num(href_list["time"]) + last_process = world.timeofday + START_PROCESSING(SSobj, src) + else if (href_list["tp"]) + var/tp = text2num(href_list["tp"]) + time += tp + time = min(max(round(time), 0), 120) + + updateUsrDialog() + +/obj/machinery/firealarm/proc/reset() + if (!working) + return + var/area/A = get_area(src) + A.firereset() + for(var/obj/machinery/firealarm/FA in A) + FA.detecting = TRUE + FA.update_icon() + +/obj/machinery/firealarm/proc/alarm() + if (!working) + return + var/area/A = get_area(src) + A.firealert() + for(var/obj/machinery/firealarm/FA in A) + FA.detecting = FALSE + FA.update_icon() + +/obj/machinery/firealarm/atom_init(mapload, dir, building) + . = ..() + + firealarm_list += src + + 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 == ZLEVEL_STATION || z == ZLEVEL_ASTEROID) + if(security_level) + overlays += image('icons/obj/monitors.dmi', "overlay_[get_security_level()]") + else + overlays += image('icons/obj/monitors.dmi', "overlay_green") + + update_icon() + +/obj/machinery/firealarm/Destroy() + firealarm_list -= src + return ..() + +/* +FIRE ALARM CIRCUIT +Just a object used in constructing fire alarms +*/ +/obj/item/weapon/firealarm_electronics + name = "fire alarm electronics" + icon = 'icons/obj/doors/door_electronics.dmi' + icon_state = "door_electronics" + desc = "A circuit. It has a label on it, it says \"Can handle heat levels up to 40 degrees celsius!\"" + w_class = 2.0 + m_amt = 50 + g_amt = 50 + + +/* +FIRE ALARM ITEM +Handheld fire alarm frame, for placing on walls +Code shamelessly copied from apc_frame +*/ +/obj/item/firealarm_frame + name = "fire alarm frame" + desc = "Used for building Fire Alarms." + icon = 'icons/obj/monitors.dmi' + icon_state = "fire_bitem" + flags = CONDUCT + +/obj/item/firealarm_frame/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + user.SetNextMove(CLICK_CD_RAPID) + new /obj/item/stack/sheet/metal(loc, 2) + qdel(src) + return + ..() + +/obj/item/firealarm_frame/proc/try_build(turf/on_wall) + if (get_dist(on_wall,usr) > 1) + return + + var/ndir = get_dir(on_wall,usr) + if (!(ndir in cardinal)) + return + + var/turf/loc = get_turf_loc(usr) + var/area/A = get_area(src) + if (!istype(loc, /turf/simulated/floor)) + to_chat(usr, "\red Fire Alarm cannot be placed on this spot.") + return + if (A.requires_power == 0 || A.name == "Space") + to_chat(usr, "\red Fire Alarm cannot be placed in this area.") + return + + if(gotwallitem(loc, ndir)) + to_chat(usr, "\red There's already an item on this wall!") + return + + new /obj/machinery/firealarm(loc, ndir, 1) + + qdel(src) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 96257139646a..524a2f6c932a 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -1,341 +1,341 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -var/global/list/autolathe_recipes = list( \ - /* screwdriver removed*/ \ - new /obj/item/weapon/reagent_containers/glass/bucket(), \ - new /obj/item/weapon/crowbar(), \ - new /obj/item/device/flashlight(), \ - new /obj/item/weapon/extinguisher(), \ - new /obj/item/device/multitool(), \ - new /obj/item/device/t_scanner(), \ - new /obj/item/device/analyzer(), \ - new /obj/item/device/plant_analyzer(), \ - new /obj/item/device/healthanalyzer(), \ - new /obj/item/weapon/weldingtool(), \ - new /obj/item/weapon/screwdriver(), \ - new /obj/item/weapon/wirecutters(), \ - new /obj/item/weapon/wrench(), \ - new /obj/item/clothing/head/welding(), \ - new /obj/item/weapon/stock_parts/console_screen(), \ - new /obj/item/weapon/airlock_electronics(), \ - new /obj/item/weapon/airalarm_electronics(), \ - new /obj/item/weapon/firealarm_electronics(), \ - new /obj/item/weapon/module/power_control(), \ - new /obj/item/stack/sheet/metal(), \ - new /obj/item/stack/sheet/glass(), \ - new /obj/item/stack/sheet/rglass(), \ - new /obj/item/stack/rods(), \ - new /obj/item/weapon/rcd_ammo(), \ - new /obj/item/weapon/kitchenknife(), \ - 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(),\ - new /obj/item/weapon/reagent_containers/glass/beaker(), \ - new /obj/item/weapon/reagent_containers/glass/beaker/large(), \ - new /obj/item/weapon/reagent_containers/glass/beaker/vial(), \ - new /obj/item/weapon/reagent_containers/syringe(), \ - new /obj/item/ammo_casing/shotgun/beanbag(), \ - new /obj/item/ammo_box/magazine/c45r(), \ - new /obj/item/ammo_box/magazine/m9mmr_2(), \ - new /obj/item/device/taperecorder(), \ - new /obj/item/device/assembly/igniter(), \ - new /obj/item/device/assembly/signaler(), \ - new /obj/item/device/radio/headset(), \ - new /obj/item/device/assembly/voice(), \ - new /obj/item/device/radio/off(), \ - new /obj/item/device/assembly/infra(), \ - new /obj/item/device/assembly/timer(), \ - new /obj/item/device/assembly/prox_sensor(), \ - new /obj/item/weapon/light/tube(), \ - new /obj/item/weapon/light/bulb(), \ - new /obj/item/ashtray/glass(), \ - new /obj/item/weapon/camera_assembly(), \ - new /obj/item/weapon/shovel(), \ - new /obj/item/weapon/minihoe(), \ - new /obj/item/weapon/hand_labeler(), \ - new /obj/item/device/destTagger(), \ - new /obj/item/weapon/game_kit/random(), \ - new /obj/item/newscaster_frame(), - new /obj/item/device/tabletop_assistant() - ) - -var/global/list/autolathe_recipes_hidden = list( \ - new /obj/item/weapon/flamethrower/full(), \ - new /obj/item/weapon/rcd(), \ - new /obj/item/device/radio/electropack(), \ - new /obj/item/weapon/weldingtool/largetank(), \ - new /obj/item/weapon/handcuffs(), \ - new /obj/item/ammo_box/a357(), \ - new /obj/item/ammo_box/magazine/c45m(), \ - new /obj/item/ammo_box/magazine/m9mm_2(), \ - new /obj/item/ammo_casing/shotgun(), \ - new /obj/item/ammo_casing/shotgun/dart(), \ - new /obj/item/ammo_casing/shotgun/buckshot(), \ - new /obj/item/device/harmonica(), \ - new /obj/item/weapon/bell() - ) - -/obj/machinery/autolathe - name = "\improper Autolathe" - desc = "It produces items using metal and glass." - icon_state = "autolathe" - density = TRUE - anchored = TRUE - use_power = 1 - idle_power_usage = 10 - active_power_usage = 100 - allowed_checks = ALLOWED_CHECK_TOPIC - - var/m_amount = 0.0 - var/max_m_amount = 150000.0 - - var/g_amount = 0.0 - var/max_g_amount = 75000.0 - - var/operating = 0.0 - - var/list/L - var/list/LL - var/hacked = 0 - var/disabled = 0 - var/shocked = 0 - var/datum/wires/autolathe/wires = null - - var/busy = 0 - var/prod_coeff - -/obj/machinery/autolathe/atom_init() - . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/autolathe(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/weapon/stock_parts/console_screen(null) - RefreshParts() - - L = autolathe_recipes - LL = autolathe_recipes_hidden - - wires = new(src) - -/obj/machinery/autolathe/Destroy() - QDEL_NULL(wires) - return ..() - -/obj/machinery/autolathe/RefreshParts() - ..() - var/tot_rating = 0 - prod_coeff = 0 - for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts) - tot_rating += MB.rating - tot_rating *= 25000 - max_m_amount = tot_rating * 3 - max_g_amount = tot_rating * 3 - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - prod_coeff += M.rating - 1 - -/obj/machinery/autolathe/ui_interact(mob/user) - if(disabled) - return - - var/coeff = 2 ** prod_coeff - var/dat - - dat = text("Metal Amount: [src.m_amount] cm3 (MAX: [max_m_amount])
    \nGlass Amount: [src.g_amount] cm3 (MAX: [max_g_amount])
    ") - var/list/objs = list() - objs += src.L - if (src.hacked) - objs += src.LL - for(var/obj/t in objs) - if (istype(t, /obj/item/stack)) - var/title = "[t.name] ([t.m_amt] m /[t.g_amt] g)" - if (m_amount" - continue - dat += "[title]" - - var/obj/item/stack/S = t - var/max_multiplier = min(S.max_amount, S.m_amt?round(m_amount/S.m_amt):INFINITY, S.g_amt?round(g_amount/S.g_amt):INFINITY) - if (max_multiplier>1) - dat += " |" - if (max_multiplier>10) - dat += " x[10]" - if (max_multiplier>25) - dat += " x[25]" - if (max_multiplier>1) - dat += " x[max_multiplier]" - else - var/title = "[t.name] ([t.m_amt/coeff] m /[t.g_amt/coeff] g)" - if (m_amount" - continue - dat += "[title]" - dat += "
    " - - user << browse("Autolathe Control Panel[entity_ja(dat)]", "window=autolathe_regular") - onclose(user, "autolathe_regular") - -/obj/machinery/autolathe/proc/shock(mob/user, prb) - 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 (electrocute_mob(user, get_area(src), src, 0.7)) - return 1 - else - return 0 - -/obj/machinery/autolathe/interact(mob/user) - if (shocked && !issilicon(user) && !isobserver(user)) - shock(user,50) - if (disabled) - to_chat(user, "\red You press the button, but nothing happens.") - return - ..() - -/obj/machinery/autolathe/attackby(obj/item/I, mob/user) - if (busy) - to_chat(user, "\red The autolathe is busy. Please wait for completion of previous operation.") - return 1 - - if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", I)) - updateUsrDialog() - return - - if(exchange_parts(user, I)) - return - - if (panel_open) - if(istype(I, /obj/item/weapon/crowbar)) - if(m_amount >= 3750) - new /obj/item/stack/sheet/metal(loc, round(m_amount / 3750)) - if(g_amount >= 3750) - new /obj/item/stack/sheet/glass(loc, round(g_amount / 3750)) - default_deconstruction_crowbar(I) - return 1 - else if(is_wire_tool(I)) - wires.interact(user) - return 1 - - if (stat) - return 1 - - if (src.m_amount + I.m_amt > max_m_amount) - to_chat(user, "\red The autolathe is full. Please remove metal from the autolathe in order to insert more.") - return 1 - if (src.g_amount + I.g_amt > max_g_amount) - to_chat(user, "\red The autolathe is full. Please remove glass from the autolathe in order to insert more.") - return 1 - if (I.m_amt == 0 && I.g_amt == 0) - to_chat(user, "\red This object does not contain significant amounts of metal or glass, or cannot be accepted by the autolathe due to size or hazardous materials.") - return 1 - - var/amount = 1 - var/obj/item/stack/stack - var/m_amt = I.m_amt - var/g_amt = I.g_amt - if (istype(I, /obj/item/stack)) - stack = I - amount = stack.get_amount() - if (m_amt) - amount = min(amount, round((max_m_amount-src.m_amount)/m_amt)) - flick("autolathe_o",src)//plays metal insertion animation - if (g_amt) - amount = min(amount, round((max_g_amount-src.g_amount)/g_amt)) - flick("autolathe_r",src)//plays glass insertion animation - stack.use(amount) - else - usr.remove_from_mob(I) - I.loc = src - icon_state = "autolathe" - busy = 1 - use_power(max(1000, (m_amt+g_amt)*amount/10)) - src.m_amount += m_amt * amount - src.g_amount += g_amt * amount - to_chat(user, "You insert [amount] sheet[amount>1 ? "s" : ""] to the autolathe.") - if (I && I.loc == src) - qdel(I) - busy = 0 - src.updateUsrDialog() - -/obj/machinery/autolathe/Topic(href, href_list) - . = ..() - if(!.) - return - - if(busy) - to_chat(usr, "\red The autolathe is busy. Please wait for completion of previous operation.") - return FALSE - - if(href_list["make"]) - var/coeff = 2 ** prod_coeff - var/turf/T = get_step(src.loc, get_dir(src,usr)) - - // critical exploit fix start -walter0o - var/obj/item/template = null - var/attempting_to_build = locate(href_list["make"]) - - if(!attempting_to_build) - return FALSE - - if(locate(attempting_to_build, src.L) || locate(attempting_to_build, src.LL)) // see if the requested object is in one of the construction lists, if so, it is legit -walter0o - template = attempting_to_build - - else // somebody is trying to exploit, alert admins -walter0o - - var/turf/LOC = get_turf(usr) - message_admins("[key_name_admin(usr)] tried to exploit an autolathe to duplicate [attempting_to_build] ! ([LOC ? "JMP" : "null"])", 0) - log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe to duplicate [attempting_to_build] !") - return FALSE - - // now check for legit multiplier, also only stacks should pass with one to prevent raw-materials-manipulation -walter0o - - var/multiplier = text2num(href_list["multiplier"]) - - if (!multiplier) multiplier = 1 - var/max_multiplier = 1 - - if(istype(template, /obj/item/stack)) // stacks are the only items which can have a multiplier higher than 1 -walter0o - var/obj/item/stack/S = template - max_multiplier = min(S.max_amount, S.m_amt?round(m_amount/S.m_amt):INFINITY, S.g_amt?round(g_amount/S.g_amt):INFINITY) // pasta from regular_win() to make sure the numbers match -walter0o - - if( (multiplier > max_multiplier) || (multiplier <= 0) ) // somebody is trying to exploit, alert admins-walter0o - - var/turf/LOC = get_turf(usr) - message_admins("[key_name_admin(usr)] tried to exploit an autolathe with multiplier set to [multiplier] on [template] ! ([LOC ? "JMP" : "null"])" , 0) - log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe with multiplier set to [multiplier] on [template] !") - return FALSE - - var/power = max(2000, (template.m_amt+template.g_amt)*multiplier/5) - if(src.m_amount >= template.m_amt*multiplier/coeff && src.g_amount >= template.g_amt*multiplier/coeff) - busy = 1 - use_power(power) - icon_state = "autolathe" - flick("autolathe_n",src) - spawn(32/coeff) - if(istype(template, /obj/item/stack)) - src.m_amount -= template.m_amt*multiplier - src.g_amount -= template.g_amt*multiplier - var/obj/new_item = new template.type(T) - var/obj/item/stack/S = new_item - S.set_amount(multiplier) - else - src.m_amount -= template.m_amt/coeff - src.g_amount -= template.g_amt/coeff - var/obj/new_item = new template.type(T) - new_item.m_amt /= coeff - new_item.g_amt /= coeff - if(src.m_amount < 0) - src.m_amount = 0 - if(src.g_amount < 0) - src.g_amount = 0 - busy = 0 - updateUsrDialog() +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +var/global/list/autolathe_recipes = list( \ + /* screwdriver removed*/ \ + new /obj/item/weapon/reagent_containers/glass/bucket(), \ + new /obj/item/weapon/crowbar(), \ + new /obj/item/device/flashlight(), \ + new /obj/item/weapon/extinguisher(), \ + new /obj/item/device/multitool(), \ + new /obj/item/device/t_scanner(), \ + new /obj/item/device/analyzer(), \ + new /obj/item/device/plant_analyzer(), \ + new /obj/item/device/healthanalyzer(), \ + new /obj/item/weapon/weldingtool(), \ + new /obj/item/weapon/screwdriver(), \ + new /obj/item/weapon/wirecutters(), \ + new /obj/item/weapon/wrench(), \ + new /obj/item/clothing/head/welding(), \ + new /obj/item/weapon/stock_parts/console_screen(), \ + new /obj/item/weapon/airlock_electronics(), \ + new /obj/item/weapon/airalarm_electronics(), \ + new /obj/item/weapon/firealarm_electronics(), \ + new /obj/item/weapon/module/power_control(), \ + new /obj/item/stack/sheet/metal(), \ + new /obj/item/stack/sheet/glass(), \ + new /obj/item/stack/sheet/rglass(), \ + new /obj/item/stack/rods(), \ + new /obj/item/weapon/rcd_ammo(), \ + new /obj/item/weapon/kitchenknife(), \ + 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(),\ + new /obj/item/weapon/reagent_containers/glass/beaker(), \ + new /obj/item/weapon/reagent_containers/glass/beaker/large(), \ + new /obj/item/weapon/reagent_containers/glass/beaker/vial(), \ + new /obj/item/weapon/reagent_containers/syringe(), \ + new /obj/item/ammo_casing/shotgun/beanbag(), \ + new /obj/item/ammo_box/magazine/c45r(), \ + new /obj/item/ammo_box/magazine/m9mmr_2(), \ + new /obj/item/device/taperecorder(), \ + new /obj/item/device/assembly/igniter(), \ + new /obj/item/device/assembly/signaler(), \ + new /obj/item/device/radio/headset(), \ + new /obj/item/device/assembly/voice(), \ + new /obj/item/device/radio/off(), \ + new /obj/item/device/assembly/infra(), \ + new /obj/item/device/assembly/timer(), \ + new /obj/item/device/assembly/prox_sensor(), \ + new /obj/item/weapon/light/tube(), \ + new /obj/item/weapon/light/bulb(), \ + new /obj/item/ashtray/glass(), \ + new /obj/item/weapon/camera_assembly(), \ + new /obj/item/weapon/shovel(), \ + new /obj/item/weapon/minihoe(), \ + new /obj/item/weapon/hand_labeler(), \ + new /obj/item/device/destTagger(), \ + new /obj/item/weapon/game_kit/random(), \ + new /obj/item/newscaster_frame(), + new /obj/item/device/tabletop_assistant() + ) + +var/global/list/autolathe_recipes_hidden = list( \ + new /obj/item/weapon/flamethrower/full(), \ + new /obj/item/weapon/rcd(), \ + new /obj/item/device/radio/electropack(), \ + new /obj/item/weapon/weldingtool/largetank(), \ + new /obj/item/weapon/handcuffs(), \ + new /obj/item/ammo_box/a357(), \ + new /obj/item/ammo_box/magazine/c45m(), \ + new /obj/item/ammo_box/magazine/m9mm_2(), \ + new /obj/item/ammo_casing/shotgun(), \ + new /obj/item/ammo_casing/shotgun/dart(), \ + new /obj/item/ammo_casing/shotgun/buckshot(), \ + new /obj/item/device/harmonica(), \ + new /obj/item/weapon/bell() + ) + +/obj/machinery/autolathe + name = "\improper Autolathe" + desc = "It produces items using metal and glass." + icon_state = "autolathe" + density = TRUE + anchored = TRUE + use_power = 1 + idle_power_usage = 10 + active_power_usage = 100 + allowed_checks = ALLOWED_CHECK_TOPIC + + var/m_amount = 0.0 + var/max_m_amount = 150000.0 + + var/g_amount = 0.0 + var/max_g_amount = 75000.0 + + var/operating = 0.0 + + var/list/L + var/list/LL + var/hacked = 0 + var/disabled = 0 + var/shocked = 0 + var/datum/wires/autolathe/wires = null + + var/busy = 0 + var/prod_coeff + +/obj/machinery/autolathe/atom_init() + . = ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/autolathe(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + RefreshParts() + + L = autolathe_recipes + LL = autolathe_recipes_hidden + + wires = new(src) + +/obj/machinery/autolathe/Destroy() + QDEL_NULL(wires) + return ..() + +/obj/machinery/autolathe/RefreshParts() + ..() + var/tot_rating = 0 + prod_coeff = 0 + for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts) + tot_rating += MB.rating + tot_rating *= 25000 + max_m_amount = tot_rating * 3 + max_g_amount = tot_rating * 3 + for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + prod_coeff += M.rating - 1 + +/obj/machinery/autolathe/ui_interact(mob/user) + if(disabled) + return + + var/coeff = 2 ** prod_coeff + var/dat + + dat = text("Metal Amount: [src.m_amount] cm3 (MAX: [max_m_amount])
    \nGlass Amount: [src.g_amount] cm3 (MAX: [max_g_amount])
    ") + var/list/objs = list() + objs += src.L + if (src.hacked) + objs += src.LL + for(var/obj/t in objs) + if (istype(t, /obj/item/stack)) + var/title = "[t.name] ([t.m_amt] m /[t.g_amt] g)" + if (m_amount" + continue + dat += "[title]" + + var/obj/item/stack/S = t + var/max_multiplier = min(S.max_amount, S.m_amt?round(m_amount/S.m_amt):INFINITY, S.g_amt?round(g_amount/S.g_amt):INFINITY) + if (max_multiplier>1) + dat += " |" + if (max_multiplier>10) + dat += " x[10]" + if (max_multiplier>25) + dat += " x[25]" + if (max_multiplier>1) + dat += " x[max_multiplier]" + else + var/title = "[t.name] ([t.m_amt/coeff] m /[t.g_amt/coeff] g)" + if (m_amount" + continue + dat += "[title]" + dat += "
    " + + user << browse("Autolathe Control Panel[entity_ja(dat)]", "window=autolathe_regular") + onclose(user, "autolathe_regular") + +/obj/machinery/autolathe/proc/shock(mob/user, prb) + 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 (electrocute_mob(user, get_area(src), src, 0.7)) + return 1 + else + return 0 + +/obj/machinery/autolathe/interact(mob/user) + if (shocked && !issilicon(user) && !isobserver(user)) + shock(user,50) + if (disabled) + to_chat(user, "\red You press the button, but nothing happens.") + return + ..() + +/obj/machinery/autolathe/attackby(obj/item/I, mob/user) + if (busy) + to_chat(user, "\red The autolathe is busy. Please wait for completion of previous operation.") + return 1 + + if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", I)) + updateUsrDialog() + return + + if(exchange_parts(user, I)) + return + + if (panel_open) + if(istype(I, /obj/item/weapon/crowbar)) + if(m_amount >= 3750) + new /obj/item/stack/sheet/metal(loc, round(m_amount / 3750)) + if(g_amount >= 3750) + new /obj/item/stack/sheet/glass(loc, round(g_amount / 3750)) + default_deconstruction_crowbar(I) + return 1 + else if(is_wire_tool(I)) + wires.interact(user) + return 1 + + if (stat) + return 1 + + if (src.m_amount + I.m_amt > max_m_amount) + to_chat(user, "\red The autolathe is full. Please remove metal from the autolathe in order to insert more.") + return 1 + if (src.g_amount + I.g_amt > max_g_amount) + to_chat(user, "\red The autolathe is full. Please remove glass from the autolathe in order to insert more.") + return 1 + if (I.m_amt == 0 && I.g_amt == 0) + to_chat(user, "\red This object does not contain significant amounts of metal or glass, or cannot be accepted by the autolathe due to size or hazardous materials.") + return 1 + + var/amount = 1 + var/obj/item/stack/stack + var/m_amt = I.m_amt + var/g_amt = I.g_amt + if (istype(I, /obj/item/stack)) + stack = I + amount = stack.get_amount() + if (m_amt) + amount = min(amount, round((max_m_amount-src.m_amount)/m_amt)) + flick("autolathe_o",src)//plays metal insertion animation + if (g_amt) + amount = min(amount, round((max_g_amount-src.g_amount)/g_amt)) + flick("autolathe_r",src)//plays glass insertion animation + stack.use(amount) + else + usr.remove_from_mob(I) + I.loc = src + icon_state = "autolathe" + busy = 1 + use_power(max(1000, (m_amt+g_amt)*amount/10)) + src.m_amount += m_amt * amount + src.g_amount += g_amt * amount + to_chat(user, "You insert [amount] sheet[amount>1 ? "s" : ""] to the autolathe.") + if (I && I.loc == src) + qdel(I) + busy = 0 + src.updateUsrDialog() + +/obj/machinery/autolathe/Topic(href, href_list) + . = ..() + if(!.) + return + + if(busy) + to_chat(usr, "\red The autolathe is busy. Please wait for completion of previous operation.") + return FALSE + + if(href_list["make"]) + var/coeff = 2 ** prod_coeff + var/turf/T = get_step(src.loc, get_dir(src,usr)) + + // critical exploit fix start -walter0o + var/obj/item/template = null + var/attempting_to_build = locate(href_list["make"]) + + if(!attempting_to_build) + return FALSE + + if(locate(attempting_to_build, src.L) || locate(attempting_to_build, src.LL)) // see if the requested object is in one of the construction lists, if so, it is legit -walter0o + template = attempting_to_build + + else // somebody is trying to exploit, alert admins -walter0o + + var/turf/LOC = get_turf(usr) + message_admins("[key_name_admin(usr)] tried to exploit an autolathe to duplicate [attempting_to_build] ! ([LOC ? "JMP" : "null"])", 0) + log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe to duplicate [attempting_to_build] !") + return FALSE + + // now check for legit multiplier, also only stacks should pass with one to prevent raw-materials-manipulation -walter0o + + var/multiplier = text2num(href_list["multiplier"]) + + if (!multiplier) multiplier = 1 + var/max_multiplier = 1 + + if(istype(template, /obj/item/stack)) // stacks are the only items which can have a multiplier higher than 1 -walter0o + var/obj/item/stack/S = template + max_multiplier = min(S.max_amount, S.m_amt?round(m_amount/S.m_amt):INFINITY, S.g_amt?round(g_amount/S.g_amt):INFINITY) // pasta from regular_win() to make sure the numbers match -walter0o + + if( (multiplier > max_multiplier) || (multiplier <= 0) ) // somebody is trying to exploit, alert admins-walter0o + + var/turf/LOC = get_turf(usr) + message_admins("[key_name_admin(usr)] tried to exploit an autolathe with multiplier set to [multiplier] on [template] ! ([LOC ? "JMP" : "null"])" , 0) + log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe with multiplier set to [multiplier] on [template] !") + return FALSE + + var/power = max(2000, (template.m_amt+template.g_amt)*multiplier/5) + if(src.m_amount >= template.m_amt*multiplier/coeff && src.g_amount >= template.g_amt*multiplier/coeff) + busy = 1 + use_power(power) + icon_state = "autolathe" + flick("autolathe_n",src) + spawn(32/coeff) + if(istype(template, /obj/item/stack)) + src.m_amount -= template.m_amt*multiplier + src.g_amount -= template.g_amt*multiplier + var/obj/new_item = new template.type(T) + var/obj/item/stack/S = new_item + S.set_amount(multiplier) + else + src.m_amount -= template.m_amt/coeff + src.g_amount -= template.g_amt/coeff + var/obj/new_item = new template.type(T) + new_item.m_amt /= coeff + new_item.g_amt /= coeff + if(src.m_amount < 0) + src.m_amount = 0 + if(src.g_amount < 0) + src.g_amount = 0 + busy = 0 + updateUsrDialog() diff --git a/code/game/machinery/bees_items.dm b/code/game/machinery/bees_items.dm index d5db0dc49c54..2928e609e478 100644 --- a/code/game/machinery/bees_items.dm +++ b/code/game/machinery/bees_items.dm @@ -1,90 +1,90 @@ - -/obj/item/queen_bee - name = "queen bee packet" - desc = "Place her into an apiary so she can get busy." - icon = 'icons/obj/hydroponics/seeds.dmi' - icon_state = "seed-kudzu" - w_class = 1 - -/obj/item/weapon/bee_net - name = "bee net" - desc = "For catching rogue bees." - icon = 'icons/obj/apiary_bees_etc.dmi' - icon_state = "bee_net" - item_state = "bedsheet" - w_class = 3 - var/caught_bees = 0 - -/obj/item/weapon/bee_net/attack_self(mob/user) - var/turf/T = get_step(get_turf(user), user.dir) - for(var/mob/living/simple_animal/bee/B in T) - if(B.feral < 0) - caught_bees += B.strength - qdel(B) - user.visible_message("\blue [user] nets some bees.","\blue You net up some of the becalmed bees.") - else - user.visible_message("\red [user] swings at some bees, they don't seem to like it.","\red You swing at some bees, they don't seem to like it.") - B.feral = 5 - B.target_mob = user - -/obj/item/weapon/bee_net/verb/empty_bees() - set src in usr - set name = "Empty bee net" - set category = "Object" - var/mob/living/carbon/M - if(iscarbon(usr)) - M = usr - - while(caught_bees > 0) - //release a few super massive swarms - while(caught_bees > 5) - var/mob/living/simple_animal/bee/B = new(src.loc) - B.feral = 5 - B.target_mob = M - B.strength = 6 - B.icon_state = "bees_swarm" - caught_bees -= 6 - - //what's left over - var/mob/living/simple_animal/bee/B = new(src.loc) - B.strength = caught_bees - B.icon_state = "bees[B.strength]" - B.feral = 5 - B.target_mob = M - - caught_bees = 0 - -/obj/item/apiary - name = "moveable apiary" - icon = 'icons/obj/apiary_bees_etc.dmi' - icon_state = "apiary_item" - item_state = "giftbag" - w_class = 5 - -/obj/item/beezeez - name = "bottle of BeezEez" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle17" - -/obj/item/beezeez/atom_init() - . = ..() - pixel_x = rand(-5.0, 5) - pixel_y = rand(-5.0, 5) - -/obj/item/weapon/reagent_containers/food/snacks/honeycomb - name = "honeycomb" - icon_state = "honeycomb" - desc = "Dripping with sugary sweetness." - -/obj/item/weapon/reagent_containers/food/snacks/honeycomb/atom_init() - . = ..() - reagents.add_reagent("honey",10) - reagents.add_reagent("nutriment", 0.5) - reagents.add_reagent("sugar", 2) - bitesize = 2 - -/datum/reagent/honey - name = "Honey" - id = "honey" - description = "A golden yellow syrup, loaded with sugary sweetness." - color = "#FFFF00" + +/obj/item/queen_bee + name = "queen bee packet" + desc = "Place her into an apiary so she can get busy." + icon = 'icons/obj/hydroponics/seeds.dmi' + icon_state = "seed-kudzu" + w_class = 1 + +/obj/item/weapon/bee_net + name = "bee net" + desc = "For catching rogue bees." + icon = 'icons/obj/apiary_bees_etc.dmi' + icon_state = "bee_net" + item_state = "bedsheet" + w_class = 3 + var/caught_bees = 0 + +/obj/item/weapon/bee_net/attack_self(mob/user) + var/turf/T = get_step(get_turf(user), user.dir) + for(var/mob/living/simple_animal/bee/B in T) + if(B.feral < 0) + caught_bees += B.strength + qdel(B) + user.visible_message("\blue [user] nets some bees.","\blue You net up some of the becalmed bees.") + else + user.visible_message("\red [user] swings at some bees, they don't seem to like it.","\red You swing at some bees, they don't seem to like it.") + B.feral = 5 + B.target_mob = user + +/obj/item/weapon/bee_net/verb/empty_bees() + set src in usr + set name = "Empty bee net" + set category = "Object" + var/mob/living/carbon/M + if(iscarbon(usr)) + M = usr + + while(caught_bees > 0) + //release a few super massive swarms + while(caught_bees > 5) + var/mob/living/simple_animal/bee/B = new(src.loc) + B.feral = 5 + B.target_mob = M + B.strength = 6 + B.icon_state = "bees_swarm" + caught_bees -= 6 + + //what's left over + var/mob/living/simple_animal/bee/B = new(src.loc) + B.strength = caught_bees + B.icon_state = "bees[B.strength]" + B.feral = 5 + B.target_mob = M + + caught_bees = 0 + +/obj/item/apiary + name = "moveable apiary" + icon = 'icons/obj/apiary_bees_etc.dmi' + icon_state = "apiary_item" + item_state = "giftbag" + w_class = 5 + +/obj/item/beezeez + name = "bottle of BeezEez" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle17" + +/obj/item/beezeez/atom_init() + . = ..() + pixel_x = rand(-5.0, 5) + pixel_y = rand(-5.0, 5) + +/obj/item/weapon/reagent_containers/food/snacks/honeycomb + name = "honeycomb" + icon_state = "honeycomb" + desc = "Dripping with sugary sweetness." + +/obj/item/weapon/reagent_containers/food/snacks/honeycomb/atom_init() + . = ..() + reagents.add_reagent("honey",10) + reagents.add_reagent("nutriment", 0.5) + reagents.add_reagent("sugar", 2) + bitesize = 2 + +/datum/reagent/honey + name = "Honey" + id = "honey" + description = "A golden yellow syrup, loaded with sugary sweetness." + color = "#FFFF00" diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm index ffb390f6c464..1012d7f72515 100644 --- a/code/game/machinery/biogenerator.dm +++ b/code/game/machinery/biogenerator.dm @@ -1,315 +1,315 @@ -/obj/machinery/biogenerator - name = "Biogenerator" - desc = "" - icon = 'icons/obj/biogenerator.dmi' - icon_state = "biogen-empty" - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 40 - var/processing = 0 - var/obj/item/weapon/reagent_containers/glass/beaker = null - var/points = 0 - var/menustat = "menu" - var/efficiency = 0 - var/productivity = 0 - var/max_items = 10 - -/obj/machinery/biogenerator/atom_init() - . = ..() - var/datum/reagents/R = new/datum/reagents(1000) - reagents = R - R.my_atom = src - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/biogenerator(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/weapon/stock_parts/console_screen(null) - component_parts += new /obj/item/stack/cable_coil/random(null, 1) - RefreshParts() - -/obj/machinery/biogenerator/RefreshParts() - var/E = 0 - var/P = 0 - var/max_storage = 10 - for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) - P += B.rating - max_storage = B.rating * 3 + 10 - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - E += M.rating - efficiency = E - productivity = P - max_items = max_storage - -/obj/machinery/biogenerator/on_reagent_change() - update_icon() - -/obj/machinery/biogenerator/update_icon() - if(panel_open) - icon_state = "biogen-empty-o" - else if(!src.beaker) - icon_state = "biogen-empty" - else if(!src.processing) - icon_state = "biogen-stand" - else - icon_state = "biogen-work" - return - -/obj/machinery/biogenerator/attackby(obj/item/O, mob/user) - if(istype(O, /obj/item/weapon/reagent_containers/glass) && !panel_open) - if(beaker) - to_chat(user, "The biogenerator already occuped.") - else - user.remove_from_mob(O) - O.loc = src - beaker = O - updateUsrDialog() - else if(processing) - to_chat(user, "The biogenerator is currently processing.") - else if(istype(O, /obj/item/weapon/storage/bag/plants)) - var/obj/item/weapon/storage/bag/plants/P = O - P.close(user) // , - var/i = 0 - for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents) - i++ - if(i >= max_items) - to_chat(user, "The biogenerator is already full! Activate it.") - else - for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in O.contents) - if(i >= max_items) - break - G.loc = src - i++ - if(iYou empty the plant bag into the biogenerator.
    ") - else if(O.contents.len == 0) - to_chat(user, "You empty the plant bag into the biogenerator, filling it to its capacity.") - else - to_chat(user, "You fill the biogenerator to its capacity.") - - - else if(!istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown)) - to_chat(user, "You cannot put this in [src.name]") - else - var/i = 0 - for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents) - i++ - if(i >= max_items) - to_chat(user, "The biogenerator is full! Activate it.") - else - user.remove_from_mob(O) - O.loc = src - to_chat(user, "You put [O.name] in [src.name]") - - if(!processing) - if(default_deconstruction_screwdriver(user, "biogen-empty-o", "biogen-empty", O)) - if(beaker) - var/obj/item/weapon/reagent_containers/glass/B = beaker - B.loc = loc - beaker = null - - if(exchange_parts(user, O)) - return - - default_deconstruction_crowbar(O) - - update_icon() - return - -/obj/machinery/biogenerator/ui_interact(mob/user) - var/dat - if(processing) - dat += "
    Biogenerator is processing! Please wait...

    " - else - switch(menustat) - if("nopoints") - dat += "
    You do not have biomass to create products.
    Please, put growns into reactor and activate it.
    " - menustat = "menu" - if("complete") - dat += "
    Operation complete.
    " - menustat = "menu" - if("void") - dat += "
    Error: No growns inside.
    Please, put growns into reactor.
    " - menustat = "menu" - if(beaker) - dat += "
    Biomass: [points] units.

    " - dat += "ActivateDetach Container" - dat += "

    Food:

    " - dat += "
    " - dat += "10 milk: Make ([20/efficiency])
    " - dat += "10 cream: Make ([30/efficiency])
    " - dat += "Monkey cube: Make ([250/efficiency])
    " - dat += "Meat: Makex5 ([125/efficiency])
    " - dat += "
    " - dat += "

    Nutrients:

    " - dat += "
    " - dat += "E-Z-Nutrient: Makex5 ([10/efficiency])
    " - dat += "Left 4 Zed: Makex5 ([20/efficiency])
    " - dat += "Robust Harvest: Makex5 ([25/efficiency])
    " - dat += "
    " - dat += "

    Leather:

    " - dat += "
    " - dat += "Wallet: Make ([100/efficiency])
    " - //dat += "Book bag: Make ([200/efficiency])
    " - dat += "Plant bag: Make ([200/efficiency])
    " - dat += "Mining satchel: Make ([200/efficiency])
    " - dat += "Botanical gloves: Make ([250/efficiency])
    " - dat += "Utility belt: Make ([300/efficiency])
    " - dat += "Leather Satchel: Make ([400/efficiency])
    " - dat += "Cash Bag: Make ([400/efficiency])
    " - dat += "Leather Jacket: Make ([500/efficiency])
    " - dat += "Leather Overcoat: Make ([1000/efficiency])
    " - dat += "
    " - else - dat += "
    No beaker inside, please insert beaker.
    " - - var/datum/browser/popup = new(user, "biogen", name, 350, 520) - popup.set_content(dat) - popup.open() - -/obj/machinery/biogenerator/proc/activate() - if(processing) - to_chat(usr, "The biogenerator is in the process of working.") - return - - var/S = 0 - for(var/obj/item/weapon/reagent_containers/food/snacks/grown/I in contents) - S += 5 - if(I.reagents.get_reagent_amount("nutriment") < 0.1) - points += 1*productivity - else points += I.reagents.get_reagent_amount("nutriment")*10*productivity - qdel(I) - - if(S) - processing = 1 - update_icon() - updateUsrDialog() - playsound(src, 'sound/machines/blender.ogg', 35, 1) - use_power(S*30) - sleep(S+15/productivity) - processing = 0 - update_icon() - else - menustat = "void" - -/obj/machinery/biogenerator/proc/check_cost(cost) - if (cost > points) - menustat = "nopoints" - return 1 - else - points -= cost - processing = 1 - update_icon() - updateUsrDialog() - sleep(30) - return 0 - -/obj/machinery/biogenerator/proc/create_product(create) - switch(create) - if("milk") - if (check_cost(20/efficiency)) return 0 - else beaker.reagents.add_reagent("milk",10) - if("cream") - if (check_cost(30/efficiency)) return 0 - else beaker.reagents.add_reagent("cream",10) - if("meat") - if (check_cost(125/efficiency)) return 0 - else new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) - if("monkey") - if(check_cost(250/efficiency)) return 0 - else new/obj/item/weapon/reagent_containers/food/snacks/monkeycube(src.loc) - if("ez") - if (check_cost(10/efficiency)) return 0 - else new/obj/item/nutrient/ez(src.loc) - if("l4z") - if (check_cost(20/efficiency)) return 0 - else new/obj/item/nutrient/l4z(src.loc) - if("rh") - if (check_cost(25/efficiency)) return 0 - else new/obj/item/nutrient/rh(src.loc) - if("ez5") //It's not an elegant method, but it's safe and easy. -Cheridan - if (check_cost(50/efficiency)) return 0 - else - new/obj/item/nutrient/ez(src.loc) - new/obj/item/nutrient/ez(src.loc) - new/obj/item/nutrient/ez(src.loc) - new/obj/item/nutrient/ez(src.loc) - new/obj/item/nutrient/ez(src.loc) - if("l4z5") - if (check_cost(100/efficiency)) return 0 - else - new/obj/item/nutrient/l4z(src.loc) - new/obj/item/nutrient/l4z(src.loc) - new/obj/item/nutrient/l4z(src.loc) - new/obj/item/nutrient/l4z(src.loc) - new/obj/item/nutrient/l4z(src.loc) - if("rh5") - if (check_cost(125/efficiency)) return 0 - else - new/obj/item/nutrient/rh(src.loc) - new/obj/item/nutrient/rh(src.loc) - new/obj/item/nutrient/rh(src.loc) - new/obj/item/nutrient/rh(src.loc) - new/obj/item/nutrient/rh(src.loc) - if("meat5") - if (check_cost(125/efficiency)) return 0 - else - new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) - new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) - new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) - new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) - new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) - if("wallet") - if (check_cost(100/efficiency)) return 0 - else new/obj/item/weapon/storage/wallet(src.loc) - //if("bkbag") - // if (check_cost(200/efficiency)) return 0 - // else new/obj/item/weapon/storage/bag/books(src.loc) - if("ptbag") - if (check_cost(200/efficiency)) return 0 - else new/obj/item/weapon/storage/bag/plants(src.loc) - if("mnbag") - if (check_cost(200/efficiency)) return 0 - else new/obj/item/weapon/storage/bag/ore(src.loc) - if("gloves") - if (check_cost(250/efficiency)) return 0 - else new/obj/item/clothing/gloves/botanic_leather(src.loc) - if("tbelt") - if (check_cost(300/efficiency)) return 0 - else new/obj/item/weapon/storage/belt/utility(src.loc) - if("satchel") - if (check_cost(400/efficiency)) return 0 - else new/obj/item/weapon/storage/backpack/satchel(src.loc) - if("cashbag") - if (check_cost(400/efficiency)) return 0 - else new/obj/item/weapon/storage/bag/cash(src.loc) - if("jacket") - if (check_cost(500/efficiency)) return 0 - else new/obj/item/clothing/suit/jacket/leather(src.loc) - if("overcoat") - if (check_cost(1000/efficiency)) return 0 - else new/obj/item/clothing/suit/jacket/leather/overcoat(src.loc) - processing = 0 - menustat = "complete" - update_icon() - return 1 - -/obj/machinery/biogenerator/Topic(href, href_list) - . = ..() - if(!. || panel_open) - return - - switch(href_list["action"]) - if("activate") - activate() - if("detach") - if(beaker) - beaker.loc = src.loc - beaker = null - update_icon() - if("create") - create_product(href_list["item"]) - if("menu") - menustat = "menu" - - updateUsrDialog() +/obj/machinery/biogenerator + name = "Biogenerator" + desc = "" + icon = 'icons/obj/biogenerator.dmi' + icon_state = "biogen-empty" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 40 + var/processing = 0 + var/obj/item/weapon/reagent_containers/glass/beaker = null + var/points = 0 + var/menustat = "menu" + var/efficiency = 0 + var/productivity = 0 + var/max_items = 10 + +/obj/machinery/biogenerator/atom_init() + . = ..() + var/datum/reagents/R = new/datum/reagents(1000) + reagents = R + R.my_atom = src + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/biogenerator(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + component_parts += new /obj/item/stack/cable_coil/random(null, 1) + RefreshParts() + +/obj/machinery/biogenerator/RefreshParts() + var/E = 0 + var/P = 0 + var/max_storage = 10 + for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) + P += B.rating + max_storage = B.rating * 3 + 10 + for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + E += M.rating + efficiency = E + productivity = P + max_items = max_storage + +/obj/machinery/biogenerator/on_reagent_change() + update_icon() + +/obj/machinery/biogenerator/update_icon() + if(panel_open) + icon_state = "biogen-empty-o" + else if(!src.beaker) + icon_state = "biogen-empty" + else if(!src.processing) + icon_state = "biogen-stand" + else + icon_state = "biogen-work" + return + +/obj/machinery/biogenerator/attackby(obj/item/O, mob/user) + if(istype(O, /obj/item/weapon/reagent_containers/glass) && !panel_open) + if(beaker) + to_chat(user, "The biogenerator already occuped.") + else + user.remove_from_mob(O) + O.loc = src + beaker = O + updateUsrDialog() + else if(processing) + to_chat(user, "The biogenerator is currently processing.") + else if(istype(O, /obj/item/weapon/storage/bag/plants)) + var/obj/item/weapon/storage/bag/plants/P = O + P.close(user) // , + var/i = 0 + for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents) + i++ + if(i >= max_items) + to_chat(user, "The biogenerator is already full! Activate it.") + else + for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in O.contents) + if(i >= max_items) + break + G.loc = src + i++ + if(iYou empty the plant bag into the biogenerator.
    ") + else if(O.contents.len == 0) + to_chat(user, "You empty the plant bag into the biogenerator, filling it to its capacity.") + else + to_chat(user, "You fill the biogenerator to its capacity.") + + + else if(!istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown)) + to_chat(user, "You cannot put this in [src.name]") + else + var/i = 0 + for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents) + i++ + if(i >= max_items) + to_chat(user, "The biogenerator is full! Activate it.") + else + user.remove_from_mob(O) + O.loc = src + to_chat(user, "You put [O.name] in [src.name]") + + if(!processing) + if(default_deconstruction_screwdriver(user, "biogen-empty-o", "biogen-empty", O)) + if(beaker) + var/obj/item/weapon/reagent_containers/glass/B = beaker + B.loc = loc + beaker = null + + if(exchange_parts(user, O)) + return + + default_deconstruction_crowbar(O) + + update_icon() + return + +/obj/machinery/biogenerator/ui_interact(mob/user) + var/dat + if(processing) + dat += "
    Biogenerator is processing! Please wait...

    " + else + switch(menustat) + if("nopoints") + dat += "
    You do not have biomass to create products.
    Please, put growns into reactor and activate it.
    " + menustat = "menu" + if("complete") + dat += "
    Operation complete.
    " + menustat = "menu" + if("void") + dat += "
    Error: No growns inside.
    Please, put growns into reactor.
    " + menustat = "menu" + if(beaker) + dat += "
    Biomass: [points] units.

    " + dat += "ActivateDetach Container" + dat += "

    Food:

    " + dat += "
    " + dat += "10 milk: Make ([20/efficiency])
    " + dat += "10 cream: Make ([30/efficiency])
    " + dat += "Monkey cube: Make ([250/efficiency])
    " + dat += "Meat: Makex5 ([125/efficiency])
    " + dat += "
    " + dat += "

    Nutrients:

    " + dat += "
    " + dat += "E-Z-Nutrient: Makex5 ([10/efficiency])
    " + dat += "Left 4 Zed: Makex5 ([20/efficiency])
    " + dat += "Robust Harvest: Makex5 ([25/efficiency])
    " + dat += "
    " + dat += "

    Leather:

    " + dat += "
    " + dat += "Wallet: Make ([100/efficiency])
    " + //dat += "Book bag: Make ([200/efficiency])
    " + dat += "Plant bag: Make ([200/efficiency])
    " + dat += "Mining satchel: Make ([200/efficiency])
    " + dat += "Botanical gloves: Make ([250/efficiency])
    " + dat += "Utility belt: Make ([300/efficiency])
    " + dat += "Leather Satchel: Make ([400/efficiency])
    " + dat += "Cash Bag: Make ([400/efficiency])
    " + dat += "Leather Jacket: Make ([500/efficiency])
    " + dat += "Leather Overcoat: Make ([1000/efficiency])
    " + dat += "
    " + else + dat += "
    No beaker inside, please insert beaker.
    " + + var/datum/browser/popup = new(user, "biogen", name, 350, 520) + popup.set_content(dat) + popup.open() + +/obj/machinery/biogenerator/proc/activate() + if(processing) + to_chat(usr, "The biogenerator is in the process of working.") + return + + var/S = 0 + for(var/obj/item/weapon/reagent_containers/food/snacks/grown/I in contents) + S += 5 + if(I.reagents.get_reagent_amount("nutriment") < 0.1) + points += 1*productivity + else points += I.reagents.get_reagent_amount("nutriment")*10*productivity + qdel(I) + + if(S) + processing = 1 + update_icon() + updateUsrDialog() + playsound(src, 'sound/machines/blender.ogg', 35, 1) + use_power(S*30) + sleep(S+15/productivity) + processing = 0 + update_icon() + else + menustat = "void" + +/obj/machinery/biogenerator/proc/check_cost(cost) + if (cost > points) + menustat = "nopoints" + return 1 + else + points -= cost + processing = 1 + update_icon() + updateUsrDialog() + sleep(30) + return 0 + +/obj/machinery/biogenerator/proc/create_product(create) + switch(create) + if("milk") + if (check_cost(20/efficiency)) return 0 + else beaker.reagents.add_reagent("milk",10) + if("cream") + if (check_cost(30/efficiency)) return 0 + else beaker.reagents.add_reagent("cream",10) + if("meat") + if (check_cost(125/efficiency)) return 0 + else new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) + if("monkey") + if(check_cost(250/efficiency)) return 0 + else new/obj/item/weapon/reagent_containers/food/snacks/monkeycube(src.loc) + if("ez") + if (check_cost(10/efficiency)) return 0 + else new/obj/item/nutrient/ez(src.loc) + if("l4z") + if (check_cost(20/efficiency)) return 0 + else new/obj/item/nutrient/l4z(src.loc) + if("rh") + if (check_cost(25/efficiency)) return 0 + else new/obj/item/nutrient/rh(src.loc) + if("ez5") //It's not an elegant method, but it's safe and easy. -Cheridan + if (check_cost(50/efficiency)) return 0 + else + new/obj/item/nutrient/ez(src.loc) + new/obj/item/nutrient/ez(src.loc) + new/obj/item/nutrient/ez(src.loc) + new/obj/item/nutrient/ez(src.loc) + new/obj/item/nutrient/ez(src.loc) + if("l4z5") + if (check_cost(100/efficiency)) return 0 + else + new/obj/item/nutrient/l4z(src.loc) + new/obj/item/nutrient/l4z(src.loc) + new/obj/item/nutrient/l4z(src.loc) + new/obj/item/nutrient/l4z(src.loc) + new/obj/item/nutrient/l4z(src.loc) + if("rh5") + if (check_cost(125/efficiency)) return 0 + else + new/obj/item/nutrient/rh(src.loc) + new/obj/item/nutrient/rh(src.loc) + new/obj/item/nutrient/rh(src.loc) + new/obj/item/nutrient/rh(src.loc) + new/obj/item/nutrient/rh(src.loc) + if("meat5") + if (check_cost(125/efficiency)) return 0 + else + new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) + new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) + new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) + new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) + new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc) + if("wallet") + if (check_cost(100/efficiency)) return 0 + else new/obj/item/weapon/storage/wallet(src.loc) + //if("bkbag") + // if (check_cost(200/efficiency)) return 0 + // else new/obj/item/weapon/storage/bag/books(src.loc) + if("ptbag") + if (check_cost(200/efficiency)) return 0 + else new/obj/item/weapon/storage/bag/plants(src.loc) + if("mnbag") + if (check_cost(200/efficiency)) return 0 + else new/obj/item/weapon/storage/bag/ore(src.loc) + if("gloves") + if (check_cost(250/efficiency)) return 0 + else new/obj/item/clothing/gloves/botanic_leather(src.loc) + if("tbelt") + if (check_cost(300/efficiency)) return 0 + else new/obj/item/weapon/storage/belt/utility(src.loc) + if("satchel") + if (check_cost(400/efficiency)) return 0 + else new/obj/item/weapon/storage/backpack/satchel(src.loc) + if("cashbag") + if (check_cost(400/efficiency)) return 0 + else new/obj/item/weapon/storage/bag/cash(src.loc) + if("jacket") + if (check_cost(500/efficiency)) return 0 + else new/obj/item/clothing/suit/jacket/leather(src.loc) + if("overcoat") + if (check_cost(1000/efficiency)) return 0 + else new/obj/item/clothing/suit/jacket/leather/overcoat(src.loc) + processing = 0 + menustat = "complete" + update_icon() + return 1 + +/obj/machinery/biogenerator/Topic(href, href_list) + . = ..() + if(!. || panel_open) + return + + switch(href_list["action"]) + if("activate") + activate() + if("detach") + if(beaker) + beaker.loc = src.loc + beaker = null + update_icon() + if("create") + create_product(href_list["item"]) + if("menu") + menustat = "menu" + + updateUsrDialog() diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index b4c5a973293d..675eb942ceea 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -1,189 +1,189 @@ -// AI (i.e. game AI, not the AI player) controlled bots - -/obj/machinery/bot - icon = 'icons/obj/aibots.dmi' - layer = MOB_LAYER - light_range = 3 - use_power = 0 - allowed_checks = ALLOWED_CHECK_NONE - 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/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots - var/x_last - var/y_last - var/same_pos_count - -/obj/machinery/bot/atom_init() - . = ..() - bots_list += src - -/obj/machinery/bot/Destroy() - bots_list -= src - return ..() - -/obj/machinery/bot/proc/turn_on() - if(stat) return 0 - on = 1 - set_light(initial(light_range)) - 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) - 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 (health < maxhealth) - if (health > maxhealth/3) - to_chat(user, "[src]'s parts look loose.") - else - to_chat(user, "[src]'s parts look very loose!") - -/obj/machinery/bot/attack_alien(mob/living/carbon/alien/user) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - src.health -= rand(15,30)*brute_dam_coeff - src.visible_message("\red [user] has slashed [src]!") - playsound(src.loc, 'sound/weapons/slice.ogg', 25, 1, -1) - if(prob(10)) - new /obj/effect/decal/cleanable/blood/oil(src.loc) - healthcheck() - - -/obj/machinery/bot/attack_animal(mob/living/simple_animal/M) - ..() - if(M.melee_damage_upper == 0) - return - src.health -= M.melee_damage_upper - src.visible_message("\red [M] has [M.attacktext] [src]!") - M.attack_log += text("\[[time_stamp()]\] attacked [src.name]") - if(prob(10)) - new /obj/effect/decal/cleanable/blood/oil(src.loc) - healthcheck() - - - - -/obj/machinery/bot/attackby(obj/item/weapon/W, mob/user) - 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("\red [user] repairs [src]!","\blue You repair [src]!") - else - to_chat(user, "Unable to repair with the maintenance panel closed.") - 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(obj/item/projectile/Proj) - health -= Proj.damage - ..() - healthcheck() - -/obj/machinery/bot/meteorhit() - src.explode() - return - -/obj/machinery/bot/blob_act() - src.health -= rand(20,40)*fire_dam_coeff - healthcheck() - return - -/obj/machinery/bot/ex_act(severity) - 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) - var/was_on = on - stat |= EMPED - var/obj/effect/overlay/pulse2 = new /obj/effect/overlay(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) - src.attack_hand(user) - -/obj/machinery/bot/is_operational_topic() - return TRUE - -/obj/machinery/bot/proc/inaction_check() - if(is_on_patrol() && (x_last == x && y_last == y)) - same_pos_count++ - if(same_pos_count >= 15) - turn_off() - return FALSE - else - same_pos_count = 0 - - x_last = x - y_last = y - - return TRUE - -/obj/machinery/bot/proc/is_on_patrol() - return FALSE +// AI (i.e. game AI, not the AI player) controlled bots + +/obj/machinery/bot + icon = 'icons/obj/aibots.dmi' + layer = MOB_LAYER + light_range = 3 + use_power = 0 + allowed_checks = ALLOWED_CHECK_NONE + 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/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots + var/x_last + var/y_last + var/same_pos_count + +/obj/machinery/bot/atom_init() + . = ..() + bots_list += src + +/obj/machinery/bot/Destroy() + bots_list -= src + return ..() + +/obj/machinery/bot/proc/turn_on() + if(stat) return 0 + on = 1 + set_light(initial(light_range)) + 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) + 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 (health < maxhealth) + if (health > maxhealth/3) + to_chat(user, "[src]'s parts look loose.") + else + to_chat(user, "[src]'s parts look very loose!") + +/obj/machinery/bot/attack_alien(mob/living/carbon/alien/user) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + src.health -= rand(15,30)*brute_dam_coeff + src.visible_message("\red [user] has slashed [src]!") + playsound(src.loc, 'sound/weapons/slice.ogg', 25, 1, -1) + if(prob(10)) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + healthcheck() + + +/obj/machinery/bot/attack_animal(mob/living/simple_animal/M) + ..() + if(M.melee_damage_upper == 0) + return + src.health -= M.melee_damage_upper + src.visible_message("\red [M] has [M.attacktext] [src]!") + M.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + if(prob(10)) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + healthcheck() + + + + +/obj/machinery/bot/attackby(obj/item/weapon/W, mob/user) + 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("\red [user] repairs [src]!","\blue You repair [src]!") + else + to_chat(user, "Unable to repair with the maintenance panel closed.") + 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(obj/item/projectile/Proj) + health -= Proj.damage + ..() + healthcheck() + +/obj/machinery/bot/meteorhit() + src.explode() + return + +/obj/machinery/bot/blob_act() + src.health -= rand(20,40)*fire_dam_coeff + healthcheck() + return + +/obj/machinery/bot/ex_act(severity) + 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) + var/was_on = on + stat |= EMPED + var/obj/effect/overlay/pulse2 = new /obj/effect/overlay(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) + src.attack_hand(user) + +/obj/machinery/bot/is_operational_topic() + return TRUE + +/obj/machinery/bot/proc/inaction_check() + if(is_on_patrol() && (x_last == x && y_last == y)) + same_pos_count++ + if(same_pos_count >= 15) + turn_off() + return FALSE + else + same_pos_count = 0 + + x_last = x + y_last = y + + return TRUE + +/obj/machinery/bot/proc/is_on_patrol() + return FALSE diff --git a/code/game/machinery/bots/cleanbot.dm b/code/game/machinery/bots/cleanbot.dm index 0f6004226e46..3c88a0ac307f 100644 --- a/code/game/machinery/bots/cleanbot.dm +++ b/code/game/machinery/bots/cleanbot.dm @@ -1,363 +1,363 @@ -//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 - 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 = MOB_LAYER - density = 0 - anchored = 0 - //weight = 1.0E7 - health = 25 - maxhealth = 25 - var/cleaning = 0 - var/screwloose = 0 - var/oddbutton = 0 - var/blood = 1 - var/list/target_types = list() - var/obj/effect/decal/cleanable/target - var/obj/effect/decal/cleanable/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/atom_init() - . = ..() - 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/Destroy() - if(radio_controller) - radio_controller.remove_object(src,beacon_freq) - return ..() - -/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.targeted_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/ui_interact(mob/user) - 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) || isobserver(user)) - dat += text({"
    Cleans Blood: []
    "}, text("[src.blood ? "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[entity_ja(dat)]", "window=autocleaner") - onclose(user, "autocleaner") - -/obj/machinery/bot/cleanbot/Topic(href, href_list) - . = ..() - if(!.) - return - - switch(href_list["operation"]) - if("start") - if (src.on) - turn_off() - else - turn_on() - if("blood") - src.blood =!src.blood - src.get_targets() - if("patrol") - src.should_patrol =!src.should_patrol - src.patrol_path = null - if("freq") - var/freq = input("Select frequency for navigation beacons", "Frequnecy", num2text(beacon_freq / 10)) as num - if (freq > 0) - src.beacon_freq = freq * 10 - 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) - 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) - ..() - if(open && !locked) - if(user) - to_chat(user, "The [src] buzzes and beeps.") - src.oddbutton = 1 - src.screwloose = 1 - -/obj/machinery/bot/cleanbot/is_on_patrol() - return should_patrol - -/obj/machinery/bot/cleanbot/process() - if(!src.on) - return - if(src.cleaning) - return - if(!inaction_check()) - 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.make_wet_floor(WATER_FLOOR) - 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 = new /obj/effect/decal/cleanable/blood/gibs(src.loc) - //gib.streak(list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) - src.oldtarget = gib - if(!src.target || src.target == null) - for (var/obj/effect/decal/cleanable/D in view(7,src)) - for(var/T in src.target_types) - if(isnull(D.targeted_by) && (D.type == T || D.parent_type == T) && D != src.oldtarget) // If the mess isn't targeted - src.oldtarget = D // or if it is but the bot is gone. - src.target = D // and it's stuff we clean? Clean it. - D.targeted_by = src // Claim the mess we are targeting. - return - - 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 - - var/datum/signal/signal = new() - 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 = get_path_to(src, next_dest_loc, /turf/proc/Distance_cardinal, 0, 120, id=botcard, exclude=null) - else - patrol_move() - - return - - if(target && path.len == 0) - spawn(0) - if(!src || !target) return - src.path = get_path_to(src, get_turf(src.target), /turf/proc/Distance_cardinal, 0, 30, id=botcard) - if(src.path.len == 0) - src.oldtarget = src.target - target.targeted_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.loc) - 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) - var/closest_dest = null - if (dist < closest_dist && signal.source.loc != src.loc) - closest_dist = dist - closest_loc = signal.source.loc - closest_dest = recv - if(next_dest == null || patrol_path == null || next_dest_loc == null) - next_dest_loc = closest_loc - next_dest = closest_dest - if(next_dest_loc == src.loc && recv == next_dest) - next_dest_loc = signal.source.loc - next_dest = signal.data["next_patrol"] - -/obj/machinery/bot/cleanbot/proc/get_targets() - src.target_types = new/list() - target_types += /obj/effect/decal/cleanable/blood/oil - target_types += /obj/effect/decal/cleanable/blood/gibs/robot - target_types += /obj/effect/decal/cleanable/vomit - target_types += /obj/effect/decal/cleanable/crayon - target_types += /obj/effect/decal/cleanable/liquid_fuel - target_types += /obj/effect/decal/cleanable/mucus - target_types += /obj/effect/decal/cleanable/dirt - target_types += /obj/effect/decal/cleanable/flour - target_types += /obj/effect/decal/cleanable/tomato_smudge - target_types += /obj/effect/decal/cleanable/egg_smudge - target_types += /obj/effect/decal/cleanable/pie_smudge - target_types += /obj/effect/fluid - target_types += /obj/effect/decal/cleanable/molten_item - target_types += /obj/effect/decal/cleanable/ash - target_types += /obj/effect/decal/cleanable/greenglow - target_types += /obj/effect/decal/cleanable/spiderling_remains - if(src.blood) - target_types += /obj/effect/decal/cleanable/blood/ - target_types += /obj/effect/decal/cleanable/blood/gibs/ - target_types += /obj/effect/decal/cleanable/blood/tracks - target_types += /obj/effect/decal/cleanable/blood/tracks/footprints - target_types += /obj/effect/decal/cleanable/blood/tracks/wheels - target_types += /obj/effect/decal/cleanable/blood/splatter - target_types += /obj/effect/decal/cleanable/blood/drip - target_types += /obj/effect/decal/cleanable/blood/trail_holder - -/obj/machinery/bot/cleanbot/proc/clean(obj/effect/decal/cleanable/target) - anchored = 1 - icon_state = "cleanbot-c" - visible_message("\red [src] begins to clean up the [target]") - cleaning = 1 - var/cleantime = 50 - if(istype(target,/obj/effect/decal/cleanable/dirt)) // Clean Dirt much faster - cleantime = 10 - spawn(cleantime) - if(istype(loc,/turf/simulated)) - var/turf/simulated/f = loc - f.dirt = 0 - cleaning = 0 - qdel(target) - icon_state = "cleanbot[on]" - anchored = 0 - target = null - -/obj/machinery/bot/cleanbot/explode() - src.on = 0 - src.visible_message("\red [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(obj/item/W, mob/user) - ..() - if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) - user.drop_item() - 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 = sanitize_safe(input(user, "Enter new robot name", src.name, input_default(src.created_name)), 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 + 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 = MOB_LAYER + density = 0 + anchored = 0 + //weight = 1.0E7 + health = 25 + maxhealth = 25 + var/cleaning = 0 + var/screwloose = 0 + var/oddbutton = 0 + var/blood = 1 + var/list/target_types = list() + var/obj/effect/decal/cleanable/target + var/obj/effect/decal/cleanable/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/atom_init() + . = ..() + 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/Destroy() + if(radio_controller) + radio_controller.remove_object(src,beacon_freq) + return ..() + +/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.targeted_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/ui_interact(mob/user) + 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) || isobserver(user)) + dat += text({"
    Cleans Blood: []
    "}, text("[src.blood ? "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[entity_ja(dat)]", "window=autocleaner") + onclose(user, "autocleaner") + +/obj/machinery/bot/cleanbot/Topic(href, href_list) + . = ..() + if(!.) + return + + switch(href_list["operation"]) + if("start") + if (src.on) + turn_off() + else + turn_on() + if("blood") + src.blood =!src.blood + src.get_targets() + if("patrol") + src.should_patrol =!src.should_patrol + src.patrol_path = null + if("freq") + var/freq = input("Select frequency for navigation beacons", "Frequnecy", num2text(beacon_freq / 10)) as num + if (freq > 0) + src.beacon_freq = freq * 10 + 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) + 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) + ..() + if(open && !locked) + if(user) + to_chat(user, "The [src] buzzes and beeps.") + src.oddbutton = 1 + src.screwloose = 1 + +/obj/machinery/bot/cleanbot/is_on_patrol() + return should_patrol + +/obj/machinery/bot/cleanbot/process() + if(!src.on) + return + if(src.cleaning) + return + if(!inaction_check()) + 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.make_wet_floor(WATER_FLOOR) + 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 = new /obj/effect/decal/cleanable/blood/gibs(src.loc) + //gib.streak(list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) + src.oldtarget = gib + if(!src.target || src.target == null) + for (var/obj/effect/decal/cleanable/D in view(7,src)) + for(var/T in src.target_types) + if(isnull(D.targeted_by) && (D.type == T || D.parent_type == T) && D != src.oldtarget) // If the mess isn't targeted + src.oldtarget = D // or if it is but the bot is gone. + src.target = D // and it's stuff we clean? Clean it. + D.targeted_by = src // Claim the mess we are targeting. + return + + 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 + + var/datum/signal/signal = new() + 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 = get_path_to(src, next_dest_loc, /turf/proc/Distance_cardinal, 0, 120, id=botcard, exclude=null) + else + patrol_move() + + return + + if(target && path.len == 0) + spawn(0) + if(!src || !target) return + src.path = get_path_to(src, get_turf(src.target), /turf/proc/Distance_cardinal, 0, 30, id=botcard) + if(src.path.len == 0) + src.oldtarget = src.target + target.targeted_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.loc) + 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) + var/closest_dest = null + if (dist < closest_dist && signal.source.loc != src.loc) + closest_dist = dist + closest_loc = signal.source.loc + closest_dest = recv + if(next_dest == null || patrol_path == null || next_dest_loc == null) + next_dest_loc = closest_loc + next_dest = closest_dest + if(next_dest_loc == src.loc && recv == next_dest) + next_dest_loc = signal.source.loc + next_dest = signal.data["next_patrol"] + +/obj/machinery/bot/cleanbot/proc/get_targets() + src.target_types = new/list() + target_types += /obj/effect/decal/cleanable/blood/oil + target_types += /obj/effect/decal/cleanable/blood/gibs/robot + target_types += /obj/effect/decal/cleanable/vomit + target_types += /obj/effect/decal/cleanable/crayon + target_types += /obj/effect/decal/cleanable/liquid_fuel + target_types += /obj/effect/decal/cleanable/mucus + target_types += /obj/effect/decal/cleanable/dirt + target_types += /obj/effect/decal/cleanable/flour + target_types += /obj/effect/decal/cleanable/tomato_smudge + target_types += /obj/effect/decal/cleanable/egg_smudge + target_types += /obj/effect/decal/cleanable/pie_smudge + target_types += /obj/effect/fluid + target_types += /obj/effect/decal/cleanable/molten_item + target_types += /obj/effect/decal/cleanable/ash + target_types += /obj/effect/decal/cleanable/greenglow + target_types += /obj/effect/decal/cleanable/spiderling_remains + if(src.blood) + target_types += /obj/effect/decal/cleanable/blood/ + target_types += /obj/effect/decal/cleanable/blood/gibs/ + target_types += /obj/effect/decal/cleanable/blood/tracks + target_types += /obj/effect/decal/cleanable/blood/tracks/footprints + target_types += /obj/effect/decal/cleanable/blood/tracks/wheels + target_types += /obj/effect/decal/cleanable/blood/splatter + target_types += /obj/effect/decal/cleanable/blood/drip + target_types += /obj/effect/decal/cleanable/blood/trail_holder + +/obj/machinery/bot/cleanbot/proc/clean(obj/effect/decal/cleanable/target) + anchored = 1 + icon_state = "cleanbot-c" + visible_message("\red [src] begins to clean up the [target]") + cleaning = 1 + var/cleantime = 50 + if(istype(target,/obj/effect/decal/cleanable/dirt)) // Clean Dirt much faster + cleantime = 10 + spawn(cleantime) + if(istype(loc,/turf/simulated)) + var/turf/simulated/f = loc + f.dirt = 0 + cleaning = 0 + qdel(target) + icon_state = "cleanbot[on]" + anchored = 0 + target = null + +/obj/machinery/bot/cleanbot/explode() + src.on = 0 + src.visible_message("\red [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(obj/item/W, mob/user) + ..() + if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm)) + user.drop_item() + 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 = sanitize_safe(input(user, "Enter new robot name", src.name, input_default(src.created_name)), 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 7c00b956d67d..87ffb22d3040 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -1,516 +1,516 @@ -/obj/machinery/bot/secbot/ed209 - name = "ED-209 Security Robot" - desc = "A security robot. He looks less than thrilled." - icon = 'icons/obj/aibots.dmi' - icon_state = "ed2090" - icon_state_arrest = "ed209-c" - health = 100 - maxhealth = 100 - - var/lastfired = 0 - var/shot_delay = 3 //.3 seconds between shots - - 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 - idcheck = 1 //If false, all station IDs are authorized for weapons. - check_records = 1 //Does it check security records? Checks arrest status and existence of record - var/projectile = null//Holder for projectile type, to avoid so many else if chains - -#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 - - -/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/secbot/ed209/atom_init(mapload, created_name, created_lasercolor) - . = ..() - if(created_name) - name = created_name - if(created_lasercolor) - lasercolor = created_lasercolor - update_icon() - - 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_one_access.Cut() - 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/secbot/ed209/update_icon() - icon_state = "[lasercolor]ed209[on]" - -/obj/machinery/bot/secbot/ed209/is_operational_topic() - if(lasercolor && ishuman(usr)) - 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 FALSE - else if((lasercolor == "r") && istype(H.wear_suit, /obj/item/clothing/suit/bluetag)) - return FALSE - return TRUE - -/obj/machinery/bot/secbot/ed209/ui_interact(mob/user) - var/dat - - dat += text({" - Automatic Security Unit v2.5

    - Status: []
    - Behaviour controls are [locked ? "locked" : "unlocked"]
    - Maintenance panel panel is [open ? "opened" : "closed"]"}, - - "[on ? "On" : "Off"]" ) - - if(!locked || issilicon(user) || isobserver(user)) - if(!lasercolor) - dat += text({"
    - Check for Weapon Authorization: []
    - Check Security Records: []
    - Operating Mode: []
    - Report Arrests: []"}, - - "[idcheck ? "Yes" : "No"]", - "[check_records ? "Yes" : "No"]", - "[arrest_type ? "Detain" : "Arrest"]", - "[declare_arrests ? "Yes" : "No"]" ) - - dat += text({"
    - Auto Patrol: []"}, - - "[auto_patrol ? "On" : "Off"]" ) - - user << browse("Securitron v2.5 controls[entity_ja(dat)]", "window=autosec") - onclose(user, "autosec") - - -/obj/machinery/bot/secbot/ed209/beingAttacked(obj/item/weapon/W, mob/user) - if(!istype(W, /obj/item/weapon/screwdriver) && W.force && !target) - target = user - mode = SECBOT_HUNT - if(lasercolor)//To make up for the fact that lasertag bots don't hunt - shootAt(user) - - -/obj/machinery/bot/secbot/ed209/Emag(mob/user) - ..() - if(open && !locked) - projectile = null - -/obj/machinery/bot/secbot/ed209/process() - if(!on) - return - - var/list/mob/living/targets = list() - for(var/mob/living/L in view(12, src)) //Let's find us a target - var/threatlevel = 0 - if(L.stat || L.lying && !L.crawling) - continue - threatlevel = assess_perp(L) - //speak(C.real_name + text(": threat: []", threatlevel)) - if(threatlevel < 4) - continue - - var/dst = get_dist(src, L) - if(dst <= 1) - continue - targets += L - - if(targets.len) - shootAt(pick(targets)) - - if((mode == SECBOT_HUNT || mode == SECBOT_PREP_ARREST) && lasercolor) //Lasertag bots do not tase or arrest anyone, just patrol and shoot and whatnot - mode = SECBOT_IDLE - return - - ..() - -// perform a single patrol step - -/obj/machinery/bot/secbot/ed209/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() - if(lasercolor) - sleep(20) - else // failed to move - blockcount++ - if(blockcount > 5) // attempt 5 times before recomputing - // find new path excluding blocked turf - addtimer(CALLBACK(src, .proc/patrol_substep, next), 2) - - else // not a valid turf - mode = SECBOT_IDLE - - else // no path, so calculate new one - mode = SECBOT_START_PATROL - - - -// look for a criminal in view of the bot - -/obj/machinery/bot/secbot/ed209/look_for_perp() - if(disabled) - return - - anchored = 0 - threatlevel = 0 - for(var/mob/living/L in view(12, src)) //Let's find us a criminal - if(L.stat || (lasercolor && L.lying && !L.crawling)) - 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(iscarbon(L)) - var/mob/living/carbon/C = L - if(C.handcuffed) - continue - - if((L.name == oldtarget_name) && (world.time < last_found + 100)) - continue - - threatlevel = assess_perp(L) - - if(threatlevel >= 4) - target = L - oldtarget_name = L.name - speak("Level [threatlevel] infraction alert!") - if(!lasercolor) - playsound(loc, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/EDPlaceholder.ogg'), 50, 0) - visible_message("[src] points at [L.name]!") - mode = SECBOT_HUNT - 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/ed209/assess_perp(mob/living/perp) - var/threatcount = ..() - - if(lasercolor && ishuman(perp)) - var/mob/living/carbon/human/hperp = perp - if(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(hperp.wear_suit, /obj/item/clothing/suit/redtag)) - threatcount += 4 - if(istype(hperp.r_hand, /obj/item/weapon/gun/energy/laser/redtag) || istype(hperp.l_hand, /obj/item/weapon/gun/energy/laser/redtag)) - threatcount += 4 - if(istype(hperp.belt, /obj/item/weapon/gun/energy/laser/redtag)) - threatcount += 2 - - else if(lasercolor == "r") - threatcount = 0 - if(istype(hperp.wear_suit, /obj/item/clothing/suit/bluetag)) - threatcount += 4 - if(istype(hperp.r_hand, /obj/item/weapon/gun/energy/laser/bluetag) || istype(hperp.l_hand, /obj/item/weapon/gun/energy/laser/bluetag)) - threatcount += 4 - if(istype(hperp.belt, /obj/item/weapon/gun/energy/laser/bluetag)) - threatcount += 2 - - if(idcheck && allowed(perp) && !lasercolor) - threatcount = 0//Corrupt cops cannot exist beep boop - - return threatcount - -/obj/machinery/bot/secbot/ed209/explode() - walk_to(src, 0) - visible_message("\red [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 = 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/storage/flak(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() - - new /obj/effect/decal/cleanable/blood/oil(loc) - qdel(src) - - -/obj/machinery/bot/secbot/ed209/proc/shootAt(mob/target) - if(lastfired && world.time - lastfired < shot_delay) - return - lastfired = world.time - var/turf/T = get_turf(src) - var/atom/U = get_turf(target) - if(!istype(T) || !istype(U)) - return - - //if(lastfired && world.time - lastfired < 100) - // playsound(loc, 'ed209_shoot.ogg', 50, 0) - - if(!projectile) - if(!lasercolor) - if(emagged == 2) - projectile = /obj/item/projectile/beam - else - projectile = /obj/item/projectile/energy/electrode - else if(lasercolor == "b") - if(emagged == 2) - projectile = /obj/item/projectile/beam/lastertag/omni - else - projectile = /obj/item/projectile/beam/lastertag/blue - else if(lasercolor == "r") - if(emagged == 2) - projectile = /obj/item/projectile/beam/lastertag/omni - else - projectile = /obj/item/projectile/beam/lastertag/red - - var/obj/item/projectile/A = new projectile(loc) - A.original = target - A.current = T - A.starting = T - A.fake = TRUE - A.yo = U.y - T.y - A.xo = U.x - T.x - A.process() - -/obj/machinery/bot/secbot/ed209/attack_alien(mob/living/carbon/alien/user) - ..() - if(!isalien(target)) - target = user - mode = SECBOT_HUNT - - -/obj/machinery/bot/secbot/ed209/emp_act(severity) - if(severity == 2 && prob(70)) - ..(severity - 1) - else - var/obj/effect/overlay/pulse2 = new/obj/effect/overlay(loc) - pulse2.icon = 'icons/effects/effects.dmi' - pulse2.icon_state = "empdisable" - pulse2.name = "emp sparks" - pulse2.anchored = 1 - pulse2.dir = pick(cardinal) - QDEL_IN(pulse2, 10) - var/list/mob/living/carbon/targets = new - for(var/mob/living/carbon/C in view(12, src)) - if(C.stat == DEAD) - 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) - target = toarrest - mode = SECBOT_HUNT - - - -/obj/item/weapon/ed209_assembly/attackby(obj/item/weapon/W, mob/user) - ..() - - if(istype(W, /obj/item/weapon/pen)) - var/t = sanitize_safe(input(user, "Enter new robot name", name, input_default(created_name)), MAX_NAME_LEN) - if(!t) - return - if(!in_range(src, usr) && 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)) - user.drop_item() - 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/storage/flak)) - user.drop_item() - 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)) - user.drop_item() - 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)) - user.drop_item() - 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 - if(user.is_busy(src)) return - to_chat(user, "You start to wire [src]...") - if(do_after(user, 40, target = src)) - if(build_step == 6 && coil.use(1)) - build_step++ - to_chat(user, "You wire the ED-209 assembly.") - name = "wired ED-209 assembly" - - if(7) - 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].") - item_state = "[lasercolor]ed209_taser" - icon_state = "[lasercolor]ed209_taser" - user.drop_item() - qdel(W) - - if(8) - if(istype(W, /obj/item/weapon/screwdriver)) - if(user.is_busy(src)) return - playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) - to_chat(user, "Now attaching the gun to the frame...") - if(do_after(user, 40, target = src)) - if(build_step == 8) - build_step++ - name = "armed [name]" - to_chat(user, "Taser gun attached.") - - if(9) - if(istype(W, /obj/item/weapon/stock_parts/cell)) - build_step++ - to_chat(user, "You complete the ED-209.") - var/turf/T = get_turf(src) - new /obj/machinery/bot/secbot/ed209(T, created_name, lasercolor) - user.drop_item() - qdel(W) - user.drop_from_inventory(src) - qdel(src) - - -/obj/machinery/bot/secbot/ed209/bullet_act(obj/item/projectile/Proj) - if(!disabled && ((lasercolor == "b") && istype(Proj, /obj/item/projectile/beam/lastertag/red) \ - || (lasercolor == "r") && istype(Proj, /obj/item/projectile/beam/lastertag/blue))) - disabled = 1 - qdel(Proj) - addtimer(CALLBACK(src, .proc/enable), 100) - ..() - -/obj/machinery/bot/secbot/ed209/proc/enable() - disabled = 0 - -/obj/machinery/bot/secbot/ed209/bluetag/atom_init() // If desired, you spawn red and bluetag bots easily - ..() - new /obj/machinery/bot/secbot/ed209(get_turf(src), null, "b") - return INITIALIZE_HINT_QDEL - -/obj/machinery/bot/secbot/ed209/redtag/atom_init() - ..() - new /obj/machinery/bot/secbot/ed209(get_turf(src), null, "r") - return INITIALIZE_HINT_QDEL +/obj/machinery/bot/secbot/ed209 + name = "ED-209 Security Robot" + desc = "A security robot. He looks less than thrilled." + icon = 'icons/obj/aibots.dmi' + icon_state = "ed2090" + icon_state_arrest = "ed209-c" + health = 100 + maxhealth = 100 + + var/lastfired = 0 + var/shot_delay = 3 //.3 seconds between shots + + 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 + idcheck = 1 //If false, all station IDs are authorized for weapons. + check_records = 1 //Does it check security records? Checks arrest status and existence of record + var/projectile = null//Holder for projectile type, to avoid so many else if chains + +#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 + + +/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/secbot/ed209/atom_init(mapload, created_name, created_lasercolor) + . = ..() + if(created_name) + name = created_name + if(created_lasercolor) + lasercolor = created_lasercolor + update_icon() + + 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_one_access.Cut() + 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/secbot/ed209/update_icon() + icon_state = "[lasercolor]ed209[on]" + +/obj/machinery/bot/secbot/ed209/is_operational_topic() + if(lasercolor && ishuman(usr)) + 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 FALSE + else if((lasercolor == "r") && istype(H.wear_suit, /obj/item/clothing/suit/bluetag)) + return FALSE + return TRUE + +/obj/machinery/bot/secbot/ed209/ui_interact(mob/user) + var/dat + + dat += text({" + Automatic Security Unit v2.5

    + Status: []
    + Behaviour controls are [locked ? "locked" : "unlocked"]
    + Maintenance panel panel is [open ? "opened" : "closed"]"}, + + "[on ? "On" : "Off"]" ) + + if(!locked || issilicon(user) || isobserver(user)) + if(!lasercolor) + dat += text({"
    + Check for Weapon Authorization: []
    + Check Security Records: []
    + Operating Mode: []
    + Report Arrests: []"}, + + "[idcheck ? "Yes" : "No"]", + "[check_records ? "Yes" : "No"]", + "[arrest_type ? "Detain" : "Arrest"]", + "[declare_arrests ? "Yes" : "No"]" ) + + dat += text({"
    + Auto Patrol: []"}, + + "[auto_patrol ? "On" : "Off"]" ) + + user << browse("Securitron v2.5 controls[entity_ja(dat)]", "window=autosec") + onclose(user, "autosec") + + +/obj/machinery/bot/secbot/ed209/beingAttacked(obj/item/weapon/W, mob/user) + if(!istype(W, /obj/item/weapon/screwdriver) && W.force && !target) + target = user + mode = SECBOT_HUNT + if(lasercolor)//To make up for the fact that lasertag bots don't hunt + shootAt(user) + + +/obj/machinery/bot/secbot/ed209/Emag(mob/user) + ..() + if(open && !locked) + projectile = null + +/obj/machinery/bot/secbot/ed209/process() + if(!on) + return + + var/list/mob/living/targets = list() + for(var/mob/living/L in view(12, src)) //Let's find us a target + var/threatlevel = 0 + if(L.stat || L.lying && !L.crawling) + continue + threatlevel = assess_perp(L) + //speak(C.real_name + text(": threat: []", threatlevel)) + if(threatlevel < 4) + continue + + var/dst = get_dist(src, L) + if(dst <= 1) + continue + targets += L + + if(targets.len) + shootAt(pick(targets)) + + if((mode == SECBOT_HUNT || mode == SECBOT_PREP_ARREST) && lasercolor) //Lasertag bots do not tase or arrest anyone, just patrol and shoot and whatnot + mode = SECBOT_IDLE + return + + ..() + +// perform a single patrol step + +/obj/machinery/bot/secbot/ed209/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() + if(lasercolor) + sleep(20) + else // failed to move + blockcount++ + if(blockcount > 5) // attempt 5 times before recomputing + // find new path excluding blocked turf + addtimer(CALLBACK(src, .proc/patrol_substep, next), 2) + + else // not a valid turf + mode = SECBOT_IDLE + + else // no path, so calculate new one + mode = SECBOT_START_PATROL + + + +// look for a criminal in view of the bot + +/obj/machinery/bot/secbot/ed209/look_for_perp() + if(disabled) + return + + anchored = 0 + threatlevel = 0 + for(var/mob/living/L in view(12, src)) //Let's find us a criminal + if(L.stat || (lasercolor && L.lying && !L.crawling)) + 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(iscarbon(L)) + var/mob/living/carbon/C = L + if(C.handcuffed) + continue + + if((L.name == oldtarget_name) && (world.time < last_found + 100)) + continue + + threatlevel = assess_perp(L) + + if(threatlevel >= 4) + target = L + oldtarget_name = L.name + speak("Level [threatlevel] infraction alert!") + if(!lasercolor) + playsound(loc, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/EDPlaceholder.ogg'), 50, 0) + visible_message("[src] points at [L.name]!") + mode = SECBOT_HUNT + 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/ed209/assess_perp(mob/living/perp) + var/threatcount = ..() + + if(lasercolor && ishuman(perp)) + var/mob/living/carbon/human/hperp = perp + if(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(hperp.wear_suit, /obj/item/clothing/suit/redtag)) + threatcount += 4 + if(istype(hperp.r_hand, /obj/item/weapon/gun/energy/laser/redtag) || istype(hperp.l_hand, /obj/item/weapon/gun/energy/laser/redtag)) + threatcount += 4 + if(istype(hperp.belt, /obj/item/weapon/gun/energy/laser/redtag)) + threatcount += 2 + + else if(lasercolor == "r") + threatcount = 0 + if(istype(hperp.wear_suit, /obj/item/clothing/suit/bluetag)) + threatcount += 4 + if(istype(hperp.r_hand, /obj/item/weapon/gun/energy/laser/bluetag) || istype(hperp.l_hand, /obj/item/weapon/gun/energy/laser/bluetag)) + threatcount += 4 + if(istype(hperp.belt, /obj/item/weapon/gun/energy/laser/bluetag)) + threatcount += 2 + + if(idcheck && allowed(perp) && !lasercolor) + threatcount = 0//Corrupt cops cannot exist beep boop + + return threatcount + +/obj/machinery/bot/secbot/ed209/explode() + walk_to(src, 0) + visible_message("\red [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 = 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/storage/flak(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() + + new /obj/effect/decal/cleanable/blood/oil(loc) + qdel(src) + + +/obj/machinery/bot/secbot/ed209/proc/shootAt(mob/target) + if(lastfired && world.time - lastfired < shot_delay) + return + lastfired = world.time + var/turf/T = get_turf(src) + var/atom/U = get_turf(target) + if(!istype(T) || !istype(U)) + return + + //if(lastfired && world.time - lastfired < 100) + // playsound(loc, 'ed209_shoot.ogg', 50, 0) + + if(!projectile) + if(!lasercolor) + if(emagged == 2) + projectile = /obj/item/projectile/beam + else + projectile = /obj/item/projectile/energy/electrode + else if(lasercolor == "b") + if(emagged == 2) + projectile = /obj/item/projectile/beam/lastertag/omni + else + projectile = /obj/item/projectile/beam/lastertag/blue + else if(lasercolor == "r") + if(emagged == 2) + projectile = /obj/item/projectile/beam/lastertag/omni + else + projectile = /obj/item/projectile/beam/lastertag/red + + var/obj/item/projectile/A = new projectile(loc) + A.original = target + A.current = T + A.starting = T + A.fake = TRUE + A.yo = U.y - T.y + A.xo = U.x - T.x + A.process() + +/obj/machinery/bot/secbot/ed209/attack_alien(mob/living/carbon/alien/user) + ..() + if(!isalien(target)) + target = user + mode = SECBOT_HUNT + + +/obj/machinery/bot/secbot/ed209/emp_act(severity) + if(severity == 2 && prob(70)) + ..(severity - 1) + else + var/obj/effect/overlay/pulse2 = new/obj/effect/overlay(loc) + pulse2.icon = 'icons/effects/effects.dmi' + pulse2.icon_state = "empdisable" + pulse2.name = "emp sparks" + pulse2.anchored = 1 + pulse2.dir = pick(cardinal) + QDEL_IN(pulse2, 10) + var/list/mob/living/carbon/targets = new + for(var/mob/living/carbon/C in view(12, src)) + if(C.stat == DEAD) + 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) + target = toarrest + mode = SECBOT_HUNT + + + +/obj/item/weapon/ed209_assembly/attackby(obj/item/weapon/W, mob/user) + ..() + + if(istype(W, /obj/item/weapon/pen)) + var/t = sanitize_safe(input(user, "Enter new robot name", name, input_default(created_name)), MAX_NAME_LEN) + if(!t) + return + if(!in_range(src, usr) && 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)) + user.drop_item() + 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/storage/flak)) + user.drop_item() + 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)) + user.drop_item() + 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)) + user.drop_item() + 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 + if(user.is_busy(src)) return + to_chat(user, "You start to wire [src]...") + if(do_after(user, 40, target = src)) + if(build_step == 6 && coil.use(1)) + build_step++ + to_chat(user, "You wire the ED-209 assembly.") + name = "wired ED-209 assembly" + + if(7) + 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].") + item_state = "[lasercolor]ed209_taser" + icon_state = "[lasercolor]ed209_taser" + user.drop_item() + qdel(W) + + if(8) + if(istype(W, /obj/item/weapon/screwdriver)) + if(user.is_busy(src)) return + playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) + to_chat(user, "Now attaching the gun to the frame...") + if(do_after(user, 40, target = src)) + if(build_step == 8) + build_step++ + name = "armed [name]" + to_chat(user, "Taser gun attached.") + + if(9) + if(istype(W, /obj/item/weapon/stock_parts/cell)) + build_step++ + to_chat(user, "You complete the ED-209.") + var/turf/T = get_turf(src) + new /obj/machinery/bot/secbot/ed209(T, created_name, lasercolor) + user.drop_item() + qdel(W) + user.drop_from_inventory(src) + qdel(src) + + +/obj/machinery/bot/secbot/ed209/bullet_act(obj/item/projectile/Proj) + if(!disabled && ((lasercolor == "b") && istype(Proj, /obj/item/projectile/beam/lastertag/red) \ + || (lasercolor == "r") && istype(Proj, /obj/item/projectile/beam/lastertag/blue))) + disabled = 1 + qdel(Proj) + addtimer(CALLBACK(src, .proc/enable), 100) + ..() + +/obj/machinery/bot/secbot/ed209/proc/enable() + disabled = 0 + +/obj/machinery/bot/secbot/ed209/bluetag/atom_init() // If desired, you spawn red and bluetag bots easily + ..() + new /obj/machinery/bot/secbot/ed209(get_turf(src), null, "b") + return INITIALIZE_HINT_QDEL + +/obj/machinery/bot/secbot/ed209/redtag/atom_init() + ..() + new /obj/machinery/bot/secbot/ed209(get_turf(src), null, "r") + return INITIALIZE_HINT_QDEL diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm index bc14d263a194..d7958edd6a62 100644 --- a/code/game/machinery/bots/floorbot.dm +++ b/code/game/machinery/bots/floorbot.dm @@ -1,431 +1,431 @@ -//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 - 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 - var/created_name = "Floorbot" - -//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/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 - - -/obj/machinery/bot/floorbot/atom_init() - . = ..() - updateicon() - -/obj/machinery/bot/floorbot/turn_on() - . = ..() - src.updateicon() - src.updateUsrDialog() - -/obj/machinery/bot/floorbot/turn_off() - ..() - src.target = null - src.oldtarget = null - src.oldloc = null - src.updateicon() - src.path = new() - src.updateUsrDialog() - -/obj/machinery/bot/floorbot/ui_interact(mob/user) - 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) ||isobserver(user)) - dat += "Improves floors: [src.improvefloors ? "Yes" : "No"]
    " - dat += "Finds tiles: [src.eattiles ? "Yes" : "No"]
    " - dat += "Make singles pieces of metal into tiles when empty: [src.maketiles ? "Yes" : "No"]
    " - var/bmode - if (src.targetdirection) - bmode = dir2text(src.targetdirection) - else - bmode = "Disabled" - dat += "

    Bridge Mode : [bmode]
    " - - user << browse("Repairbot v1.0 controls[entity_ja(dat)]", "window=autorepair") - onclose(user, "autorepair") - - -/obj/machinery/bot/floorbot/attackby(obj/item/W , mob/user) - 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.get_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) - ..() - if(open && !locked && user) - to_chat(user, "The [src] buzzes and beeps.") - -/obj/machinery/bot/floorbot/Topic(href, href_list) - . = ..() - if(!.) - return - switch(href_list["operation"]) - if("start") - if (src.on) - turn_off() - else - turn_on() - if("improve") - src.improvefloors = !src.improvefloors - if("tiles") - src.eattiles = !src.eattiles - if("make") - src.maketiles = !src.maketiles - if("bridgemode") - switch(src.targetdirection) - if(null) - targetdirection = 1 - if(1) - targetdirection = 2 - if(2) - targetdirection = 4 - if(4) - targetdirection = 8 - if(8) - targetdirection = null - else - targetdirection = null - src.updateUsrDialog() - -/obj/machinery/bot/floorbot/process() - //set background = 1 - - if(!src.on) - return - if(src.repairing) - return - var/list/floorbottargets = list() - if(src.amount <= 0 && ((src.target == null) || !src.target)) - if(src.eattiles) - for(var/obj/item/stack/tile/plasteel/T in view(7, src)) - if(T != src.oldtarget && !(target in floorbottargets)) - src.oldtarget = T - src.target = T - return - if(src.target == null || !src.target) - if(src.maketiles) - for(var/obj/item/stack/sheet/metal/M in view(7, src)) - if(!(M in floorbottargets) && M != src.oldtarget && M.get_amount() == 1 && !(istype(M.loc, /turf/simulated/wall))) - src.oldtarget = M - src.target = M - return - else - return - if(prob(5)) - visible_message("[src] makes an excited booping beeping sound!") - - if((!src.target || src.target == null) && emagged < 2) - if(targetdirection != null) - /* - for (var/turf/space/D in view(7,src)) - 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)) - src.oldtarget = T - src.target = T - if(!src.target || src.target == null) - for (var/turf/space/D in view(7,src)) - if(!(D in floorbottargets) && D != src.oldtarget && (D.loc.name != "Space")) - src.oldtarget = D - src.target = D - break - if((!src.target || src.target == null ) && src.improvefloors) - for (var/turf/simulated/floor/F in view(7,src)) - if(!(F in floorbottargets) && F != src.oldtarget && F.icon_state == "Floor1" && !(istype(F, /turf/simulated/floor/plating))) - src.oldtarget = F - src.target = F - break - if((!src.target || src.target == null) && src.eattiles) - for(var/obj/item/stack/tile/plasteel/T in view(7, src)) - if(!(T in floorbottargets) && T != src.oldtarget) - src.oldtarget = T - src.target = T - break - - if((!src.target || src.target == null) && emagged == 2) - if(!src.target || src.target == null) - for (var/turf/simulated/floor/D in view(7,src)) - if(!(D in floorbottargets) && D != src.oldtarget && D.floor_type) - src.oldtarget = D - src.target = D - break - - if(!src.target || src.target == null) - if(src.loc != src.oldloc) - src.oldtarget = null - return - - if(src.target && (src.target != null) && src.path.len == 0) - spawn(0) - if(!istype(src.target, /turf/)) - src.path = get_path_to(src, get_turf(src.target), /turf/proc/Distance_cardinal, 0, 30, id=botcard, simulated_only = FALSE) - else - src.path = get_path_to(src, get_turf(src.target), /turf/proc/Distance_cardinal, 0, 30, id=botcard, simulated_only = FALSE) - if(src.path.len == 0) - src.oldtarget = src.target - 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) - 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) - else if(istype(src.target, /obj/item/stack/sheet/metal)) - src.maketile(src.target) - else if(istype(src.target, /turf/) && emagged < 2) - repair(src.target) - else if(emagged == 2 && istype(src.target,/turf/simulated/floor)) - 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("\red [src] makes an excited booping sound.") - spawn(50) - src.amount ++ - src.anchored = 0 - src.repairing = 0 - src.target = null - src.path = new() - return - - src.oldloc = src.loc - - -/obj/machinery/bot/floorbot/proc/repair(turf/target) - if(istype(target, /turf/space/)) - if(target.loc.name == "Space") - 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("\red [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 - src.target = null - else - visible_message("\red [src] begins to improve the floor.") - src.repairing = 1 - spawn(50) - src.loc.icon_state = "floor" - src.repairing = 0 - src.amount -= 1 - src.updateicon() - src.anchored = 0 - src.target = null - -/obj/machinery/bot/floorbot/proc/eattile(obj/item/stack/tile/plasteel/T) - if(!istype(T)) - return - visible_message("\red [src] begins to collect tiles.") - src.repairing = 1 - spawn(20) - if(QDELETED(T)) - src.target = null - src.repairing = 0 - return - if(src.amount + T.get_amount() > 50) - var/i = 50 - src.amount - src.amount += i - T.use(i) - else - src.amount += T.get_amount() - qdel(T) - src.updateicon() - src.target = null - src.repairing = 0 - -/obj/machinery/bot/floorbot/proc/maketile(obj/item/stack/sheet/metal/M) - if(!istype(M)) - return - if(M.get_amount() > 1) - return - visible_message("\red [src] begins to create tiles.") - src.repairing = 1 - spawn(20) - if(QDELETED(M)) - src.target = null - src.repairing = 0 - return - new /obj/item/stack/tile/plasteel(M.loc, 4) - qdel(M) - 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/explode() - src.on = 0 - src.visible_message("\red [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) - - while (amount)//Dumps the tiles into the appropriate sized stacks - if(amount >= 16) - new /obj/item/stack/tile/plasteel(Tsec, 16) - amount -= 16 - else - new /obj/item/stack/tile/plasteel(Tsec, 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(obj/item/stack/tile/plasteel/T, mob/user) - 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) - 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(obj/item/W, mob/user) - ..() - if(isprox(W)) - qdel(W) - 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 = sanitize_safe(input(user, "Enter new robot name", src.name, input_default(src.created_name)),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(obj/item/W, mob/user) - ..() - 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 = sanitize_safe(input(user, "Enter new robot name", src.name, input_default(src.created_name)), MAX_NAME_LEN) - - if (!t) - return - if (!in_range(src, usr) && src.loc != usr) - return - - src.created_name = t - -/obj/machinery/bot/floorbot/Process_Spacemove(movement_dir = 0) - return 1 +//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 + 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 + var/created_name = "Floorbot" + +//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/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 + + +/obj/machinery/bot/floorbot/atom_init() + . = ..() + updateicon() + +/obj/machinery/bot/floorbot/turn_on() + . = ..() + src.updateicon() + src.updateUsrDialog() + +/obj/machinery/bot/floorbot/turn_off() + ..() + src.target = null + src.oldtarget = null + src.oldloc = null + src.updateicon() + src.path = new() + src.updateUsrDialog() + +/obj/machinery/bot/floorbot/ui_interact(mob/user) + 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) ||isobserver(user)) + dat += "Improves floors: [src.improvefloors ? "Yes" : "No"]
    " + dat += "Finds tiles: [src.eattiles ? "Yes" : "No"]
    " + dat += "Make singles pieces of metal into tiles when empty: [src.maketiles ? "Yes" : "No"]
    " + var/bmode + if (src.targetdirection) + bmode = dir2text(src.targetdirection) + else + bmode = "Disabled" + dat += "

    Bridge Mode : [bmode]
    " + + user << browse("Repairbot v1.0 controls[entity_ja(dat)]", "window=autorepair") + onclose(user, "autorepair") + + +/obj/machinery/bot/floorbot/attackby(obj/item/W , mob/user) + 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.get_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) + ..() + if(open && !locked && user) + to_chat(user, "The [src] buzzes and beeps.") + +/obj/machinery/bot/floorbot/Topic(href, href_list) + . = ..() + if(!.) + return + switch(href_list["operation"]) + if("start") + if (src.on) + turn_off() + else + turn_on() + if("improve") + src.improvefloors = !src.improvefloors + if("tiles") + src.eattiles = !src.eattiles + if("make") + src.maketiles = !src.maketiles + if("bridgemode") + switch(src.targetdirection) + if(null) + targetdirection = 1 + if(1) + targetdirection = 2 + if(2) + targetdirection = 4 + if(4) + targetdirection = 8 + if(8) + targetdirection = null + else + targetdirection = null + src.updateUsrDialog() + +/obj/machinery/bot/floorbot/process() + //set background = 1 + + if(!src.on) + return + if(src.repairing) + return + var/list/floorbottargets = list() + if(src.amount <= 0 && ((src.target == null) || !src.target)) + if(src.eattiles) + for(var/obj/item/stack/tile/plasteel/T in view(7, src)) + if(T != src.oldtarget && !(target in floorbottargets)) + src.oldtarget = T + src.target = T + return + if(src.target == null || !src.target) + if(src.maketiles) + for(var/obj/item/stack/sheet/metal/M in view(7, src)) + if(!(M in floorbottargets) && M != src.oldtarget && M.get_amount() == 1 && !(istype(M.loc, /turf/simulated/wall))) + src.oldtarget = M + src.target = M + return + else + return + if(prob(5)) + visible_message("[src] makes an excited booping beeping sound!") + + if((!src.target || src.target == null) && emagged < 2) + if(targetdirection != null) + /* + for (var/turf/space/D in view(7,src)) + 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)) + src.oldtarget = T + src.target = T + if(!src.target || src.target == null) + for (var/turf/space/D in view(7,src)) + if(!(D in floorbottargets) && D != src.oldtarget && (D.loc.name != "Space")) + src.oldtarget = D + src.target = D + break + if((!src.target || src.target == null ) && src.improvefloors) + for (var/turf/simulated/floor/F in view(7,src)) + if(!(F in floorbottargets) && F != src.oldtarget && F.icon_state == "Floor1" && !(istype(F, /turf/simulated/floor/plating))) + src.oldtarget = F + src.target = F + break + if((!src.target || src.target == null) && src.eattiles) + for(var/obj/item/stack/tile/plasteel/T in view(7, src)) + if(!(T in floorbottargets) && T != src.oldtarget) + src.oldtarget = T + src.target = T + break + + if((!src.target || src.target == null) && emagged == 2) + if(!src.target || src.target == null) + for (var/turf/simulated/floor/D in view(7,src)) + if(!(D in floorbottargets) && D != src.oldtarget && D.floor_type) + src.oldtarget = D + src.target = D + break + + if(!src.target || src.target == null) + if(src.loc != src.oldloc) + src.oldtarget = null + return + + if(src.target && (src.target != null) && src.path.len == 0) + spawn(0) + if(!istype(src.target, /turf/)) + src.path = get_path_to(src, get_turf(src.target), /turf/proc/Distance_cardinal, 0, 30, id=botcard, simulated_only = FALSE) + else + src.path = get_path_to(src, get_turf(src.target), /turf/proc/Distance_cardinal, 0, 30, id=botcard, simulated_only = FALSE) + if(src.path.len == 0) + src.oldtarget = src.target + 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) + 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) + else if(istype(src.target, /obj/item/stack/sheet/metal)) + src.maketile(src.target) + else if(istype(src.target, /turf/) && emagged < 2) + repair(src.target) + else if(emagged == 2 && istype(src.target,/turf/simulated/floor)) + 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("\red [src] makes an excited booping sound.") + spawn(50) + src.amount ++ + src.anchored = 0 + src.repairing = 0 + src.target = null + src.path = new() + return + + src.oldloc = src.loc + + +/obj/machinery/bot/floorbot/proc/repair(turf/target) + if(istype(target, /turf/space/)) + if(target.loc.name == "Space") + 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("\red [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 + src.target = null + else + visible_message("\red [src] begins to improve the floor.") + src.repairing = 1 + spawn(50) + src.loc.icon_state = "floor" + src.repairing = 0 + src.amount -= 1 + src.updateicon() + src.anchored = 0 + src.target = null + +/obj/machinery/bot/floorbot/proc/eattile(obj/item/stack/tile/plasteel/T) + if(!istype(T)) + return + visible_message("\red [src] begins to collect tiles.") + src.repairing = 1 + spawn(20) + if(QDELETED(T)) + src.target = null + src.repairing = 0 + return + if(src.amount + T.get_amount() > 50) + var/i = 50 - src.amount + src.amount += i + T.use(i) + else + src.amount += T.get_amount() + qdel(T) + src.updateicon() + src.target = null + src.repairing = 0 + +/obj/machinery/bot/floorbot/proc/maketile(obj/item/stack/sheet/metal/M) + if(!istype(M)) + return + if(M.get_amount() > 1) + return + visible_message("\red [src] begins to create tiles.") + src.repairing = 1 + spawn(20) + if(QDELETED(M)) + src.target = null + src.repairing = 0 + return + new /obj/item/stack/tile/plasteel(M.loc, 4) + qdel(M) + 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/explode() + src.on = 0 + src.visible_message("\red [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) + + while (amount)//Dumps the tiles into the appropriate sized stacks + if(amount >= 16) + new /obj/item/stack/tile/plasteel(Tsec, 16) + amount -= 16 + else + new /obj/item/stack/tile/plasteel(Tsec, 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(obj/item/stack/tile/plasteel/T, mob/user) + 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) + 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(obj/item/W, mob/user) + ..() + if(isprox(W)) + qdel(W) + 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 = sanitize_safe(input(user, "Enter new robot name", src.name, input_default(src.created_name)),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(obj/item/W, mob/user) + ..() + 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 = sanitize_safe(input(user, "Enter new robot name", src.name, input_default(src.created_name)), MAX_NAME_LEN) + + if (!t) + return + if (!in_range(src, usr) && src.loc != usr) + return + + src.created_name = t + +/obj/machinery/bot/floorbot/Process_Spacemove(movement_dir = 0) + return 1 diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm index 3a7fa8568e57..d15883bb2e6f 100644 --- a/code/game/machinery/bots/medbot.dm +++ b/code/game/machinery/bots/medbot.dm @@ -1,593 +1,593 @@ -//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 = 1 //When attempting to treat a patient, should it notify everyone wearing medhuds? - var/shut_up = 0 //self explanatory :) - -/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 - -/obj/item/weapon/firstaid_arm_assembly/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/item/weapon/firstaid_arm_assembly/atom_init_late() - if(skin) - overlays += image('icons/obj/aibots.dmi', "kit_skin_[skin]") - -/obj/machinery/bot/medbot/atom_init() - ..() - botcard = new /obj/item/weapon/card/id(src) - if(isnull(botcard_access) || (botcard_access.len < 1)) - var/datum/job/doctor/J = new/datum/job/doctor - botcard.access = J.get_access() - else - botcard.access = botcard_access - icon_state = "medibot[on]" - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/bot/medbot/atom_init_late() - if(skin) - overlays += image('icons/obj/aibots.dmi', "medskin_[skin]") - -/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/ui_interact(mob/user) - 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) || isobserver(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
    " - - user << browse("Medibot v1.0 controls[entity_ja(dat)]", "window=automed") - onclose(user, "automed") - -/obj/machinery/bot/medbot/Topic(href, href_list) - . = ..() - if(!.) - return - - if ((href_list["power"]) && (src.allowed(usr))) - if (src.on) - turn_off() - else - turn_on() - - else if(src.locked && !issilicon(usr) && !isobserver(usr)) - return - - else if(href_list["adj_threshold"]) - 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"]) - 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.use_beaker = !src.use_beaker - - else if (href_list["eject"] && reagent_glass) - src.reagent_glass.loc = get_turf(src) - src.reagent_glass = null - - else if (href_list["togglevoice"]) - src.shut_up = !src.shut_up - - else if (href_list["declaretreatment"]) - src.declare_treatment = !src.declare_treatment - - src.updateUsrDialog() - -/obj/machinery/bot/medbot/attackby(obj/item/weapon/W, mob/user) - 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 - - user.drop_item() - W.loc = 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) - ..() - if(open && !locked) - 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("\red [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 == DEAD) || !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.patient && Adjacent(patient)) - 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 = get_path_to(src, get_turf(src.patient), /turf/proc/Distance_cardinal, 0, 30, id=botcard) - 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) - //Time to see if they need medical help! - if(C.stat == DEAD) - 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 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) - 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 == DEAD) - 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("\red [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("\red [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(message) - if((!src.on) || (!message)) - return - visible_message("[src] beeps, \"[message]\"") - return - -/obj/machinery/bot/medbot/bullet_act(obj/item/projectile/Proj) - if(is_type_in_list(Proj, taser_projectiles)) //taser_projectiles defined in projectile.dm - src.stunned = min(stunned+10,20) - ..() - -/obj/machinery/bot/medbot/explode() - src.on = 0 - visible_message("\red [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(atom/M) //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) && !istype(D,/obj/machinery/door/poddoor)) - 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) - 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, 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(obj/item/robot_parts/S, mob/user) - - 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) - 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, mob/user) - ..() - if(istype(W, /obj/item/weapon/pen)) - var/t = sanitize_safe(input(user, "Enter new robot name", src.name, input_default(src.created_name)), 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)) - user.drop_item() - 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)) - user.drop_item() - 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) +//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 = 1 //When attempting to treat a patient, should it notify everyone wearing medhuds? + var/shut_up = 0 //self explanatory :) + +/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 + +/obj/item/weapon/firstaid_arm_assembly/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/item/weapon/firstaid_arm_assembly/atom_init_late() + if(skin) + overlays += image('icons/obj/aibots.dmi', "kit_skin_[skin]") + +/obj/machinery/bot/medbot/atom_init() + ..() + botcard = new /obj/item/weapon/card/id(src) + if(isnull(botcard_access) || (botcard_access.len < 1)) + var/datum/job/doctor/J = new/datum/job/doctor + botcard.access = J.get_access() + else + botcard.access = botcard_access + icon_state = "medibot[on]" + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/bot/medbot/atom_init_late() + if(skin) + overlays += image('icons/obj/aibots.dmi', "medskin_[skin]") + +/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/ui_interact(mob/user) + 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) || isobserver(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
    " + + user << browse("Medibot v1.0 controls[entity_ja(dat)]", "window=automed") + onclose(user, "automed") + +/obj/machinery/bot/medbot/Topic(href, href_list) + . = ..() + if(!.) + return + + if ((href_list["power"]) && (src.allowed(usr))) + if (src.on) + turn_off() + else + turn_on() + + else if(src.locked && !issilicon(usr) && !isobserver(usr)) + return + + else if(href_list["adj_threshold"]) + 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"]) + 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.use_beaker = !src.use_beaker + + else if (href_list["eject"] && reagent_glass) + src.reagent_glass.loc = get_turf(src) + src.reagent_glass = null + + else if (href_list["togglevoice"]) + src.shut_up = !src.shut_up + + else if (href_list["declaretreatment"]) + src.declare_treatment = !src.declare_treatment + + src.updateUsrDialog() + +/obj/machinery/bot/medbot/attackby(obj/item/weapon/W, mob/user) + 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 + + user.drop_item() + W.loc = 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) + ..() + if(open && !locked) + 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("\red [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 == DEAD) || !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.patient && Adjacent(patient)) + 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 = get_path_to(src, get_turf(src.patient), /turf/proc/Distance_cardinal, 0, 30, id=botcard) + 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) + //Time to see if they need medical help! + if(C.stat == DEAD) + 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 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) + 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 == DEAD) + 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("\red [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("\red [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(message) + if((!src.on) || (!message)) + return + visible_message("[src] beeps, \"[message]\"") + return + +/obj/machinery/bot/medbot/bullet_act(obj/item/projectile/Proj) + if(is_type_in_list(Proj, taser_projectiles)) //taser_projectiles defined in projectile.dm + src.stunned = min(stunned+10,20) + ..() + +/obj/machinery/bot/medbot/explode() + src.on = 0 + visible_message("\red [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(atom/M) //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) && !istype(D,/obj/machinery/door/poddoor)) + 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) + 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, 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(obj/item/robot_parts/S, mob/user) + + 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) + 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, mob/user) + ..() + if(istype(W, /obj/item/weapon/pen)) + var/t = sanitize_safe(input(user, "Enter new robot name", src.name, input_default(src.created_name)), 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)) + user.drop_item() + 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)) + user.drop_item() + 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) diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index e9884f2cfd78..c3d5f481e71c 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -1,860 +1,860 @@ -//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 - -#define SIGH 0 -#define ANNOYED 1 -#define DELIGHT 2 - -/obj/machinery/bot/mulebot - name = "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 - - can_buckle = 1 - buckle_lying = 0 - - suffix = "" - 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/atom/movable/load = null // the loaded crate (usually) - var/beacon_freq = 1400 - var/control_freq = 1447 - 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 - - 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/stock_parts/cell/cell - // the installed power cell - var/datum/wires/mulebot/wires = null - var/bloodiness = 0 // count of bloodiness - -/obj/machinery/bot/mulebot/atom_init() - ..() - 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 - - if(radio_controller) - radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/bot/mulebot/atom_init_late() - var/count = 0 - for(var/obj/machinery/bot/mulebot/other in bots_list) - count++ - if(!suffix) - suffix = "#[count]" - name = "Mulebot ([suffix])" - -/obj/machinery/bot/mulebot/Destroy() - QDEL_NULL(wires) - if(radio_controller) - radio_controller.remove_object(src,beacon_freq) - radio_controller.remove_object(src,control_freq) - unload(0) - return ..() - -// 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(obj/item/I, mob/user) - if(istype(I,/obj/item/weapon/card/emag)) - locked = !locked - to_chat(user, "\blue You [locked ? "lock" : "unlock"] the mulebot's controls!") - flick("mulebot-emagged", src) - playsound(src.loc, 'sound/effects/sparks1.ogg', 100, 0) - else if(istype(I,/obj/item/weapon/stock_parts/cell) && open && !cell) - var/obj/item/weapon/stock_parts/cell/C = I - user.drop_item() - C.loc = src - cell = C - updateDialog() - else if(istype(I,/obj/item/weapon/screwdriver)) - if(locked) - to_chat(user, "\blue 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]", "\blue You open [src]'s maintenance hatch.") - on = 0 - icon_state="mulebot-hatch" - else - src.visible_message("[user] closes the maintenance hatch of [src]", "\blue You close [src]'s maintenance hatch.") - icon_state = "mulebot0" - - updateDialog() - else if(is_wire_tool(I)) - wires.interact(user) - else if (istype(I, /obj/item/weapon/wrench)) - if (src.health < maxhealth) - src.health = min(maxhealth, src.health+25) - user.visible_message( - "\red [user] repairs [src]!", - "\blue You repair [src]!" - ) - else - to_chat(user, "\blue [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("\red [user] knocks [load] off [src] with \the [I]!", "\red 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(severity) - unload(0) - switch(severity) - if(2) - wires.random_cut() - wires.random_cut() - wires.random_cut() - if(3) - wires.random_cut() - ..() - return - -/obj/machinery/bot/mulebot/bullet_act() - if(prob(50) && !isnull(load)) - unload(0) - if(prob(25)) - visible_message("Something shorts out inside [src]!") - wires.random_cut() - ..() - -/obj/machinery/bot/mulebot/ui_interact(mob/user) - var/ai = isAI(user) || isobserver(user) - 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 locate 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
    " - else - dat += "The bot is in maintenance mode and cannot be controlled.
    " - - user << browse("Mulebot [suffix ? "([suffix])" : ""][entity_ja(dat)]", "window=mulebot;size=350x500") - onclose(user, "mulebot") - -/obj/machinery/bot/mulebot/Topic(href, href_list) - . = ..() - if(!.) - return - - switch(href_list["op"]) - if("lock", "unlock") - if(src.allowed(usr)) - locked = !locked - else - to_chat(usr, "\red Access denied.") - return FALSE - if("power") - if (src.on) - turn_off() - else if (cell && !open) - if (!turn_on()) - to_chat(usr, "\red You can't switch on [src].") - return FALSE - else - return FALSE - visible_message("[usr] switches [on ? "on" : "off"] [src].") - - - 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("\blue [usr] removes the power cell from [src].", "\blue You remove the power cell from [src].") - - if("cellinsert") - if(open && !cell) - var/obj/item/weapon/stock_parts/cell/C = usr.get_active_hand() - if(istype(C)) - usr.drop_item() - cell = C - C.loc = src - C.add_fingerprint(usr) - - usr.visible_message("\blue [usr] inserts a power cell into [src].", "\blue You insert the power cell into [src].") - - - if("stop") - if(mode >=2) - mode = 0 - - if("go") - if(mode == 0) - start() - - if("home") - if(mode == 0 || mode == 2) - start_home() - - if("destination") - refresh=0 - var/new_dest = sanitize_safe(input("Enter new destination tag", "Mulebot [suffix ? "([suffix])" : ""]", input_default(destination)) as text|null, MAX_LNAME_LEN) - refresh=1 - if(new_dest) - set_destination(new_dest) - - - if("setid") - refresh=0 - var/new_id = sanitize_safe(input("Enter new bot ID", "Mulebot [suffix ? "([suffix])" : ""]", input_default(suffix)) as text|null, MAX_LNAME_LEN) - refresh=1 - if(new_id) - suffix = new_id - name = "Mulebot ([suffix])" - - if("sethome") - refresh=0 - var/new_home = sanitize_safe(input("Enter new home tag", "Mulebot [suffix ? "([suffix])" : ""]", input_default(home_destination)) as text|null, MAX_LNAME_LEN) - refresh=1 - if(new_home) - home_destination = new_home - - 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() - -// returns true if the bot has power -/obj/machinery/bot/mulebot/proc/has_power() - return !open && cell && cell.charge>0 && wires.has_power() - -/obj/machinery/bot/mulebot/proc/buzz(type) - switch(type) - if(SIGH) - visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") - playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - if(ANNOYED) - visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") - playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0) - if(DELIGHT) - visible_message("[src] makes a delighted ping!", "You hear a ping.") - playsound(loc, 'sound/machines/ping.ogg', 50, 0) - -/obj/machinery/bot/mulebot/MouseDrop_T(atom/movable/AM, mob/user) - if(!iscarbon(user) && !isrobot(user)) - return - if(user.stat) - return - - if(user.incapacitated() || user.lying) - return - - if (!istype(AM)) - return - - load(AM) - -// mousedrop a crate to load the bot -// can load anything if emagged -/obj/machinery/bot/mulebot/MouseDrop_T(atom/movable/AM, mob/user) - if(!iscarbon(usr) && !isrobot(usr)) - return - if(user.incapacitated() || user.lying) - return - if (!istype(AM)) - return - load(AM) - -// called to load a crate -/obj/machinery/bot/mulebot/proc/load(atom/movable/AM) - if(load || AM.anchored) - return - if(!isturf(AM.loc)) //To prevent the loading from stuff from someone's inventory or screen icons. - return - - var/obj/structure/closet/crate/CRATE - if(istype(AM,/obj/structure/closet/crate)) - CRATE = AM - else - if(wires.load_check()) - buzz(SIGH) - return // if not emagged, only allow crates to be loaded - - if(CRATE) // if it's a crate, close before loading - CRATE.close() - - if(isobj(AM)) - var/obj/O = AM - if(O.buckled_mob || (locate(/mob) in AM)) //can't load non crates objects with mobs buckled to it or inside it. - buzz(SIGH) - return - - if(isliving(AM)) - if(!buckle_mob(AM)) - return - else - AM.loc = src - AM.pixel_y += 9 - if(AM.layer < layer) - AM.layer = layer + 0.1 - overlays += AM - - load= AM - mode = 0 - send_status() - -/obj/machinery/bot/mulebot/buckle_mob(mob/living/M) - if(M.buckled) - return 0 - var/turf/T = get_turf(src) - if(M.loc != T) - density = 0 - var/can_step = step_towards(M, T) - density = 1 - if(!can_step) - return 0 - return ..() - - -/obj/machinery/bot/mulebot/post_buckle_mob(mob/living/M) - if(M == buckled_mob) //post buckling - M.pixel_y = initial(M.pixel_y) + 9 - if(M.layer < layer) - M.layer = layer + 0.1 - - else //post unbuckling - load = null - M.layer = initial(M.layer) - M.plane = initial(M.plane) - M.pixel_y = initial(M.pixel_y) - -// called to unload the bot -// argument is optional direction to unload -// if zero, unload at bot's location -/obj/machinery/bot/mulebot/proc/unload(dirn) - if(!load) - return - - mode = 0 - - overlays.Cut() - - if(buckled_mob) - unbuckle_mob() - return - - load.loc = loc - load.pixel_y = initial(load.pixel_y) - load.layer = initial(load.layer) - load.plane = initial(load.plane) - if(dirn) - var/turf/T = loc - var/turf/newT = get_step(T,dirn) - if(load.CanPass(load,newT)) //Can't get off onto anything that wouldn't let you pass normally - step(load, dirn) - - load = null - - -/obj/machinery/bot/mulebot/process() - if(!has_power()) - on = 0 - return - if(on) - var/speed = (wires.motor1() ? 1 : 0) + (wires.motor2() ? 2 : 0) - //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() - if(!on) - return - - 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)) - if(bloodiness) - var/obj/effect/decal/cleanable/blood/tracks/B = new(loc) - var/newdir = get_dir(next, loc) - if(newdir == dir) - B.dir = newdir - else - newdir = newdir | dir - if(newdir == 3) - newdir = 1 - else if(newdir == 12) - newdir = 4 - B.dir = newdir - bloodiness-- - - var/moved = step_towards(src, next) // attempt to move - if(cell) cell.use(1) - if(moved) // 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++ - mode = 4 - if(blockcount == 3) - buzz(ANNOYED) - - if(blockcount > 5) // attempt 5 times before recomputing - // find new path excluding blocked turf - buzz(SIGH) - - spawn(2) - calc_path(next) - if(path.len > 0) - buzz(DELIGHT) - mode = 4 - mode =6 - return - return - else - buzz(ANNOYED) - mode = 5 - return - else - mode = 5 - return - - if(5) // calculate new path - mode = 6 - spawn(0) - - calc_path() - - if(path.len > 0) - blockcount = 0 - mode = 4 - buzz(DELIGHT) - - else - buzz(SIGH) - - mode = 7 - return - - -// calculates a path to the current destination -// given an optional turf to avoid -/obj/machinery/bot/mulebot/proc/calc_path(turf/avoid = null) - src.path = get_path_to(src.loc, src.target, /turf/proc/Distance_cardinal, 0, 250, id=botcard, exclude=avoid) - - -// 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(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(!on) - return - if(destination == home_destination) - mode = 3 - else - mode = 2 - icon_state = "mulebot[wires.mob_avoid()]" - -// starts bot moving to home -// sends a beacon query to find -/obj/machinery/bot/mulebot/proc/start_home() - if(!on) - return - spawn(0) - set_destination(home_destination) - mode = 4 - icon_state = "mulebot[wires.mob_avoid()]" - -// 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(src.loc, '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.load_check()) // 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 - AM = locate(/obj/structure/closet/crate) in get_step(loc,loaddir) - if(AM && AM.Adjacent(src)) - load(AM) - // 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(atom/obs) - if(!wires.mob_avoid()) //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("\red [src] bumps into [M]!") - else - src.visible_message("\red [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() -// when mulebot is in the same loc -/obj/machinery/bot/mulebot/proc/RunOver(mob/living/carbon/human/H) - src.visible_message("\red [src] drives over [H]!") - playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) - - var/damage = rand(5,15) - H.apply_damage(2*damage, BRUTE, BP_HEAD) - H.apply_damage(2*damage, BRUTE, BP_CHEST) - H.apply_damage(0.5*damage, BRUTE, BP_L_LEG) - H.apply_damage(0.5*damage, BRUTE, BP_R_LEG) - H.apply_damage(0.5*damage, BRUTE, BP_L_ARM) - H.apply_damage(0.5*damage, BRUTE, BP_R_ARM) - - var/obj/effect/decal/cleanable/blood/B = new(src.loc) - B.blood_DNA = list() - B.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type - - bloodiness += 4 - -// player on mulebot attempted to move -/obj/machinery/bot/mulebot/relaymove(mob/user) - if(user.incapacitated()) - return - if(load == user) - unload(0) - -// receive a radio signal -// used for control and beacon reception - -/obj/machinery/bot/mulebot/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" && wires.remote_rx()) - send_status() - - - recv = signal.data["command [suffix]"] - if(wires.remote_rx()) - // 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.beacon_rx()) - 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.mob_avoid()]" - calc_path() - updateDialog() - -// send a radio signal with a single data key/value pair -/obj/machinery/bot/mulebot/proc/post_signal(freq, key, 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(freq, list/keyval) - - if(freq == beacon_freq && !wires.beacon_rx()) - return - if(freq == control_freq && !wires.remote_tx()) - return - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - var/datum/signal/signal = new() - signal.source = src - signal.transmission_method = 1 - //for(var/key in keyval) - // signal.data[key] = keyval[key] - signal.data = keyval - //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/red(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() - - new /obj/effect/decal/cleanable/blood/oil(src.loc) - qdel(src) - -#undef SIGH -#undef ANNOYED -#undef DELIGHT +//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 + +#define SIGH 0 +#define ANNOYED 1 +#define DELIGHT 2 + +/obj/machinery/bot/mulebot + name = "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 + + can_buckle = 1 + buckle_lying = 0 + + suffix = "" + 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/atom/movable/load = null // the loaded crate (usually) + var/beacon_freq = 1400 + var/control_freq = 1447 + 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 + + 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/stock_parts/cell/cell + // the installed power cell + var/datum/wires/mulebot/wires = null + var/bloodiness = 0 // count of bloodiness + +/obj/machinery/bot/mulebot/atom_init() + ..() + 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 + + if(radio_controller) + radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) + radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) + + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/bot/mulebot/atom_init_late() + var/count = 0 + for(var/obj/machinery/bot/mulebot/other in bots_list) + count++ + if(!suffix) + suffix = "#[count]" + name = "Mulebot ([suffix])" + +/obj/machinery/bot/mulebot/Destroy() + QDEL_NULL(wires) + if(radio_controller) + radio_controller.remove_object(src,beacon_freq) + radio_controller.remove_object(src,control_freq) + unload(0) + return ..() + +// 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(obj/item/I, mob/user) + if(istype(I,/obj/item/weapon/card/emag)) + locked = !locked + to_chat(user, "\blue You [locked ? "lock" : "unlock"] the mulebot's controls!") + flick("mulebot-emagged", src) + playsound(src.loc, 'sound/effects/sparks1.ogg', 100, 0) + else if(istype(I,/obj/item/weapon/stock_parts/cell) && open && !cell) + var/obj/item/weapon/stock_parts/cell/C = I + user.drop_item() + C.loc = src + cell = C + updateDialog() + else if(istype(I,/obj/item/weapon/screwdriver)) + if(locked) + to_chat(user, "\blue 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]", "\blue You open [src]'s maintenance hatch.") + on = 0 + icon_state="mulebot-hatch" + else + src.visible_message("[user] closes the maintenance hatch of [src]", "\blue You close [src]'s maintenance hatch.") + icon_state = "mulebot0" + + updateDialog() + else if(is_wire_tool(I)) + wires.interact(user) + else if (istype(I, /obj/item/weapon/wrench)) + if (src.health < maxhealth) + src.health = min(maxhealth, src.health+25) + user.visible_message( + "\red [user] repairs [src]!", + "\blue You repair [src]!" + ) + else + to_chat(user, "\blue [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("\red [user] knocks [load] off [src] with \the [I]!", "\red 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(severity) + unload(0) + switch(severity) + if(2) + wires.random_cut() + wires.random_cut() + wires.random_cut() + if(3) + wires.random_cut() + ..() + return + +/obj/machinery/bot/mulebot/bullet_act() + if(prob(50) && !isnull(load)) + unload(0) + if(prob(25)) + visible_message("Something shorts out inside [src]!") + wires.random_cut() + ..() + +/obj/machinery/bot/mulebot/ui_interact(mob/user) + var/ai = isAI(user) || isobserver(user) + 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 locate 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
    " + else + dat += "The bot is in maintenance mode and cannot be controlled.
    " + + user << browse("Mulebot [suffix ? "([suffix])" : ""][entity_ja(dat)]", "window=mulebot;size=350x500") + onclose(user, "mulebot") + +/obj/machinery/bot/mulebot/Topic(href, href_list) + . = ..() + if(!.) + return + + switch(href_list["op"]) + if("lock", "unlock") + if(src.allowed(usr)) + locked = !locked + else + to_chat(usr, "\red Access denied.") + return FALSE + if("power") + if (src.on) + turn_off() + else if (cell && !open) + if (!turn_on()) + to_chat(usr, "\red You can't switch on [src].") + return FALSE + else + return FALSE + visible_message("[usr] switches [on ? "on" : "off"] [src].") + + + 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("\blue [usr] removes the power cell from [src].", "\blue You remove the power cell from [src].") + + if("cellinsert") + if(open && !cell) + var/obj/item/weapon/stock_parts/cell/C = usr.get_active_hand() + if(istype(C)) + usr.drop_item() + cell = C + C.loc = src + C.add_fingerprint(usr) + + usr.visible_message("\blue [usr] inserts a power cell into [src].", "\blue You insert the power cell into [src].") + + + if("stop") + if(mode >=2) + mode = 0 + + if("go") + if(mode == 0) + start() + + if("home") + if(mode == 0 || mode == 2) + start_home() + + if("destination") + refresh=0 + var/new_dest = sanitize_safe(input("Enter new destination tag", "Mulebot [suffix ? "([suffix])" : ""]", input_default(destination)) as text|null, MAX_LNAME_LEN) + refresh=1 + if(new_dest) + set_destination(new_dest) + + + if("setid") + refresh=0 + var/new_id = sanitize_safe(input("Enter new bot ID", "Mulebot [suffix ? "([suffix])" : ""]", input_default(suffix)) as text|null, MAX_LNAME_LEN) + refresh=1 + if(new_id) + suffix = new_id + name = "Mulebot ([suffix])" + + if("sethome") + refresh=0 + var/new_home = sanitize_safe(input("Enter new home tag", "Mulebot [suffix ? "([suffix])" : ""]", input_default(home_destination)) as text|null, MAX_LNAME_LEN) + refresh=1 + if(new_home) + home_destination = new_home + + 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() + +// returns true if the bot has power +/obj/machinery/bot/mulebot/proc/has_power() + return !open && cell && cell.charge>0 && wires.has_power() + +/obj/machinery/bot/mulebot/proc/buzz(type) + switch(type) + if(SIGH) + visible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.") + playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + if(ANNOYED) + visible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.") + playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0) + if(DELIGHT) + visible_message("[src] makes a delighted ping!", "You hear a ping.") + playsound(loc, 'sound/machines/ping.ogg', 50, 0) + +/obj/machinery/bot/mulebot/MouseDrop_T(atom/movable/AM, mob/user) + if(!iscarbon(user) && !isrobot(user)) + return + if(user.stat) + return + + if(user.incapacitated() || user.lying) + return + + if (!istype(AM)) + return + + load(AM) + +// mousedrop a crate to load the bot +// can load anything if emagged +/obj/machinery/bot/mulebot/MouseDrop_T(atom/movable/AM, mob/user) + if(!iscarbon(usr) && !isrobot(usr)) + return + if(user.incapacitated() || user.lying) + return + if (!istype(AM)) + return + load(AM) + +// called to load a crate +/obj/machinery/bot/mulebot/proc/load(atom/movable/AM) + if(load || AM.anchored) + return + if(!isturf(AM.loc)) //To prevent the loading from stuff from someone's inventory or screen icons. + return + + var/obj/structure/closet/crate/CRATE + if(istype(AM,/obj/structure/closet/crate)) + CRATE = AM + else + if(wires.load_check()) + buzz(SIGH) + return // if not emagged, only allow crates to be loaded + + if(CRATE) // if it's a crate, close before loading + CRATE.close() + + if(isobj(AM)) + var/obj/O = AM + if(O.buckled_mob || (locate(/mob) in AM)) //can't load non crates objects with mobs buckled to it or inside it. + buzz(SIGH) + return + + if(isliving(AM)) + if(!buckle_mob(AM)) + return + else + AM.loc = src + AM.pixel_y += 9 + if(AM.layer < layer) + AM.layer = layer + 0.1 + overlays += AM + + load= AM + mode = 0 + send_status() + +/obj/machinery/bot/mulebot/buckle_mob(mob/living/M) + if(M.buckled) + return 0 + var/turf/T = get_turf(src) + if(M.loc != T) + density = 0 + var/can_step = step_towards(M, T) + density = 1 + if(!can_step) + return 0 + return ..() + + +/obj/machinery/bot/mulebot/post_buckle_mob(mob/living/M) + if(M == buckled_mob) //post buckling + M.pixel_y = initial(M.pixel_y) + 9 + if(M.layer < layer) + M.layer = layer + 0.1 + + else //post unbuckling + load = null + M.layer = initial(M.layer) + M.plane = initial(M.plane) + M.pixel_y = initial(M.pixel_y) + +// called to unload the bot +// argument is optional direction to unload +// if zero, unload at bot's location +/obj/machinery/bot/mulebot/proc/unload(dirn) + if(!load) + return + + mode = 0 + + overlays.Cut() + + if(buckled_mob) + unbuckle_mob() + return + + load.loc = loc + load.pixel_y = initial(load.pixel_y) + load.layer = initial(load.layer) + load.plane = initial(load.plane) + if(dirn) + var/turf/T = loc + var/turf/newT = get_step(T,dirn) + if(load.CanPass(load,newT)) //Can't get off onto anything that wouldn't let you pass normally + step(load, dirn) + + load = null + + +/obj/machinery/bot/mulebot/process() + if(!has_power()) + on = 0 + return + if(on) + var/speed = (wires.motor1() ? 1 : 0) + (wires.motor2() ? 2 : 0) + //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() + if(!on) + return + + 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)) + if(bloodiness) + var/obj/effect/decal/cleanable/blood/tracks/B = new(loc) + var/newdir = get_dir(next, loc) + if(newdir == dir) + B.dir = newdir + else + newdir = newdir | dir + if(newdir == 3) + newdir = 1 + else if(newdir == 12) + newdir = 4 + B.dir = newdir + bloodiness-- + + var/moved = step_towards(src, next) // attempt to move + if(cell) cell.use(1) + if(moved) // 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++ + mode = 4 + if(blockcount == 3) + buzz(ANNOYED) + + if(blockcount > 5) // attempt 5 times before recomputing + // find new path excluding blocked turf + buzz(SIGH) + + spawn(2) + calc_path(next) + if(path.len > 0) + buzz(DELIGHT) + mode = 4 + mode =6 + return + return + else + buzz(ANNOYED) + mode = 5 + return + else + mode = 5 + return + + if(5) // calculate new path + mode = 6 + spawn(0) + + calc_path() + + if(path.len > 0) + blockcount = 0 + mode = 4 + buzz(DELIGHT) + + else + buzz(SIGH) + + mode = 7 + return + + +// calculates a path to the current destination +// given an optional turf to avoid +/obj/machinery/bot/mulebot/proc/calc_path(turf/avoid = null) + src.path = get_path_to(src.loc, src.target, /turf/proc/Distance_cardinal, 0, 250, id=botcard, exclude=avoid) + + +// 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(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(!on) + return + if(destination == home_destination) + mode = 3 + else + mode = 2 + icon_state = "mulebot[wires.mob_avoid()]" + +// starts bot moving to home +// sends a beacon query to find +/obj/machinery/bot/mulebot/proc/start_home() + if(!on) + return + spawn(0) + set_destination(home_destination) + mode = 4 + icon_state = "mulebot[wires.mob_avoid()]" + +// 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(src.loc, '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.load_check()) // 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 + AM = locate(/obj/structure/closet/crate) in get_step(loc,loaddir) + if(AM && AM.Adjacent(src)) + load(AM) + // 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(atom/obs) + if(!wires.mob_avoid()) //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("\red [src] bumps into [M]!") + else + src.visible_message("\red [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() +// when mulebot is in the same loc +/obj/machinery/bot/mulebot/proc/RunOver(mob/living/carbon/human/H) + src.visible_message("\red [src] drives over [H]!") + playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) + + var/damage = rand(5,15) + H.apply_damage(2*damage, BRUTE, BP_HEAD) + H.apply_damage(2*damage, BRUTE, BP_CHEST) + H.apply_damage(0.5*damage, BRUTE, BP_L_LEG) + H.apply_damage(0.5*damage, BRUTE, BP_R_LEG) + H.apply_damage(0.5*damage, BRUTE, BP_L_ARM) + H.apply_damage(0.5*damage, BRUTE, BP_R_ARM) + + var/obj/effect/decal/cleanable/blood/B = new(src.loc) + B.blood_DNA = list() + B.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type + + bloodiness += 4 + +// player on mulebot attempted to move +/obj/machinery/bot/mulebot/relaymove(mob/user) + if(user.incapacitated()) + return + if(load == user) + unload(0) + +// receive a radio signal +// used for control and beacon reception + +/obj/machinery/bot/mulebot/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" && wires.remote_rx()) + send_status() + + + recv = signal.data["command [suffix]"] + if(wires.remote_rx()) + // 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.beacon_rx()) + 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.mob_avoid()]" + calc_path() + updateDialog() + +// send a radio signal with a single data key/value pair +/obj/machinery/bot/mulebot/proc/post_signal(freq, key, 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(freq, list/keyval) + + if(freq == beacon_freq && !wires.beacon_rx()) + return + if(freq == control_freq && !wires.remote_tx()) + return + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) return + + var/datum/signal/signal = new() + signal.source = src + signal.transmission_method = 1 + //for(var/key in keyval) + // signal.data[key] = keyval[key] + signal.data = keyval + //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/red(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() + + new /obj/effect/decal/cleanable/blood/oil(src.loc) + qdel(src) + +#undef SIGH +#undef ANNOYED +#undef DELIGHT diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index bac136fd636c..28725329a12d 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -1,702 +1,702 @@ -/obj/machinery/bot/secbot - name = "Securitron" - desc = "A little security robot. He looks less than thrilled." - icon = 'icons/obj/aibots.dmi' - icon_state = "secbot0" - var/icon_state_arrest = "secbot-c" - layer = 5.0 - density = 0 - anchored = 0 - health = 25 - maxhealth = 25 - fire_dam_coeff = 0.7 - brute_dam_coeff = 0.5 - - req_one_access = list(access_security, access_forensics_lockers) - var/mob/living/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/lasercolor = "" //Used by ED209 -// var/emagged = 0 //Emagged Secbots view everyone as a criminal - var/idcheck = 0 //If false, all station IDs are authorized for weapons. - var/check_records = 1 //Does it check security records? - var/arrest_type = 0 //If true, don't handcuff - var/declare_arrests = 1 //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 - - -/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 - layer = MOB_LAYER - -/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/atom_init() - . = ..() - botcard = new /obj/item/weapon/card/id(src) - var/datum/job/detective/J = new/datum/job/detective - 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) - update_icon() - -/obj/machinery/bot/secbot/turn_on() - ..() - same_pos_count = 0 - update_icon() - updateUsrDialog() - -/obj/machinery/bot/secbot/turn_off() - ..() - target = null - oldtarget_name = null - anchored = 0 - mode = SECBOT_IDLE - walk_to(src, 0) - update_icon() - updateUsrDialog() - -/obj/machinery/bot/secbot/ui_interact(mob/user) - var/dat - - dat += text({" - Automatic Security Unit v1.3

    - Status: []
    - Behaviour controls are [locked ? "locked" : "unlocked"]
    - Maintenance panel panel is [open ? "opened" : "closed"]"}, - - "[on ? "On" : "Off"]" ) - - if(!locked || issilicon(user) || isobserver(user)) - dat += text({"
    - Check for Weapon Authorization: []
    - Check Security Records: []
    - Operating Mode: []
    - Report Arrests: []
    - Auto Patrol: []"}, - - "[idcheck ? "Yes" : "No"]", - "[check_records ? "Yes" : "No"]", - "[arrest_type ? "Detain" : "Arrest"]", - "[declare_arrests ? "Yes" : "No"]", - "[auto_patrol ? "On" : "Off"]" ) - - user << browse("Securitron v1.3 controls[entity_ja(dat)]", "window=autosec") - onclose(user, "autosec") - -/obj/machinery/bot/secbot/Topic(href, href_list) - . = ..() - if(!.) - return - - if(href_list["power"] && allowed(usr)) - if(on) - turn_off() - else - turn_on() - return - - switch(href_list["operation"]) - if("idcheck") - idcheck = !idcheck - if("ignorerec") - check_records = !check_records - if("switchmode") - arrest_type = !arrest_type - if("patrol") - auto_patrol = !auto_patrol - mode = SECBOT_IDLE - if("declarearrests") - declare_arrests = !declare_arrests - - updateUsrDialog() - -/obj/machinery/bot/secbot/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)) - if(emagged) - to_chat(user, "ERROR") - else if(open) - to_chat(user, "Please close the access panel before locking it.") - else if(allowed(user)) - locked = !locked - to_chat(user, "Controls are now [locked ? "locked" : "unlocked"].") - else - to_chat(user, "Access denied.") - else - ..() - beingAttacked(W, user) - - -/obj/machinery/bot/secbot/proc/beingAttacked(obj/item/weapon/W, mob/user) - if(!istype(W, /obj/item/weapon/screwdriver) && W.force && !target) - target = user - mode = SECBOT_HUNT - -/obj/machinery/bot/secbot/proc/forgetCurrentTarget() - target = null - last_found = world.time - mode = SECBOT_IDLE - walk_to(src, 0) - frustration = 0 - anchored = FALSE - -/obj/machinery/bot/secbot/Emag(mob/user) - ..() - if(open && !locked) - if(user) - to_chat(user, "You short out [src]'s target assessment circuits.") - audible_message("[src] buzzes oddly!") - target = null - if(user) - oldtarget_name = user.name - last_found = world.time - anchored = 0 - emagged = 2 - on = 1 - update_icon() - mode = SECBOT_IDLE - -/obj/machinery/bot/secbot/is_on_patrol() - return mode == SECBOT_START_PATROL - -/obj/machinery/bot/secbot/process() - if(!on) - return - if(!inaction_check()) - 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(frustration >= 8) - forgetCurrentTarget() - - if(target) // make sure target exists - if(Adjacent(target) && istype(target.loc, /turf)) - if(iscarbon(target)) - playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) - icon_state = "[lasercolor][icon_state_arrest]" - addtimer(CALLBACK(src, .proc/update_icon), 2) - var/mob/living/carbon/M = target - var/maxstuns = 4 - if(M.stuttering < 10 && !(HULK in M.mutations)) - M.stuttering = 10 - M.Stun(10) - M.Weaken(10) - maxstuns-- - if(maxstuns <= 0) - target = null - - if(declare_arrests) - var/area/location = get_area(src) - broadcast_security_hud_message("[name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] suspect [target] in [location]", src) - visible_message("[target] has been stunned by [src]!") - - mode = SECBOT_PREP_ARREST - anchored = TRUE - target_lastloc = M.loc - return - - else - //just harmbaton them until dead - if(world.time > next_harm_time) - next_harm_time = world.time + 15 - playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) - visible_message("[src] beats [target] with the stun baton!") - icon_state = "[lasercolor][icon_state_arrest]" - addtimer(CALLBACK(src, .proc/update_icon), 2) - target.AdjustStunned(10) - target.adjustBruteLoss(15) - if(target.stat) - forgetCurrentTarget() - playsound(loc, 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, target) - walk_to(src, target, 1, 4) - if(get_dist(src, target) >= olddist) - frustration++ - else - frustration = 0 - else - frustration = 8 - - if(SECBOT_PREP_ARREST) // preparing to arrest target - // see if he got away - if(!Adjacent(target) || ((target.loc != target_lastloc) && (target.weakened < 2))) - anchored = 0 - mode = SECBOT_HUNT - return - - if(iscarbon(target)) - var/mob/living/carbon/C = target - if(!C.handcuffed && !arrest_type) - playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2) - mode = SECBOT_ARREST - visible_message("\red [src] is trying to put handcuffs on [target]!") - addtimer(CALLBACK(src, .proc/subprocess, SECBOT_PREP_ARREST), 60) - - else - forgetCurrentTarget() - - if(SECBOT_ARREST) // arresting - if(!target || !iscarbon(target)) - forgetCurrentTarget() - else - var/mob/living/carbon/C = target - if(C.handcuffed) - forgetCurrentTarget() - - if(SECBOT_START_PATROL) // start a patrol - 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 - INVOKE_ASYNC(src, .proc/subprocess, SECBOT_START_PATROL) - - else // no patrol target, so need a new one - find_patrol_target() - speak("Engaging patrol mode.") - - - if(SECBOT_PATROL) // patrol mode - patrol_step() - addtimer(CALLBACK(src, .proc/subprocess, SECBOT_PATROL), 5) - - if(SECBOT_SUMMON) // summoned to PDA - patrol_step() - addtimer(CALLBACK(src, .proc/subprocess, SECBOT_SUMMON), 4) - addtimer(CALLBACK(src, .proc/subprocess, SECBOT_SUMMON), 8) - -/obj/machinery/bot/secbot/proc/subprocess(oldmode) - switch(oldmode) - if(SECBOT_PREP_ARREST) - if(!target) //All will be cleared in /process() - return - if(Adjacent(target)) - if(iscarbon(target)) - var/mob/living/carbon/mob_carbon = target - if(!mob_carbon.handcuffed) - mob_carbon.handcuffed = new /obj/item/weapon/handcuffs(target) - mob_carbon.update_inv_handcuffed() //update the handcuffs overlay - forgetCurrentTarget() - playsound(loc, 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) - else if(mode == SECBOT_ARREST) - anchored = FALSE - mode = SECBOT_HUNT - - if(SECBOT_START_PATROL) - calc_path() // so just find a route to it - if(path.len == 0) - patrol_target = 0 - return - mode = SECBOT_PATROL - - if(SECBOT_PATROL) - if(mode == SECBOT_PATROL) - patrol_step() - - if(SECBOT_SUMMON) - if(mode == SECBOT_SUMMON) - patrol_step() - - -/obj/machinery/bot/secbot/update_icon() - icon_state = "secbot[on]" - -// 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 - addtimer(CALLBACK(src, .proc/patrol_substep, next), 2) - - else // not a valid turf - mode = SECBOT_IDLE - - else // no path, so calculate new one - mode = SECBOT_START_PATROL - -/obj/machinery/bot/secbot/proc/patrol_substep(turf/next) - calc_path(next) - if(path.len == 0) - find_patrol_target() - else - blockcount = 0 - -// 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() - - -// 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 - addtimer(CALLBACK(src, .proc/find_nearest_beacon_substep), 10) - -/obj/machinery/bot/secbot/proc/find_nearest_beacon_substep() - 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() - - -// 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(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 < get_dist(src, nearest_beacon_loc)) - nearest_beacon = recv - nearest_beacon_loc = signal.source.loc - return - else - return - else if(dist > 1) - nearest_beacon = recv - nearest_beacon_loc = signal.source.loc - - -// send a radio signal with a single data key/value pair -/obj/machinery/bot/secbot/proc/post_signal(freq, key, 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(freq, list/keyval) - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - if(!frequency) - return - - var/datum/signal/signal = new() - signal.source = src - signal.transmission_method = 1 - //for(var/key in keyval) - // signal.data[key] = keyval[key] - signal.data = keyval - //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() - if(!(src && loc && loc.loc)) - return - 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(turf/avoid = null) - path = get_path_to(src, patrol_target, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid) - -// look for a criminal in view of the bot - -/obj/machinery/bot/secbot/proc/look_for_perp() - anchored = 0 - for(var/mob/living/L in view(7, src)) //Let's find us a criminal - if(L.stat) - continue - - if(iscarbon(L)) - var/mob/living/carbon/C = L - if(C.handcuffed) - continue - - if((L.name == oldtarget_name) && (world.time < last_found + 100)) - continue - - threatlevel = assess_perp(L) - - if(threatlevel >= 4) - target = L - oldtarget_name = L.name - speak("Level [threatlevel] infraction alert!") - playsound(loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0) - visible_message("[src] points at [L.name]!") - mode = SECBOT_HUNT - 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/perp) - var/threatcount = 0 - - if(!istype(perp)) - return 0 - - if(emagged == 2) - return 10 //Everyone is a criminal! - - threatcount = perp.assess_perp(src, FALSE, idcheck, FALSE, check_records) - return threatcount - -/obj/machinery/bot/secbot/Bump(atom/M) //Leave no door unopened! - if(istype(M, /obj/machinery/door) && !isnull(botcard)) - var/obj/machinery/door/D = M - if(!istype(D, /obj/machinery/door/firedoor) && D.check_access(botcard) && !istype(D,/obj/machinery/door/poddoor)) - D.open() - frustration = 0 - else if(isliving(M) && !anchored) - loc = M.loc - frustration = 0 - -/obj/machinery/bot/secbot/proc/speak(message) - audible_message("[src] beeps, \"[message]\"") - - -/obj/machinery/bot/secbot/explode() - walk_to(src,0) - visible_message("\red [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 = name - new /obj/item/device/assembly/prox_sensor(Tsec) - - var/obj/item/weapon/melee/baton/B = new /obj/item/weapon/melee/baton(Tsec) - B.charges = 0 - - 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() - - new /obj/effect/decal/cleanable/blood/oil(loc) - qdel(src) - -/obj/machinery/bot/secbot/attack_alien(mob/living/carbon/alien/user) - ..() - if(!isalien(target)) - target = user - mode = SECBOT_HUNT - -//Secbot Construction - -/obj/item/clothing/head/helmet/attackby(obj/item/device/assembly/signaler/S, mob/user) - if(!issignaler(S) || !istype(src, /obj/item/clothing/head/helmet) || !S.secured) //Eh, but we don't want people making secbots out of space helmets. - ..() - return - - 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) - -/obj/item/weapon/secbot_assembly/attackby(obj/item/weapon/W, mob/user) - ..() - if(istype(W, /obj/item/weapon/weldingtool) && !build_step) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - build_step++ - overlays += image('icons/obj/aibots.dmi', "hs_hole") - to_chat(user, "You weld a hole in [src]!") - - else if(isprox(W) && build_step == 1) - user.drop_item() - build_step++ - to_chat(user, "You add the prox sensor to [src]!") - overlays += image('icons/obj/aibots.dmi', "hs_eye") - 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)) && (build_step == 2)) - user.drop_item() - build_step++ - to_chat(user, "You add the robot arm to [src]!") - name = "helmet/signaler/prox sensor/robot arm assembly" - overlays += image('icons/obj/aibots.dmi', "hs_arm") - qdel(W) - - else if(istype(W, /obj/item/weapon/melee/baton) && (build_step >= 3)) - user.drop_item() - 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 = created_name - qdel(W) - qdel(src) - - else if(istype(W, /obj/item/weapon/pen)) - var/t = sanitize_safe(input(user, "Enter new robot name", name, input_default(created_name)), MAX_NAME_LEN) - if(!t) - return - if(!in_range(src, usr) && loc != usr) - return - created_name = t +/obj/machinery/bot/secbot + name = "Securitron" + desc = "A little security robot. He looks less than thrilled." + icon = 'icons/obj/aibots.dmi' + icon_state = "secbot0" + var/icon_state_arrest = "secbot-c" + layer = 5.0 + density = 0 + anchored = 0 + health = 25 + maxhealth = 25 + fire_dam_coeff = 0.7 + brute_dam_coeff = 0.5 + + req_one_access = list(access_security, access_forensics_lockers) + var/mob/living/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/lasercolor = "" //Used by ED209 +// var/emagged = 0 //Emagged Secbots view everyone as a criminal + var/idcheck = 0 //If false, all station IDs are authorized for weapons. + var/check_records = 1 //Does it check security records? + var/arrest_type = 0 //If true, don't handcuff + var/declare_arrests = 1 //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 + + +/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 + layer = MOB_LAYER + +/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/atom_init() + . = ..() + botcard = new /obj/item/weapon/card/id(src) + var/datum/job/detective/J = new/datum/job/detective + 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) + update_icon() + +/obj/machinery/bot/secbot/turn_on() + ..() + same_pos_count = 0 + update_icon() + updateUsrDialog() + +/obj/machinery/bot/secbot/turn_off() + ..() + target = null + oldtarget_name = null + anchored = 0 + mode = SECBOT_IDLE + walk_to(src, 0) + update_icon() + updateUsrDialog() + +/obj/machinery/bot/secbot/ui_interact(mob/user) + var/dat + + dat += text({" + Automatic Security Unit v1.3

    + Status: []
    + Behaviour controls are [locked ? "locked" : "unlocked"]
    + Maintenance panel panel is [open ? "opened" : "closed"]"}, + + "[on ? "On" : "Off"]" ) + + if(!locked || issilicon(user) || isobserver(user)) + dat += text({"
    + Check for Weapon Authorization: []
    + Check Security Records: []
    + Operating Mode: []
    + Report Arrests: []
    + Auto Patrol: []"}, + + "[idcheck ? "Yes" : "No"]", + "[check_records ? "Yes" : "No"]", + "[arrest_type ? "Detain" : "Arrest"]", + "[declare_arrests ? "Yes" : "No"]", + "[auto_patrol ? "On" : "Off"]" ) + + user << browse("Securitron v1.3 controls[entity_ja(dat)]", "window=autosec") + onclose(user, "autosec") + +/obj/machinery/bot/secbot/Topic(href, href_list) + . = ..() + if(!.) + return + + if(href_list["power"] && allowed(usr)) + if(on) + turn_off() + else + turn_on() + return + + switch(href_list["operation"]) + if("idcheck") + idcheck = !idcheck + if("ignorerec") + check_records = !check_records + if("switchmode") + arrest_type = !arrest_type + if("patrol") + auto_patrol = !auto_patrol + mode = SECBOT_IDLE + if("declarearrests") + declare_arrests = !declare_arrests + + updateUsrDialog() + +/obj/machinery/bot/secbot/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)) + if(emagged) + to_chat(user, "ERROR") + else if(open) + to_chat(user, "Please close the access panel before locking it.") + else if(allowed(user)) + locked = !locked + to_chat(user, "Controls are now [locked ? "locked" : "unlocked"].") + else + to_chat(user, "Access denied.") + else + ..() + beingAttacked(W, user) + + +/obj/machinery/bot/secbot/proc/beingAttacked(obj/item/weapon/W, mob/user) + if(!istype(W, /obj/item/weapon/screwdriver) && W.force && !target) + target = user + mode = SECBOT_HUNT + +/obj/machinery/bot/secbot/proc/forgetCurrentTarget() + target = null + last_found = world.time + mode = SECBOT_IDLE + walk_to(src, 0) + frustration = 0 + anchored = FALSE + +/obj/machinery/bot/secbot/Emag(mob/user) + ..() + if(open && !locked) + if(user) + to_chat(user, "You short out [src]'s target assessment circuits.") + audible_message("[src] buzzes oddly!") + target = null + if(user) + oldtarget_name = user.name + last_found = world.time + anchored = 0 + emagged = 2 + on = 1 + update_icon() + mode = SECBOT_IDLE + +/obj/machinery/bot/secbot/is_on_patrol() + return mode == SECBOT_START_PATROL + +/obj/machinery/bot/secbot/process() + if(!on) + return + if(!inaction_check()) + 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(frustration >= 8) + forgetCurrentTarget() + + if(target) // make sure target exists + if(Adjacent(target) && istype(target.loc, /turf)) + if(iscarbon(target)) + playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) + icon_state = "[lasercolor][icon_state_arrest]" + addtimer(CALLBACK(src, .proc/update_icon), 2) + var/mob/living/carbon/M = target + var/maxstuns = 4 + if(M.stuttering < 10 && !(HULK in M.mutations)) + M.stuttering = 10 + M.Stun(10) + M.Weaken(10) + maxstuns-- + if(maxstuns <= 0) + target = null + + if(declare_arrests) + var/area/location = get_area(src) + broadcast_security_hud_message("[name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] suspect [target] in [location]", src) + visible_message("[target] has been stunned by [src]!") + + mode = SECBOT_PREP_ARREST + anchored = TRUE + target_lastloc = M.loc + return + + else + //just harmbaton them until dead + if(world.time > next_harm_time) + next_harm_time = world.time + 15 + playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) + visible_message("[src] beats [target] with the stun baton!") + icon_state = "[lasercolor][icon_state_arrest]" + addtimer(CALLBACK(src, .proc/update_icon), 2) + target.AdjustStunned(10) + target.adjustBruteLoss(15) + if(target.stat) + forgetCurrentTarget() + playsound(loc, 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, target) + walk_to(src, target, 1, 4) + if(get_dist(src, target) >= olddist) + frustration++ + else + frustration = 0 + else + frustration = 8 + + if(SECBOT_PREP_ARREST) // preparing to arrest target + // see if he got away + if(!Adjacent(target) || ((target.loc != target_lastloc) && (target.weakened < 2))) + anchored = 0 + mode = SECBOT_HUNT + return + + if(iscarbon(target)) + var/mob/living/carbon/C = target + if(!C.handcuffed && !arrest_type) + playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2) + mode = SECBOT_ARREST + visible_message("\red [src] is trying to put handcuffs on [target]!") + addtimer(CALLBACK(src, .proc/subprocess, SECBOT_PREP_ARREST), 60) + + else + forgetCurrentTarget() + + if(SECBOT_ARREST) // arresting + if(!target || !iscarbon(target)) + forgetCurrentTarget() + else + var/mob/living/carbon/C = target + if(C.handcuffed) + forgetCurrentTarget() + + if(SECBOT_START_PATROL) // start a patrol + 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 + INVOKE_ASYNC(src, .proc/subprocess, SECBOT_START_PATROL) + + else // no patrol target, so need a new one + find_patrol_target() + speak("Engaging patrol mode.") + + + if(SECBOT_PATROL) // patrol mode + patrol_step() + addtimer(CALLBACK(src, .proc/subprocess, SECBOT_PATROL), 5) + + if(SECBOT_SUMMON) // summoned to PDA + patrol_step() + addtimer(CALLBACK(src, .proc/subprocess, SECBOT_SUMMON), 4) + addtimer(CALLBACK(src, .proc/subprocess, SECBOT_SUMMON), 8) + +/obj/machinery/bot/secbot/proc/subprocess(oldmode) + switch(oldmode) + if(SECBOT_PREP_ARREST) + if(!target) //All will be cleared in /process() + return + if(Adjacent(target)) + if(iscarbon(target)) + var/mob/living/carbon/mob_carbon = target + if(!mob_carbon.handcuffed) + mob_carbon.handcuffed = new /obj/item/weapon/handcuffs(target) + mob_carbon.update_inv_handcuffed() //update the handcuffs overlay + forgetCurrentTarget() + playsound(loc, 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) + else if(mode == SECBOT_ARREST) + anchored = FALSE + mode = SECBOT_HUNT + + if(SECBOT_START_PATROL) + calc_path() // so just find a route to it + if(path.len == 0) + patrol_target = 0 + return + mode = SECBOT_PATROL + + if(SECBOT_PATROL) + if(mode == SECBOT_PATROL) + patrol_step() + + if(SECBOT_SUMMON) + if(mode == SECBOT_SUMMON) + patrol_step() + + +/obj/machinery/bot/secbot/update_icon() + icon_state = "secbot[on]" + +// 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 + addtimer(CALLBACK(src, .proc/patrol_substep, next), 2) + + else // not a valid turf + mode = SECBOT_IDLE + + else // no path, so calculate new one + mode = SECBOT_START_PATROL + +/obj/machinery/bot/secbot/proc/patrol_substep(turf/next) + calc_path(next) + if(path.len == 0) + find_patrol_target() + else + blockcount = 0 + +// 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() + + +// 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 + addtimer(CALLBACK(src, .proc/find_nearest_beacon_substep), 10) + +/obj/machinery/bot/secbot/proc/find_nearest_beacon_substep() + 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() + + +// 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(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 < get_dist(src, nearest_beacon_loc)) + nearest_beacon = recv + nearest_beacon_loc = signal.source.loc + return + else + return + else if(dist > 1) + nearest_beacon = recv + nearest_beacon_loc = signal.source.loc + + +// send a radio signal with a single data key/value pair +/obj/machinery/bot/secbot/proc/post_signal(freq, key, 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(freq, list/keyval) + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + if(!frequency) + return + + var/datum/signal/signal = new() + signal.source = src + signal.transmission_method = 1 + //for(var/key in keyval) + // signal.data[key] = keyval[key] + signal.data = keyval + //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() + if(!(src && loc && loc.loc)) + return + 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(turf/avoid = null) + path = get_path_to(src, patrol_target, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid) + +// look for a criminal in view of the bot + +/obj/machinery/bot/secbot/proc/look_for_perp() + anchored = 0 + for(var/mob/living/L in view(7, src)) //Let's find us a criminal + if(L.stat) + continue + + if(iscarbon(L)) + var/mob/living/carbon/C = L + if(C.handcuffed) + continue + + if((L.name == oldtarget_name) && (world.time < last_found + 100)) + continue + + threatlevel = assess_perp(L) + + if(threatlevel >= 4) + target = L + oldtarget_name = L.name + speak("Level [threatlevel] infraction alert!") + playsound(loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0) + visible_message("[src] points at [L.name]!") + mode = SECBOT_HUNT + 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/perp) + var/threatcount = 0 + + if(!istype(perp)) + return 0 + + if(emagged == 2) + return 10 //Everyone is a criminal! + + threatcount = perp.assess_perp(src, FALSE, idcheck, FALSE, check_records) + return threatcount + +/obj/machinery/bot/secbot/Bump(atom/M) //Leave no door unopened! + if(istype(M, /obj/machinery/door) && !isnull(botcard)) + var/obj/machinery/door/D = M + if(!istype(D, /obj/machinery/door/firedoor) && D.check_access(botcard) && !istype(D,/obj/machinery/door/poddoor)) + D.open() + frustration = 0 + else if(isliving(M) && !anchored) + loc = M.loc + frustration = 0 + +/obj/machinery/bot/secbot/proc/speak(message) + audible_message("[src] beeps, \"[message]\"") + + +/obj/machinery/bot/secbot/explode() + walk_to(src,0) + visible_message("\red [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 = name + new /obj/item/device/assembly/prox_sensor(Tsec) + + var/obj/item/weapon/melee/baton/B = new /obj/item/weapon/melee/baton(Tsec) + B.charges = 0 + + 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() + + new /obj/effect/decal/cleanable/blood/oil(loc) + qdel(src) + +/obj/machinery/bot/secbot/attack_alien(mob/living/carbon/alien/user) + ..() + if(!isalien(target)) + target = user + mode = SECBOT_HUNT + +//Secbot Construction + +/obj/item/clothing/head/helmet/attackby(obj/item/device/assembly/signaler/S, mob/user) + if(!issignaler(S) || !istype(src, /obj/item/clothing/head/helmet) || !S.secured) //Eh, but we don't want people making secbots out of space helmets. + ..() + return + + 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) + +/obj/item/weapon/secbot_assembly/attackby(obj/item/weapon/W, mob/user) + ..() + if(istype(W, /obj/item/weapon/weldingtool) && !build_step) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + build_step++ + overlays += image('icons/obj/aibots.dmi', "hs_hole") + to_chat(user, "You weld a hole in [src]!") + + else if(isprox(W) && build_step == 1) + user.drop_item() + build_step++ + to_chat(user, "You add the prox sensor to [src]!") + overlays += image('icons/obj/aibots.dmi', "hs_eye") + 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)) && (build_step == 2)) + user.drop_item() + build_step++ + to_chat(user, "You add the robot arm to [src]!") + name = "helmet/signaler/prox sensor/robot arm assembly" + overlays += image('icons/obj/aibots.dmi', "hs_arm") + qdel(W) + + else if(istype(W, /obj/item/weapon/melee/baton) && (build_step >= 3)) + user.drop_item() + 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 = created_name + qdel(W) + qdel(src) + + else if(istype(W, /obj/item/weapon/pen)) + var/t = sanitize_safe(input(user, "Enter new robot name", name, input_default(created_name)), MAX_NAME_LEN) + if(!t) + return + if(!in_range(src, usr) && loc != usr) + return + created_name = t diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index 3d61a1fbfb59..53dc3403633d 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -1,47 +1,47 @@ -/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 = null - var/active = FALSE - anchored = TRUE - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - -/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 = null - var/active = FALSE - anchored = TRUE - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - -/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 = null - var/active = FALSE - anchored = TRUE - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - -/obj/machinery/crema_switch - desc = "Burn baby burn!" - name = "crematorium igniter" - icon = 'icons/obj/power.dmi' - icon_state = "crema_switch" - anchored = TRUE - req_access = list(access_crematorium) - var/on = FALSE - var/area/area = null - var/otherarea = null - var/id = 1 +/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 = null + var/active = FALSE + anchored = TRUE + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + +/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 = null + var/active = FALSE + anchored = TRUE + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + +/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 = null + var/active = FALSE + anchored = TRUE + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + +/obj/machinery/crema_switch + desc = "Burn baby burn!" + name = "crematorium igniter" + icon = 'icons/obj/power.dmi' + icon_state = "crema_switch" + anchored = TRUE + req_access = list(access_crematorium) + var/on = FALSE + var/area/area = null + var/otherarea = null + var/id = 1 diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index febcb16f163d..5ee0480f807e 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -1,401 +1,401 @@ -/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/list/network = list("SS13") - var/c_tag = null - var/c_tag_order = 999 - var/status = 1 - anchored = 1 - var/invuln = null - var/obj/item/device/camera_bug/bug = null - var/obj/item/weapon/camera_assembly/assembly = null - var/hidden = 0 //Hidden cameras will be unreachable for AI - - var/datum/wires/camera/wires = null - - //OTHER - var/view_range = 7 - var/short_range = 2 - - var/light_disabled = 0 - var/alarm_on = 0 - var/painted = FALSE // Barber's paint can obstruct camera's view. - -/obj/machinery/camera/atom_init() - . = ..() - cameranet.cameras += src //Camera must be added to global list of all cameras no matter what... - var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS) //...but if all of camera's networks are restricted, it only works for specific camera consoles. - if(open_networks.len) //If there is at least one open network, chunk is available for AI usage. - cameranet.addCamera(src) - wires = new(src) - assembly = new(src) - assembly.state = 4 - /* // Use this to look for cameras that have the same c_tag. - for(var/obj/machinery/camera/C in cameranet.cameras) - var/list/tempnetwork = C.network&src.network - if(C != src && C.c_tag == src.c_tag && tempnetwork.len) - world.log << "[src.c_tag] [src.x] [src.y] [src.z] conflicts with [C.c_tag] [C.x] [C.y] [C.z]" - */ - if(!network || network.len < 1) - if(loc) - error("[name] in [get_area(src)] ([COORD(src)]) has errored. [network ? "Empty network list" : "Null network list"]") - else - error("[name] in [get_area(src)]has errored. [network ? "Empty network list" : "Null network list"]") - ASSERT(network) - ASSERT(network.len > 0) - -/obj/machinery/camera/Destroy() - disconnect_viewers() - QDEL_NULL(wires) - QDEL_NULL(assembly) - if(bug) - bug.bugged_cameras -= c_tag - if(bug.current == src) - bug.current = null - bug = null - cameranet.cameras -= src - var/list/open_networks = difflist(network, RESTRICTED_CAMERA_NETWORKS) - if(open_networks.len) - cameranet.removeCamera(src) - return ..() - -/obj/machinery/camera/update_icon() - if(!status) - icon_state = "[initial(icon_state)]1" - else if(stat & EMPED) - icon_state = "[initial(icon_state)]emp" - else - icon_state = "[initial(icon_state)]" - -/obj/machinery/camera/examine(mob/user) - ..() - if(painted) - to_chat(user, "This camera appears to be painted.") - -/obj/machinery/camera/emp_act(severity) - if(!isEmpProof() && status) - if(prob(100/severity)) - addtimer(CALLBACK(src, .proc/fix_emp_state, network), 900) - network = list() - stat |= EMPED - toggle_cam(TRUE) - triggerCameraAlarm() - ..() - -/obj/machinery/camera/proc/fix_emp_state(list/previous_network) - stat &= ~EMPED - if(!painted) - network = previous_network - cancelCameraAlarm() - toggle_cam(TRUE) - -/obj/machinery/camera/proc/remove_paint_state() - if(!painted) // Water and paint remover can remove paint before the callback call, failsafe. - return - painted = FALSE - if(!(stat & EMPED)) - visible_message("[bicon(src)] Paint drips from [src].") - cancelCameraAlarm() - toggle_cam(FALSE) - -/obj/machinery/camera/ex_act(severity) - if(src.invuln) - return - else - ..(severity) - return - -/obj/machinery/camera/blob_act() - return - -/obj/machinery/camera/proc/setViewRange(num = 7) - src.view_range = num - cameranet.updateVisibility(src, 0) - -/obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user) - if(!istype(user)) - return - if(status) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - visible_message("\The [user] slashes at [src]!") - playsound(src, 'sound/weapons/slash.ogg', 100, 1) - toggle_cam(FALSE, user) - -/obj/machinery/camera/attackby(W, mob/living/user) - var/msg = "You attach [W] into the assembly inner circuits." - var/msg2 = "The camera already has that upgrade!" - - // DECONSTRUCTION - if(isscrewdriver(W)) - //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 - panel_open = !panel_open - user.visible_message("[user] screws the camera's panel [panel_open ? "open" : "closed"]!", - "You screw the camera's panel [panel_open ? "open" : "closed"].") - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - - else if(is_wire_tool(W) && panel_open) - wires.interact(user) - - else if(iswelder(W) && wires.is_deconstructable()) - if(weld(W, user)) - drop_assembly(1) - qdel(src) - else if(istype(W, /obj/item/device/analyzer) && panel_open) //XRay - if(!isXRay()) - upgradeXRay() - qdel(W) - to_chat(user, "[msg]") - else - to_chat(user, "[msg2]") - - else if(istype(W, /obj/item/stack/sheet/mineral/phoron) && panel_open) - if(!isEmpProof()) - upgradeEmpProof() - to_chat(user, "[msg]") - qdel(W) - else - to_chat(user, "[msg2]") - else if(istype(W, /obj/item/device/assembly/prox_sensor) && panel_open) - if(!isMotion()) - upgradeMotion() - to_chat(user, "[msg]") - qdel(W) - else - to_chat(user, "[msg2]") - - // OTHER - else if ((istype(W, /obj/item/weapon/paper) && !(W:crumpled==1) || istype(W, /obj/item/device/pda)) && isliving(user)) - 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 \the [itemname] up to the camera ...") - for(var/mob/living/silicon/ai/O in ai_list) - if(!O.client || O.stat == DEAD) - continue - to_chat(O, "[U.name] holds \a [itemname] up to one of your cameras ...") - O << browse(text("[][]", itemname, entity_ja(info)), text("window=[]", itemname)) - for(var/mob/O in player_list) - if (O.client && O.client.eye == src) - to_chat(O, "[U] holds \a [itemname] up to one of the cameras ...") - O << browse(text("[][]", itemname, entity_ja(info)), text("window=[]", itemname)) - else if (istype(W, /obj/item/device/camera_bug)) - if(!src.can_use()) - to_chat(user, "Camera non-functional") - return - if(bug) - to_chat(user, "Camera bug removed.") - src.bug.bugged_cameras -= src.c_tag - src.bug = null - else - to_chat(user, "Camera bugged.") - src.bug = W - src.bug.bugged_cameras[src.c_tag] = src - else if(istype(W, /obj/item/weapon/melee/energy) || istype(W, /obj/item/weapon/pen/edagger) || istype(W, /obj/item/weapon/twohanded/dualsaber))//Putting it here last since it's a special case. I wonder if there is a better way to do these than type casting. - if(W:force > 3) - user.do_attack_animation(src) - disconnect_viewers() - var/datum/effect/effect/system/spark_spread/spark_system = new() - spark_system.set_up(5, 0, loc) - spark_system.start() - playsound(loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(loc, "sparks", 50, 1) - visible_message("The camera has been sliced apart by [user] with [W]!") - drop_assembly() - new /obj/item/stack/cable_coil/cut/red(loc) - qdel(src) - else - ..() - return - -/obj/machinery/camera/proc/drop_assembly(state = 0) - if(assembly) - assembly.state = state - assembly.loc = loc - assembly = null - -/obj/machinery/camera/proc/toggle_cam(show_message, mob/living/user = null) - status = !status - - if(can_use()) - cameranet.addCamera(src) - else - set_light(0) - cameranet.removeCamera(src) - - if(user) - add_hiddenprint(user) - - if(show_message) - var/status_message = (status ? "reactivates" : "deactivates") - if(user) - visible_message("[bicon(src)] [user] [status_message] [src]!") - else - visible_message("[bicon(src)] \The [src] [status_message]!") - playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) - - update_icon() - - if(!status) - disconnect_viewers() - -/obj/machinery/camera/proc/disconnect_viewers() - for(var/mob/O in player_list) - if(O.client && O.client.eye == src) - O.unset_machine() - O.reset_view(null) - to_chat(O, "The screen bursts into static.") - -/obj/machinery/camera/proc/triggerCameraAlarm() - alarm_on = 1 - for(var/mob/living/silicon/S in silicon_list) - S.triggerAlarm("Camera", get_area(src), list(src), src) - - -/obj/machinery/camera/proc/cancelCameraAlarm() - alarm_on = 0 - for(var/mob/living/silicon/S in silicon_list) - S.cancelAlarm("Camera", get_area(src), src) - -/obj/machinery/camera/proc/can_use(check_paint = TRUE) - if(!status) - return FALSE - if(stat & EMPED) - return FALSE - if(check_paint && painted && !isXRay()) - return FALSE - return TRUE - -/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 = hear(view_range, pos) - return see - -/atom/proc/auto_turn() - //Automatically turns based on nearby walls. - var/turf/simulated/wall/T = null - for(var/i = 1, i <= 8; i += i) - T = get_ranged_target_turf(src, i, 1) - if(istype(T)) - //If someone knows a better way to do this, let me know. -Giacom - switch(i) - if(NORTH) - src.dir = SOUTH - if(SOUTH) - src.dir = NORTH - if(WEST) - src.dir = EAST - if(EAST) - src.dir = WEST - break - -//Return a working camera that can see a given mob -//or null if none -/proc/seen_by_camera(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(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(obj/item/weapon/weldingtool/WT, mob/user) - - if(!WT.isOn()) - return 0 - if(user.is_busy(src)) return - // Do after stuff here - to_chat(user, "You start to weld the [src]..") - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) - WT.eyecheck(user) - if(do_after(user, 100, target = src)) - if(!WT.isOn()) - return 0 - return 1 - return 0 - -/obj/machinery/camera/proc/add_network(network_name) - add_networks(list(network_name)) - -/obj/machinery/camera/proc/remove_network(network_name) - remove_networks(list(network_name)) - -/obj/machinery/camera/proc/add_networks(list/networks) - var/network_added - network_added = 0 - for(var/network_name in networks) - if(!(network_name in src.network)) - network += network_name - network_added = 1 - - if(network_added) - invalidateCameraCache() - -/obj/machinery/camera/proc/remove_networks(list/networks) - var/network_removed - network_removed = 0 - for(var/network_name in networks) - if(network_name in src.network) - network -= network_name - network_removed = 1 - - if(network_removed) - invalidateCameraCache() - -/obj/machinery/camera/proc/replace_networks(list/networks) - if(networks.len != network.len) - network = networks - invalidateCameraCache() - return - - for(var/new_network in networks) - if(!(new_network in network)) - network = networks - invalidateCameraCache() - return - -/obj/machinery/camera/proc/clear_all_networks() - if(network.len) - network.Cut() - invalidateCameraCache() - -/obj/machinery/camera/proc/nano_structure() - var/cam[0] - cam["name"] = sanitize(c_tag) - cam["deact"] = !can_use() - cam["camera"] = "\ref[src]" - cam["x"] = x - cam["y"] = y - cam["z"] = z - return cam +/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/list/network = list("SS13") + var/c_tag = null + var/c_tag_order = 999 + var/status = 1 + anchored = 1 + var/invuln = null + var/obj/item/device/camera_bug/bug = null + var/obj/item/weapon/camera_assembly/assembly = null + var/hidden = 0 //Hidden cameras will be unreachable for AI + + var/datum/wires/camera/wires = null + + //OTHER + var/view_range = 7 + var/short_range = 2 + + var/light_disabled = 0 + var/alarm_on = 0 + var/painted = FALSE // Barber's paint can obstruct camera's view. + +/obj/machinery/camera/atom_init() + . = ..() + cameranet.cameras += src //Camera must be added to global list of all cameras no matter what... + var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS) //...but if all of camera's networks are restricted, it only works for specific camera consoles. + if(open_networks.len) //If there is at least one open network, chunk is available for AI usage. + cameranet.addCamera(src) + wires = new(src) + assembly = new(src) + assembly.state = 4 + /* // Use this to look for cameras that have the same c_tag. + for(var/obj/machinery/camera/C in cameranet.cameras) + var/list/tempnetwork = C.network&src.network + if(C != src && C.c_tag == src.c_tag && tempnetwork.len) + world.log << "[src.c_tag] [src.x] [src.y] [src.z] conflicts with [C.c_tag] [C.x] [C.y] [C.z]" + */ + if(!network || network.len < 1) + if(loc) + error("[name] in [get_area(src)] ([COORD(src)]) has errored. [network ? "Empty network list" : "Null network list"]") + else + error("[name] in [get_area(src)]has errored. [network ? "Empty network list" : "Null network list"]") + ASSERT(network) + ASSERT(network.len > 0) + +/obj/machinery/camera/Destroy() + disconnect_viewers() + QDEL_NULL(wires) + QDEL_NULL(assembly) + if(bug) + bug.bugged_cameras -= c_tag + if(bug.current == src) + bug.current = null + bug = null + cameranet.cameras -= src + var/list/open_networks = difflist(network, RESTRICTED_CAMERA_NETWORKS) + if(open_networks.len) + cameranet.removeCamera(src) + return ..() + +/obj/machinery/camera/update_icon() + if(!status) + icon_state = "[initial(icon_state)]1" + else if(stat & EMPED) + icon_state = "[initial(icon_state)]emp" + else + icon_state = "[initial(icon_state)]" + +/obj/machinery/camera/examine(mob/user) + ..() + if(painted) + to_chat(user, "This camera appears to be painted.") + +/obj/machinery/camera/emp_act(severity) + if(!isEmpProof() && status) + if(prob(100/severity)) + addtimer(CALLBACK(src, .proc/fix_emp_state, network), 900) + network = list() + stat |= EMPED + toggle_cam(TRUE) + triggerCameraAlarm() + ..() + +/obj/machinery/camera/proc/fix_emp_state(list/previous_network) + stat &= ~EMPED + if(!painted) + network = previous_network + cancelCameraAlarm() + toggle_cam(TRUE) + +/obj/machinery/camera/proc/remove_paint_state() + if(!painted) // Water and paint remover can remove paint before the callback call, failsafe. + return + painted = FALSE + if(!(stat & EMPED)) + visible_message("[bicon(src)] Paint drips from [src].") + cancelCameraAlarm() + toggle_cam(FALSE) + +/obj/machinery/camera/ex_act(severity) + if(src.invuln) + return + else + ..(severity) + return + +/obj/machinery/camera/blob_act() + return + +/obj/machinery/camera/proc/setViewRange(num = 7) + src.view_range = num + cameranet.updateVisibility(src, 0) + +/obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user) + if(!istype(user)) + return + if(status) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + visible_message("\The [user] slashes at [src]!") + playsound(src, 'sound/weapons/slash.ogg', 100, 1) + toggle_cam(FALSE, user) + +/obj/machinery/camera/attackby(W, mob/living/user) + var/msg = "You attach [W] into the assembly inner circuits." + var/msg2 = "The camera already has that upgrade!" + + // DECONSTRUCTION + if(isscrewdriver(W)) + //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 + panel_open = !panel_open + user.visible_message("[user] screws the camera's panel [panel_open ? "open" : "closed"]!", + "You screw the camera's panel [panel_open ? "open" : "closed"].") + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + + else if(is_wire_tool(W) && panel_open) + wires.interact(user) + + else if(iswelder(W) && wires.is_deconstructable()) + if(weld(W, user)) + drop_assembly(1) + qdel(src) + else if(istype(W, /obj/item/device/analyzer) && panel_open) //XRay + if(!isXRay()) + upgradeXRay() + qdel(W) + to_chat(user, "[msg]") + else + to_chat(user, "[msg2]") + + else if(istype(W, /obj/item/stack/sheet/mineral/phoron) && panel_open) + if(!isEmpProof()) + upgradeEmpProof() + to_chat(user, "[msg]") + qdel(W) + else + to_chat(user, "[msg2]") + else if(istype(W, /obj/item/device/assembly/prox_sensor) && panel_open) + if(!isMotion()) + upgradeMotion() + to_chat(user, "[msg]") + qdel(W) + else + to_chat(user, "[msg2]") + + // OTHER + else if ((istype(W, /obj/item/weapon/paper) && !(W:crumpled==1) || istype(W, /obj/item/device/pda)) && isliving(user)) + 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 \the [itemname] up to the camera ...") + for(var/mob/living/silicon/ai/O in ai_list) + if(!O.client || O.stat == DEAD) + continue + to_chat(O, "[U.name] holds \a [itemname] up to one of your cameras ...") + O << browse(text("[][]", itemname, entity_ja(info)), text("window=[]", itemname)) + for(var/mob/O in player_list) + if (O.client && O.client.eye == src) + to_chat(O, "[U] holds \a [itemname] up to one of the cameras ...") + O << browse(text("[][]", itemname, entity_ja(info)), text("window=[]", itemname)) + else if (istype(W, /obj/item/device/camera_bug)) + if(!src.can_use()) + to_chat(user, "Camera non-functional") + return + if(bug) + to_chat(user, "Camera bug removed.") + src.bug.bugged_cameras -= src.c_tag + src.bug = null + else + to_chat(user, "Camera bugged.") + src.bug = W + src.bug.bugged_cameras[src.c_tag] = src + else if(istype(W, /obj/item/weapon/melee/energy) || istype(W, /obj/item/weapon/pen/edagger) || istype(W, /obj/item/weapon/twohanded/dualsaber))//Putting it here last since it's a special case. I wonder if there is a better way to do these than type casting. + if(W:force > 3) + user.do_attack_animation(src) + disconnect_viewers() + var/datum/effect/effect/system/spark_spread/spark_system = new() + spark_system.set_up(5, 0, loc) + spark_system.start() + playsound(loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(loc, "sparks", 50, 1) + visible_message("The camera has been sliced apart by [user] with [W]!") + drop_assembly() + new /obj/item/stack/cable_coil/cut/red(loc) + qdel(src) + else + ..() + return + +/obj/machinery/camera/proc/drop_assembly(state = 0) + if(assembly) + assembly.state = state + assembly.loc = loc + assembly = null + +/obj/machinery/camera/proc/toggle_cam(show_message, mob/living/user = null) + status = !status + + if(can_use()) + cameranet.addCamera(src) + else + set_light(0) + cameranet.removeCamera(src) + + if(user) + add_hiddenprint(user) + + if(show_message) + var/status_message = (status ? "reactivates" : "deactivates") + if(user) + visible_message("[bicon(src)] [user] [status_message] [src]!") + else + visible_message("[bicon(src)] \The [src] [status_message]!") + playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) + + update_icon() + + if(!status) + disconnect_viewers() + +/obj/machinery/camera/proc/disconnect_viewers() + for(var/mob/O in player_list) + if(O.client && O.client.eye == src) + O.unset_machine() + O.reset_view(null) + to_chat(O, "The screen bursts into static.") + +/obj/machinery/camera/proc/triggerCameraAlarm() + alarm_on = 1 + for(var/mob/living/silicon/S in silicon_list) + S.triggerAlarm("Camera", get_area(src), list(src), src) + + +/obj/machinery/camera/proc/cancelCameraAlarm() + alarm_on = 0 + for(var/mob/living/silicon/S in silicon_list) + S.cancelAlarm("Camera", get_area(src), src) + +/obj/machinery/camera/proc/can_use(check_paint = TRUE) + if(!status) + return FALSE + if(stat & EMPED) + return FALSE + if(check_paint && painted && !isXRay()) + return FALSE + return TRUE + +/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 = hear(view_range, pos) + return see + +/atom/proc/auto_turn() + //Automatically turns based on nearby walls. + var/turf/simulated/wall/T = null + for(var/i = 1, i <= 8; i += i) + T = get_ranged_target_turf(src, i, 1) + if(istype(T)) + //If someone knows a better way to do this, let me know. -Giacom + switch(i) + if(NORTH) + src.dir = SOUTH + if(SOUTH) + src.dir = NORTH + if(WEST) + src.dir = EAST + if(EAST) + src.dir = WEST + break + +//Return a working camera that can see a given mob +//or null if none +/proc/seen_by_camera(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(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(obj/item/weapon/weldingtool/WT, mob/user) + + if(!WT.isOn()) + return 0 + if(user.is_busy(src)) return + // Do after stuff here + to_chat(user, "You start to weld the [src]..") + playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + WT.eyecheck(user) + if(do_after(user, 100, target = src)) + if(!WT.isOn()) + return 0 + return 1 + return 0 + +/obj/machinery/camera/proc/add_network(network_name) + add_networks(list(network_name)) + +/obj/machinery/camera/proc/remove_network(network_name) + remove_networks(list(network_name)) + +/obj/machinery/camera/proc/add_networks(list/networks) + var/network_added + network_added = 0 + for(var/network_name in networks) + if(!(network_name in src.network)) + network += network_name + network_added = 1 + + if(network_added) + invalidateCameraCache() + +/obj/machinery/camera/proc/remove_networks(list/networks) + var/network_removed + network_removed = 0 + for(var/network_name in networks) + if(network_name in src.network) + network -= network_name + network_removed = 1 + + if(network_removed) + invalidateCameraCache() + +/obj/machinery/camera/proc/replace_networks(list/networks) + if(networks.len != network.len) + network = networks + invalidateCameraCache() + return + + for(var/new_network in networks) + if(!(new_network in network)) + network = networks + invalidateCameraCache() + return + +/obj/machinery/camera/proc/clear_all_networks() + if(network.len) + network.Cut() + invalidateCameraCache() + +/obj/machinery/camera/proc/nano_structure() + var/cam[0] + cam["name"] = sanitize(c_tag) + cam["deact"] = !can_use() + cam["camera"] = "\ref[src]" + cam["x"] = x + cam["y"] = y + cam["z"] = z + return cam diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 8d3cf237518c..6d4cb42bee95 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -1,165 +1,165 @@ -/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 - - m_amt = 700 - g_amt = 300 - - // Motion, EMP-Proof, X-Ray - var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/phoron, /obj/item/device/analyzer) - var/list/upgrades = list() - var/state = 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, mob/living/user) - - switch(state) - - if(0) - // State 0 - if(iswrench(W) && isturf(src.loc)) - playsound(src.loc, '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)) - to_chat(user, "You weld the assembly securely into place.") - anchored = 1 - state = 2 - return - - else if(iswrench(W)) - playsound(src.loc, '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)) - to_chat(user, "You add wires to the assembly.") - 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(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - - var/input = sanitize_safe(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"), MAX_LNAME_LEN) - if(!input) - to_chat(usr, "No input found please hang up and try your call again.") - return - - var/list/tempnetwork = splittext(input, ",") - if(tempnetwork.len < 1) - to_chat(usr, "No network found please hang up and try your call again.") - return - - var/temptag = "[get_area(src)] ([rand(1, 999)])" - input = sanitize_safe(input(usr, "How would you like to name the camera?", "Set Camera Name", input_default(temptag)), MAX_LNAME_LEN) - - state = 4 - var/obj/machinery/camera/C = new(src.loc) - src.loc = C - C.assembly = src - - C.auto_turn() - - C.replace_networks(uniquelist(tempnetwork)) - tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS) - if(!tempnetwork.len)//Camera isn't on any open network - remove its chunk from AI visibility. - cameranet.removeCamera(C) - - C.c_tag = input - - 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/red(get_turf(src), 2) - playsound(src.loc, '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_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already. - to_chat(user, "You attach the [W] into the assembly inner circuits.") - upgrades += W - user.drop_item() - W.loc = src - return - - // Taking out upgrades - else if(iscrowbar(W) && upgrades.len) - var/obj/U = locate(/obj) in upgrades - if(U) - to_chat(user, "You unattach an upgrade from the assembly.") - playsound(src.loc, '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) - if(!anchored) - ..() - -/obj/item/weapon/camera_assembly/proc/weld(obj/item/weapon/weldingtool/WT, mob/user) - if(!WT.isOn()) - return 0 - if(user.is_busy(src)) return - to_chat(user, "You start to weld the [src]..") - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) - WT.eyecheck(user) - if(do_after(user, 20, target = src)) - if(!WT.isOn()) - return 0 - return 1 - return 0 +/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 + + m_amt = 700 + g_amt = 300 + + // Motion, EMP-Proof, X-Ray + var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/phoron, /obj/item/device/analyzer) + var/list/upgrades = list() + var/state = 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, mob/living/user) + + switch(state) + + if(0) + // State 0 + if(iswrench(W) && isturf(src.loc)) + playsound(src.loc, '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)) + to_chat(user, "You weld the assembly securely into place.") + anchored = 1 + state = 2 + return + + else if(iswrench(W)) + playsound(src.loc, '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)) + to_chat(user, "You add wires to the assembly.") + 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(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + + var/input = sanitize_safe(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"), MAX_LNAME_LEN) + if(!input) + to_chat(usr, "No input found please hang up and try your call again.") + return + + var/list/tempnetwork = splittext(input, ",") + if(tempnetwork.len < 1) + to_chat(usr, "No network found please hang up and try your call again.") + return + + var/temptag = "[get_area(src)] ([rand(1, 999)])" + input = sanitize_safe(input(usr, "How would you like to name the camera?", "Set Camera Name", input_default(temptag)), MAX_LNAME_LEN) + + state = 4 + var/obj/machinery/camera/C = new(src.loc) + src.loc = C + C.assembly = src + + C.auto_turn() + + C.replace_networks(uniquelist(tempnetwork)) + tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS) + if(!tempnetwork.len)//Camera isn't on any open network - remove its chunk from AI visibility. + cameranet.removeCamera(C) + + C.c_tag = input + + 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/red(get_turf(src), 2) + playsound(src.loc, '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_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already. + to_chat(user, "You attach the [W] into the assembly inner circuits.") + upgrades += W + user.drop_item() + W.loc = src + return + + // Taking out upgrades + else if(iscrowbar(W) && upgrades.len) + var/obj/U = locate(/obj) in upgrades + if(U) + to_chat(user, "You unattach an upgrade from the assembly.") + playsound(src.loc, '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) + if(!anchored) + ..() + +/obj/item/weapon/camera_assembly/proc/weld(obj/item/weapon/weldingtool/WT, mob/user) + if(!WT.isOn()) + return 0 + if(user.is_busy(src)) return + to_chat(user, "You start to weld the [src]..") + playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + WT.eyecheck(user) + if(do_after(user, 20, target = src)) + if(!WT.isOn()) + return 0 + return 1 + return 0 diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm index a921c4601e82..1058afc0c0c0 100644 --- a/code/game/machinery/camera/motion.dm +++ b/code/game/machinery/camera/motion.dm @@ -1,61 +1,61 @@ -/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() - - -/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 == DEAD) lostTarget(target) - // If not detecting with motion camera... - if (!area_motion) - // See if the camera is still in range - if(!in_range(src, target)) - // If they aren't in range, lose the target. - lostTarget(target) - -/obj/machinery/camera/proc/newTarget(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(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", get_area(src), src) - detectTime = 0 - return 1 - -/obj/machinery/camera/proc/triggerAlarm() - if (!detectTime) return 0 - for (var/mob/living/silicon/aiPlayer in player_list) - if (status) aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src) - detectTime = -1 - return 1 - -/obj/machinery/camera/HasProximity(atom/movable/AM) - // 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() + + +/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 == DEAD) lostTarget(target) + // If not detecting with motion camera... + if (!area_motion) + // See if the camera is still in range + if(!in_range(src, target)) + // If they aren't in range, lose the target. + lostTarget(target) + +/obj/machinery/camera/proc/newTarget(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(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", get_area(src), src) + detectTime = 0 + return 1 + +/obj/machinery/camera/proc/triggerAlarm() + if (!detectTime) return 0 + for (var/mob/living/silicon/aiPlayer in player_list) + if (status) aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src) + detectTime = -1 + return 1 + +/obj/machinery/camera/HasProximity(atom/movable/AM) + // 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 76c37c5dbb22..9755a481468e 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -1,82 +1,82 @@ -// PRESETS - -// EMP - -/obj/machinery/camera/emp_proof/atom_init() - . = ..() - upgradeEmpProof() - -// X-RAY - -/obj/machinery/camera/xray - icon_state = "xraycam" // Thanks to Krutchen for the icons. - -/obj/machinery/camera/xray/atom_init() - . = ..() - upgradeXRay() - -// MOTION -/obj/machinery/camera/motion - name = "motion-sensitive security camera" - -/obj/machinery/camera/motion/atom_init() - . = ..() - upgradeMotion() - -// ALL UPGRADES - -/obj/machinery/camera/all/atom_init() - . = ..() - upgradeEmpProof() - upgradeXRay() - upgradeMotion() - -// 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/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/camera/autoname/atom_init_late() - 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/phoron) in assembly.upgrades - return O - -/obj/machinery/camera/proc/isXRay() - var/O = locate(/obj/item/device/analyzer) in assembly.upgrades - return O - -/obj/machinery/camera/proc/isMotion() - var/O = locate(/obj/item/device/assembly/prox_sensor) in assembly.upgrades - return O - -// UPGRADE PROCS - -/obj/machinery/camera/proc/upgradeEmpProof() - assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/phoron(assembly)) - -/obj/machinery/camera/proc/upgradeXRay() - assembly.upgrades.Add(new /obj/item/device/analyzer(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)) +// PRESETS + +// EMP + +/obj/machinery/camera/emp_proof/atom_init() + . = ..() + upgradeEmpProof() + +// X-RAY + +/obj/machinery/camera/xray + icon_state = "xraycam" // Thanks to Krutchen for the icons. + +/obj/machinery/camera/xray/atom_init() + . = ..() + upgradeXRay() + +// MOTION +/obj/machinery/camera/motion + name = "motion-sensitive security camera" + +/obj/machinery/camera/motion/atom_init() + . = ..() + upgradeMotion() + +// ALL UPGRADES + +/obj/machinery/camera/all/atom_init() + . = ..() + upgradeEmpProof() + upgradeXRay() + upgradeMotion() + +// 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/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/camera/autoname/atom_init_late() + 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/phoron) in assembly.upgrades + return O + +/obj/machinery/camera/proc/isXRay() + var/O = locate(/obj/item/device/analyzer) in assembly.upgrades + return O + +/obj/machinery/camera/proc/isMotion() + var/O = locate(/obj/item/device/assembly/prox_sensor) in assembly.upgrades + return O + +// UPGRADE PROCS + +/obj/machinery/camera/proc/upgradeEmpProof() + assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/phoron(assembly)) + +/obj/machinery/camera/proc/upgradeXRay() + assembly.upgrades.Add(new /obj/item/device/analyzer(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)) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 6270626e6b68..fd2eb08245fd 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -1,284 +1,284 @@ -/mob/living/silicon/ai/var/max_locations = 5 -/mob/living/silicon/ai/var/stored_locations[0] - -/mob/living/silicon/ai/proc/InvalidTurf(turf/T) - if(!T) - return 1 - if(T.z == ZLEVEL_CENTCOMM) - return 1 - if(T.z > ZLEVEL_EMPTY) - return 1 - return 0 - -/mob/living/silicon/ai/proc/get_camera_list() - - if(src.stat == DEAD) - return - - var/list/L = list() - for (var/obj/machinery/camera/C in cameranet.cameras) - L.Add(C) - - camera_sort(L) - - var/list/T = list() - T["Cancel"] = "Cancel" - 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 = new() - track.cameras = T - return T - - -/mob/living/silicon/ai/proc/ai_camera_list(camera in get_camera_list()) - - if(src.stat == DEAD) - to_chat(src, "You can't list the cameras because you are dead!") - return - - if (!camera || camera == "Cancel") - return 0 - - var/obj/machinery/camera/C = track.cameras[camera] - track = null - src.eyeobj.setLoc(C) - - return - -/mob/living/silicon/ai/proc/ai_store_location(loc as text) - set category = "AI Commands" - set name = "Store Camera Location" - set desc = "Stores your current camera location by the given name." - - if(stored_locations.len >= max_locations) - to_chat(src, "\red Cannot store additional locations. Remove one first") - return - - loc = trim(loc) - if(!loc) - to_chat(src, "\red Must supply a location name") - return - - if(loc in stored_locations) - to_chat(src, "\red There is already a stored location by this name") - return - - var/L = src.eyeobj.getLoc() - if (InvalidTurf(get_turf(L))) - to_chat(src, "\red Unable to store this location") - return - - stored_locations[loc] = L - to_chat(src, "Location '[loc]' stored") - -/mob/living/silicon/ai/proc/sorted_stored_locations() - return sortList(stored_locations) - -/mob/living/silicon/ai/proc/ai_goto_location(loc in sorted_stored_locations()) - set category = "AI Commands" - set name = "Goto Camera Location" - set desc = "Returns to the selected camera location." - - if (!(loc in stored_locations)) - to_chat(src, "\red Location [loc] not found") - return - - var/L = stored_locations[loc] - src.eyeobj.setLoc(L) - -/mob/living/silicon/ai/proc/ai_remove_location(loc in sorted_stored_locations()) - set category = "AI Commands" - set name = "Delete Camera Location" - set desc = "Deletes the selected camera location." - - if (!(loc in stored_locations)) - to_chat(src, "\red Location [loc] not found") - return - - stored_locations.Remove(loc) - to_chat(src, "Location [loc] removed") - -// 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() - - if(usr.stat == DEAD) - return list() - - var/datum/trackable/TB = new() - for(var/mob/living/M in living_list) - // Easy checks first. - // Don't detect mobs on Centcom. Since the wizard den is on Centcomm, we only need this. - if(InvalidTurf(get_turf(M))) - 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 hat with blockTracking. - if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) - continue - if(istype(H.head, /obj/item/clothing/head)) - var/obj/item/clothing/head/hat = H.head - if(hat.blockTracking) - 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 TB.names) - TB.namecounts[name]++ - name = text("[] ([])", name, TB.namecounts[name]) - else - TB.names.Add(name) - TB.namecounts[name] = 1 - if(human) - TB.humans[name] = M - else - TB.others[name] = M - - var/list/targets = list() - targets.Add("Cancel") - targets.Add(sortList(TB.humans) + sortList(TB.others)) - src.track = TB - return targets - -/mob/living/silicon/ai/proc/ai_camera_track(target_name in trackable_mobs()) - - if(src.stat == DEAD) - to_chat(src, "You can't track with camera because you are dead!") - return - if(target_name == "Cancel") - return 0 - if(!target_name) - src.cameraFollow = null - - var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name]) - - src.track = null - ai_actual_track(target) - -/mob/living/silicon/ai/proc/ai_cancel_tracking(forced = 0) - if(!cameraFollow) - return - - to_chat(src, "Follow camera mode [forced ? "terminated" : "ended"].") - cameraFollow.tracking_cancelled() - cameraFollow = null - -/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target) - if(!istype(target)) return - var/mob/living/silicon/ai/U = usr - - U.cameraFollow = target - to_chat(U, "Now tracking [target.name] on camera.") - target.tracking_initiated() - - 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(istype(H.head, /obj/item/clothing/head)) - var/obj/item/clothing/head/hat = H.head - if(hat.blockTracking) - to_chat(U, "Follow camera mode terminated.") - 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)) - to_chat(U, "Follow camera mode ended.") - 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.setLoc(get_turf(target)) - else - view_core() - return - sleep(10) - -/proc/near_camera(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(mob/living/silicon/ai/user) - if (!istype(user)) - return - if (!src.can_use()) - return - user.eyeobj.setLoc(get_turf(src)) - - -/mob/living/silicon/ai/attack_ai(mob/user) - 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 - -mob/living/proc/tracking_initiated() - -mob/living/silicon/robot/tracking_initiated() - tracking_entities++ - if(tracking_entities == 1 && has_zeroth_law()) - to_chat(src, "Internal camera is currently being accessed.") - -mob/living/proc/tracking_cancelled() - -mob/living/silicon/robot/tracking_initiated() - tracking_entities-- - if(!tracking_entities && has_zeroth_law()) - to_chat(src, "Internal camera is no longer being accessed.") +/mob/living/silicon/ai/var/max_locations = 5 +/mob/living/silicon/ai/var/stored_locations[0] + +/mob/living/silicon/ai/proc/InvalidTurf(turf/T) + if(!T) + return 1 + if(T.z == ZLEVEL_CENTCOMM) + return 1 + if(T.z > ZLEVEL_EMPTY) + return 1 + return 0 + +/mob/living/silicon/ai/proc/get_camera_list() + + if(src.stat == DEAD) + return + + var/list/L = list() + for (var/obj/machinery/camera/C in cameranet.cameras) + L.Add(C) + + camera_sort(L) + + var/list/T = list() + T["Cancel"] = "Cancel" + 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 = new() + track.cameras = T + return T + + +/mob/living/silicon/ai/proc/ai_camera_list(camera in get_camera_list()) + + if(src.stat == DEAD) + to_chat(src, "You can't list the cameras because you are dead!") + return + + if (!camera || camera == "Cancel") + return 0 + + var/obj/machinery/camera/C = track.cameras[camera] + track = null + src.eyeobj.setLoc(C) + + return + +/mob/living/silicon/ai/proc/ai_store_location(loc as text) + set category = "AI Commands" + set name = "Store Camera Location" + set desc = "Stores your current camera location by the given name." + + if(stored_locations.len >= max_locations) + to_chat(src, "\red Cannot store additional locations. Remove one first") + return + + loc = trim(loc) + if(!loc) + to_chat(src, "\red Must supply a location name") + return + + if(loc in stored_locations) + to_chat(src, "\red There is already a stored location by this name") + return + + var/L = src.eyeobj.getLoc() + if (InvalidTurf(get_turf(L))) + to_chat(src, "\red Unable to store this location") + return + + stored_locations[loc] = L + to_chat(src, "Location '[loc]' stored") + +/mob/living/silicon/ai/proc/sorted_stored_locations() + return sortList(stored_locations) + +/mob/living/silicon/ai/proc/ai_goto_location(loc in sorted_stored_locations()) + set category = "AI Commands" + set name = "Goto Camera Location" + set desc = "Returns to the selected camera location." + + if (!(loc in stored_locations)) + to_chat(src, "\red Location [loc] not found") + return + + var/L = stored_locations[loc] + src.eyeobj.setLoc(L) + +/mob/living/silicon/ai/proc/ai_remove_location(loc in sorted_stored_locations()) + set category = "AI Commands" + set name = "Delete Camera Location" + set desc = "Deletes the selected camera location." + + if (!(loc in stored_locations)) + to_chat(src, "\red Location [loc] not found") + return + + stored_locations.Remove(loc) + to_chat(src, "Location [loc] removed") + +// 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() + + if(usr.stat == DEAD) + return list() + + var/datum/trackable/TB = new() + for(var/mob/living/M in living_list) + // Easy checks first. + // Don't detect mobs on Centcom. Since the wizard den is on Centcomm, we only need this. + if(InvalidTurf(get_turf(M))) + 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 hat with blockTracking. + if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) + continue + if(istype(H.head, /obj/item/clothing/head)) + var/obj/item/clothing/head/hat = H.head + if(hat.blockTracking) + 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 TB.names) + TB.namecounts[name]++ + name = text("[] ([])", name, TB.namecounts[name]) + else + TB.names.Add(name) + TB.namecounts[name] = 1 + if(human) + TB.humans[name] = M + else + TB.others[name] = M + + var/list/targets = list() + targets.Add("Cancel") + targets.Add(sortList(TB.humans) + sortList(TB.others)) + src.track = TB + return targets + +/mob/living/silicon/ai/proc/ai_camera_track(target_name in trackable_mobs()) + + if(src.stat == DEAD) + to_chat(src, "You can't track with camera because you are dead!") + return + if(target_name == "Cancel") + return 0 + if(!target_name) + src.cameraFollow = null + + var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name]) + + src.track = null + ai_actual_track(target) + +/mob/living/silicon/ai/proc/ai_cancel_tracking(forced = 0) + if(!cameraFollow) + return + + to_chat(src, "Follow camera mode [forced ? "terminated" : "ended"].") + cameraFollow.tracking_cancelled() + cameraFollow = null + +/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target) + if(!istype(target)) return + var/mob/living/silicon/ai/U = usr + + U.cameraFollow = target + to_chat(U, "Now tracking [target.name] on camera.") + target.tracking_initiated() + + 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(istype(H.head, /obj/item/clothing/head)) + var/obj/item/clothing/head/hat = H.head + if(hat.blockTracking) + to_chat(U, "Follow camera mode terminated.") + 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)) + to_chat(U, "Follow camera mode ended.") + 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.setLoc(get_turf(target)) + else + view_core() + return + sleep(10) + +/proc/near_camera(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(mob/living/silicon/ai/user) + if (!istype(user)) + return + if (!src.can_use()) + return + user.eyeobj.setLoc(get_turf(src)) + + +/mob/living/silicon/ai/attack_ai(mob/user) + 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 + +mob/living/proc/tracking_initiated() + +mob/living/silicon/robot/tracking_initiated() + tracking_entities++ + if(tracking_entities == 1 && has_zeroth_law()) + to_chat(src, "Internal camera is currently being accessed.") + +mob/living/proc/tracking_cancelled() + +mob/living/silicon/robot/tracking_initiated() + tracking_entities-- + if(!tracking_entities && has_zeroth_law()) + to_chat(src, "Internal camera is no longer being accessed.") diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 493501e7ced7..dab929894b84 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -1,106 +1,106 @@ -/obj/machinery/cell_charger - name = "cell charger" - desc = "It charges power cells." - icon = 'icons/obj/power.dmi' - icon_state = "ccharger0" - anchored = 1 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 60 - power_channel = EQUIP - interact_offline = TRUE - var/obj/item/weapon/stock_parts/cell/charging = null - var/chargelevel = -1 - var/efficiency = 0.875 //<1.0 means some power is lost in the charging process, >1.0 means free energy. - -/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) - //world << "nl: [newlevel]" - - if(chargelevel != newlevel) - - overlays.Cut() - overlays += "ccharger-o[newlevel]" - - chargelevel = newlevel - else - overlays.Cut() -/obj/machinery/cell_charger/examine(mob/user) - ..() - to_chat(user, "There's [charging ? "a" : "no"] cell in the charger.") - 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(istype(W, /obj/item/weapon/stock_parts/cell) && anchored) - if(charging) - to_chat(user, "\red There is already a cell in the charger.") - return - else - var/area/a = loc.loc // Gets our locations location, like a dream within a dream - if(!isarea(a)) - return - if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power! - to_chat(user, "\red The [name] blinks red as you try to insert the cell!") - return - - user.drop_item() - W.loc = src - charging = W - user.visible_message("[user] inserts a cell into the charger.", "You insert a cell into the charger.") - chargelevel = -1 - updateicon() - else if(istype(W, /obj/item/weapon/wrench)) - if(charging) - to_chat(user, "\red Remove the cell first!") - return - - anchored = !anchored - to_chat(user, "You [anchored ? "attach" : "detach"] the cell charger [anchored ? "to" : "from"] the ground") - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - -/obj/machinery/cell_charger/attack_hand(mob/user) - . = ..() - if(.) - return - - if(charging) - usr.put_in_hands(charging) - charging.add_fingerprint(user) - charging.updateicon() - - charging = null - user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.") - chargelevel = -1 - updateicon() - -/obj/machinery/cell_charger/attack_ai(mob/user) - if(IsAdminGhost(user)) // why not? - 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() - //world << "ccpt [charging] [stat]" - if(!charging || (stat & (BROKEN|NOPOWER)) || !anchored) - return - - var/power_used = 100000 //for 200 units of charge. Yes, thats right, 100 kW. Is something wrong with CELLRATE? - - power_used = charging.give(power_used*CELLRATE*efficiency) - use_power(power_used) - - updateicon() +/obj/machinery/cell_charger + name = "cell charger" + desc = "It charges power cells." + icon = 'icons/obj/power.dmi' + icon_state = "ccharger0" + anchored = 1 + use_power = 1 + idle_power_usage = 5 + active_power_usage = 60 + power_channel = EQUIP + interact_offline = TRUE + var/obj/item/weapon/stock_parts/cell/charging = null + var/chargelevel = -1 + var/efficiency = 0.875 //<1.0 means some power is lost in the charging process, >1.0 means free energy. + +/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) + //world << "nl: [newlevel]" + + if(chargelevel != newlevel) + + overlays.Cut() + overlays += "ccharger-o[newlevel]" + + chargelevel = newlevel + else + overlays.Cut() +/obj/machinery/cell_charger/examine(mob/user) + ..() + to_chat(user, "There's [charging ? "a" : "no"] cell in the charger.") + 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(istype(W, /obj/item/weapon/stock_parts/cell) && anchored) + if(charging) + to_chat(user, "\red There is already a cell in the charger.") + return + else + var/area/a = loc.loc // Gets our locations location, like a dream within a dream + if(!isarea(a)) + return + if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power! + to_chat(user, "\red The [name] blinks red as you try to insert the cell!") + return + + user.drop_item() + W.loc = src + charging = W + user.visible_message("[user] inserts a cell into the charger.", "You insert a cell into the charger.") + chargelevel = -1 + updateicon() + else if(istype(W, /obj/item/weapon/wrench)) + if(charging) + to_chat(user, "\red Remove the cell first!") + return + + anchored = !anchored + to_chat(user, "You [anchored ? "attach" : "detach"] the cell charger [anchored ? "to" : "from"] the ground") + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + +/obj/machinery/cell_charger/attack_hand(mob/user) + . = ..() + if(.) + return + + if(charging) + usr.put_in_hands(charging) + charging.add_fingerprint(user) + charging.updateicon() + + charging = null + user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.") + chargelevel = -1 + updateicon() + +/obj/machinery/cell_charger/attack_ai(mob/user) + if(IsAdminGhost(user)) // why not? + 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() + //world << "ccpt [charging] [stat]" + if(!charging || (stat & (BROKEN|NOPOWER)) || !anchored) + return + + var/power_used = 100000 //for 200 units of charge. Yes, thats right, 100 kW. Is something wrong with CELLRATE? + + power_used = charging.give(power_used*CELLRATE*efficiency) + use_power(power_used) + + updateicon() diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 6a9af83ace46..eb4598dec435 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -1,509 +1,509 @@ -//Cloning revival method. -//The pod handles the actual cloning while the computer manages the clone profiles - -//Potential replacement for genetics revives or something I dunno (?) - -#define CLONE_BIOMASS 150 -#define CLONE_INITIAL_DAMAGE 190 //Clones in clonepods start with 190 cloneloss damage and 190 brainloss damage, thats just logical - - -/obj/machinery/clonepod - anchored = 1 - name = "cloning pod" - desc = "An electronically-lockable pod for growing organic tissue." - density = 1 - icon = 'icons/obj/cloning.dmi' - icon_state = "pod_0" - req_access = list(access_genetics) //For premature unlocking. - allowed_checks = ALLOWED_CHECK_NONE - var/heal_level = 90 //The clone is released once its health reaches this level. - var/locked = 0 - var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine. - var/mess = 0 //Need to clean out it if it's full of exploded clone. - var/attempting = 0 //One clone attempt at a time thanks - var/eject_wait = 0 //Don't eject them as soon as they are created fuckkk - var/biomass = CLONE_BIOMASS * 3 - var/speed_coeff - var/efficiency - light_color = "#00FF00" - -/obj/machinery/clonepod/atom_init() - . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/clonepod(null) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(null) - component_parts += new /obj/item/weapon/stock_parts/scanning_module(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/weapon/stock_parts/console_screen(null) - component_parts += new /obj/item/stack/cable_coil/red(null, 1) - component_parts += new /obj/item/stack/cable_coil/red(null, 1) - RefreshParts() - -/obj/machinery/clonepod/RefreshParts() - speed_coeff = 0 - efficiency = 0 - for(var/obj/item/weapon/stock_parts/scanning_module/S in component_parts) - efficiency += S.rating - for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts) - speed_coeff += P.rating - heal_level = (efficiency * 15) + 10 - if(heal_level > 100) - heal_level = 100 - -//The return of data disks?? Just for transferring between genetics machine/cloning machine. -//TO-DO: Make the genetics machine accept them. -/obj/item/weapon/disk/data - name = "Cloning Data Disk" - icon = 'icons/obj/cloning.dmi' - icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk. - item_state = "card-id" - w_class = 2.0 - var/datum/dna2/record/buf=null - var/read_only = 0 //Well,it's still a floppy disk - -/obj/item/weapon/disk/data/proc/Initialize() - buf = new - buf.dna=new - -/obj/item/weapon/disk/data/demo - name = "data disk - 'God Emperor of Mankind'" - read_only = 1 - -/obj/item/weapon/disk/data/demo/atom_init() - . = ..() - Initialize() - buf.types=DNA2_BUF_UE|DNA2_BUF_UI - //data = "066000033000000000AF00330660FF4DB002690" - //data = "0C80C80C80C80C80C8000000000000161FBDDEF" - Farmer Jeff - buf.dna.real_name="God Emperor of Mankind" - buf.dna.unique_enzymes = md5(buf.dna.real_name) - buf.dna.UI=list(0x066,0x000,0x033,0x000,0x000,0x000,0xAF0,0x033,0x066,0x0FF,0x4DB,0x002,0x690) - //buf.dna.UI=list(0x0C8,0x0C8,0x0C8,0x0C8,0x0C8,0x0C8,0x000,0x000,0x000,0x000,0x161,0xFBD,0xDEF) // Farmer Jeff - buf.dna.UpdateUI() - -/obj/item/weapon/disk/data/monkey - name = "data disk - 'Mr. Muggles'" - read_only = 1 - -/obj/item/weapon/disk/data/monkey/atom_init() - . = ..() - Initialize() - buf.types=DNA2_BUF_SE - var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4) - for(var/i=new_SE.len;i<=DNA_SE_LENGTH;i++) - new_SE += rand(1,1024) - buf.dna.SE=new_SE - buf.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) - - -//Find a dead mob with a brain and client. -/proc/find_dead_player(find_key) - if (isnull(find_key)) - return - - var/mob/selected = null - for(var/mob/M in player_list) - //Dead people only thanks! - if ((M.stat != DEAD) || (!M.client)) - continue - //They need a brain! - if ((istype(M, /mob/living/carbon/human)) && (M:brain_op_stage >= 4.0)) - continue - - if (M.ckey == find_key) - selected = M - break - return selected - -//Disk stuff. -/obj/item/weapon/disk/data/atom_init() - . = ..() - var/diskcolor = pick(0,1,2) - src.icon_state = "datadisk[diskcolor]" - -/obj/item/weapon/disk/data/attack_self(mob/user) - src.read_only = !src.read_only - to_chat(user, "You flip the write-protect tab to [src.read_only ? "protected" : "unprotected"].") - -/obj/item/weapon/disk/data/examine(mob/user) - ..() - to_chat(user, "The write-protect tab is set to [src.read_only ? "protected" : "unprotected"].") - -//Health Tracker Implant - -/obj/item/weapon/implant/health - name = "health implant" - var/healthstring = "" - -/obj/item/weapon/implant/health/proc/sensehealth() - if (!src.implanted) - return "ERROR" - else - if(isliving(src.implanted)) - var/mob/living/L = src.implanted - src.healthstring = "[round(L.getOxyLoss())] - [round(L.getFireLoss())] - [round(L.getToxLoss())] - [round(L.getBruteLoss())]" - if (!src.healthstring) - src.healthstring = "ERROR" - return src.healthstring - -/obj/machinery/clonepod/examine(mob/user) - if(..(user, 3)) - if ((isnull(occupant)) || (stat & NOPOWER)) - return - if ((!isnull(occupant)) && (occupant.stat != DEAD)) - var/completion = (100 * ((occupant.health + 100) / (heal_level + 100))) - to_chat(user, "Current clone cycle is [round(completion)]% complete.") - -//Clonepod - -//Start growing a human clone in the pod! -/obj/machinery/clonepod/proc/growclone(datum/dna2/record/R) - if(panel_open) - return 0 - if(mess || attempting) - return 0 - var/datum/mind/clonemind = locate(R.mind) - if(!istype(clonemind,/datum/mind)) //not a mind - return 0 - if( clonemind.current && clonemind.current.stat != DEAD ) //mind is associated with a non-dead body - return 0 - if(clonemind.active) //somebody is using that mind - if( ckey(clonemind.key)!=R.ckey ) - return 0 - else - for(var/mob/dead/observer/G in player_list) - if(G.ckey == R.ckey) - if(G.can_reenter_corpse) - break - else - return 0 - - - src.attempting = 1 //One at a time!! - src.locked = 1 - - src.eject_wait = 1 - spawn(30) - src.eject_wait = 0 - - var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species) - occupant = H - - if(!R.dna.real_name) //to prevent null names - R.dna.real_name = "clone ([rand(0,999)])" - H.real_name = R.dna.real_name - - src.icon_state = "pod_1" - //Get the clone body ready - H.adjustCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health - H.adjustBrainLoss(CLONE_INITIAL_DAMAGE) - H.Paralyse(4) - - //Here let's calculate their health so the pod doesn't immediately eject them!!! - H.updatehealth() - - clonemind.transfer_to(H) - H.ckey = R.ckey - to_chat(H, "Consciousness slowly creeps over you as your body regenerates.
    So this is what cloning feels like?
    ") - - for(var/V in R.quirks) - new V(H) - - // -- Mode/mind specific stuff goes here - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if(mode) - mode.update_icon(H) - - if((H.mind in ticker.mode.revolutionaries) || (H.mind in ticker.mode.head_revolutionaries)) - ticker.mode.update_all_rev_icons() //So the icon actually appears - if((H.mind in ticker.mode.A_bosses) || ((H.mind in ticker.mode.A_gang) || (H.mind in ticker.mode.B_bosses)) || (H.mind in ticker.mode.B_gang)) - ticker.mode.update_all_gang_icons() - if(H.mind in ticker.mode.syndicates) - ticker.mode.update_all_synd_icons() - if (H.mind in ticker.mode.cult) - ticker.mode.add_cultist(src.occupant.mind) - ticker.mode.update_all_cult_icons() //So the icon actually appears - - // -- End mode specific stuff - - if(!R.dna) - H.dna = new /datum/dna() - H.dna.real_name = H.real_name - else - H.dna=R.dna - H.UpdateAppearance() - //if(efficiency > 2) - // for(var/A in bad_se_blocks) - // setblock(H.dna.struc_enzymes, A, construct_block(0,2)) - if(efficiency > 5 && prob(20)) - randmutg(H) - if(efficiency < 3 && prob(50)) - randmutb(H) - H.dna.UpdateSE() - H.dna.UpdateUI() - - H.f_style = "Shaved" - if(R.dna.species == HUMAN) //no more xenos losing ears/tentacles - H.h_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") - - for(var/datum/language/L in R.languages) - H.add_language(L.name) - H.suiciding = 0 - src.attempting = 0 - return 1 - -//Grow clones to maturity then kick them out. FREELOADERS -/obj/machinery/clonepod/process() - - if(stat & NOPOWER) //Autoeject if power is lost - if (src.occupant) - src.locked = 0 - src.go_out() - return - - if((src.occupant) && (src.occupant.loc == src)) - - if((src.occupant.stat == DEAD) || (src.occupant.suiciding) || !occupant.key) //Autoeject corpses and suiciding dudes. - src.locked = 0 - src.go_out() - src.connected_message("Clone Rejected: Deceased.") - return - - else if(src.occupant.cloneloss > (100 - src.heal_level)) - src.occupant.Paralyse(4) - - //Slowly get that clone healed and finished. - src.occupant.adjustCloneLoss(-((speed_coeff/2))) - - //Premature clones may have brain damage. - src.occupant.adjustBrainLoss(-((speed_coeff/2))) - - //So clones don't die of oxyloss in a running pod. - if (src.occupant.reagents.get_reagent_amount("inaprovaline") < 30) - src.occupant.reagents.add_reagent("inaprovaline", 60) - - //So clones will remain asleep for long enough to get them into cryo (Bay RP edit) - if (src.occupant.reagents.get_reagent_amount("stoxin") < 10) - src.occupant.reagents.add_reagent("stoxin", 5) - if (src.occupant.reagents.get_reagent_amount("chloralhydrate") < 1) - src.occupant.reagents.add_reagent("chloralhydrate", 1) - - //Also heal some oxyloss ourselves because inaprovaline is so bad at preventing it!! - src.occupant.adjustOxyLoss(-4) - - use_power(7500) //This might need tweaking. - return - - else if((src.occupant.cloneloss <= (100 - src.heal_level)) && (!src.eject_wait) || src.occupant.health >= 100) - src.connected_message("Cloning Process Complete.") - src.locked = 0 - src.go_out() - return - - else if ((!src.occupant) || (src.occupant.loc != src)) - src.occupant = null - if (src.locked) - src.locked = 0 - if (!src.mess && !panel_open) - icon_state = "pod_0" - use_power(200) - return - - return - -//Let's unlock this early I guess. Might be too early, needs tweaking. -/obj/machinery/clonepod/attackby(obj/item/weapon/W, mob/user) - if(!(occupant || mess || locked)) - if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]",W)) - return - - if(exchange_parts(user, W)) - return - - default_deconstruction_crowbar(W) - - if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) - if (!src.check_access(W)) - to_chat(user, "Access Denied.") - return - if ((!src.locked) || (isnull(src.occupant))) - return - if ((src.occupant.health < -20) && (src.occupant.stat != DEAD)) - to_chat(user, "Access Refused.") - return - else - src.locked = 0 - to_chat(user, "System unlocked.") - else if (istype(W, /obj/item/weapon/card/emag)) - if (isnull(src.occupant)) - return - user.SetNextMove(CLICK_CD_INTERACT) - to_chat(user, "You force an emergency ejection.") - src.locked = 0 - src.go_out() - return - else if (istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) - to_chat(user, "\blue \The [src] processes \the [W].") - biomass += 50 - user.drop_item() - qdel(W) - return - else - ..() - -//Put messages in the connected computer's temp var for display. -/obj/machinery/clonepod/proc/connected_message(message) - if ((isnull(src.connected)) || (!istype(src.connected, /obj/machinery/computer/cloning))) - return 0 - if (!message) - return 0 - - src.connected.temp = message - src.connected.updateUsrDialog() - return 1 - -/obj/machinery/clonepod/verb/eject() - set name = "Eject Cloner" - set category = "Object" - set src in oview(1) - - if(!usr) - return - if (usr.stat != CONSCIOUS) - return - src.go_out() - add_fingerprint(usr) - return - -/obj/machinery/clonepod/proc/go_out() - if (src.locked) - return - - if (src.mess) //Clean that mess and dump those gibs! - src.mess = 0 - gibs(src.loc) - src.icon_state = "pod_0" - - /* - for(var/obj/O in src) - O.loc = src.loc - */ - return - - if (!(src.occupant)) - 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.icon_state = "pod_0" - src.eject_wait = 0 //If it's still set somehow. - domutcheck(src.occupant) //Waiting until they're out before possible monkeyizing. -// src.occupant.add_side_effect("Bad Stomach") // Give them an extra side-effect for free. - src.occupant = null - - src.biomass -= CLONE_BIOMASS - - return - -/obj/machinery/clonepod/proc/malfunction() - if(src.occupant) - src.connected_message("Critical Error!") - src.mess = 1 - src.icon_state = "pod_g" - src.occupant.ghostize() - spawn(5) - qdel(src.occupant) - src.occupant = null - return - -/obj/machinery/clonepod/relaymove(mob/user) - if (user.stat) - return - src.go_out() - return - -/obj/machinery/clonepod/emp_act(severity) - if(prob(100/(severity*efficiency))) malfunction() - ..() - -/obj/machinery/clonepod/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 - else - return - -/* - * Diskette Box - */ - -/obj/item/weapon/storage/box/disks - name = "Diskette Box" - icon_state = "disk_box" - -/obj/item/weapon/storage/box/disks/atom_init() - . = ..() - for (var/i in 1 to 7) - new /obj/item/weapon/disk/data(src) - -/* - * Manual -- A big ol' manual. - */ - -/obj/item/weapon/paper/Cloning - name = "H-87 Cloning Apparatus Manual" - info = {"

    Getting Started

    - Congratulations, your station has purchased the H-87 industrial cloning device!
    - Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!
    - That's all there is to it!
    - Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.
    -

    Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR IMPLANT into the subject, which may be viewed from each profile. - Profile Deletion has been restricted to \[Station Head\] level access.

    -

    Cloning from a profile

    - Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.
    - Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.
    -
    -

    The provided CLONEPOD SYSTEM will produce the desired clone. Standard clone maturation times (With SPEEDCLONE technology) are roughly 90 seconds. - The cloning pod may be unlocked early with any \[Medical Researcher\] ID after initial maturation is complete.


    - Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.
    -

    Profile Management

    -

    The H-87 (as well as your station's standard genetics machine) can accept STANDARD DATA DISKETTES. - These diskettes are used to transfer genetic information between machines and profiles. - A load/save dialog will become available in each profile if a disk is inserted.


    - A good diskette is a great way to counter aforementioned genetic drift!
    -
    - This technology produced under license from Thinktronic Systems, LTD."} - -//SOME SCRAPS I GUESS -/* EMP grenade/spell effect - if(istype(A, /obj/machinery/clonepod)) - A:malfunction() -*/ - -#undef CLONE_INITIAL_DAMAGE +//Cloning revival method. +//The pod handles the actual cloning while the computer manages the clone profiles + +//Potential replacement for genetics revives or something I dunno (?) + +#define CLONE_BIOMASS 150 +#define CLONE_INITIAL_DAMAGE 190 //Clones in clonepods start with 190 cloneloss damage and 190 brainloss damage, thats just logical + + +/obj/machinery/clonepod + anchored = 1 + name = "cloning pod" + desc = "An electronically-lockable pod for growing organic tissue." + density = 1 + icon = 'icons/obj/cloning.dmi' + icon_state = "pod_0" + req_access = list(access_genetics) //For premature unlocking. + allowed_checks = ALLOWED_CHECK_NONE + var/heal_level = 90 //The clone is released once its health reaches this level. + var/locked = 0 + var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine. + var/mess = 0 //Need to clean out it if it's full of exploded clone. + var/attempting = 0 //One clone attempt at a time thanks + var/eject_wait = 0 //Don't eject them as soon as they are created fuckkk + var/biomass = CLONE_BIOMASS * 3 + var/speed_coeff + var/efficiency + light_color = "#00FF00" + +/obj/machinery/clonepod/atom_init() + . = ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/clonepod(null) + component_parts += new /obj/item/weapon/stock_parts/scanning_module(null) + component_parts += new /obj/item/weapon/stock_parts/scanning_module(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + component_parts += new /obj/item/stack/cable_coil/red(null, 1) + component_parts += new /obj/item/stack/cable_coil/red(null, 1) + RefreshParts() + +/obj/machinery/clonepod/RefreshParts() + speed_coeff = 0 + efficiency = 0 + for(var/obj/item/weapon/stock_parts/scanning_module/S in component_parts) + efficiency += S.rating + for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts) + speed_coeff += P.rating + heal_level = (efficiency * 15) + 10 + if(heal_level > 100) + heal_level = 100 + +//The return of data disks?? Just for transferring between genetics machine/cloning machine. +//TO-DO: Make the genetics machine accept them. +/obj/item/weapon/disk/data + name = "Cloning Data Disk" + icon = 'icons/obj/cloning.dmi' + icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk. + item_state = "card-id" + w_class = 2.0 + var/datum/dna2/record/buf=null + var/read_only = 0 //Well,it's still a floppy disk + +/obj/item/weapon/disk/data/proc/Initialize() + buf = new + buf.dna=new + +/obj/item/weapon/disk/data/demo + name = "data disk - 'God Emperor of Mankind'" + read_only = 1 + +/obj/item/weapon/disk/data/demo/atom_init() + . = ..() + Initialize() + buf.types=DNA2_BUF_UE|DNA2_BUF_UI + //data = "066000033000000000AF00330660FF4DB002690" + //data = "0C80C80C80C80C80C8000000000000161FBDDEF" - Farmer Jeff + buf.dna.real_name="God Emperor of Mankind" + buf.dna.unique_enzymes = md5(buf.dna.real_name) + buf.dna.UI=list(0x066,0x000,0x033,0x000,0x000,0x000,0xAF0,0x033,0x066,0x0FF,0x4DB,0x002,0x690) + //buf.dna.UI=list(0x0C8,0x0C8,0x0C8,0x0C8,0x0C8,0x0C8,0x000,0x000,0x000,0x000,0x161,0xFBD,0xDEF) // Farmer Jeff + buf.dna.UpdateUI() + +/obj/item/weapon/disk/data/monkey + name = "data disk - 'Mr. Muggles'" + read_only = 1 + +/obj/item/weapon/disk/data/monkey/atom_init() + . = ..() + Initialize() + buf.types=DNA2_BUF_SE + var/list/new_SE=list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4) + for(var/i=new_SE.len;i<=DNA_SE_LENGTH;i++) + new_SE += rand(1,1024) + buf.dna.SE=new_SE + buf.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) + + +//Find a dead mob with a brain and client. +/proc/find_dead_player(find_key) + if (isnull(find_key)) + return + + var/mob/selected = null + for(var/mob/M in player_list) + //Dead people only thanks! + if ((M.stat != DEAD) || (!M.client)) + continue + //They need a brain! + if ((istype(M, /mob/living/carbon/human)) && (M:brain_op_stage >= 4.0)) + continue + + if (M.ckey == find_key) + selected = M + break + return selected + +//Disk stuff. +/obj/item/weapon/disk/data/atom_init() + . = ..() + var/diskcolor = pick(0,1,2) + src.icon_state = "datadisk[diskcolor]" + +/obj/item/weapon/disk/data/attack_self(mob/user) + src.read_only = !src.read_only + to_chat(user, "You flip the write-protect tab to [src.read_only ? "protected" : "unprotected"].") + +/obj/item/weapon/disk/data/examine(mob/user) + ..() + to_chat(user, "The write-protect tab is set to [src.read_only ? "protected" : "unprotected"].") + +//Health Tracker Implant + +/obj/item/weapon/implant/health + name = "health implant" + var/healthstring = "" + +/obj/item/weapon/implant/health/proc/sensehealth() + if (!src.implanted) + return "ERROR" + else + if(isliving(src.implanted)) + var/mob/living/L = src.implanted + src.healthstring = "[round(L.getOxyLoss())] - [round(L.getFireLoss())] - [round(L.getToxLoss())] - [round(L.getBruteLoss())]" + if (!src.healthstring) + src.healthstring = "ERROR" + return src.healthstring + +/obj/machinery/clonepod/examine(mob/user) + if(..(user, 3)) + if ((isnull(occupant)) || (stat & NOPOWER)) + return + if ((!isnull(occupant)) && (occupant.stat != DEAD)) + var/completion = (100 * ((occupant.health + 100) / (heal_level + 100))) + to_chat(user, "Current clone cycle is [round(completion)]% complete.") + +//Clonepod + +//Start growing a human clone in the pod! +/obj/machinery/clonepod/proc/growclone(datum/dna2/record/R) + if(panel_open) + return 0 + if(mess || attempting) + return 0 + var/datum/mind/clonemind = locate(R.mind) + if(!istype(clonemind,/datum/mind)) //not a mind + return 0 + if( clonemind.current && clonemind.current.stat != DEAD ) //mind is associated with a non-dead body + return 0 + if(clonemind.active) //somebody is using that mind + if( ckey(clonemind.key)!=R.ckey ) + return 0 + else + for(var/mob/dead/observer/G in player_list) + if(G.ckey == R.ckey) + if(G.can_reenter_corpse) + break + else + return 0 + + + src.attempting = 1 //One at a time!! + src.locked = 1 + + src.eject_wait = 1 + spawn(30) + src.eject_wait = 0 + + var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species) + occupant = H + + if(!R.dna.real_name) //to prevent null names + R.dna.real_name = "clone ([rand(0,999)])" + H.real_name = R.dna.real_name + + src.icon_state = "pod_1" + //Get the clone body ready + H.adjustCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health + H.adjustBrainLoss(CLONE_INITIAL_DAMAGE) + H.Paralyse(4) + + //Here let's calculate their health so the pod doesn't immediately eject them!!! + H.updatehealth() + + clonemind.transfer_to(H) + H.ckey = R.ckey + to_chat(H, "Consciousness slowly creeps over you as your body regenerates.
    So this is what cloning feels like?
    ") + + for(var/V in R.quirks) + new V(H) + + // -- Mode/mind specific stuff goes here + var/datum/game_mode/mutiny/mode = get_mutiny_mode() + if(mode) + mode.update_icon(H) + + if((H.mind in ticker.mode.revolutionaries) || (H.mind in ticker.mode.head_revolutionaries)) + ticker.mode.update_all_rev_icons() //So the icon actually appears + if((H.mind in ticker.mode.A_bosses) || ((H.mind in ticker.mode.A_gang) || (H.mind in ticker.mode.B_bosses)) || (H.mind in ticker.mode.B_gang)) + ticker.mode.update_all_gang_icons() + if(H.mind in ticker.mode.syndicates) + ticker.mode.update_all_synd_icons() + if (H.mind in ticker.mode.cult) + ticker.mode.add_cultist(src.occupant.mind) + ticker.mode.update_all_cult_icons() //So the icon actually appears + + // -- End mode specific stuff + + if(!R.dna) + H.dna = new /datum/dna() + H.dna.real_name = H.real_name + else + H.dna=R.dna + H.UpdateAppearance() + //if(efficiency > 2) + // for(var/A in bad_se_blocks) + // setblock(H.dna.struc_enzymes, A, construct_block(0,2)) + if(efficiency > 5 && prob(20)) + randmutg(H) + if(efficiency < 3 && prob(50)) + randmutb(H) + H.dna.UpdateSE() + H.dna.UpdateUI() + + H.f_style = "Shaved" + if(R.dna.species == HUMAN) //no more xenos losing ears/tentacles + H.h_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") + + for(var/datum/language/L in R.languages) + H.add_language(L.name) + H.suiciding = 0 + src.attempting = 0 + return 1 + +//Grow clones to maturity then kick them out. FREELOADERS +/obj/machinery/clonepod/process() + + if(stat & NOPOWER) //Autoeject if power is lost + if (src.occupant) + src.locked = 0 + src.go_out() + return + + if((src.occupant) && (src.occupant.loc == src)) + + if((src.occupant.stat == DEAD) || (src.occupant.suiciding) || !occupant.key) //Autoeject corpses and suiciding dudes. + src.locked = 0 + src.go_out() + src.connected_message("Clone Rejected: Deceased.") + return + + else if(src.occupant.cloneloss > (100 - src.heal_level)) + src.occupant.Paralyse(4) + + //Slowly get that clone healed and finished. + src.occupant.adjustCloneLoss(-((speed_coeff/2))) + + //Premature clones may have brain damage. + src.occupant.adjustBrainLoss(-((speed_coeff/2))) + + //So clones don't die of oxyloss in a running pod. + if (src.occupant.reagents.get_reagent_amount("inaprovaline") < 30) + src.occupant.reagents.add_reagent("inaprovaline", 60) + + //So clones will remain asleep for long enough to get them into cryo (Bay RP edit) + if (src.occupant.reagents.get_reagent_amount("stoxin") < 10) + src.occupant.reagents.add_reagent("stoxin", 5) + if (src.occupant.reagents.get_reagent_amount("chloralhydrate") < 1) + src.occupant.reagents.add_reagent("chloralhydrate", 1) + + //Also heal some oxyloss ourselves because inaprovaline is so bad at preventing it!! + src.occupant.adjustOxyLoss(-4) + + use_power(7500) //This might need tweaking. + return + + else if((src.occupant.cloneloss <= (100 - src.heal_level)) && (!src.eject_wait) || src.occupant.health >= 100) + src.connected_message("Cloning Process Complete.") + src.locked = 0 + src.go_out() + return + + else if ((!src.occupant) || (src.occupant.loc != src)) + src.occupant = null + if (src.locked) + src.locked = 0 + if (!src.mess && !panel_open) + icon_state = "pod_0" + use_power(200) + return + + return + +//Let's unlock this early I guess. Might be too early, needs tweaking. +/obj/machinery/clonepod/attackby(obj/item/weapon/W, mob/user) + if(!(occupant || mess || locked)) + if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]",W)) + return + + if(exchange_parts(user, W)) + return + + default_deconstruction_crowbar(W) + + if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) + if (!src.check_access(W)) + to_chat(user, "Access Denied.") + return + if ((!src.locked) || (isnull(src.occupant))) + return + if ((src.occupant.health < -20) && (src.occupant.stat != DEAD)) + to_chat(user, "Access Refused.") + return + else + src.locked = 0 + to_chat(user, "System unlocked.") + else if (istype(W, /obj/item/weapon/card/emag)) + if (isnull(src.occupant)) + return + user.SetNextMove(CLICK_CD_INTERACT) + to_chat(user, "You force an emergency ejection.") + src.locked = 0 + src.go_out() + return + else if (istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) + to_chat(user, "\blue \The [src] processes \the [W].") + biomass += 50 + user.drop_item() + qdel(W) + return + else + ..() + +//Put messages in the connected computer's temp var for display. +/obj/machinery/clonepod/proc/connected_message(message) + if ((isnull(src.connected)) || (!istype(src.connected, /obj/machinery/computer/cloning))) + return 0 + if (!message) + return 0 + + src.connected.temp = message + src.connected.updateUsrDialog() + return 1 + +/obj/machinery/clonepod/verb/eject() + set name = "Eject Cloner" + set category = "Object" + set src in oview(1) + + if(!usr) + return + if (usr.stat != CONSCIOUS) + return + src.go_out() + add_fingerprint(usr) + return + +/obj/machinery/clonepod/proc/go_out() + if (src.locked) + return + + if (src.mess) //Clean that mess and dump those gibs! + src.mess = 0 + gibs(src.loc) + src.icon_state = "pod_0" + + /* + for(var/obj/O in src) + O.loc = src.loc + */ + return + + if (!(src.occupant)) + 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.icon_state = "pod_0" + src.eject_wait = 0 //If it's still set somehow. + domutcheck(src.occupant) //Waiting until they're out before possible monkeyizing. +// src.occupant.add_side_effect("Bad Stomach") // Give them an extra side-effect for free. + src.occupant = null + + src.biomass -= CLONE_BIOMASS + + return + +/obj/machinery/clonepod/proc/malfunction() + if(src.occupant) + src.connected_message("Critical Error!") + src.mess = 1 + src.icon_state = "pod_g" + src.occupant.ghostize() + spawn(5) + qdel(src.occupant) + src.occupant = null + return + +/obj/machinery/clonepod/relaymove(mob/user) + if (user.stat) + return + src.go_out() + return + +/obj/machinery/clonepod/emp_act(severity) + if(prob(100/(severity*efficiency))) malfunction() + ..() + +/obj/machinery/clonepod/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 + else + return + +/* + * Diskette Box + */ + +/obj/item/weapon/storage/box/disks + name = "Diskette Box" + icon_state = "disk_box" + +/obj/item/weapon/storage/box/disks/atom_init() + . = ..() + for (var/i in 1 to 7) + new /obj/item/weapon/disk/data(src) + +/* + * Manual -- A big ol' manual. + */ + +/obj/item/weapon/paper/Cloning + name = "H-87 Cloning Apparatus Manual" + info = {"

    Getting Started

    + Congratulations, your station has purchased the H-87 industrial cloning device!
    + Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!
    + That's all there is to it!
    + Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.
    +

    Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR IMPLANT into the subject, which may be viewed from each profile. + Profile Deletion has been restricted to \[Station Head\] level access.

    +

    Cloning from a profile

    + Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.
    + Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.
    +
    +

    The provided CLONEPOD SYSTEM will produce the desired clone. Standard clone maturation times (With SPEEDCLONE technology) are roughly 90 seconds. + The cloning pod may be unlocked early with any \[Medical Researcher\] ID after initial maturation is complete.


    + Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.
    +

    Profile Management

    +

    The H-87 (as well as your station's standard genetics machine) can accept STANDARD DATA DISKETTES. + These diskettes are used to transfer genetic information between machines and profiles. + A load/save dialog will become available in each profile if a disk is inserted.


    + A good diskette is a great way to counter aforementioned genetic drift!
    +
    + This technology produced under license from Thinktronic Systems, LTD."} + +//SOME SCRAPS I GUESS +/* EMP grenade/spell effect + if(istype(A, /obj/machinery/clonepod)) + A:malfunction() +*/ + +#undef CLONE_INITIAL_DAMAGE diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 11ebc2a37003..ab0de8fffbad 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -1,59 +1,59 @@ -//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" - light_color = "#315ab4" - circuit = /obj/item/weapon/circuitboard/operating - var/mob/living/carbon/human/victim = null - var/obj/machinery/optable/table = null - -/obj/machinery/computer/operating/atom_init() - . = ..() - for(dir in list(NORTH,EAST,SOUTH,WEST)) - table = locate(/obj/machinery/optable, get_step(src, dir)) - if (table) - table.computer = src - break - -/obj/machinery/computer/operating/ui_interact(mob/user) - if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) ) - if (!issilicon(user) && !isobserver(user)) - user.unset_machine() - user << browse(null, "window=op") - return - - var/dat = "Operating Computer\n" - dat += "Close

    " //| Update" - if(src.table && (src.table.check_victim())) - src.victim = src.table.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"]
    - Heartbeat rate: [victim.get_pulse(GETPULSE_TOOL)]
    - "} - else - src.victim = null - dat += {" - Patient Information:
    -
    - No Patient Detected - "} - user << browse(entity_ja(dat), "window=op") - onclose(user, "op") - -/obj/machinery/computer/operating/process() - if(..()) - src.updateDialog() +//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" + light_color = "#315ab4" + circuit = /obj/item/weapon/circuitboard/operating + var/mob/living/carbon/human/victim = null + var/obj/machinery/optable/table = null + +/obj/machinery/computer/operating/atom_init() + . = ..() + for(dir in list(NORTH,EAST,SOUTH,WEST)) + table = locate(/obj/machinery/optable, get_step(src, dir)) + if (table) + table.computer = src + break + +/obj/machinery/computer/operating/ui_interact(mob/user) + if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) ) + if (!issilicon(user) && !isobserver(user)) + user.unset_machine() + user << browse(null, "window=op") + return + + var/dat = "Operating Computer\n" + dat += "Close

    " //| Update" + if(src.table && (src.table.check_victim())) + src.victim = src.table.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"]
    + Heartbeat rate: [victim.get_pulse(GETPULSE_TOOL)]
    + "} + else + src.victim = null + dat += {" + Patient Information:
    +
    + No Patient Detected + "} + user << browse(entity_ja(dat), "window=op") + onclose(user, "op") + +/obj/machinery/computer/operating/process() + if(..()) + src.updateDialog() diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index 01d9788a9772..b9c4967c628e 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -1,115 +1,115 @@ -/obj/machinery/computer/aifixer - name = "AI System Integrity Restorer" - icon = 'icons/obj/computer.dmi' - icon_state = "ai-fixer" - light_color = "#a97faa" - circuit = /obj/item/weapon/circuitboard/aifixer - req_access = list(access_captain, access_robotics, access_heads) - var/mob/living/silicon/ai/occupier = null - var/active = 0 - circuit = /obj/item/weapon/circuitboard/aifixer - -/obj/machinery/computer/aifixer/atom_init() - overlays += image('icons/obj/computer.dmi', "ai-fixer-empty") - . = ..() - -/obj/machinery/computer/aifixer/attackby(I, user) - 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 - var/obj/item/device/aicard/AIcard = I - AIcard.transfer_ai("AIFIXER", "AICARD", src, user) - else - ..() - return - -/obj/machinery/computer/aifixer/ui_interact(mob/user) - var/dat = "

    AI System Integrity Restorer



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

    Begin Reconstruction"} - else - dat += "

    Reconstruction in process, please wait.
    " - dat += {" Close"} - - user << browse(entity_ja(dat), "window=computer;size=400x500") - onclose(user, "computer") - -/obj/machinery/computer/aifixer/process() - if(..()) - src.updateDialog() - 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.occupier.health < 100) - src.occupier.adjustOxyLoss(-1) - src.occupier.adjustFireLoss(-1) - src.occupier.adjustToxLoss(-1) - src.occupier.adjustBruteLoss(-1) - src.occupier.updatehealth() - if (src.occupier.health >= 0 && src.occupier.stat == DEAD) - src.occupier.stat = CONSCIOUS - src.occupier.lying = 0 - dead_mob_list -= src.occupier - alive_mob_list += src.occupier - src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-404") - src.overlays += image('icons/obj/computer.dmi', "ai-fixer-full") - src.occupier.add_ai_verbs() - src.updateUsrDialog() - sleep(10) - src.active = 0 - src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-on") - - src.updateUsrDialog() - - -/obj/machinery/computer/aifixer/update_icon() - ..() - // Broken / Unpowered - if((stat & BROKEN) || (stat & NOPOWER)) - overlays.Cut() - - // Working / Powered - else - if (occupier) - switch (occupier.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") +/obj/machinery/computer/aifixer + name = "AI System Integrity Restorer" + icon = 'icons/obj/computer.dmi' + icon_state = "ai-fixer" + light_color = "#a97faa" + circuit = /obj/item/weapon/circuitboard/aifixer + req_access = list(access_captain, access_robotics, access_heads) + var/mob/living/silicon/ai/occupier = null + var/active = 0 + circuit = /obj/item/weapon/circuitboard/aifixer + +/obj/machinery/computer/aifixer/atom_init() + overlays += image('icons/obj/computer.dmi', "ai-fixer-empty") + . = ..() + +/obj/machinery/computer/aifixer/attackby(I, user) + 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 + var/obj/item/device/aicard/AIcard = I + AIcard.transfer_ai("AIFIXER", "AICARD", src, user) + else + ..() + return + +/obj/machinery/computer/aifixer/ui_interact(mob/user) + var/dat = "

    AI System Integrity Restorer



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

    Begin Reconstruction"} + else + dat += "

    Reconstruction in process, please wait.
    " + dat += {" Close"} + + user << browse(entity_ja(dat), "window=computer;size=400x500") + onclose(user, "computer") + +/obj/machinery/computer/aifixer/process() + if(..()) + src.updateDialog() + 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.occupier.health < 100) + src.occupier.adjustOxyLoss(-1) + src.occupier.adjustFireLoss(-1) + src.occupier.adjustToxLoss(-1) + src.occupier.adjustBruteLoss(-1) + src.occupier.updatehealth() + if (src.occupier.health >= 0 && src.occupier.stat == DEAD) + src.occupier.stat = CONSCIOUS + src.occupier.lying = 0 + dead_mob_list -= src.occupier + alive_mob_list += src.occupier + src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-404") + src.overlays += image('icons/obj/computer.dmi', "ai-fixer-full") + src.occupier.add_ai_verbs() + src.updateUsrDialog() + sleep(10) + src.active = 0 + src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-on") + + src.updateUsrDialog() + + +/obj/machinery/computer/aifixer/update_icon() + ..() + // Broken / Unpowered + if((stat & BROKEN) || (stat & NOPOWER)) + overlays.Cut() + + // Working / Powered + else + if (occupier) + switch (occupier.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 8096a014e782..c3930501b788 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -1,337 +1,337 @@ -/obj/machinery/computer/arcade - name = "arcade machine" - desc = "Does not support Pin ball." - icon = 'icons/obj/computer.dmi' - icon_state = "arcade" - circuit = /obj/item/weapon/circuitboard/arcade - 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 - var/list/prizes = list( /obj/item/weapon/storage/box/snappops = 2, - /obj/item/toy/blink = 2, - /obj/item/clothing/under/syndicate/tacticool = 2, - /obj/item/toy/sword = 2, - /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/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/item/toy/waterflower = 1, - /obj/item/toy/nuke = 1, - /obj/item/toy/minimeteor = 2, - /obj/item/toy/carpplushie = 2, - /obj/item/toy/owl = 2, - /obj/item/toy/griffin = 2, - /obj/item/toy/figure/cmo = 1, - /obj/item/toy/figure/assistant = 1, - /obj/item/toy/figure/atmos = 1, - /obj/item/toy/figure/bartender = 1, - /obj/item/toy/figure/borg = 1, - /obj/item/toy/figure/botanist = 1, - /obj/item/toy/figure/captain = 1, - /obj/item/toy/figure/cargotech = 1, - /obj/item/toy/figure/ce = 1, - /obj/item/toy/figure/chaplain = 1, - /obj/item/toy/figure/chef = 1, - /obj/item/toy/figure/chemist = 1, - /obj/item/toy/figure/clown = 1, - /obj/item/toy/figure/ian = 1, - /obj/item/toy/figure/detective = 1, - /obj/item/toy/figure/dsquad = 1, - /obj/item/toy/figure/engineer = 1, - /obj/item/toy/figure/geneticist = 1, - /obj/item/toy/figure/hop = 1, - /obj/item/toy/figure/hos = 1, - /obj/item/toy/figure/qm = 1, - /obj/item/toy/figure/janitor = 1, - /obj/item/toy/figure/lawyer = 1, - /obj/item/toy/figure/librarian = 1, - /obj/item/toy/figure/md = 1, - /obj/item/toy/figure/mime = 1, - /obj/item/toy/figure/ninja = 1, - /obj/item/toy/figure/wizard = 1, - /obj/item/toy/figure/rd = 1, - /obj/item/toy/figure/roboticist = 1, - /obj/item/toy/figure/scientist = 1, - /obj/item/toy/figure/syndie = 1, - /obj/item/toy/figure/secofficer = 1, - /obj/item/toy/figure/virologist = 1, - /obj/item/toy/figure/warden = 1, - /obj/item/toy/prize/poly/polyclassic = 1, - /obj/item/toy/prize/poly/polypink = 1, - /obj/item/toy/prize/poly/polydark = 1, - /obj/item/toy/prize/poly/polywhite = 1, - /obj/item/toy/prize/poly/polyalien = 1, - /obj/item/toy/prize/poly/polyjungle = 1, - /obj/item/toy/prize/poly/polyfury = 1, - /obj/item/toy/prize/poly/polysky = 1, - /obj/item/toy/prize/poly/polysec = 1, - /obj/item/toy/prize/poly/polycompanion = 1, - /obj/item/toy/prize/poly/polygold = 1, - /obj/item/toy/prize/poly/polyspecial = 1, - /obj/item/toy/eight_ball = 3, - /obj/item/toy/eight_ball/conch = 2, - /obj/item/toy/carpplushie = 1, - /obj/item/toy/carpplushie = 1, - /obj/item/toy/carpplushie = 1, - /obj/item/toy/carpplushie = 1, - /obj/item/toy/carpplushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1, - /obj/random/plushie = 1 - ) - - light_color = "#00ff00" - -/obj/machinery/computer/arcade - var/turtle = 0 - -/obj/machinery/computer/arcade/atom_init() - . = ..() - 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") - - enemy_name = replacetext((name_part1 + name_part2), "the ", "") - name = (name_action + name_part1 + name_part2) - -/obj/machinery/computer/arcade/ui_interact(mob/user) - var/dat = "Close" - - 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 += "
    " - - user << browse(entity_ja(dat), "window=arcade") - onclose(user, "arcade") - -/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.updateUsrDialog() - -/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) - message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb. (JMP)") - 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/attackby(I, user) - if(istype(I, /obj/item/weapon/card/emag) && !emagged) - 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() - else - ..() - return - -/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 + name = "arcade machine" + desc = "Does not support Pin ball." + icon = 'icons/obj/computer.dmi' + icon_state = "arcade" + circuit = /obj/item/weapon/circuitboard/arcade + 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 + var/list/prizes = list( /obj/item/weapon/storage/box/snappops = 2, + /obj/item/toy/blink = 2, + /obj/item/clothing/under/syndicate/tacticool = 2, + /obj/item/toy/sword = 2, + /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/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/item/toy/waterflower = 1, + /obj/item/toy/nuke = 1, + /obj/item/toy/minimeteor = 2, + /obj/item/toy/carpplushie = 2, + /obj/item/toy/owl = 2, + /obj/item/toy/griffin = 2, + /obj/item/toy/figure/cmo = 1, + /obj/item/toy/figure/assistant = 1, + /obj/item/toy/figure/atmos = 1, + /obj/item/toy/figure/bartender = 1, + /obj/item/toy/figure/borg = 1, + /obj/item/toy/figure/botanist = 1, + /obj/item/toy/figure/captain = 1, + /obj/item/toy/figure/cargotech = 1, + /obj/item/toy/figure/ce = 1, + /obj/item/toy/figure/chaplain = 1, + /obj/item/toy/figure/chef = 1, + /obj/item/toy/figure/chemist = 1, + /obj/item/toy/figure/clown = 1, + /obj/item/toy/figure/ian = 1, + /obj/item/toy/figure/detective = 1, + /obj/item/toy/figure/dsquad = 1, + /obj/item/toy/figure/engineer = 1, + /obj/item/toy/figure/geneticist = 1, + /obj/item/toy/figure/hop = 1, + /obj/item/toy/figure/hos = 1, + /obj/item/toy/figure/qm = 1, + /obj/item/toy/figure/janitor = 1, + /obj/item/toy/figure/lawyer = 1, + /obj/item/toy/figure/librarian = 1, + /obj/item/toy/figure/md = 1, + /obj/item/toy/figure/mime = 1, + /obj/item/toy/figure/ninja = 1, + /obj/item/toy/figure/wizard = 1, + /obj/item/toy/figure/rd = 1, + /obj/item/toy/figure/roboticist = 1, + /obj/item/toy/figure/scientist = 1, + /obj/item/toy/figure/syndie = 1, + /obj/item/toy/figure/secofficer = 1, + /obj/item/toy/figure/virologist = 1, + /obj/item/toy/figure/warden = 1, + /obj/item/toy/prize/poly/polyclassic = 1, + /obj/item/toy/prize/poly/polypink = 1, + /obj/item/toy/prize/poly/polydark = 1, + /obj/item/toy/prize/poly/polywhite = 1, + /obj/item/toy/prize/poly/polyalien = 1, + /obj/item/toy/prize/poly/polyjungle = 1, + /obj/item/toy/prize/poly/polyfury = 1, + /obj/item/toy/prize/poly/polysky = 1, + /obj/item/toy/prize/poly/polysec = 1, + /obj/item/toy/prize/poly/polycompanion = 1, + /obj/item/toy/prize/poly/polygold = 1, + /obj/item/toy/prize/poly/polyspecial = 1, + /obj/item/toy/eight_ball = 3, + /obj/item/toy/eight_ball/conch = 2, + /obj/item/toy/carpplushie = 1, + /obj/item/toy/carpplushie = 1, + /obj/item/toy/carpplushie = 1, + /obj/item/toy/carpplushie = 1, + /obj/item/toy/carpplushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1, + /obj/random/plushie = 1 + ) + + light_color = "#00ff00" + +/obj/machinery/computer/arcade + var/turtle = 0 + +/obj/machinery/computer/arcade/atom_init() + . = ..() + 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") + + enemy_name = replacetext((name_part1 + name_part2), "the ", "") + name = (name_action + name_part1 + name_part2) + +/obj/machinery/computer/arcade/ui_interact(mob/user) + var/dat = "Close" + + 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 += "
    " + + user << browse(entity_ja(dat), "window=arcade") + onclose(user, "arcade") + +/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.updateUsrDialog() + +/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) + message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb. (JMP)") + 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/attackby(I, user) + if(istype(I, /obj/item/weapon/card/emag) && !emagged) + 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() + else + ..() + return + +/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) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 0940e8d7e557..7ef7005997c9 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -1,476 +1,476 @@ -//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/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 = "electronic" - origin_tech = "programming=2" - var/id = 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/turbine_computer - name = "circuit board (Turbine Computer)" - build_path = /obj/machinery/computer/turbine_computer - origin_tech = "programming=4;engineering=4;power=4" -/obj/item/weapon/circuitboard/telesci_console - name = "circuit board (Telescience Console)" - build_path = /obj/machinery/computer/telescience - origin_tech = "programming=3;bluespace=2" -/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 - var/network = list("SS13") - req_access = list(access_security) - var/locked = 1 - var/emagged = 0 -/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" - var/cooldown = 0 - -/obj/item/weapon/circuitboard/communications/atom_init() - . = ..() - circuitboard_communications_list += src - START_PROCESSING(SSobj, src) - -/obj/item/weapon/circuitboard/communications/Destroy() - circuitboard_communications_list -= src - - for(var/obj/machinery/computer/communications/commconsole in communications_list) - if(istype(commconsole.loc,/turf)) - return ..() - - for(var/obj/item/weapon/circuitboard/communications/commboard in circuitboard_communications_list) - if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage))) - return ..() - - for(var/mob/living/silicon/ai/shuttlecaller in ai_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 ..() - - SSshuttle.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.") - captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - world << sound('sound/AI/shuttlecalled.ogg') - - return ..() - -/obj/item/weapon/circuitboard/communications/process() - cooldown = max(cooldown - 1, 0) - -/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/skills - name = "Circuit board (Employment Records)" - build_path = /obj/machinery/computer/skills -/obj/item/weapon/circuitboard/stationalert - name = "Circuit board (Station Alerts)" - build_path = /obj/machinery/computer/station_alert -/obj/item/weapon/circuitboard/air_management - name = "Circuit board (Atmospheric monitor)" - build_path = /obj/machinery/computer/general_air_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/robotics - name = "Circuit board (Robotics Control)" - build_path = /obj/machinery/computer/robotics - origin_tech = "programming=3" -/obj/item/weapon/circuitboard/drone_control - name = "Circuit board (Drone Control)" - build_path = /obj/machinery/computer/drone_control - origin_tech = "programming=3" -/obj/item/weapon/circuitboard/cloning - name = "Circuit board (Cloning)" - build_path = /obj/machinery/computer/cloning - 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" -/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/computer/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 (RD Console)" - build_path = /obj/machinery/computer/rdconsole/core -/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/computer/cargo/request - name = "Circuit board (Supply ordering console)" - build_path = /obj/machinery/computer/cargo/request - origin_tech = "programming=2" -/obj/item/weapon/circuitboard/computer/cargo - name = "Circuit board (Supply shuttle console)" - build_path = /obj/machinery/computer/cargo - origin_tech = "programming=3" - var/contraband_enabled = FALSE - var/hacked = FALSE -/obj/item/weapon/circuitboard/computer/stockexchange - name = "Circuit board (Stock exchange computer)" - build_path = /obj/machinery/computer/stockexchange - origin_tech = "programming=3" -/*/obj/item/weapon/circuitboard/research_shuttle - name = "Circuit board (Research Shuttle)" - build_path = /obj/machinery/computer/research_shuttle - origin_tech = "programming=2"*/ -/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/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/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 - -/*/obj/item/weapon/circuitboard/mining_shuttle - name = "Circuit board (Mining Shuttle)" - build_path = /obj/machinery/computer/mining_shuttle - origin_tech = "programming=2"*/ - -/obj/item/weapon/circuitboard/mine_sci_shuttle - name = "Circuit board (Mining Shuttle)" - build_path = /obj/machinery/computer/mine_sci_shuttle - origin_tech = "programming=2" - -/obj/item/weapon/circuitboard/mine_sci_shuttle/flight_comp - name = "Circuit board (Mining Shuttle flight computer)" - build_path = /obj/machinery/computer/mine_sci_shuttle/flight_comp - origin_tech = "programming=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/libraryconsole - name = "circuit board (Library Visitor Console)" - build_path = /obj/machinery/computer/libraryconsole - origin_tech = "programming=1" - - -/obj/item/weapon/circuitboard/computer/cargo/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/card/emag) && !hacked) - to_chat(user, "\blue Special supplies unlocked.") - hacked = TRUE - contraband_enabled = TRUE - return - else if(istype(I,/obj/item/device/multitool)) - var/catastasis = src.contraband_enabled - var/opposite_catastasis - if(catastasis) - opposite_catastasis = "STANDARD" - catastasis = "BROAD" - else - opposite_catastasis = "BROAD" - catastasis = "STANDARD" - - switch( alert("Current receiver spectrum is set to: [catastasis]","Multitool-Circuitboard interface","Switch to [opposite_catastasis]","Cancel") ) - //switch( alert("Current receiver spectrum is set to: " {(src.contraband_enabled) ? ("BROAD") : ("STANDARD")} , "Multitool-Circuitboard interface" , "Switch to " {(src.contraband_enabled) ? ("STANDARD") : ("BROAD")}, "Cancel") ) - if("Switch to STANDARD","Switch to BROAD") - src.contraband_enabled = !src.contraband_enabled - - if("Cancel") - return - else - to_chat(user, "DERP! BUG! Report this (And what you were doing to cause it) to Agouri") - return - -/obj/item/weapon/circuitboard/libraryconsole/attackby(obj/item/I, mob/user) - if(istype(I,/obj/item/weapon/screwdriver)) - if(build_path == /obj/machinery/computer/libraryconsole/bookmanagement) - name = "circuit board (Library Visitor Console)" - build_path = /obj/machinery/computer/libraryconsole - to_chat(user, "Defaulting access protocols.") - else - name = "circuit board (Book Inventory Management Console)" - build_path = /obj/machinery/computer/libraryconsole/bookmanagement - to_chat(user, "Access protocols successfully updated.") - return - -/obj/item/weapon/circuitboard/security/attackby(obj/item/I, mob/user) - if(istype(I,/obj/item/weapon/card/emag)) - if(emagged) - to_chat(user, "Circuit lock is already removed.") - return - to_chat(user, "\blue You override the circuit lock and open controls.") - emagged = 1 - locked = 0 - else if(istype(I,/obj/item/weapon/card/id)) - if(emagged) - to_chat(user, "\red Circuit lock does not respond.") - return - if(check_access(I)) - locked = !locked - to_chat(user, "\blue You [locked ? "" : "un"]lock the circuit controls.") - else - to_chat(user, "\red Access denied.") - else if(istype(I,/obj/item/device/multitool)) - if(locked) - to_chat(user, "\red Circuit controls are locked.") - return - var/existing_networks = jointext(network,",") - var/input = sanitize_safe(input(usr, "Which networks would you like to connect this camera console circuit to? Seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Multitool-Circuitboard interface", input_default(existing_networks)), MAX_LNAME_LEN) - if(!input) - to_chat(usr, "No input found please hang up and try your call again.") - return - var/list/tempnetwork = splittext(input, ",") - tempnetwork = difflist(tempnetwork,RESTRICTED_CAMERA_NETWORKS,1) - if(tempnetwork.len < 1) - to_chat(usr, "No network found please hang up and try your call again.") - return - network = tempnetwork - return - -/obj/item/weapon/circuitboard/rdconsole/attackby(obj/item/I, mob/user) - if(istype(I,/obj/item/weapon/screwdriver)) - user.visible_message("\blue \the [user] adjusts the jumper on the [src]'s access protocol pins.", "\blue You adjust the jumper on the access protocol pins.") - switch(src.build_path) - - if(/obj/machinery/computer/rdconsole/core) - src.name = "Circuit Board (RD Console - Robotics)" - src.build_path = /obj/machinery/computer/rdconsole/robotics - to_chat(user, "\blue Access protocols set to robotics.") - - if(/obj/machinery/computer/rdconsole/robotics) - src.name = "Circuit Board (RD Console - Mining)" - src.build_path = /obj/machinery/computer/rdconsole/mining - to_chat(user, "\blue Access protocols set to mining.") - - if(/obj/machinery/computer/rdconsole/mining) - src.name = "Circuit Board (RD Console)" - src.build_path = /obj/machinery/computer/rdconsole/core - to_chat(user, "\blue Access protocols set to default.") - - /*if(src.build_path == /obj/machinery/computer/rdconsole/core) - src.name = "Circuit Board (RD Console - Robotics)" - src.build_path = /obj/machinery/computer/rdconsole/robotics - to_chat(user, "\blue Access protocols set to robotics.") - else - src.name = "Circuit Board (RD Console)" - src.build_path = /obj/machinery/computer/rdconsole/core - to_chat(user, "\blue Access protocols set to default.")*/ - return - -/obj/structure/computerframe/attackby(obj/item/P, mob/user) - switch(state) - if(0) - if(istype(P, /obj/item/weapon/wrench)) - if(user.is_busy(src)) return - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, 20, target = src)) - to_chat(user, "\blue You wrench the frame into place.") - src.anchored = 1 - src.state = 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 - if(user.is_busy(src)) return - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) - if(do_after(user, 20, target = src)) - if(!src || !WT.isOn()) return - to_chat(user, "\blue You deconstruct the frame.") - new /obj/item/stack/sheet/metal( src.loc, 5 ) - qdel(src) - if(1) - if(istype(P, /obj/item/weapon/wrench)) - if(user.is_busy(src)) return - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, 20, target = src)) - to_chat(user, "\blue You unfasten the frame.") - src.anchored = 0 - src.state = 0 - if(istype(P, /obj/item/weapon/circuitboard) && !circuit) - var/obj/item/weapon/circuitboard/B = P - if(B.board_type == "computer") - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - to_chat(user, "\blue You place the circuit board inside the frame.") - icon_state = "1" - circuit = P - user.drop_item() - circuit.add_fingerprint(user) - P.loc = null - else - to_chat(user, "\red This frame does not accept circuit boards of this type!") - if(istype(P, /obj/item/weapon/screwdriver) && circuit) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "\blue You screw the circuit board into place.") - src.state = 2 - src.icon_state = "2" - if(istype(P, /obj/item/weapon/crowbar) && circuit) - playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) - to_chat(user, "\blue You remove the circuit board.") - src.state = 1 - src.icon_state = "0" - circuit.loc = src.loc - src.circuit = null - if(2) - if(istype(P, /obj/item/weapon/screwdriver) && circuit) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "\blue You unfasten the circuit board.") - src.state = 1 - src.icon_state = "1" - if(istype(P, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = P - if(C.get_amount() >= 5) - if(user.is_busy(src)) return - playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, 20, target = src)) - if(C.use(5)) - to_chat(user, "\blue 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) - to_chat(user, "\blue You remove the cables.") - src.state = 2 - src.icon_state = "2" - new /obj/item/stack/cable_coil/random(loc, 5) - - if(istype(P, /obj/item/stack/sheet/glass)) - var/obj/item/stack/sheet/glass/G = P - if(G.get_amount() >= 2) - if(user.is_busy(src)) return - playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, 20, target = src)) - if(G.use(2)) - to_chat(user, "\blue 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) - to_chat(user, "\blue You remove the glass panel.") - src.state = 3 - src.icon_state = "3" - new /obj/item/stack/sheet/glass( src.loc, 2 ) - if(istype(P, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "\blue You connect the monitor.") - new src.circuit.build_path (src.loc, circuit) - qdel(src) +//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/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 = "electronic" + origin_tech = "programming=2" + var/id = 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/turbine_computer + name = "circuit board (Turbine Computer)" + build_path = /obj/machinery/computer/turbine_computer + origin_tech = "programming=4;engineering=4;power=4" +/obj/item/weapon/circuitboard/telesci_console + name = "circuit board (Telescience Console)" + build_path = /obj/machinery/computer/telescience + origin_tech = "programming=3;bluespace=2" +/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 + var/network = list("SS13") + req_access = list(access_security) + var/locked = 1 + var/emagged = 0 +/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" + var/cooldown = 0 + +/obj/item/weapon/circuitboard/communications/atom_init() + . = ..() + circuitboard_communications_list += src + START_PROCESSING(SSobj, src) + +/obj/item/weapon/circuitboard/communications/Destroy() + circuitboard_communications_list -= src + + for(var/obj/machinery/computer/communications/commconsole in communications_list) + if(istype(commconsole.loc,/turf)) + return ..() + + for(var/obj/item/weapon/circuitboard/communications/commboard in circuitboard_communications_list) + if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage))) + return ..() + + for(var/mob/living/silicon/ai/shuttlecaller in ai_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 ..() + + SSshuttle.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.") + captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + world << sound('sound/AI/shuttlecalled.ogg') + + return ..() + +/obj/item/weapon/circuitboard/communications/process() + cooldown = max(cooldown - 1, 0) + +/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/skills + name = "Circuit board (Employment Records)" + build_path = /obj/machinery/computer/skills +/obj/item/weapon/circuitboard/stationalert + name = "Circuit board (Station Alerts)" + build_path = /obj/machinery/computer/station_alert +/obj/item/weapon/circuitboard/air_management + name = "Circuit board (Atmospheric monitor)" + build_path = /obj/machinery/computer/general_air_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/robotics + name = "Circuit board (Robotics Control)" + build_path = /obj/machinery/computer/robotics + origin_tech = "programming=3" +/obj/item/weapon/circuitboard/drone_control + name = "Circuit board (Drone Control)" + build_path = /obj/machinery/computer/drone_control + origin_tech = "programming=3" +/obj/item/weapon/circuitboard/cloning + name = "Circuit board (Cloning)" + build_path = /obj/machinery/computer/cloning + 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" +/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/computer/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 (RD Console)" + build_path = /obj/machinery/computer/rdconsole/core +/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/computer/cargo/request + name = "Circuit board (Supply ordering console)" + build_path = /obj/machinery/computer/cargo/request + origin_tech = "programming=2" +/obj/item/weapon/circuitboard/computer/cargo + name = "Circuit board (Supply shuttle console)" + build_path = /obj/machinery/computer/cargo + origin_tech = "programming=3" + var/contraband_enabled = FALSE + var/hacked = FALSE +/obj/item/weapon/circuitboard/computer/stockexchange + name = "Circuit board (Stock exchange computer)" + build_path = /obj/machinery/computer/stockexchange + origin_tech = "programming=3" +/*/obj/item/weapon/circuitboard/research_shuttle + name = "Circuit board (Research Shuttle)" + build_path = /obj/machinery/computer/research_shuttle + origin_tech = "programming=2"*/ +/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/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/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 + +/*/obj/item/weapon/circuitboard/mining_shuttle + name = "Circuit board (Mining Shuttle)" + build_path = /obj/machinery/computer/mining_shuttle + origin_tech = "programming=2"*/ + +/obj/item/weapon/circuitboard/mine_sci_shuttle + name = "Circuit board (Mining Shuttle)" + build_path = /obj/machinery/computer/mine_sci_shuttle + origin_tech = "programming=2" + +/obj/item/weapon/circuitboard/mine_sci_shuttle/flight_comp + name = "Circuit board (Mining Shuttle flight computer)" + build_path = /obj/machinery/computer/mine_sci_shuttle/flight_comp + origin_tech = "programming=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/libraryconsole + name = "circuit board (Library Visitor Console)" + build_path = /obj/machinery/computer/libraryconsole + origin_tech = "programming=1" + + +/obj/item/weapon/circuitboard/computer/cargo/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/card/emag) && !hacked) + to_chat(user, "\blue Special supplies unlocked.") + hacked = TRUE + contraband_enabled = TRUE + return + else if(istype(I,/obj/item/device/multitool)) + var/catastasis = src.contraband_enabled + var/opposite_catastasis + if(catastasis) + opposite_catastasis = "STANDARD" + catastasis = "BROAD" + else + opposite_catastasis = "BROAD" + catastasis = "STANDARD" + + switch( alert("Current receiver spectrum is set to: [catastasis]","Multitool-Circuitboard interface","Switch to [opposite_catastasis]","Cancel") ) + //switch( alert("Current receiver spectrum is set to: " {(src.contraband_enabled) ? ("BROAD") : ("STANDARD")} , "Multitool-Circuitboard interface" , "Switch to " {(src.contraband_enabled) ? ("STANDARD") : ("BROAD")}, "Cancel") ) + if("Switch to STANDARD","Switch to BROAD") + src.contraband_enabled = !src.contraband_enabled + + if("Cancel") + return + else + to_chat(user, "DERP! BUG! Report this (And what you were doing to cause it) to Agouri") + return + +/obj/item/weapon/circuitboard/libraryconsole/attackby(obj/item/I, mob/user) + if(istype(I,/obj/item/weapon/screwdriver)) + if(build_path == /obj/machinery/computer/libraryconsole/bookmanagement) + name = "circuit board (Library Visitor Console)" + build_path = /obj/machinery/computer/libraryconsole + to_chat(user, "Defaulting access protocols.") + else + name = "circuit board (Book Inventory Management Console)" + build_path = /obj/machinery/computer/libraryconsole/bookmanagement + to_chat(user, "Access protocols successfully updated.") + return + +/obj/item/weapon/circuitboard/security/attackby(obj/item/I, mob/user) + if(istype(I,/obj/item/weapon/card/emag)) + if(emagged) + to_chat(user, "Circuit lock is already removed.") + return + to_chat(user, "\blue You override the circuit lock and open controls.") + emagged = 1 + locked = 0 + else if(istype(I,/obj/item/weapon/card/id)) + if(emagged) + to_chat(user, "\red Circuit lock does not respond.") + return + if(check_access(I)) + locked = !locked + to_chat(user, "\blue You [locked ? "" : "un"]lock the circuit controls.") + else + to_chat(user, "\red Access denied.") + else if(istype(I,/obj/item/device/multitool)) + if(locked) + to_chat(user, "\red Circuit controls are locked.") + return + var/existing_networks = jointext(network,",") + var/input = sanitize_safe(input(usr, "Which networks would you like to connect this camera console circuit to? Seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Multitool-Circuitboard interface", input_default(existing_networks)), MAX_LNAME_LEN) + if(!input) + to_chat(usr, "No input found please hang up and try your call again.") + return + var/list/tempnetwork = splittext(input, ",") + tempnetwork = difflist(tempnetwork,RESTRICTED_CAMERA_NETWORKS,1) + if(tempnetwork.len < 1) + to_chat(usr, "No network found please hang up and try your call again.") + return + network = tempnetwork + return + +/obj/item/weapon/circuitboard/rdconsole/attackby(obj/item/I, mob/user) + if(istype(I,/obj/item/weapon/screwdriver)) + user.visible_message("\blue \the [user] adjusts the jumper on the [src]'s access protocol pins.", "\blue You adjust the jumper on the access protocol pins.") + switch(src.build_path) + + if(/obj/machinery/computer/rdconsole/core) + src.name = "Circuit Board (RD Console - Robotics)" + src.build_path = /obj/machinery/computer/rdconsole/robotics + to_chat(user, "\blue Access protocols set to robotics.") + + if(/obj/machinery/computer/rdconsole/robotics) + src.name = "Circuit Board (RD Console - Mining)" + src.build_path = /obj/machinery/computer/rdconsole/mining + to_chat(user, "\blue Access protocols set to mining.") + + if(/obj/machinery/computer/rdconsole/mining) + src.name = "Circuit Board (RD Console)" + src.build_path = /obj/machinery/computer/rdconsole/core + to_chat(user, "\blue Access protocols set to default.") + + /*if(src.build_path == /obj/machinery/computer/rdconsole/core) + src.name = "Circuit Board (RD Console - Robotics)" + src.build_path = /obj/machinery/computer/rdconsole/robotics + to_chat(user, "\blue Access protocols set to robotics.") + else + src.name = "Circuit Board (RD Console)" + src.build_path = /obj/machinery/computer/rdconsole/core + to_chat(user, "\blue Access protocols set to default.")*/ + return + +/obj/structure/computerframe/attackby(obj/item/P, mob/user) + switch(state) + if(0) + if(istype(P, /obj/item/weapon/wrench)) + if(user.is_busy(src)) return + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, 20, target = src)) + to_chat(user, "\blue You wrench the frame into place.") + src.anchored = 1 + src.state = 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 + if(user.is_busy(src)) return + playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + if(do_after(user, 20, target = src)) + if(!src || !WT.isOn()) return + to_chat(user, "\blue You deconstruct the frame.") + new /obj/item/stack/sheet/metal( src.loc, 5 ) + qdel(src) + if(1) + if(istype(P, /obj/item/weapon/wrench)) + if(user.is_busy(src)) return + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, 20, target = src)) + to_chat(user, "\blue You unfasten the frame.") + src.anchored = 0 + src.state = 0 + if(istype(P, /obj/item/weapon/circuitboard) && !circuit) + var/obj/item/weapon/circuitboard/B = P + if(B.board_type == "computer") + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "\blue You place the circuit board inside the frame.") + icon_state = "1" + circuit = P + user.drop_item() + circuit.add_fingerprint(user) + P.loc = null + else + to_chat(user, "\red This frame does not accept circuit boards of this type!") + if(istype(P, /obj/item/weapon/screwdriver) && circuit) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "\blue You screw the circuit board into place.") + src.state = 2 + src.icon_state = "2" + if(istype(P, /obj/item/weapon/crowbar) && circuit) + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + to_chat(user, "\blue You remove the circuit board.") + src.state = 1 + src.icon_state = "0" + circuit.loc = src.loc + src.circuit = null + if(2) + if(istype(P, /obj/item/weapon/screwdriver) && circuit) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "\blue You unfasten the circuit board.") + src.state = 1 + src.icon_state = "1" + if(istype(P, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = P + if(C.get_amount() >= 5) + if(user.is_busy(src)) return + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, 20, target = src)) + if(C.use(5)) + to_chat(user, "\blue 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) + to_chat(user, "\blue You remove the cables.") + src.state = 2 + src.icon_state = "2" + new /obj/item/stack/cable_coil/random(loc, 5) + + if(istype(P, /obj/item/stack/sheet/glass)) + var/obj/item/stack/sheet/glass/G = P + if(G.get_amount() >= 2) + if(user.is_busy(src)) return + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) + if(do_after(user, 20, target = src)) + if(G.use(2)) + to_chat(user, "\blue 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) + to_chat(user, "\blue You remove the glass panel.") + src.state = 3 + src.icon_state = "3" + new /obj/item/stack/sheet/glass( src.loc, 2 ) + if(istype(P, /obj/item/weapon/screwdriver)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "\blue You connect the monitor.") + new src.circuit.build_path (src.loc, circuit) + qdel(src) diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 1fec2d8a11f8..8af4ae431b86 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -1,261 +1,261 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/proc/invalidateCameraCache() - for(var/obj/machinery/computer/security/s in computer_list) - s.camera_cache = null - for(var/datum/alarm/A in datum_alarm_list) - A.cameras = null - -/obj/machinery/computer/security - name = "security camera monitor" - desc = "Used to access the various cameras on the station." - icon_state = "cameras" - circuit = /obj/item/weapon/circuitboard/security - light_color = "#a91515" - 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. - - var/camera_cache = null - -/obj/machinery/computer/security/check_eye(mob/user) - if ((get_dist(user, src) > 1 || user.incapacitated() || user.blinded) && !issilicon(user) && !isobserver(user)) - return null - if (!current || !current.can_use()) //camera doesn't work - reset_current() - var/list/viewing = viewers(src) - if(isrobot(user) && !viewing.Find(user)) - return null - user.reset_view(current) - return 1 - -/obj/machinery/computer/security/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) - if(stat & (NOPOWER|BROKEN)) return - if(user.stat) return - - var/data[0] - - data["current"] = null - - if(isnull(camera_cache)) - cameranet.process_sort() - - var/cameras[0] - for(var/obj/machinery/camera/C in cameranet.cameras) - if(!can_access_camera(C)) - continue - - var/cam = C.nano_structure() - cameras[++cameras.len] = cam - - if(C == current) - data["current"] = cam - - var/list/camera_list = list("cameras" = cameras) - camera_cache = list2json(camera_list) - else - if(current) - data["current"] = current.nano_structure() - - - if(ui) - ui.load_cached_data(camera_cache) - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "sec_camera.tmpl", "Camera Console", 900, 600) - - // adding a template with the key "mapContent" enables the map ui functionality - ui.add_template("mapContent", "sec_camera_map_content.tmpl") - // adding a template with the key "mapHeader" replaces the map header content - ui.add_template("mapHeader", "sec_camera_map_header.tmpl") - - ui.load_cached_data(camera_cache) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/computer/security/Topic(href, href_list) - . = ..() - if(!.) - return - - if(href_list["switchTo"]) - if(usr.blinded) - return FALSE - var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.cameras - if(!C) - return FALSE - switch_to_camera(usr, C) - else if(href_list["reset"]) - if(usr.blinded) - return FALSE - reset_current() - usr.check_eye(current) - -/obj/machinery/computer/security/attack_ghost(mob/user) // this should not ever be opened to ghots, there is simply no point (even for admin) and also this thing eats up ALOT of resources. - return - -/obj/machinery/computer/security/attack_hand(mob/user) - if (!network) - world.log << "A computer lacks a network at [x],[y],[z]." - return - if (!istype(network, /list)) - world.log << "The computer at [x],[y],[z] has a network that is not a list!" - return - - ..() - -/obj/machinery/computer/security/proc/can_access_camera(obj/machinery/camera/C) - var/list/shared_networks = src.network & C.network - if(shared_networks.len) - return 1 - return 0 - -/obj/machinery/computer/security/proc/switch_to_camera(mob/user, obj/machinery/camera/C) - //don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras. - if(isAI(user)) - var/mob/living/silicon/ai/A = user - // Only allow non-carded AIs to view because the interaction with the eye gets all wonky otherwise. - if(!A.is_in_chassis()) - return 0 - - A.eyeobj.setLoc(get_turf(C)) - A.client.eye = A.eyeobj - return 1 - set_current(C) - if(!check_eye(user)) - return 0 - use_power(50) - return 1 - -//Camera control: moving. -/obj/machinery/computer/security/proc/jump_on_click(mob/user,A) - if(user.machine != src) - return - var/obj/machinery/camera/jump_to - if(istype(A,/obj/machinery/camera)) - jump_to = A - else if(ismob(A)) - if(ishuman(A)) - jump_to = locate() in A:head - else if(isrobot(A)) - jump_to = A:camera - else if(isobj(A)) - jump_to = locate() in A - else if(isturf(A)) - var/best_dist = INFINITY - for(var/obj/machinery/camera/camera in get_area(A)) - if(!camera.can_use()) - continue - if(!can_access_camera(camera)) - continue - var/dist = get_dist(camera,A) - if(dist < best_dist) - best_dist = dist - jump_to = camera - if(isnull(jump_to)) - return - if(can_access_camera(jump_to)) - switch_to_camera(user,jump_to) - -/obj/machinery/computer/security/proc/set_current(obj/machinery/camera/C) - if(current == C) - return - - if(current) - reset_current() - - src.current = C - if(current) - var/mob/living/L = current.loc - if(istype(L)) - L.tracking_initiated() - -/obj/machinery/computer/security/proc/reset_current() - if(current) - var/mob/living/L = current.loc - if(istype(L)) - L.tracking_cancelled() - current = null - -//Camera control: mouse. -/atom/DblClick() - ..() - if(istype(usr.machine,/obj/machinery/computer/security)) - var/obj/machinery/computer/security/console = usr.machine - console.jump_on_click(usr,src) - -/obj/machinery/computer/security/telescreen - name = "Telescreen" - desc = "Used for watching an empty arena." - icon = 'icons/obj/objects.dmi' - icon_state = "telescreen" - light_color = "#ffffbb" - network = list("thunder") - density = 0 - -/obj/machinery/computer/security/telescreen/update_icon() - icon_state = initial(icon_state) - if(stat & BROKEN) - icon_state += "b" - playsound(src.loc, 'sound/effects/Glassbr3.ogg', 100, 1) - return - -/obj/machinery/computer/security/telescreen/entertainment - name = "entertainment monitor" - desc = "Damn, why do they never have anything interesting on these things?" - icon = 'icons/obj/status_display.dmi' - icon_state = "entertainment" - light_color = "#ea4444" - -/obj/machinery/computer/security/wooden_tv - name = "security camera monitor" - desc = "An old TV hooked into the stations camera network." - icon_state = "security_det" - light_color = "#3550b6" - -/obj/machinery/computer/security/mining - name = "outpost camera monitor" - desc = "Used to access the various cameras on the outpost." - icon_state = "miningcameras" - network = list("MINE") - -/obj/machinery/computer/security/engineering - name = "engineering camera monitor" - desc = "Used to monitor fires and breaches." - icon_state = "engineeringcameras" - network = list("Engineering","Power Alarms","Atmosphere Alarms","Fire Alarms") - light_color = "#b88b2e" - -/obj/machinery/computer/security/nuclear - name = "head mounted camera monitor" - desc = "Used to access the built-in cameras in helmets." - icon_state = "syndicam" - network = list("NUKE") - light_color = "#a91515" - -/obj/machinery/computer/security/abductor_ag - name = "agent observation monitor" - desc = "Used to access the cameras in agent helmet." - icon = 'icons/obj/abductor.dmi' - icon_state = "camera" - light_color = "#642850" - network = list() - var/team - -/obj/machinery/computer/security/abductor_ag/attack_hand(mob/user) - if(network.len < 1) - to_chat(user, "Monitor network doesn't established. Activate helmet at first.") - return - else - ..() - -/obj/machinery/computer/security/abductor_hu - name = "human observation monitor" - desc = "Shows how subjects are living." - icon = 'icons/obj/abductor.dmi' - icon_state = "camera_alt" - network = list("SS13") - light_color = "#642850" +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/proc/invalidateCameraCache() + for(var/obj/machinery/computer/security/s in computer_list) + s.camera_cache = null + for(var/datum/alarm/A in datum_alarm_list) + A.cameras = null + +/obj/machinery/computer/security + name = "security camera monitor" + desc = "Used to access the various cameras on the station." + icon_state = "cameras" + circuit = /obj/item/weapon/circuitboard/security + light_color = "#a91515" + 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. + + var/camera_cache = null + +/obj/machinery/computer/security/check_eye(mob/user) + if ((get_dist(user, src) > 1 || user.incapacitated() || user.blinded) && !issilicon(user) && !isobserver(user)) + return null + if (!current || !current.can_use()) //camera doesn't work + reset_current() + var/list/viewing = viewers(src) + if(isrobot(user) && !viewing.Find(user)) + return null + user.reset_view(current) + return 1 + +/obj/machinery/computer/security/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) + if(stat & (NOPOWER|BROKEN)) return + if(user.stat) return + + var/data[0] + + data["current"] = null + + if(isnull(camera_cache)) + cameranet.process_sort() + + var/cameras[0] + for(var/obj/machinery/camera/C in cameranet.cameras) + if(!can_access_camera(C)) + continue + + var/cam = C.nano_structure() + cameras[++cameras.len] = cam + + if(C == current) + data["current"] = cam + + var/list/camera_list = list("cameras" = cameras) + camera_cache = list2json(camera_list) + else + if(current) + data["current"] = current.nano_structure() + + + if(ui) + ui.load_cached_data(camera_cache) + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "sec_camera.tmpl", "Camera Console", 900, 600) + + // adding a template with the key "mapContent" enables the map ui functionality + ui.add_template("mapContent", "sec_camera_map_content.tmpl") + // adding a template with the key "mapHeader" replaces the map header content + ui.add_template("mapHeader", "sec_camera_map_header.tmpl") + + ui.load_cached_data(camera_cache) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/computer/security/Topic(href, href_list) + . = ..() + if(!.) + return + + if(href_list["switchTo"]) + if(usr.blinded) + return FALSE + var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.cameras + if(!C) + return FALSE + switch_to_camera(usr, C) + else if(href_list["reset"]) + if(usr.blinded) + return FALSE + reset_current() + usr.check_eye(current) + +/obj/machinery/computer/security/attack_ghost(mob/user) // this should not ever be opened to ghots, there is simply no point (even for admin) and also this thing eats up ALOT of resources. + return + +/obj/machinery/computer/security/attack_hand(mob/user) + if (!network) + world.log << "A computer lacks a network at [x],[y],[z]." + return + if (!istype(network, /list)) + world.log << "The computer at [x],[y],[z] has a network that is not a list!" + return + + ..() + +/obj/machinery/computer/security/proc/can_access_camera(obj/machinery/camera/C) + var/list/shared_networks = src.network & C.network + if(shared_networks.len) + return 1 + return 0 + +/obj/machinery/computer/security/proc/switch_to_camera(mob/user, obj/machinery/camera/C) + //don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras. + if(isAI(user)) + var/mob/living/silicon/ai/A = user + // Only allow non-carded AIs to view because the interaction with the eye gets all wonky otherwise. + if(!A.is_in_chassis()) + return 0 + + A.eyeobj.setLoc(get_turf(C)) + A.client.eye = A.eyeobj + return 1 + set_current(C) + if(!check_eye(user)) + return 0 + use_power(50) + return 1 + +//Camera control: moving. +/obj/machinery/computer/security/proc/jump_on_click(mob/user,A) + if(user.machine != src) + return + var/obj/machinery/camera/jump_to + if(istype(A,/obj/machinery/camera)) + jump_to = A + else if(ismob(A)) + if(ishuman(A)) + jump_to = locate() in A:head + else if(isrobot(A)) + jump_to = A:camera + else if(isobj(A)) + jump_to = locate() in A + else if(isturf(A)) + var/best_dist = INFINITY + for(var/obj/machinery/camera/camera in get_area(A)) + if(!camera.can_use()) + continue + if(!can_access_camera(camera)) + continue + var/dist = get_dist(camera,A) + if(dist < best_dist) + best_dist = dist + jump_to = camera + if(isnull(jump_to)) + return + if(can_access_camera(jump_to)) + switch_to_camera(user,jump_to) + +/obj/machinery/computer/security/proc/set_current(obj/machinery/camera/C) + if(current == C) + return + + if(current) + reset_current() + + src.current = C + if(current) + var/mob/living/L = current.loc + if(istype(L)) + L.tracking_initiated() + +/obj/machinery/computer/security/proc/reset_current() + if(current) + var/mob/living/L = current.loc + if(istype(L)) + L.tracking_cancelled() + current = null + +//Camera control: mouse. +/atom/DblClick() + ..() + if(istype(usr.machine,/obj/machinery/computer/security)) + var/obj/machinery/computer/security/console = usr.machine + console.jump_on_click(usr,src) + +/obj/machinery/computer/security/telescreen + name = "Telescreen" + desc = "Used for watching an empty arena." + icon = 'icons/obj/objects.dmi' + icon_state = "telescreen" + light_color = "#ffffbb" + network = list("thunder") + density = 0 + +/obj/machinery/computer/security/telescreen/update_icon() + icon_state = initial(icon_state) + if(stat & BROKEN) + icon_state += "b" + playsound(src.loc, 'sound/effects/Glassbr3.ogg', 100, 1) + return + +/obj/machinery/computer/security/telescreen/entertainment + name = "entertainment monitor" + desc = "Damn, why do they never have anything interesting on these things?" + icon = 'icons/obj/status_display.dmi' + icon_state = "entertainment" + light_color = "#ea4444" + +/obj/machinery/computer/security/wooden_tv + name = "security camera monitor" + desc = "An old TV hooked into the stations camera network." + icon_state = "security_det" + light_color = "#3550b6" + +/obj/machinery/computer/security/mining + name = "outpost camera monitor" + desc = "Used to access the various cameras on the outpost." + icon_state = "miningcameras" + network = list("MINE") + +/obj/machinery/computer/security/engineering + name = "engineering camera monitor" + desc = "Used to monitor fires and breaches." + icon_state = "engineeringcameras" + network = list("Engineering","Power Alarms","Atmosphere Alarms","Fire Alarms") + light_color = "#b88b2e" + +/obj/machinery/computer/security/nuclear + name = "head mounted camera monitor" + desc = "Used to access the built-in cameras in helmets." + icon_state = "syndicam" + network = list("NUKE") + light_color = "#a91515" + +/obj/machinery/computer/security/abductor_ag + name = "agent observation monitor" + desc = "Used to access the cameras in agent helmet." + icon = 'icons/obj/abductor.dmi' + icon_state = "camera" + light_color = "#642850" + network = list() + var/team + +/obj/machinery/computer/security/abductor_ag/attack_hand(mob/user) + if(network.len < 1) + to_chat(user, "Monitor network doesn't established. Activate helmet at first.") + return + else + ..() + +/obj/machinery/computer/security/abductor_hu + name = "human observation monitor" + desc = "Shows how subjects are living." + icon = 'icons/obj/abductor.dmi' + icon_state = "camera_alt" + network = list("SS13") + light_color = "#642850" diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index d6acc9e49f4c..05e17ca7e644 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -1,551 +1,551 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -// 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" - light_color = "#0099ff" - req_access = list(access_heads) - circuit = /obj/item/weapon/circuitboard/communications - allowed_checks = ALLOWED_CHECK_NONE - var/prints_intercept = 1 - var/authenticated = 0 - var/list/messagetitle = list() - var/list/messagetext = list() - var/currmsg = 0 - var/aicurrmsg = 0 - var/state = STATE_DEFAULT - var/aistate = STATE_DEFAULT - var/message_cooldown = 0 - var/centcomm_message_cooldown = 0 - var/tmp_alertlevel = 0 - var/const/STATE_DEFAULT = 1 - var/const/STATE_CALLSHUTTLE = 2 - var/const/STATE_CANCELSHUTTLE = 3 - var/const/STATE_MESSAGELIST = 4 - var/const/STATE_VIEWMESSAGE = 5 - var/const/STATE_DELMESSAGE = 6 - var/const/STATE_STATUSDISPLAY = 7 - var/const/STATE_ALERT_LEVEL = 8 - var/const/STATE_CONFIRM_LEVEL = 9 - var/const/STATE_CREWTRANSFER = 10 - - var/status_display_freq = "1435" - var/stat_msg1 - var/stat_msg2 - -/obj/machinery/computer/communications/atom_init() - . = ..() - communications_list += src - -/obj/machinery/computer/communications/Destroy() - communications_list -= src - - for(var/obj/machinery/computer/communications/commconsole in communications_list) - if(istype(commconsole.loc, /turf)) - return ..() - - for(var/obj/item/weapon/circuitboard/communications/commboard in circuitboard_communications_list) - if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) - return ..() - - for(var/mob/living/silicon/ai/shuttlecaller in ai_list) - if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) - return ..() - - if(sent_strike_team) - return ..() - - SSshuttle.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.") - captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - world << sound('sound/AI/shuttlecalled.ogg') - - return ..() - -/obj/machinery/computer/communications/process() - if(..()) - if(state != STATE_STATUSDISPLAY) - src.updateDialog() - - -/obj/machinery/computer/communications/Topic(href, href_list) - . = ..() - if(!.) - return - - if (src.z > ZLEVEL_STATION) - to_chat(usr, "\red Unable to establish a connection: \black You're too far away from the station!") - return FALSE - if(!href_list["operation"]) - return FALSE - - var/obj/item/weapon/circuitboard/communications/CM = circuit - switch(href_list["operation"]) - // main interface - if("main") - src.state = STATE_DEFAULT - if("login") - var/mob/M = usr - if(isobserver(M)) - authenticated = 2 - else - 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(src.check_access(I)) - authenticated = 1 - if(20 in I.access || 57 in I.access || 58 in I.access)//cap, hop, hos - authenticated = 2 - if("logout") - authenticated = 0 - - if("swipeidseclevel") - 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_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()]. (JMP)") - 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 - state = STATE_DEFAULT - else - to_chat(usr, "You need to swipe your ID.") - - if("announce") - if(src.authenticated==2) - if(message_cooldown) return - var/input = sanitize(input(usr, "Please choose a message to announce to the station crew.", "What?"), extra = FALSE) - if(!input || !(usr in view(1,src))) - return - captain_announce(input)//This should really tell who is, IE HoP, CE, HoS, RD, Captain - log_say("[key_name(usr)] has made a captain announcement: [input]") - message_admins("[key_name_admin(usr)] has made a captain announcement. (JMP)") - message_cooldown = 1 - spawn(600)//One minute cooldown - message_cooldown = 0 - - if("callshuttle") - src.state = STATE_DEFAULT - if(src.authenticated) - src.state = STATE_CALLSHUTTLE - if("callshuttle2") - if(src.authenticated) - call_shuttle_proc(usr) - if(SSshuttle.online) - post_status("shuttle") - src.state = STATE_DEFAULT - if("cancelshuttle") - src.state = STATE_DEFAULT - if(src.authenticated) - src.state = STATE_CANCELSHUTTLE - if("cancelshuttle2") - if(src.authenticated) - cancel_call_proc(usr) - src.state = STATE_DEFAULT - if("messagelist") - src.currmsg = 0 - src.state = STATE_MESSAGELIST - if("viewmessage") - src.state = STATE_VIEWMESSAGE - if (!src.currmsg) - if(href_list["message-num"]) - src.currmsg = text2num(href_list["message-num"]) - else - src.state = STATE_MESSAGELIST - if("delmessage") - src.state = (src.currmsg) ? STATE_DELMESSAGE : STATE_MESSAGELIST - if("delmessage2") - if(src.authenticated) - if(src.currmsg) - var/title = src.messagetitle[src.currmsg] - var/text = src.messagetext[src.currmsg] - src.messagetitle.Remove(title) - src.messagetext.Remove(text) - if(src.currmsg == src.aicurrmsg) - src.aicurrmsg = 0 - src.currmsg = 0 - src.state = STATE_MESSAGELIST - else - src.state = STATE_VIEWMESSAGE - if("status") - src.state = STATE_STATUSDISPLAY - - // Status display stuff - if("setstat") - switch(href_list["statdisp"]) - if("message") - post_status("message", stat_msg1, stat_msg2) - if("alert") - post_status("alert", href_list["alert"]) - else - post_status(href_list["statdisp"]) - - if("setmsg1") - stat_msg1 = sanitize_safe(input("Line 1", "Enter Message Text", stat_msg1) as text|null, MAX_LNAME_LEN) - src.updateDialog() - if("setmsg2") - stat_msg2 = sanitize_safe(input("Line 2", "Enter Message Text", stat_msg2) as text|null, MAX_LNAME_LEN) - src.updateDialog() - - // OMG CENTCOMM LETTERHEAD - if("MessageCentcomm") - if(src.authenticated==2) - if(CM.cooldown) - to_chat(usr, "\red Arrays recycling. Please stand by.") - return - var/input = sanitize(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, "\blue Message transmitted.") - log_say("[key_name(usr)] has made an IA Centcomm announcement: [input]") - CM.cooldown = 55 - - - // OMG SYNDICATE ...LETTERHEAD - if("MessageSyndicate") - if((src.authenticated==2) && (src.emagged)) - if(CM.cooldown) - to_chat(usr, "\red Arrays recycling. Please stand by.") - return - var/input = sanitize(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, "\blue Message transmitted.") - log_say("[key_name(usr)] has made a Syndicate announcement: [input]") - CM.cooldown = 55 //about one minute - - if("RestoreBackup") - to_chat(usr, "Backup routing data restored!") - src.emagged = 0 - src.updateDialog() - - - - // AI interface - if("ai-main") - src.aicurrmsg = 0 - src.aistate = STATE_DEFAULT - if("ai-callshuttle") - src.aistate = STATE_CALLSHUTTLE - if("ai-callshuttle2") - call_shuttle_proc(usr) - src.aistate = STATE_DEFAULT - if("ai-messagelist") - src.aicurrmsg = 0 - src.aistate = STATE_MESSAGELIST - if("ai-viewmessage") - src.aistate = STATE_VIEWMESSAGE - if (!src.aicurrmsg) - if(href_list["message-num"]) - src.aicurrmsg = text2num(href_list["message-num"]) - else - src.aistate = STATE_MESSAGELIST - if("ai-delmessage") - src.aistate = (src.aicurrmsg) ? STATE_DELMESSAGE : STATE_MESSAGELIST - if("ai-delmessage2") - if(src.aicurrmsg) - var/title = src.messagetitle[src.aicurrmsg] - var/text = src.messagetext[src.aicurrmsg] - src.messagetitle.Remove(title) - src.messagetext.Remove(text) - if(src.currmsg == src.aicurrmsg) - src.currmsg = 0 - src.aicurrmsg = 0 - src.aistate = STATE_MESSAGELIST - if("ai-status") - src.aistate = STATE_STATUSDISPLAY - - if("securitylevel") - src.tmp_alertlevel = text2num( href_list["newalertlevel"] ) - if(!tmp_alertlevel) tmp_alertlevel = 0 - state = STATE_CONFIRM_LEVEL - - if("changeseclevel") - state = STATE_ALERT_LEVEL - src.updateUsrDialog() - -/obj/machinery/computer/communications/attackby(obj/I, mob/user) - if(istype(I,/obj/item/weapon/card/emag/)) - src.emagged = 1 - to_chat(user, "You scramble the communication routing circuits!") - else - ..() - return - -/obj/machinery/computer/communications/ui_interact(mob/user) - if (src.z > ZLEVEL_EMPTY) - to_chat(user, "\red Unable to establish a connection: \black You're too far away from the station!") - return - - var/dat = "Communications Console" - if (SSshuttle.online && SSshuttle.location == 0) - dat += "Emergency shuttle\n
    \nETA: [shuttleeta2text()]
    " - - if (issilicon(user)) - var/dat2 = src.interact_ai(user) // give the AI a different interact proc to limit its access - if(dat2) - dat += dat2 - user << browse(entity_ja(dat), "window=communications;size=400x500") - onclose(user, "communications") - return - - switch(src.state) - if(STATE_DEFAULT) - if (src.authenticated) - dat += "
    \[ Log Out \]" - if (src.authenticated==2) - dat += "
    \[ Make An Announcement \]" - if(src.emagged == 0) - dat += "
    \[ Send an emergency message to Centcomm \]" - else - dat += "
    \[ Send an emergency message to \[UNKNOWN\] \]" - dat += "
    \[ Restore Backup Routing Data \]" - - dat += "
    \[ Change alert level \]" - if(SSshuttle.location==0) - if (SSshuttle.online) - dat += "
    \[ Cancel Shuttle Call \]" - else - dat += "
    \[ Call Emergency Shuttle \]" - - dat += "
    \[ Set Status Display \]" - else - dat += "
    \[ Log In \]" - dat += "
    \[ Message List \]" - if(STATE_CALLSHUTTLE) - dat += "Are you sure you want to call the shuttle? \[ OK | Cancel \]" - if(STATE_CANCELSHUTTLE) - dat += "Are you sure you want to cancel the shuttle? \[ OK | Cancel \]" - if(STATE_MESSAGELIST) - dat += "Messages:" - for(var/i = 1; i<=src.messagetitle.len; i++) - dat += "
    [src.messagetitle[i]]" - if(STATE_VIEWMESSAGE) - if (src.currmsg) - dat += "[src.messagetitle[src.currmsg]]

    [src.messagetext[src.currmsg]]" - if (src.authenticated) - dat += "

    \[ Delete \]" - else - src.state = STATE_MESSAGELIST - src.attack_hand(user) - return - if(STATE_DELMESSAGE) - if (src.currmsg) - dat += "Are you sure you want to delete this message? \[ OK | Cancel \]" - else - src.state = STATE_MESSAGELIST - src.attack_hand(user) - return - if(STATE_STATUSDISPLAY) - dat += "Set Status Displays
    " - dat += "\[ Clear \]
    " - dat += "\[ Shuttle ETA \]
    " - dat += "\[ Message \]" - dat += "
    " - dat += "\[ Alert: None |" - dat += " Red Alert |" - dat += " Lockdown |" - dat += " Biohazard \]

    " - if(STATE_ALERT_LEVEL) - dat += "Current alert level: [get_security_level()]
    " - if(security_level == SEC_LEVEL_DELTA) - dat += "The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate." - else - dat += "Blue
    " - dat += "Green" - if(STATE_CONFIRM_LEVEL) - dat += "Current alert level: [get_security_level()]
    " - dat += "Confirm the change to: [num2seclevel(tmp_alertlevel)]
    " - dat += "Swipe ID to confirm change.
    " - - dat += "
    \[ [(src.state != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" - user << browse(entity_ja(dat), "window=communications;size=400x500") - onclose(user, "communications") - - - - -/obj/machinery/computer/communications/proc/interact_ai(mob/living/silicon/ai/user) - var/dat = "" - switch(src.aistate) - if(STATE_DEFAULT) - if(SSshuttle.location==0 && !SSshuttle.online) - dat += "
    \[ Call Emergency Shuttle \]" - dat += "
    \[ Message List \]" - dat += "
    \[ Set Status Display \]" - if(STATE_CALLSHUTTLE) - dat += "Are you sure you want to call the shuttle? \[ OK | Cancel \]" - if(STATE_MESSAGELIST) - dat += "Messages:" - for(var/i = 1; i<=src.messagetitle.len; i++) - dat += "
    [src.messagetitle[i]]" - if(STATE_VIEWMESSAGE) - if (src.aicurrmsg) - dat += "[src.messagetitle[src.aicurrmsg]]

    [src.messagetext[src.aicurrmsg]]" - dat += "

    \[ Delete \]" - else - src.aistate = STATE_MESSAGELIST - src.attack_hand(user) - return null - if(STATE_DELMESSAGE) - if(src.aicurrmsg) - dat += "Are you sure you want to delete this message? \[ OK | Cancel \]" - else - src.aistate = STATE_MESSAGELIST - src.attack_hand(user) - return - - if(STATE_STATUSDISPLAY) - dat += "Set Status Displays
    " - dat += "\[ Clear \]
    " - dat += "\[ Shuttle ETA \]
    " - dat += "\[ Message \]" - dat += "
    " - dat += "\[ Alert: None |" - dat += " Red Alert |" - dat += " Lockdown |" - dat += " Biohazard \]

    " - - - dat += "
    \[ [(src.aistate != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" - return dat - -/proc/call_shuttle_proc(mob/user) - if ((!( ticker ) || SSshuttle.location)) - 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)] minutes before trying again.") - return - - if(SSshuttle.direction == -1) - to_chat(user, "The emergency shuttle may not be called while returning to CentCom.") - return - - if(SSshuttle.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 - - SSshuttle.incall() - log_game("[key_name(user)] has called the shuttle.") - message_admins("[key_name_admin(user)] has called the shuttle. (JMP)") - captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - world << sound('sound/AI/shuttlecalled.ogg') - - make_maint_all_access(FALSE) - - return - -/proc/init_shift_change(mob/user, force = 0) - if ((!( ticker ) || SSshuttle.location)) - return - - if(SSshuttle.direction == -1) - to_chat(user, "The shuttle may not be called while returning to CentCom.") - return - - if(SSshuttle.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(SSshuttle.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 == "blob" || ticker.mode.name == "epidemic") - to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.") - return - - SSshuttle.shuttlealert(1) - SSshuttle.incall() - log_game("[key_name(user)] has called the shuttle.") - message_admins("[key_name_admin(user)] has called the shuttle. (JMP)") - captain_announce("A crew transfer has been initiated. The shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - - return - -/proc/cancel_call_proc(mob/user) - if ((!( ticker ) || SSshuttle.location || SSshuttle.direction == 0 || SSshuttle.timeleft() < 300)) - return - if((ticker.mode.name == "blob")||(ticker.mode.name == "meteor")) - return - - if(SSshuttle.direction != -1 && SSshuttle.online) //check that shuttle isn't already heading to centcomm - SSshuttle.recall() - log_game("[key_name(user)] has recalled the shuttle.") - message_admins("[key_name_admin(user)] has recalled the shuttle. (JMP)") - - if(timer_maint_revoke_id) - deltimer(timer_maint_revoke_id) - timer_maint_revoke_id = 0 - timer_maint_revoke_id = addtimer(CALLBACK(GLOBAL_PROC, .proc/revoke_maint_all_access, FALSE), 600, TIMER_UNIQUE|TIMER_STOPPABLE) // Want to give them time to get out of maintenance. - - return 1 - return - -/obj/machinery/computer/communications/proc/post_status(command, data1, data2) - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) - - if(!frequency) return - - var/datum/signal/status_signal = new - 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) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +// 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" + light_color = "#0099ff" + req_access = list(access_heads) + circuit = /obj/item/weapon/circuitboard/communications + allowed_checks = ALLOWED_CHECK_NONE + var/prints_intercept = 1 + var/authenticated = 0 + var/list/messagetitle = list() + var/list/messagetext = list() + var/currmsg = 0 + var/aicurrmsg = 0 + var/state = STATE_DEFAULT + var/aistate = STATE_DEFAULT + var/message_cooldown = 0 + var/centcomm_message_cooldown = 0 + var/tmp_alertlevel = 0 + var/const/STATE_DEFAULT = 1 + var/const/STATE_CALLSHUTTLE = 2 + var/const/STATE_CANCELSHUTTLE = 3 + var/const/STATE_MESSAGELIST = 4 + var/const/STATE_VIEWMESSAGE = 5 + var/const/STATE_DELMESSAGE = 6 + var/const/STATE_STATUSDISPLAY = 7 + var/const/STATE_ALERT_LEVEL = 8 + var/const/STATE_CONFIRM_LEVEL = 9 + var/const/STATE_CREWTRANSFER = 10 + + var/status_display_freq = "1435" + var/stat_msg1 + var/stat_msg2 + +/obj/machinery/computer/communications/atom_init() + . = ..() + communications_list += src + +/obj/machinery/computer/communications/Destroy() + communications_list -= src + + for(var/obj/machinery/computer/communications/commconsole in communications_list) + if(istype(commconsole.loc, /turf)) + return ..() + + for(var/obj/item/weapon/circuitboard/communications/commboard in circuitboard_communications_list) + if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) + return ..() + + for(var/mob/living/silicon/ai/shuttlecaller in ai_list) + if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf)) + return ..() + + if(sent_strike_team) + return ..() + + SSshuttle.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.") + captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + world << sound('sound/AI/shuttlecalled.ogg') + + return ..() + +/obj/machinery/computer/communications/process() + if(..()) + if(state != STATE_STATUSDISPLAY) + src.updateDialog() + + +/obj/machinery/computer/communications/Topic(href, href_list) + . = ..() + if(!.) + return + + if (src.z > ZLEVEL_STATION) + to_chat(usr, "\red Unable to establish a connection: \black You're too far away from the station!") + return FALSE + if(!href_list["operation"]) + return FALSE + + var/obj/item/weapon/circuitboard/communications/CM = circuit + switch(href_list["operation"]) + // main interface + if("main") + src.state = STATE_DEFAULT + if("login") + var/mob/M = usr + if(isobserver(M)) + authenticated = 2 + else + 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(src.check_access(I)) + authenticated = 1 + if(20 in I.access || 57 in I.access || 58 in I.access)//cap, hop, hos + authenticated = 2 + if("logout") + authenticated = 0 + + if("swipeidseclevel") + 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_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()]. (JMP)") + 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 + state = STATE_DEFAULT + else + to_chat(usr, "You need to swipe your ID.") + + if("announce") + if(src.authenticated==2) + if(message_cooldown) return + var/input = sanitize(input(usr, "Please choose a message to announce to the station crew.", "What?"), extra = FALSE) + if(!input || !(usr in view(1,src))) + return + captain_announce(input)//This should really tell who is, IE HoP, CE, HoS, RD, Captain + log_say("[key_name(usr)] has made a captain announcement: [input]") + message_admins("[key_name_admin(usr)] has made a captain announcement. (JMP)") + message_cooldown = 1 + spawn(600)//One minute cooldown + message_cooldown = 0 + + if("callshuttle") + src.state = STATE_DEFAULT + if(src.authenticated) + src.state = STATE_CALLSHUTTLE + if("callshuttle2") + if(src.authenticated) + call_shuttle_proc(usr) + if(SSshuttle.online) + post_status("shuttle") + src.state = STATE_DEFAULT + if("cancelshuttle") + src.state = STATE_DEFAULT + if(src.authenticated) + src.state = STATE_CANCELSHUTTLE + if("cancelshuttle2") + if(src.authenticated) + cancel_call_proc(usr) + src.state = STATE_DEFAULT + if("messagelist") + src.currmsg = 0 + src.state = STATE_MESSAGELIST + if("viewmessage") + src.state = STATE_VIEWMESSAGE + if (!src.currmsg) + if(href_list["message-num"]) + src.currmsg = text2num(href_list["message-num"]) + else + src.state = STATE_MESSAGELIST + if("delmessage") + src.state = (src.currmsg) ? STATE_DELMESSAGE : STATE_MESSAGELIST + if("delmessage2") + if(src.authenticated) + if(src.currmsg) + var/title = src.messagetitle[src.currmsg] + var/text = src.messagetext[src.currmsg] + src.messagetitle.Remove(title) + src.messagetext.Remove(text) + if(src.currmsg == src.aicurrmsg) + src.aicurrmsg = 0 + src.currmsg = 0 + src.state = STATE_MESSAGELIST + else + src.state = STATE_VIEWMESSAGE + if("status") + src.state = STATE_STATUSDISPLAY + + // Status display stuff + if("setstat") + switch(href_list["statdisp"]) + if("message") + post_status("message", stat_msg1, stat_msg2) + if("alert") + post_status("alert", href_list["alert"]) + else + post_status(href_list["statdisp"]) + + if("setmsg1") + stat_msg1 = sanitize_safe(input("Line 1", "Enter Message Text", stat_msg1) as text|null, MAX_LNAME_LEN) + src.updateDialog() + if("setmsg2") + stat_msg2 = sanitize_safe(input("Line 2", "Enter Message Text", stat_msg2) as text|null, MAX_LNAME_LEN) + src.updateDialog() + + // OMG CENTCOMM LETTERHEAD + if("MessageCentcomm") + if(src.authenticated==2) + if(CM.cooldown) + to_chat(usr, "\red Arrays recycling. Please stand by.") + return + var/input = sanitize(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, "\blue Message transmitted.") + log_say("[key_name(usr)] has made an IA Centcomm announcement: [input]") + CM.cooldown = 55 + + + // OMG SYNDICATE ...LETTERHEAD + if("MessageSyndicate") + if((src.authenticated==2) && (src.emagged)) + if(CM.cooldown) + to_chat(usr, "\red Arrays recycling. Please stand by.") + return + var/input = sanitize(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, "\blue Message transmitted.") + log_say("[key_name(usr)] has made a Syndicate announcement: [input]") + CM.cooldown = 55 //about one minute + + if("RestoreBackup") + to_chat(usr, "Backup routing data restored!") + src.emagged = 0 + src.updateDialog() + + + + // AI interface + if("ai-main") + src.aicurrmsg = 0 + src.aistate = STATE_DEFAULT + if("ai-callshuttle") + src.aistate = STATE_CALLSHUTTLE + if("ai-callshuttle2") + call_shuttle_proc(usr) + src.aistate = STATE_DEFAULT + if("ai-messagelist") + src.aicurrmsg = 0 + src.aistate = STATE_MESSAGELIST + if("ai-viewmessage") + src.aistate = STATE_VIEWMESSAGE + if (!src.aicurrmsg) + if(href_list["message-num"]) + src.aicurrmsg = text2num(href_list["message-num"]) + else + src.aistate = STATE_MESSAGELIST + if("ai-delmessage") + src.aistate = (src.aicurrmsg) ? STATE_DELMESSAGE : STATE_MESSAGELIST + if("ai-delmessage2") + if(src.aicurrmsg) + var/title = src.messagetitle[src.aicurrmsg] + var/text = src.messagetext[src.aicurrmsg] + src.messagetitle.Remove(title) + src.messagetext.Remove(text) + if(src.currmsg == src.aicurrmsg) + src.currmsg = 0 + src.aicurrmsg = 0 + src.aistate = STATE_MESSAGELIST + if("ai-status") + src.aistate = STATE_STATUSDISPLAY + + if("securitylevel") + src.tmp_alertlevel = text2num( href_list["newalertlevel"] ) + if(!tmp_alertlevel) tmp_alertlevel = 0 + state = STATE_CONFIRM_LEVEL + + if("changeseclevel") + state = STATE_ALERT_LEVEL + src.updateUsrDialog() + +/obj/machinery/computer/communications/attackby(obj/I, mob/user) + if(istype(I,/obj/item/weapon/card/emag/)) + src.emagged = 1 + to_chat(user, "You scramble the communication routing circuits!") + else + ..() + return + +/obj/machinery/computer/communications/ui_interact(mob/user) + if (src.z > ZLEVEL_EMPTY) + to_chat(user, "\red Unable to establish a connection: \black You're too far away from the station!") + return + + var/dat = "Communications Console" + if (SSshuttle.online && SSshuttle.location == 0) + dat += "Emergency shuttle\n
    \nETA: [shuttleeta2text()]
    " + + if (issilicon(user)) + var/dat2 = src.interact_ai(user) // give the AI a different interact proc to limit its access + if(dat2) + dat += dat2 + user << browse(entity_ja(dat), "window=communications;size=400x500") + onclose(user, "communications") + return + + switch(src.state) + if(STATE_DEFAULT) + if (src.authenticated) + dat += "
    \[ Log Out \]" + if (src.authenticated==2) + dat += "
    \[ Make An Announcement \]" + if(src.emagged == 0) + dat += "
    \[ Send an emergency message to Centcomm \]" + else + dat += "
    \[ Send an emergency message to \[UNKNOWN\] \]" + dat += "
    \[ Restore Backup Routing Data \]" + + dat += "
    \[ Change alert level \]" + if(SSshuttle.location==0) + if (SSshuttle.online) + dat += "
    \[ Cancel Shuttle Call \]" + else + dat += "
    \[ Call Emergency Shuttle \]" + + dat += "
    \[ Set Status Display \]" + else + dat += "
    \[ Log In \]" + dat += "
    \[ Message List \]" + if(STATE_CALLSHUTTLE) + dat += "Are you sure you want to call the shuttle? \[ OK | Cancel \]" + if(STATE_CANCELSHUTTLE) + dat += "Are you sure you want to cancel the shuttle? \[ OK | Cancel \]" + if(STATE_MESSAGELIST) + dat += "Messages:" + for(var/i = 1; i<=src.messagetitle.len; i++) + dat += "
    [src.messagetitle[i]]" + if(STATE_VIEWMESSAGE) + if (src.currmsg) + dat += "[src.messagetitle[src.currmsg]]

    [src.messagetext[src.currmsg]]" + if (src.authenticated) + dat += "

    \[ Delete \]" + else + src.state = STATE_MESSAGELIST + src.attack_hand(user) + return + if(STATE_DELMESSAGE) + if (src.currmsg) + dat += "Are you sure you want to delete this message? \[ OK | Cancel \]" + else + src.state = STATE_MESSAGELIST + src.attack_hand(user) + return + if(STATE_STATUSDISPLAY) + dat += "Set Status Displays
    " + dat += "\[ Clear \]
    " + dat += "\[ Shuttle ETA \]
    " + dat += "\[ Message \]" + dat += "
    " + dat += "\[ Alert: None |" + dat += " Red Alert |" + dat += " Lockdown |" + dat += " Biohazard \]

    " + if(STATE_ALERT_LEVEL) + dat += "Current alert level: [get_security_level()]
    " + if(security_level == SEC_LEVEL_DELTA) + dat += "The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate." + else + dat += "Blue
    " + dat += "Green" + if(STATE_CONFIRM_LEVEL) + dat += "Current alert level: [get_security_level()]
    " + dat += "Confirm the change to: [num2seclevel(tmp_alertlevel)]
    " + dat += "Swipe ID to confirm change.
    " + + dat += "
    \[ [(src.state != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" + user << browse(entity_ja(dat), "window=communications;size=400x500") + onclose(user, "communications") + + + + +/obj/machinery/computer/communications/proc/interact_ai(mob/living/silicon/ai/user) + var/dat = "" + switch(src.aistate) + if(STATE_DEFAULT) + if(SSshuttle.location==0 && !SSshuttle.online) + dat += "
    \[ Call Emergency Shuttle \]" + dat += "
    \[ Message List \]" + dat += "
    \[ Set Status Display \]" + if(STATE_CALLSHUTTLE) + dat += "Are you sure you want to call the shuttle? \[ OK | Cancel \]" + if(STATE_MESSAGELIST) + dat += "Messages:" + for(var/i = 1; i<=src.messagetitle.len; i++) + dat += "
    [src.messagetitle[i]]" + if(STATE_VIEWMESSAGE) + if (src.aicurrmsg) + dat += "[src.messagetitle[src.aicurrmsg]]

    [src.messagetext[src.aicurrmsg]]" + dat += "

    \[ Delete \]" + else + src.aistate = STATE_MESSAGELIST + src.attack_hand(user) + return null + if(STATE_DELMESSAGE) + if(src.aicurrmsg) + dat += "Are you sure you want to delete this message? \[ OK | Cancel \]" + else + src.aistate = STATE_MESSAGELIST + src.attack_hand(user) + return + + if(STATE_STATUSDISPLAY) + dat += "Set Status Displays
    " + dat += "\[ Clear \]
    " + dat += "\[ Shuttle ETA \]
    " + dat += "\[ Message \]" + dat += "
    " + dat += "\[ Alert: None |" + dat += " Red Alert |" + dat += " Lockdown |" + dat += " Biohazard \]

    " + + + dat += "
    \[ [(src.aistate != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" + return dat + +/proc/call_shuttle_proc(mob/user) + if ((!( ticker ) || SSshuttle.location)) + 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)] minutes before trying again.") + return + + if(SSshuttle.direction == -1) + to_chat(user, "The emergency shuttle may not be called while returning to CentCom.") + return + + if(SSshuttle.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 + + SSshuttle.incall() + log_game("[key_name(user)] has called the shuttle.") + message_admins("[key_name_admin(user)] has called the shuttle. (JMP)") + captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + world << sound('sound/AI/shuttlecalled.ogg') + + make_maint_all_access(FALSE) + + return + +/proc/init_shift_change(mob/user, force = 0) + if ((!( ticker ) || SSshuttle.location)) + return + + if(SSshuttle.direction == -1) + to_chat(user, "The shuttle may not be called while returning to CentCom.") + return + + if(SSshuttle.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(SSshuttle.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 == "blob" || ticker.mode.name == "epidemic") + to_chat(user, "Under directive 7-10, [station_name()] is quarantined until further notice.") + return + + SSshuttle.shuttlealert(1) + SSshuttle.incall() + log_game("[key_name(user)] has called the shuttle.") + message_admins("[key_name_admin(user)] has called the shuttle. (JMP)") + captain_announce("A crew transfer has been initiated. The shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + + return + +/proc/cancel_call_proc(mob/user) + if ((!( ticker ) || SSshuttle.location || SSshuttle.direction == 0 || SSshuttle.timeleft() < 300)) + return + if((ticker.mode.name == "blob")||(ticker.mode.name == "meteor")) + return + + if(SSshuttle.direction != -1 && SSshuttle.online) //check that shuttle isn't already heading to centcomm + SSshuttle.recall() + log_game("[key_name(user)] has recalled the shuttle.") + message_admins("[key_name_admin(user)] has recalled the shuttle. (JMP)") + + if(timer_maint_revoke_id) + deltimer(timer_maint_revoke_id) + timer_maint_revoke_id = 0 + timer_maint_revoke_id = addtimer(CALLBACK(GLOBAL_PROC, .proc/revoke_maint_all_access, FALSE), 600, TIMER_UNIQUE|TIMER_STOPPABLE) // Want to give them time to get out of maintenance. + + return 1 + return + +/obj/machinery/computer/communications/proc/post_status(command, data1, data2) + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) + + if(!frequency) return + + var/datum/signal/status_signal = new + 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) diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index 2ccb2bb2e18d..51b47065ab48 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -1,18 +1,18 @@ -/obj/machinery/computer/crew - name = "crew monitoring computer" - desc = "Used to monitor active health sensors built into most of the crew's uniforms." - icon_state = "crew" - light_color = "#315ab4" - use_power = 1 - idle_power_usage = 250 - active_power_usage = 500 - circuit = "/obj/item/weapon/circuitboard/crew" - var/obj/nano_module/crew_monitor/crew_monitor - -/obj/machinery/computer/crew/atom_init() - crew_monitor = new(src) - . = ..() - - -/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) - crew_monitor.ui_interact(user, ui_key, ui, force_open) +/obj/machinery/computer/crew + name = "crew monitoring computer" + desc = "Used to monitor active health sensors built into most of the crew's uniforms." + icon_state = "crew" + light_color = "#315ab4" + use_power = 1 + idle_power_usage = 250 + active_power_usage = 500 + circuit = "/obj/item/weapon/circuitboard/crew" + var/obj/nano_module/crew_monitor/crew_monitor + +/obj/machinery/computer/crew/atom_init() + crew_monitor = new(src) + . = ..() + + +/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) + crew_monitor.ui_interact(user, ui_key, ui, force_open) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index b9495c81e884..e467371f273b 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -1,535 +1,535 @@ -//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" - light_color = "#315ab4" - req_one_access = list(access_medical, access_forensics_lockers) - circuit = /obj/item/weapon/circuitboard/med_data - allowed_checks = ALLOWED_CHECK_NONE - 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 - -/obj/machinery/computer/med_data/attackby(obj/item/O, user) - if(istype(O, /obj/item/weapon/card/id) && !scan) - usr.drop_item() - O.loc = src - scan = O - to_chat(user, "You insert [O].") - ..() - -/obj/machinery/computer/med_data/ui_interact(mob/user) - 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 = active1.fields["photo_f"] - var/icon/side = active1.fields["photo_s"] - 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, decode(src.active2.fields["notes"])) - var/counter = 1 - while(src.active2.fields[text("com_[]", counter)]) - dat += text("[]
    Delete Entry

    ", src.active2.fields[text("com_[]", counter)], src, counter) - 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) - dat += "
    Medical Robot Monitor
    " - dat += "Back" - dat += "
    Medical Robots:" - var/bdat = null - for(var/obj/machinery/bot/medbot/M in bots_list) - - 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],[bl.y]\] - [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[]", entity_ja(dat)), "window=med_rec") - onclose(user, "med_rec") - -/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 (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)) - usr.drop_item() - I.loc = 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 (isAI(usr)) - src.active1 = null - src.active2 = null - src.authenticated = usr.name - src.rank = "AI" - src.screen = 1 - - else if (isrobot(usr)) - 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 (isobserver(usr)) - src.active1 = null - src.active2 = null - src.authenticated = "Centcomm Agent" - src.rank = "Overseer" - 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) - //R = null - qdel(R) - //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 = sanitize(input("Please input fingerprint hash:", "Med. records", input_default(src.active1.fields["fingerprint"]), null) as text) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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) && !issilicon(usr) && !isobserver(usr)) || src.active1 != a1)) - return - src.active1.fields["age"] = t1 - if("mi_dis") - if (istype(src.active2, /datum/data/record)) - var/t1 = sanitize(input("Please input minor disabilities list:", "Med. records", input_default(src.active2.fields["mi_dis"]), null) as text) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) - return - src.active2.fields["mi_dis"] = t1 - if("mi_dis_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = sanitize(input("Please summarize minor dis.:", "Med. records", input_default(src.active2.fields["mi_dis_d"]), null) as message) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) - return - src.active2.fields["mi_dis_d"] = t1 - if("ma_dis") - if (istype(src.active2, /datum/data/record)) - var/t1 = sanitize(input("Please input major diabilities list:", "Med. records", input_default(src.active2.fields["ma_dis"]), null) as text) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) - return - src.active2.fields["ma_dis"] = t1 - if("ma_dis_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = sanitize(input("Please summarize major dis.:", "Med. records", input_default(src.active2.fields["ma_dis_d"]), null) as message) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) - return - src.active2.fields["ma_dis_d"] = t1 - if("alg") - if (istype(src.active2, /datum/data/record)) - var/t1 = sanitize(input("Please state allergies:", "Med. records", input_default(src.active2.fields["alg"]), null) as text) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) - return - src.active2.fields["alg"] = t1 - if("alg_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = sanitize(input("Please summarize allergies:", "Med. records", input_default(src.active2.fields["alg_d"]), null) as message) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) - return - src.active2.fields["alg_d"] = t1 - if("cdi") - if (istype(src.active2, /datum/data/record)) - var/t1 = sanitize(input("Please state diseases:", "Med. records", input_default(src.active2.fields["cdi"]), null) as text) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) - return - src.active2.fields["cdi"] = t1 - if("cdi_d") - if (istype(src.active2, /datum/data/record)) - var/t1 = sanitize(input("Please summarize diseases:", "Med. records", input_default(src.active2.fields["cdi_d"]), null) as message) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) - return - src.active2.fields["cdi_d"] = t1 - if("notes") - if (istype(src.active2, /datum/data/record)) - var/t1 = sanitize(input("Please summarize notes:", "Med. records", input_default(src.active2.fields["notes"]), null) as message) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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*SSD*
    \n\tActive
    \n\tPhysically Unfit
    \n\tDisabled
    ", src, 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 = sanitize(input("Please input DNA hash:", "Med. records", input_default(src.active1.fields["dna"]), null) as text) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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 = sanitize(input("Please input pathogen name:", "VirusDB", input_default(v.fields["name"]), null) as text) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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 = sanitize(input("Please input information about pathogen:", "VirusDB", input_default(v.fields["description"]), null) as message) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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(PDA_Manifest.len) - PDA_Manifest.Cut() - - 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) - //src.active2 = null - qdel(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["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 = sanitize(input("Add Comment:", "Med. records", null, null) as message) - if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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 [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
    [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 = sanitize(input("Search String: (Name, DNA, or ID)", "Med. records", null, null) as text) - if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || ((!in_range(src, usr)) && !issilicon(usr) && !isobserver(usr)))) - 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 [].", 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 - var/datum/data/record/record1 = null - var/datum/data/record/record2 = null - if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) - record1 = active1 - if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) - record2 = active2 - sleep(50) - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc ) - P.info = "
    Medical Record

    " - if (record1) - P.info += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"]) - P.name = text("Medical Record ([])", record1.fields["name"]) - else - P.info += "General Record Lost!
    " - P.name = "Medical Record" - if (record2) - P.info += text("
    \n
    Medical Data

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

    ", record2.fields["b_type"], record2.fields["b_dna"], record2.fields["mi_dis"], record2.fields["mi_dis_d"], record2.fields["ma_dis"], record2.fields["ma_dis_d"], record2.fields["alg"], record2.fields["alg_d"], record2.fields["cdi"], record2.fields["cdi_d"], decode(record2.fields["notes"])) - var/counter = 1 - while(record2.fields[text("com_[]", counter)]) - P.info += text("[]
    ", record2.fields[text("com_[]", counter)]) - counter++ - else - P.info += "Medical Record Lost!
    " - P.info += "
    " - src.printing = null - - src.updateUsrDialog() - -/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) - continue - - ..(severity) - - -/obj/machinery/computer/med_data/laptop - name = "Medical Laptop" - desc = "Cheap Nanotrasen Laptop." - icon_state = "medlaptop" - light_color = "#00b000" +//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" + light_color = "#315ab4" + req_one_access = list(access_medical, access_forensics_lockers) + circuit = /obj/item/weapon/circuitboard/med_data + allowed_checks = ALLOWED_CHECK_NONE + 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 + +/obj/machinery/computer/med_data/attackby(obj/item/O, user) + if(istype(O, /obj/item/weapon/card/id) && !scan) + usr.drop_item() + O.loc = src + scan = O + to_chat(user, "You insert [O].") + ..() + +/obj/machinery/computer/med_data/ui_interact(mob/user) + 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 = active1.fields["photo_f"] + var/icon/side = active1.fields["photo_s"] + 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, decode(src.active2.fields["notes"])) + var/counter = 1 + while(src.active2.fields[text("com_[]", counter)]) + dat += text("[]
    Delete Entry

    ", src.active2.fields[text("com_[]", counter)], src, counter) + 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) + dat += "
    Medical Robot Monitor
    " + dat += "Back" + dat += "
    Medical Robots:" + var/bdat = null + for(var/obj/machinery/bot/medbot/M in bots_list) + + 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],[bl.y]\] - [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[]", entity_ja(dat)), "window=med_rec") + onclose(user, "med_rec") + +/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 (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)) + usr.drop_item() + I.loc = 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 (isAI(usr)) + src.active1 = null + src.active2 = null + src.authenticated = usr.name + src.rank = "AI" + src.screen = 1 + + else if (isrobot(usr)) + 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 (isobserver(usr)) + src.active1 = null + src.active2 = null + src.authenticated = "Centcomm Agent" + src.rank = "Overseer" + 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) + //R = null + qdel(R) + //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 = sanitize(input("Please input fingerprint hash:", "Med. records", input_default(src.active1.fields["fingerprint"]), null) as text) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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) && !issilicon(usr) && !isobserver(usr)) || src.active1 != a1)) + return + src.active1.fields["age"] = t1 + if("mi_dis") + if (istype(src.active2, /datum/data/record)) + var/t1 = sanitize(input("Please input minor disabilities list:", "Med. records", input_default(src.active2.fields["mi_dis"]), null) as text) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) + return + src.active2.fields["mi_dis"] = t1 + if("mi_dis_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = sanitize(input("Please summarize minor dis.:", "Med. records", input_default(src.active2.fields["mi_dis_d"]), null) as message) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) + return + src.active2.fields["mi_dis_d"] = t1 + if("ma_dis") + if (istype(src.active2, /datum/data/record)) + var/t1 = sanitize(input("Please input major diabilities list:", "Med. records", input_default(src.active2.fields["ma_dis"]), null) as text) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) + return + src.active2.fields["ma_dis"] = t1 + if("ma_dis_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = sanitize(input("Please summarize major dis.:", "Med. records", input_default(src.active2.fields["ma_dis_d"]), null) as message) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) + return + src.active2.fields["ma_dis_d"] = t1 + if("alg") + if (istype(src.active2, /datum/data/record)) + var/t1 = sanitize(input("Please state allergies:", "Med. records", input_default(src.active2.fields["alg"]), null) as text) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) + return + src.active2.fields["alg"] = t1 + if("alg_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = sanitize(input("Please summarize allergies:", "Med. records", input_default(src.active2.fields["alg_d"]), null) as message) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) + return + src.active2.fields["alg_d"] = t1 + if("cdi") + if (istype(src.active2, /datum/data/record)) + var/t1 = sanitize(input("Please state diseases:", "Med. records", input_default(src.active2.fields["cdi"]), null) as text) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) + return + src.active2.fields["cdi"] = t1 + if("cdi_d") + if (istype(src.active2, /datum/data/record)) + var/t1 = sanitize(input("Please summarize diseases:", "Med. records", input_default(src.active2.fields["cdi_d"]), null) as message) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || src.active2 != a2)) + return + src.active2.fields["cdi_d"] = t1 + if("notes") + if (istype(src.active2, /datum/data/record)) + var/t1 = sanitize(input("Please summarize notes:", "Med. records", input_default(src.active2.fields["notes"]), null) as message) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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*SSD*
    \n\tActive
    \n\tPhysically Unfit
    \n\tDisabled
    ", src, 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 = sanitize(input("Please input DNA hash:", "Med. records", input_default(src.active1.fields["dna"]), null) as text) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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 = sanitize(input("Please input pathogen name:", "VirusDB", input_default(v.fields["name"]), null) as text) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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 = sanitize(input("Please input information about pathogen:", "VirusDB", input_default(v.fields["description"]), null) as message) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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(PDA_Manifest.len) + PDA_Manifest.Cut() + + 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) + //src.active2 = null + qdel(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["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 = sanitize(input("Add Comment:", "Med. records", null, null) as message) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || 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 [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
    [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 = sanitize(input("Search String: (Name, DNA, or ID)", "Med. records", null, null) as text) + if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || ((!in_range(src, usr)) && !issilicon(usr) && !isobserver(usr)))) + 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 [].", 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 + var/datum/data/record/record1 = null + var/datum/data/record/record2 = null + if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))) + record1 = active1 + if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))) + record2 = active2 + sleep(50) + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc ) + P.info = "
    Medical Record

    " + if (record1) + P.info += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"]) + P.name = text("Medical Record ([])", record1.fields["name"]) + else + P.info += "General Record Lost!
    " + P.name = "Medical Record" + if (record2) + P.info += text("
    \n
    Medical Data

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

    ", record2.fields["b_type"], record2.fields["b_dna"], record2.fields["mi_dis"], record2.fields["mi_dis_d"], record2.fields["ma_dis"], record2.fields["ma_dis_d"], record2.fields["alg"], record2.fields["alg_d"], record2.fields["cdi"], record2.fields["cdi_d"], decode(record2.fields["notes"])) + var/counter = 1 + while(record2.fields[text("com_[]", counter)]) + P.info += text("[]
    ", record2.fields[text("com_[]", counter)]) + counter++ + else + P.info += "Medical Record Lost!
    " + P.info += "
    " + src.printing = null + + src.updateUsrDialog() + +/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) + continue + + ..(severity) + + +/obj/machinery/computer/med_data/laptop + name = "Medical Laptop" + desc = "Cheap Nanotrasen Laptop." + icon_state = "medlaptop" + light_color = "#00b000" diff --git a/code/game/machinery/computer/power.dm b/code/game/machinery/computer/power.dm index e8fdf8139587..8c728aa17d82 100644 --- a/code/game/machinery/computer/power.dm +++ b/code/game/machinery/computer/power.dm @@ -1,96 +1,96 @@ -// the power monitoring computer -// for the moment, just report the status of all APCs in the same powernet -/obj/machinery/computer/monitor - name = "Power Monitoring Console" - desc = "It monitors power levels across the station." - icon = 'icons/obj/computer.dmi' - icon_state = "power" - light_color = "#ffcc33" - density = 1 - anchored = 1 - use_power = 2 - idle_power_usage = 20 - active_power_usage = 80 - circuit = /obj/item/weapon/circuitboard/powermonitor - var/datum/powernet/powernet = null - -//fix for issue 521, by QualityVan. -//someone should really look into why circuits have a powernet var, it's several kinds of retarded. -/obj/machinery/computer/monitor/atom_init() - . = ..() - var/obj/structure/cable/attached = null - var/turf/T = loc - if(isturf(T)) - attached = locate() in T - if(attached) - powernet = attached.get_powernet() - -/obj/machinery/computer/monitor/process() //oh shit, somehow we didnt end up with a powernet... lets look for one. - if(!powernet) - var/obj/structure/cable/attached = null - var/turf/T = loc - if(isturf(T)) - attached = locate() in T - if(attached) - powernet = attached.get_powernet() - return - -/obj/machinery/computer/monitor/ui_interact(mob/user) - - if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) ) - if (!issilicon(user) && !isobserver(user)) - user.unset_machine() - user << browse(null, "window=powcomp") - return - - - var/t = "Power Monitoring
    " - - t += "

    Refresh" - t += "

    Close" - - if(!powernet) - t += "\red No connection" - else - - var/list/L = list() - for(var/obj/machinery/power/terminal/term in powernet.nodes) - if(istype(term.master, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = term.master - L += A - - t += "
    Total power: [powernet.avail] W
    Total load: [num2text(powernet.viewload,10)] W
    " - - t += "" - - if(L.len > 0) - - t += "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) - - t += copytext(add_tspace("\The [A.area]", 30), 1, 30) - t += " [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"]
    " - - t += "
    " - - user << browse(entity_ja(t), "window=powcomp;size=450x900") - onclose(user, "powcomp") - - -/obj/machinery/computer/monitor/Topic(href, href_list) - if(href_list["close"]) - usr << browse(null, "window=powcomp") - usr.unset_machine(src) - return FALSE - - . = ..() - if(!.) - return - - if( href_list["update"] ) - src.updateDialog() - return +// the power monitoring computer +// for the moment, just report the status of all APCs in the same powernet +/obj/machinery/computer/monitor + name = "Power Monitoring Console" + desc = "It monitors power levels across the station." + icon = 'icons/obj/computer.dmi' + icon_state = "power" + light_color = "#ffcc33" + density = 1 + anchored = 1 + use_power = 2 + idle_power_usage = 20 + active_power_usage = 80 + circuit = /obj/item/weapon/circuitboard/powermonitor + var/datum/powernet/powernet = null + +//fix for issue 521, by QualityVan. +//someone should really look into why circuits have a powernet var, it's several kinds of retarded. +/obj/machinery/computer/monitor/atom_init() + . = ..() + var/obj/structure/cable/attached = null + var/turf/T = loc + if(isturf(T)) + attached = locate() in T + if(attached) + powernet = attached.get_powernet() + +/obj/machinery/computer/monitor/process() //oh shit, somehow we didnt end up with a powernet... lets look for one. + if(!powernet) + var/obj/structure/cable/attached = null + var/turf/T = loc + if(isturf(T)) + attached = locate() in T + if(attached) + powernet = attached.get_powernet() + return + +/obj/machinery/computer/monitor/ui_interact(mob/user) + + if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) ) + if (!issilicon(user) && !isobserver(user)) + user.unset_machine() + user << browse(null, "window=powcomp") + return + + + var/t = "Power Monitoring
    " + + t += "

    Refresh" + t += "

    Close" + + if(!powernet) + t += "\red No connection" + else + + var/list/L = list() + for(var/obj/machinery/power/terminal/term in powernet.nodes) + if(istype(term.master, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/A = term.master + L += A + + t += "
    Total power: [powernet.avail] W
    Total load: [num2text(powernet.viewload,10)] W
    " + + t += "" + + if(L.len > 0) + + t += "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) + + t += copytext(add_tspace("\The [A.area]", 30), 1, 30) + t += " [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"]
    " + + t += "
    " + + user << browse(entity_ja(t), "window=powcomp;size=450x900") + onclose(user, "powcomp") + + +/obj/machinery/computer/monitor/Topic(href, href_list) + if(href_list["close"]) + usr << browse(null, "window=powcomp") + usr.unset_machine(src) + return FALSE + + . = ..() + if(!.) + return + + if( href_list["update"] ) + src.updateDialog() + return diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index cb1a26190a2a..3bbc52ee8c06 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -1,210 +1,210 @@ -//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" - light_color = "#a97faa" - 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 - -/obj/machinery/computer/robotics/ui_interact(mob/user) - if (src.z > ZLEVEL_EMPTY) - to_chat(user, "\red Unable to establish a connection: \black You're too far away from the station!") - return - - var/dat - if (src.temp) - dat = "[src.temp]

    Clear Screen" - else - if(screen == 0) - dat += "

    Cyborg Control Console


    " - dat += "1. Cyborg Status
    " - dat += "2. Emergency Full Destruct
    " - if(screen == 1) - for(var/mob/living/silicon/robot/R in silicon_list) - if(istype(R, /mob/living/silicon/robot/drone)) - continue //There's a specific console for drones. - if(istype(user, /mob/living/silicon/ai)) - if (R.connected_ai != user) - continue - 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) " - dat += "([R.canmove ? "Lockdown" : "Release"]) " - dat += "(Destroy)" - dat += "
    " - 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(entity_ja(dat), "window=computer;size=400x500") - onclose(user, "computer") - -/obj/machinery/computer/robotics/Topic(href, href_list) - . = ..() - if(!.) - return - - if (href_list["eject"]) - src.temp = {"Destroy Robots?
    -
    \[Swipe ID to initiate destruction sequence\]
    - Cancel"} - - else if (href_list["eject2"]) - if(allowed(usr)) - if (!status) - message_admins("\blue [key_name_admin(usr)] has initiated the global cyborg killswitch! JMP") - log_game("\blue [key_name(usr)] has initiated the global cyborg killswitch!") - src.status = 1 - src.start_sequence() - src.temp = null - else - to_chat(usr, "\red 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) - to_chat(R, "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered.") - R.ResetSecurityCodes() - - else - message_admins("\blue [key_name_admin(usr)] (JMP) detonated [R.name]! (JMP)") - log_game("\blue [key_name_admin(usr)] detonated [R.name]!") - R.self_destruct() - else - to_chat(usr, "\red 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("\blue [key_name_admin(usr)] (JMP) [R.canmove ? "locked down" : "released"] [R.name]! (JMP)") - log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [R.name]!") - R.canmove = !R.canmove - if (R.lockcharge) - R.clear_alert("locked") - // R.cell.charge = R.lockcharge - R.lockcharge = !R.lockcharge - to_chat(R, "Your lockdown has been lifted!") - else - R.throw_alert("locked") - R.lockcharge = !R.lockcharge - // R.cell.charge = 0 - to_chat(R, "You have been locked down!") - - else - to_chat(usr, "\red Access Denied.") - - else if (href_list["magbot"]) - if(src.allowed(usr)) - var/mob/living/silicon/robot/R = locate(href_list["magbot"]) - if(R) - 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("\blue [key_name_admin(usr)] emagged [R.name] using robotic console!") - log_game("[key_name(usr)] emagged [R.name] using robotic console!") - R.emagged = 1 - if(R.mind.special_role) - R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes - - src.updateUsrDialog() - -/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 silicon_list) - if(!R.scrambledcodes && !istype(R, /mob/living/silicon/robot/drone)) - R.self_destruct() - - return +//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" + light_color = "#a97faa" + 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 + +/obj/machinery/computer/robotics/ui_interact(mob/user) + if (src.z > ZLEVEL_EMPTY) + to_chat(user, "\red Unable to establish a connection: \black You're too far away from the station!") + return + + var/dat + if (src.temp) + dat = "[src.temp]

    Clear Screen" + else + if(screen == 0) + dat += "

    Cyborg Control Console


    " + dat += "1. Cyborg Status
    " + dat += "2. Emergency Full Destruct
    " + if(screen == 1) + for(var/mob/living/silicon/robot/R in silicon_list) + if(istype(R, /mob/living/silicon/robot/drone)) + continue //There's a specific console for drones. + if(istype(user, /mob/living/silicon/ai)) + if (R.connected_ai != user) + continue + 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) " + dat += "([R.canmove ? "Lockdown" : "Release"]) " + dat += "(Destroy)" + dat += "
    " + 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(entity_ja(dat), "window=computer;size=400x500") + onclose(user, "computer") + +/obj/machinery/computer/robotics/Topic(href, href_list) + . = ..() + if(!.) + return + + if (href_list["eject"]) + src.temp = {"Destroy Robots?
    +
    \[Swipe ID to initiate destruction sequence\]
    + Cancel"} + + else if (href_list["eject2"]) + if(allowed(usr)) + if (!status) + message_admins("\blue [key_name_admin(usr)] has initiated the global cyborg killswitch! JMP") + log_game("\blue [key_name(usr)] has initiated the global cyborg killswitch!") + src.status = 1 + src.start_sequence() + src.temp = null + else + to_chat(usr, "\red 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) + to_chat(R, "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered.") + R.ResetSecurityCodes() + + else + message_admins("\blue [key_name_admin(usr)] (JMP) detonated [R.name]! (JMP)") + log_game("\blue [key_name_admin(usr)] detonated [R.name]!") + R.self_destruct() + else + to_chat(usr, "\red 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("\blue [key_name_admin(usr)] (JMP) [R.canmove ? "locked down" : "released"] [R.name]! (JMP)") + log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [R.name]!") + R.canmove = !R.canmove + if (R.lockcharge) + R.clear_alert("locked") + // R.cell.charge = R.lockcharge + R.lockcharge = !R.lockcharge + to_chat(R, "Your lockdown has been lifted!") + else + R.throw_alert("locked") + R.lockcharge = !R.lockcharge + // R.cell.charge = 0 + to_chat(R, "You have been locked down!") + + else + to_chat(usr, "\red Access Denied.") + + else if (href_list["magbot"]) + if(src.allowed(usr)) + var/mob/living/silicon/robot/R = locate(href_list["magbot"]) + if(R) + 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("\blue [key_name_admin(usr)] emagged [R.name] using robotic console!") + log_game("[key_name(usr)] emagged [R.name] using robotic console!") + R.emagged = 1 + if(R.mind.special_role) + R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes + + src.updateUsrDialog() + +/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 silicon_list) + if(!R.scrambledcodes && !istype(R, /mob/living/silicon/robot/drone)) + R.self_destruct() + + return diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 8781340cb26f..8a4dd5175984 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -1,624 +1,624 @@ -//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" - light_color = "#a91515" - req_one_access = list(access_security, access_forensics_lockers) - circuit = /obj/item/weapon/circuitboard/secure_data - allowed_checks = ALLOWED_CHECK_NONE - 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 - - -/obj/machinery/computer/secure_data/attackby(obj/item/O, user) - if(istype(O, /obj/item/weapon/card/id) && !scan) - usr.drop_item() - O.loc = src - scan = O - to_chat(user, "You insert [O].") - else - ..() - -//Someone needs to break down the dat += into chunks instead of long ass lines. -/obj/machinery/computer/secure_data/ui_interact(mob/user) - if (src.z > ZLEVEL_EMPTY) - to_chat(user, "\red Unable to establish a connection: \black 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("Paroled") - 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) - dat += "Records Maintenance
    " - dat += "
    Delete All Records

    Back" - if(3.0) - dat += "
    Security Record

    " - if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) - if(istype(active1.fields["photo_f"], /icon)) - var/icon/front = active1.fields["photo_f"] - user << browse_rsc(front, "front.png") - if(istype(active1.fields["photo_s"], /icon)) - var/icon/side = active1.fields["photo_s"] - 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 \ - Home system: [active1.fields["home_system"]]
    \n \ - Citizenship: [active1.fields["citizenship"]]
    \n \ - Faction: [active1.fields["faction"]]
    \n \ - Religion: [active1.fields["religion"]]
    \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:
    \ -
    \n \ - Upload new photo: front side
    ") - 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, decode(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("Paroled") - 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[]", entity_ja(dat)), "window=secure_rec;size=600x400") - onclose(user, "secure_rec") - -/*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 - - 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(ishuman(usr) && !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)) - usr.drop_item() - I.loc = src - scan = I - - if("Log Out") - authenticated = null - screen = null - active1 = null - active2 = null - - if("Log In") - if(isAI(usr)) - src.active1 = null - src.active2 = null - src.authenticated = usr.name - src.rank = "AI" - src.screen = 1 - else if(isrobot(usr)) - 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 (isobserver(usr)) - src.active1 = null - src.active2 = null - src.authenticated = "Centcomm Agent" - src.rank = "Overseer" - src.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 = sanitize(input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text) - if(!t1 || is_not_allowed(usr)) - return - Perp = new/list() - t1 = lowertext_(t1) - var/list/components = splittext(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)) && !issilicon(usr) && !isobserver(usr))) - 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 - var/datum/data/record/record1 = null - var/datum/data/record/record2 = null - if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) - record1 = active1 - if ((istype(active2, /datum/data/record) && data_core.security.Find(active2))) - record2 = active2 - sleep(50) - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( loc ) - P.info = "
    Security Record

    " - if (record1) - P.info += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"]) - P.name = text("Security Record ([])", record1.fields["name"]) - else - P.info += "General Record Lost!
    " - P.name = "Security Record" - if (record2) - P.info += text("
    \n
    Security Data

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

    ", record2.fields["criminal"], record2.fields["mi_crim"], record2.fields["mi_crim_d"], record2.fields["ma_crim"], record2.fields["ma_crim_d"], decode(record2.fields["notes"])) - var/counter = 1 - while(record2.fields[text("com_[]", counter)]) - P.info += text("[]
    ", record2.fields[text("com_[]", counter)]) - counter++ - else - P.info += "Security Record Lost!
    " - P.info += "" - printing = null - updateUsrDialog() -//RECORD DELETE - if("Delete All Records") - temp = "" - temp += "Are you sure you wish to delete all Security records?
    " - temp += "Yes
    " - temp += "No" - - if("Purge All Records") - for(var/datum/data/record/R in data_core.security) - qdel(R) - temp = "All Security records deleted." - - if("Add Entry") - if(!istype(active2, /datum/data/record)) - return - var/a2 = active2 - var/t1 = sanitize(input("Add Comment:", "Secure. records", null, null) as message) - if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || active2 != a2)) - return FALSE - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - counter++ - active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
    [t1]") - - if("Delete Record (ALL)") - if(active1) - temp = "
    Are you sure you wish to delete the record (ALL)?
    " - temp += "Yes
    " - temp += "No" - - if("Delete Record (Security)") - if(active2) - temp = "
    Are you sure you wish to delete the record (Security Portion Only)?
    " - temp += "Yes
    " - temp += "No" - - 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) ))) - active2 = CreateSecurityRecord(active1.fields["name"], active1.fields["id"]) - screen = 3 - - if("New Record (General)") - active1 = CreateGeneralRecord() - active2 = null - -//FIELD FUNCTIONS - if("Edit Field") - if(is_not_allowed(usr)) - return - var/a1 = active1 - var/a2 = active2 - switch(href_list["field"]) - if("name") - if(istype(active1, /datum/data/record)) - var/t1 = sanitize(input("Please input name:", "Secure. records", input_default(active1.fields["name"]), null) as text) - if(!t1 || active1 != a1) - return FALSE - active1.fields["name"] = t1 - if("id") - if(istype(active2, /datum/data/record)) - var/t1 = sanitize(input("Please input id:", "Secure. records", input_default(active1.fields["id"]), null) as text) - if(!t1 || active1 != a1) - return FALSE - active1.fields["id"] = t1 - if("fingerprint") - if(istype(active1, /datum/data/record)) - var/t1 = sanitize(input("Please input fingerprint hash:", "Secure. records", input_default(active1.fields["fingerprint"]), null) as text) - if(!t1 || active1 != a1) - return FALSE - 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 || active1 != a1) - return FALSE - active1.fields["age"] = t1 - if("mi_crim") - if(istype(active2, /datum/data/record)) - var/t1 = sanitize(input("Please input minor disabilities list:", "Secure. records", input_default(active2.fields["mi_crim"]), null) as text) - if (!t1 || active2 != a2) - return FALSE - active2.fields["mi_crim"] = t1 - if("mi_crim_d") - if(istype(active2, /datum/data/record)) - var/t1 = sanitize(input("Please summarize minor dis.:", "Secure. records", input_default(active2.fields["mi_crim_d"]), null) as message) - if (!t1 || active2 != a2) - return FALSE - active2.fields["mi_crim_d"] = t1 - if("ma_crim") - if(istype(active2, /datum/data/record)) - var/t1 = sanitize(input("Please input major diabilities list:", "Secure. records", input_default(active2.fields["ma_crim"]), null) as text) - if (!t1 || active2 != a2) - return FALSE - active2.fields["ma_crim"] = t1 - if("ma_crim_d") - if (istype(active2, /datum/data/record)) - var/t1 = sanitize(input("Please summarize major dis.:", "Secure. records", input_default(active2.fields["ma_crim_d"]), null) as message) - if(!t1 || active2 != a2) - return FALSE - active2.fields["ma_crim_d"] = t1 - if("notes") - if(istype(active2, /datum/data/record)) - var/t1 = sanitize(input("Please summarize notes:", "Secure. records", input_default(active2.fields["notes"]), null) as message) - if (!t1 || active2 != a2) - return FALSE - active2.fields["notes"] = t1 - if("criminal") - if(istype(active2, /datum/data/record)) - temp = "
    Criminal Status:
    " - temp += "" - 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))) - temp = "
    Rank:
    " - temp += "
      " - for(var/rank in joblist) - 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/t1 = sanitize(input("Please enter race:", "General records", input_default(active1.fields["species"]), null) as message) - if(!t1 || is_not_allowed(usr) || (active1 != a1)) - return FALSE - active1.fields["species"] = t1 - if("photo_f") - if(istype(active1, /datum/data/record)) - if(active1 != a1) - return FALSE - var/icon/photo = get_photo(usr) - if(!photo) - return FALSE - qdel(active1.fields["photo_f"]) - active1.fields["photo_f"] = photo - if("photo_s") - if(istype(active1, /datum/data/record)) - if(active1 != a1) - return FALSE - var/icon/photo = get_photo(usr) - if(!photo) - return FALSE - qdel(active1.fields["photo_s"]) - active1.fields["photo_s"] = photo -//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 joblist) - active1.fields["real_rank"] = href_list["real_rank"] - - if ("Change Criminal Status") - if (active2) - for(var/mob/living/carbon/human/H in player_list) - H.hud_updateflag |= 1 << WANTED_HUD - switch(href_list["criminal2"]) - if("none") - active2.fields["criminal"] = "None" - if("arrest") - active2.fields["criminal"] = "*Arrest*" - if("incarcerated") - active2.fields["criminal"] = "Incarcerated" - if("paroled") - active2.fields["criminal"] = "Paroled" - if("released") - active2.fields["criminal"] = "Released" - - if ("Delete Record (Security) Execute") - if (active2) - qdel(active2) - - 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) - else - qdel(active1) - if (active2) - qdel(active2) - else - temp = "This function does not appear to be working at the moment. Our apologies." - - updateUsrDialog() - -/obj/machinery/computer/secure_data/proc/is_not_allowed(mob/user) - return !src.authenticated || user.stat || user.restrained() || (!in_range(src, user) && !issilicon(usr) && !isobserver(usr)) - -/obj/machinery/computer/secure_data/proc/get_photo(var/mob/user) - var/icon/I = null - var/obj/item/weapon/photo/P = null - if(issilicon(user)) - var/mob/living/silicon/S = user - if(!S.aiCamera) - return null - var/datum/picture/selection = S.aiCamera.selectpicture() - if(selection) - P = new() - P.construct(selection) - I = P.img - qdel(P) - else if(istype(user.get_active_hand(), /obj/item/weapon/photo)) - P = user.get_active_hand() - I = P.img - user.drop_from_inventory(P) - qdel(P) - return I - -/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", "Paroled", "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) - continue - - ..(severity) - -/obj/machinery/computer/secure_data/detective_computer - icon = 'icons/obj/computer.dmi' - icon_state = "messyfiles" +//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" + light_color = "#a91515" + req_one_access = list(access_security, access_forensics_lockers) + circuit = /obj/item/weapon/circuitboard/secure_data + allowed_checks = ALLOWED_CHECK_NONE + 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 + + +/obj/machinery/computer/secure_data/attackby(obj/item/O, user) + if(istype(O, /obj/item/weapon/card/id) && !scan) + usr.drop_item() + O.loc = src + scan = O + to_chat(user, "You insert [O].") + else + ..() + +//Someone needs to break down the dat += into chunks instead of long ass lines. +/obj/machinery/computer/secure_data/ui_interact(mob/user) + if (src.z > ZLEVEL_EMPTY) + to_chat(user, "\red Unable to establish a connection: \black 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("Paroled") + 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) + dat += "Records Maintenance
    " + dat += "
    Delete All Records

    Back" + if(3.0) + dat += "
    Security Record

    " + if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) + if(istype(active1.fields["photo_f"], /icon)) + var/icon/front = active1.fields["photo_f"] + user << browse_rsc(front, "front.png") + if(istype(active1.fields["photo_s"], /icon)) + var/icon/side = active1.fields["photo_s"] + 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 \ + Home system: [active1.fields["home_system"]]
    \n \ + Citizenship: [active1.fields["citizenship"]]
    \n \ + Faction: [active1.fields["faction"]]
    \n \ + Religion: [active1.fields["religion"]]
    \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:
    \ +
    \n \ + Upload new photo: front side
    ") + 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, decode(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("Paroled") + 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[]", entity_ja(dat)), "window=secure_rec;size=600x400") + onclose(user, "secure_rec") + +/*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 + + 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(ishuman(usr) && !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)) + usr.drop_item() + I.loc = src + scan = I + + if("Log Out") + authenticated = null + screen = null + active1 = null + active2 = null + + if("Log In") + if(isAI(usr)) + src.active1 = null + src.active2 = null + src.authenticated = usr.name + src.rank = "AI" + src.screen = 1 + else if(isrobot(usr)) + 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 (isobserver(usr)) + src.active1 = null + src.active2 = null + src.authenticated = "Centcomm Agent" + src.rank = "Overseer" + src.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 = sanitize(input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text) + if(!t1 || is_not_allowed(usr)) + return + Perp = new/list() + t1 = lowertext_(t1) + var/list/components = splittext(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)) && !issilicon(usr) && !isobserver(usr))) + 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 + var/datum/data/record/record1 = null + var/datum/data/record/record2 = null + if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) + record1 = active1 + if ((istype(active2, /datum/data/record) && data_core.security.Find(active2))) + record2 = active2 + sleep(50) + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( loc ) + P.info = "
    Security Record

    " + if (record1) + P.info += text("Name: [] ID: []
    \nSex: []
    \nAge: []
    \nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"]) + P.name = text("Security Record ([])", record1.fields["name"]) + else + P.info += "General Record Lost!
    " + P.name = "Security Record" + if (record2) + P.info += text("
    \n
    Security Data

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

    ", record2.fields["criminal"], record2.fields["mi_crim"], record2.fields["mi_crim_d"], record2.fields["ma_crim"], record2.fields["ma_crim_d"], decode(record2.fields["notes"])) + var/counter = 1 + while(record2.fields[text("com_[]", counter)]) + P.info += text("[]
    ", record2.fields[text("com_[]", counter)]) + counter++ + else + P.info += "Security Record Lost!
    " + P.info += "" + printing = null + updateUsrDialog() +//RECORD DELETE + if("Delete All Records") + temp = "" + temp += "Are you sure you wish to delete all Security records?
    " + temp += "Yes
    " + temp += "No" + + if("Purge All Records") + for(var/datum/data/record/R in data_core.security) + qdel(R) + temp = "All Security records deleted." + + if("Add Entry") + if(!istype(active2, /datum/data/record)) + return + var/a2 = active2 + var/t1 = sanitize(input("Add Comment:", "Secure. records", null, null) as message) + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && !issilicon(usr) && !isobserver(usr)) || active2 != a2)) + return FALSE + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + counter++ + active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
    [t1]") + + if("Delete Record (ALL)") + if(active1) + temp = "
    Are you sure you wish to delete the record (ALL)?
    " + temp += "Yes
    " + temp += "No" + + if("Delete Record (Security)") + if(active2) + temp = "
    Are you sure you wish to delete the record (Security Portion Only)?
    " + temp += "Yes
    " + temp += "No" + + 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) ))) + active2 = CreateSecurityRecord(active1.fields["name"], active1.fields["id"]) + screen = 3 + + if("New Record (General)") + active1 = CreateGeneralRecord() + active2 = null + +//FIELD FUNCTIONS + if("Edit Field") + if(is_not_allowed(usr)) + return + var/a1 = active1 + var/a2 = active2 + switch(href_list["field"]) + if("name") + if(istype(active1, /datum/data/record)) + var/t1 = sanitize(input("Please input name:", "Secure. records", input_default(active1.fields["name"]), null) as text) + if(!t1 || active1 != a1) + return FALSE + active1.fields["name"] = t1 + if("id") + if(istype(active2, /datum/data/record)) + var/t1 = sanitize(input("Please input id:", "Secure. records", input_default(active1.fields["id"]), null) as text) + if(!t1 || active1 != a1) + return FALSE + active1.fields["id"] = t1 + if("fingerprint") + if(istype(active1, /datum/data/record)) + var/t1 = sanitize(input("Please input fingerprint hash:", "Secure. records", input_default(active1.fields["fingerprint"]), null) as text) + if(!t1 || active1 != a1) + return FALSE + 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 || active1 != a1) + return FALSE + active1.fields["age"] = t1 + if("mi_crim") + if(istype(active2, /datum/data/record)) + var/t1 = sanitize(input("Please input minor disabilities list:", "Secure. records", input_default(active2.fields["mi_crim"]), null) as text) + if (!t1 || active2 != a2) + return FALSE + active2.fields["mi_crim"] = t1 + if("mi_crim_d") + if(istype(active2, /datum/data/record)) + var/t1 = sanitize(input("Please summarize minor dis.:", "Secure. records", input_default(active2.fields["mi_crim_d"]), null) as message) + if (!t1 || active2 != a2) + return FALSE + active2.fields["mi_crim_d"] = t1 + if("ma_crim") + if(istype(active2, /datum/data/record)) + var/t1 = sanitize(input("Please input major diabilities list:", "Secure. records", input_default(active2.fields["ma_crim"]), null) as text) + if (!t1 || active2 != a2) + return FALSE + active2.fields["ma_crim"] = t1 + if("ma_crim_d") + if (istype(active2, /datum/data/record)) + var/t1 = sanitize(input("Please summarize major dis.:", "Secure. records", input_default(active2.fields["ma_crim_d"]), null) as message) + if(!t1 || active2 != a2) + return FALSE + active2.fields["ma_crim_d"] = t1 + if("notes") + if(istype(active2, /datum/data/record)) + var/t1 = sanitize(input("Please summarize notes:", "Secure. records", input_default(active2.fields["notes"]), null) as message) + if (!t1 || active2 != a2) + return FALSE + active2.fields["notes"] = t1 + if("criminal") + if(istype(active2, /datum/data/record)) + temp = "
    Criminal Status:
    " + temp += "" + 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))) + temp = "
    Rank:
    " + temp += "
      " + for(var/rank in joblist) + 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/t1 = sanitize(input("Please enter race:", "General records", input_default(active1.fields["species"]), null) as message) + if(!t1 || is_not_allowed(usr) || (active1 != a1)) + return FALSE + active1.fields["species"] = t1 + if("photo_f") + if(istype(active1, /datum/data/record)) + if(active1 != a1) + return FALSE + var/icon/photo = get_photo(usr) + if(!photo) + return FALSE + qdel(active1.fields["photo_f"]) + active1.fields["photo_f"] = photo + if("photo_s") + if(istype(active1, /datum/data/record)) + if(active1 != a1) + return FALSE + var/icon/photo = get_photo(usr) + if(!photo) + return FALSE + qdel(active1.fields["photo_s"]) + active1.fields["photo_s"] = photo +//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 joblist) + active1.fields["real_rank"] = href_list["real_rank"] + + if ("Change Criminal Status") + if (active2) + for(var/mob/living/carbon/human/H in player_list) + H.hud_updateflag |= 1 << WANTED_HUD + switch(href_list["criminal2"]) + if("none") + active2.fields["criminal"] = "None" + if("arrest") + active2.fields["criminal"] = "*Arrest*" + if("incarcerated") + active2.fields["criminal"] = "Incarcerated" + if("paroled") + active2.fields["criminal"] = "Paroled" + if("released") + active2.fields["criminal"] = "Released" + + if ("Delete Record (Security) Execute") + if (active2) + qdel(active2) + + 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) + else + qdel(active1) + if (active2) + qdel(active2) + else + temp = "This function does not appear to be working at the moment. Our apologies." + + updateUsrDialog() + +/obj/machinery/computer/secure_data/proc/is_not_allowed(mob/user) + return !src.authenticated || user.stat || user.restrained() || (!in_range(src, user) && !issilicon(usr) && !isobserver(usr)) + +/obj/machinery/computer/secure_data/proc/get_photo(var/mob/user) + var/icon/I = null + var/obj/item/weapon/photo/P = null + if(issilicon(user)) + var/mob/living/silicon/S = user + if(!S.aiCamera) + return null + var/datum/picture/selection = S.aiCamera.selectpicture() + if(selection) + P = new() + P.construct(selection) + I = P.img + qdel(P) + else if(istype(user.get_active_hand(), /obj/item/weapon/photo)) + P = user.get_active_hand() + I = P.img + user.drop_from_inventory(P) + qdel(P) + return I + +/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", "Paroled", "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) + continue + + ..(severity) + +/obj/machinery/computer/secure_data/detective_computer + icon = 'icons/obj/computer.dmi' + icon_state = "messyfiles" diff --git a/code/game/machinery/computer/shuttle.dm b/code/game/machinery/computer/shuttle.dm index 15baa332a4d1..e555a1e77ad7 100644 --- a/code/game/machinery/computer/shuttle.dm +++ b/code/game/machinery/computer/shuttle.dm @@ -1,69 +1,69 @@ -/obj/machinery/computer/shuttle - name = "Shuttle" - desc = "For shuttle control." - icon_state = "shuttle" - var/auth_need = 3.0 - var/list/authorized = list() - - light_color = "#7BF9FF" - - -/obj/machinery/computer/shuttle/attackby(obj/item/weapon/card/W, mob/user) - if(stat & (BROKEN|NOPOWER)) return - if ((!( istype(W, /obj/item/weapon/card) ) || !( ticker ) || SSshuttle.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 - 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 - 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(SSshuttle.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("\blue 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") - to_chat(world, "\blue Alert: Shuttle launch time shortened to 10 seconds!") - SSshuttle.online = 1 - SSshuttle.settimeleft(10) - src.authorized.Cut() - - if("Repeal") - src.authorized -= W:registered_name - to_chat(world, text("\blue Alert: [] authorizations needed until shuttle is launched early", src.auth_need - src.authorized.len)) - - if("Abort") - to_chat(world, "\blue All authorizations to shortening time for shuttle launch have been revoked!") - src.authorized.Cut() - - else if (istype(W, /obj/item/weapon/card/emag) && !emagged) - var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel") - - if(!emagged && SSshuttle.location == 1 && user.get_active_hand() == W) - switch(choice) - if("Launch") - to_chat(world, "\blue Alert: Shuttle launch time shortened to 10 seconds!") - SSshuttle.settimeleft( 10 ) - emagged = 1 - if("Cancel") - return - return +/obj/machinery/computer/shuttle + name = "Shuttle" + desc = "For shuttle control." + icon_state = "shuttle" + var/auth_need = 3.0 + var/list/authorized = list() + + light_color = "#7BF9FF" + + +/obj/machinery/computer/shuttle/attackby(obj/item/weapon/card/W, mob/user) + if(stat & (BROKEN|NOPOWER)) return + if ((!( istype(W, /obj/item/weapon/card) ) || !( ticker ) || SSshuttle.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 + 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 + 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(SSshuttle.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("\blue 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") + to_chat(world, "\blue Alert: Shuttle launch time shortened to 10 seconds!") + SSshuttle.online = 1 + SSshuttle.settimeleft(10) + src.authorized.Cut() + + if("Repeal") + src.authorized -= W:registered_name + to_chat(world, text("\blue Alert: [] authorizations needed until shuttle is launched early", src.auth_need - src.authorized.len)) + + if("Abort") + to_chat(world, "\blue All authorizations to shortening time for shuttle launch have been revoked!") + src.authorized.Cut() + + else if (istype(W, /obj/item/weapon/card/emag) && !emagged) + var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel") + + if(!emagged && SSshuttle.location == 1 && user.get_active_hand() == W) + switch(choice) + if("Launch") + to_chat(world, "\blue Alert: Shuttle launch time shortened to 10 seconds!") + SSshuttle.settimeleft( 10 ) + emagged = 1 + if("Cancel") + return + return diff --git a/code/game/machinery/computer/specops_shuttle.dm b/code/game/machinery/computer/specops_shuttle.dm index 0b7daa4043e7..a3a1dbf45ef4 100644 --- a/code/game/machinery/computer/specops_shuttle.dm +++ b/code/game/machinery/computer/specops_shuttle.dm @@ -1,261 +1,261 @@ -//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 = "special operations shuttle control console" - icon = 'icons/obj/computer.dmi' - icon_state = "shuttle" - light_color = "#00ffff" - req_access = list(access_cent_specops) - var/temp = null - var/hacked = 0 - var/allowedtocall = 0 - var/specops_shuttle_timereset = 0 - -/proc/specops_return() - var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky. - announcer.config(list("Response Team" = 0)) - - 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) - announcer.autosay(message, "A.L.I.C.E.", "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\"" - announcer.autosay(message, "A.L.I.C.E.", "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 - - var/area/start_location = locate(/area/shuttle/specops/station) - var/area/end_location = locate(/area/shuttle/specops/centcom) - - SSshuttle.undock_act(start_location) - SSshuttle.undock_act(/area/hallway/secondary/entry, "arrival_specops") - - sleep(10) - - 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) - - for(var/mob/living/carbon/bug in end_location) // If someone somehow is still in the shuttle's docking area... - bug.gib() - - for(var/mob/living/simple_animal/pest in end_location) // And for the other kind of bug... - pest.gib() - - 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, "\red You have arrived at Central Command. Operation has ended!") - - SSshuttle.dock_act(end_location) - SSshuttle.dock_act(/area/centcom/living, "centcomm_specops") - - specops_shuttle_at_station = 0 - - for(var/obj/machinery/computer/specops_shuttle/S in computer_list) - S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY - - qdel(announcer) - -/proc/specops_process() - var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky. - announcer.config(list("Response Team" = 0)) - - 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) - announcer.autosay(message, "A.L.I.C.E.", "Response Team") -// message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" -// announcer.autosay(message, "A.L.I.C.E.", "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\"" - announcer.autosay(message, "A.L.I.C.E.", "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, "\red The Special Operations shuttle is unable to leave.") - return - - var/area/start_location = locate(/area/shuttle/specops/centcom) - var/area/end_location = locate(/area/shuttle/specops/station) - - SSshuttle.undock_act(start_location) - SSshuttle.undock_act(/area/centcom/living, "centcomm_specops") - - sleep(10) - - 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) - - SSshuttle.dock_act(end_location) - SSshuttle.dock_act(/area/hallway/secondary/entry, "arrival_specops") - - for(var/turf/T in get_area_turfs(end_location) ) - var/mob/M = locate(/mob) in T - to_chat(M, "\red You have arrived to [station_name]. Commence operation!") - - for(var/obj/machinery/computer/specops_shuttle/S in computer_list) - 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 computer_list) - if(world.timeofday <= S.specops_shuttle_timereset) - return 0 - return 1 - -/obj/machinery/computer/specops_shuttle/attackby(I, user) - if(istype(I,/obj/item/weapon/card/emag)) - to_chat(user, "\blue 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/ui_interact(mob/user) - 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(entity_ja(dat), "window=computer;size=575x450") - onclose(user, "computer") - -/obj/machinery/computer/specops_shuttle/Topic(href, href_list) - . = ..() - if(!. || !allowed(usr)) - return - - 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, "\blue 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) - to_chat(usr, "\blue [-((world.timeofday - specops_shuttle_timereset) / 10) / 60] minutes remain!") - to_chat(usr, "\blue [-(world.timeofday - specops_shuttle_timereset) / 10] seconds remain!") - return FALSE - - to_chat(usr, "\blue The Special Operations shuttle will arrive at Central Command in [(SPECOPS_MOVETIME / 10)] seconds.") - - temp += "Shuttle departing.

    OK" - - 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, "\red The Special Operations shuttle is unable to leave.") - return FALSE - - to_chat(usr, "\blue The Special Operations shuttle will arrive on [station_name] in [(SPECOPS_MOVETIME/10)] seconds.") - - temp += "Shuttle departing.

    OK" - - specops_shuttle_moving_to_station = 1 - - specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME - spawn(0) - specops_process() - - else if (href_list["mainmenu"]) - temp = null - - updateUsrDialog() +//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 = "special operations shuttle control console" + icon = 'icons/obj/computer.dmi' + icon_state = "shuttle" + light_color = "#00ffff" + req_access = list(access_cent_specops) + var/temp = null + var/hacked = 0 + var/allowedtocall = 0 + var/specops_shuttle_timereset = 0 + +/proc/specops_return() + var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky. + announcer.config(list("Response Team" = 0)) + + 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) + announcer.autosay(message, "A.L.I.C.E.", "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\"" + announcer.autosay(message, "A.L.I.C.E.", "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 + + var/area/start_location = locate(/area/shuttle/specops/station) + var/area/end_location = locate(/area/shuttle/specops/centcom) + + SSshuttle.undock_act(start_location) + SSshuttle.undock_act(/area/hallway/secondary/entry, "arrival_specops") + + sleep(10) + + 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) + + for(var/mob/living/carbon/bug in end_location) // If someone somehow is still in the shuttle's docking area... + bug.gib() + + for(var/mob/living/simple_animal/pest in end_location) // And for the other kind of bug... + pest.gib() + + 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, "\red You have arrived at Central Command. Operation has ended!") + + SSshuttle.dock_act(end_location) + SSshuttle.dock_act(/area/centcom/living, "centcomm_specops") + + specops_shuttle_at_station = 0 + + for(var/obj/machinery/computer/specops_shuttle/S in computer_list) + S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY + + qdel(announcer) + +/proc/specops_process() + var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky. + announcer.config(list("Response Team" = 0)) + + 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) + announcer.autosay(message, "A.L.I.C.E.", "Response Team") +// message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" +// announcer.autosay(message, "A.L.I.C.E.", "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\"" + announcer.autosay(message, "A.L.I.C.E.", "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, "\red The Special Operations shuttle is unable to leave.") + return + + var/area/start_location = locate(/area/shuttle/specops/centcom) + var/area/end_location = locate(/area/shuttle/specops/station) + + SSshuttle.undock_act(start_location) + SSshuttle.undock_act(/area/centcom/living, "centcomm_specops") + + sleep(10) + + 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) + + SSshuttle.dock_act(end_location) + SSshuttle.dock_act(/area/hallway/secondary/entry, "arrival_specops") + + for(var/turf/T in get_area_turfs(end_location) ) + var/mob/M = locate(/mob) in T + to_chat(M, "\red You have arrived to [station_name]. Commence operation!") + + for(var/obj/machinery/computer/specops_shuttle/S in computer_list) + 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 computer_list) + if(world.timeofday <= S.specops_shuttle_timereset) + return 0 + return 1 + +/obj/machinery/computer/specops_shuttle/attackby(I, user) + if(istype(I,/obj/item/weapon/card/emag)) + to_chat(user, "\blue 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/ui_interact(mob/user) + 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(entity_ja(dat), "window=computer;size=575x450") + onclose(user, "computer") + +/obj/machinery/computer/specops_shuttle/Topic(href, href_list) + . = ..() + if(!. || !allowed(usr)) + return + + 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, "\blue 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) + to_chat(usr, "\blue [-((world.timeofday - specops_shuttle_timereset) / 10) / 60] minutes remain!") + to_chat(usr, "\blue [-(world.timeofday - specops_shuttle_timereset) / 10] seconds remain!") + return FALSE + + to_chat(usr, "\blue The Special Operations shuttle will arrive at Central Command in [(SPECOPS_MOVETIME / 10)] seconds.") + + temp += "Shuttle departing.

    OK" + + 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, "\red The Special Operations shuttle is unable to leave.") + return FALSE + + to_chat(usr, "\blue The Special Operations shuttle will arrive on [station_name] in [(SPECOPS_MOVETIME/10)] seconds.") + + temp += "Shuttle departing.

    OK" + + specops_shuttle_moving_to_station = 1 + + specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME + spawn(0) + specops_process() + + else if (href_list["mainmenu"]) + temp = null + + updateUsrDialog() diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 39342ef02b80..87c87b70de6c 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -1,99 +1,99 @@ - -/obj/machinery/computer/station_alert - name = "Station Alert Console" - desc = "Used to access the station's automated alert system." - icon_state = "alert:0" - light_color = "#e6ffff" - circuit = /obj/item/weapon/circuitboard/stationalert - var/alarms = list("Fire"=list(), "Atmosphere"=list(), "Power"=list()) - -/obj/machinery/computer/station_alert/atom_init() - . = ..() - station_alert_list += src - -/obj/machinery/computer/station_alert/Destroy() - station_alert_list -= src - return ..() - -/obj/machinery/computer/station_alert/ui_interact(mob/user) - var/dat = "Current Station Alerts\n" - dat += "Close

    " - 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] - dat += "" - dat += "• " - dat += "[A.name]" - if (sources.len > 1) - dat += text(" - [] sources", sources.len) - dat += "
    \n" - else - dat += "-- All Systems Nominal
    \n" - dat += "
    \n" - user << browse(entity_ja(dat), "window=alerts") - onclose(user, "alerts") - -/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, 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(class, area/A, 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() - update_icon() - ..() - return - -/obj/machinery/computer/station_alert/update_icon() - if (stat & NOPOWER) - icon_state = "atmos0" - else if(stat & BROKEN) - icon_state = "atmosb" - else - 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" + +/obj/machinery/computer/station_alert + name = "Station Alert Console" + desc = "Used to access the station's automated alert system." + icon_state = "alert:0" + light_color = "#e6ffff" + circuit = /obj/item/weapon/circuitboard/stationalert + var/alarms = list("Fire"=list(), "Atmosphere"=list(), "Power"=list()) + +/obj/machinery/computer/station_alert/atom_init() + . = ..() + station_alert_list += src + +/obj/machinery/computer/station_alert/Destroy() + station_alert_list -= src + return ..() + +/obj/machinery/computer/station_alert/ui_interact(mob/user) + var/dat = "Current Station Alerts\n" + dat += "Close

    " + 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] + dat += "" + dat += "• " + dat += "[A.name]" + if (sources.len > 1) + dat += text(" - [] sources", sources.len) + dat += "
    \n" + else + dat += "-- All Systems Nominal
    \n" + dat += "
    \n" + user << browse(entity_ja(dat), "window=alerts") + onclose(user, "alerts") + +/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, 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(class, area/A, 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() + update_icon() + ..() + return + +/obj/machinery/computer/station_alert/update_icon() + if (stat & NOPOWER) + icon_state = "atmos0" + else if(stat & BROKEN) + icon_state = "atmosb" + else + 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" diff --git a/code/game/machinery/computer/syndicate_specops_shuttle.dm b/code/game/machinery/computer/syndicate_specops_shuttle.dm index 002d6e8cc0bf..e18a5d56284d 100644 --- a/code/game/machinery/computer/syndicate_specops_shuttle.dm +++ b/code/game/machinery/computer/syndicate_specops_shuttle.dm @@ -1,153 +1,153 @@ -//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 - -/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/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, "\red The Syndicate Elite shuttle is unable to leave.") - return - - sleep(600) - - 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) - - for(var/mob/living/carbon/bug in end_location) // If someone somehow is still in the shuttle's docking area... - bug.gib() - - for(var/mob/living/simple_animal/pest in end_location) // And for the other kind of bug... - pest.gib() - - 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, "\red 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/attackby(I, user) - if(istype(I,/obj/item/weapon/card/emag)) - to_chat(user, "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals.") - else - return attack_hand(user) - -/obj/machinery/computer/syndicate_elite_shuttle/ui_interact(mob/user) - 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(entity_ja(dat), "window=computer;size=575x450") - onclose(user, "computer") - -/obj/machinery/computer/syndicate_elite_shuttle/Topic(href, href_list) - . = ..() - if(!. || !allowed(usr)) - return - - 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, "\blue The Syndicate will not allow the Elite Squad shuttle to return.") - return FALSE - - 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, "\red The Syndicate Elite shuttle is unable to leave.") - return FALSE - - to_chat(usr, "\blue The Syndicate Elite shuttle will arrive on [station_name] in [(SYNDICATE_ELITE_MOVETIME/10)] seconds.") - - temp = "Shuttle departing.

    OK" - - 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 - - updateUsrDialog() +//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 + +/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/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, "\red The Syndicate Elite shuttle is unable to leave.") + return + + sleep(600) + + 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) + + for(var/mob/living/carbon/bug in end_location) // If someone somehow is still in the shuttle's docking area... + bug.gib() + + for(var/mob/living/simple_animal/pest in end_location) // And for the other kind of bug... + pest.gib() + + 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, "\red 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/attackby(I, user) + if(istype(I,/obj/item/weapon/card/emag)) + to_chat(user, "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals.") + else + return attack_hand(user) + +/obj/machinery/computer/syndicate_elite_shuttle/ui_interact(mob/user) + 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(entity_ja(dat), "window=computer;size=575x450") + onclose(user, "computer") + +/obj/machinery/computer/syndicate_elite_shuttle/Topic(href, href_list) + . = ..() + if(!. || !allowed(usr)) + return + + 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, "\blue The Syndicate will not allow the Elite Squad shuttle to return.") + return FALSE + + 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, "\red The Syndicate Elite shuttle is unable to leave.") + return FALSE + + to_chat(usr, "\blue The Syndicate Elite shuttle will arrive on [station_name] in [(SYNDICATE_ELITE_MOVETIME/10)] seconds.") + + temp = "Shuttle departing.

    OK" + + 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 + + updateUsrDialog() diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 87636af3b2a4..0c9e572a8ec5 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -1,803 +1,803 @@ -//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 // user-friendly names of components - var/state = 1 - -// unfortunately, we have to instance the objects really quickly to get the names -// fortunately, this is only called once when the board is added and the items are immediately GC'd -// and none of the parts do much in their constructors -/obj/machinery/constructable_frame/proc/update_namelist() - if(!req_components) - return - - req_component_names = new() - for(var/tname in req_components) - var/path = tname - var/obj/O = new path() - req_component_names[tname] = O.name - -/obj/machinery/constructable_frame/proc/get_req_components_amt() - var/amt = 0 - for(var/path in req_components) - amt += req_components[path] - return amt - -// update description of required components remaining -/obj/machinery/constructable_frame/proc/update_req_desc() - if(!req_components || !req_component_names) - return - - var/hasContent = 0 - desc = "Requires" - for(var/i = 1 to req_components.len) - var/tname = req_components[i] - var/amt = req_components[tname] - if(amt == 0) - continue - var/use_and = i == req_components.len - desc += "[(hasContent ? (use_and ? ", and" : ",") : "")] [amt] [amt == 1 ? req_component_names[tname] : "[req_component_names[tname]]\s"]" - hasContent = 1 - - if(!hasContent) - desc = "Does not require any more components." - else - desc += "." - -/obj/machinery/constructable_frame/machine_frame/attackby(obj/item/P, mob/user) - if(P.crit_fail) - to_chat(user, "This part is faulty, you cannot add this to the machine!") - return - switch(state) - if(1) - if(istype(P, /obj/item/weapon/circuitboard)) - to_chat(user, "The frame needs wiring first!") - return - - else if(istype(P, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = P - if(C.get_amount() < 5) - to_chat(user, "You need five length of cable to wire the frame!") - return - if(user.is_busy()) return - playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) - to_chat(user, "You start to add cables to the frame.") - if(do_after(user, 20/P.toolspeed, target = src)) - if(state == 1) - if(!C.use(5)) - return - - to_chat(user, "You add cables to the frame.") - state = 2 - icon_state = "box_1" - - else if(istype(P, /obj/item/weapon/screwdriver) && !anchored) - if(user.is_busy()) return - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - user.visible_message("[user] disassembles the frame.", \ - "You start to disassemble the frame...", "You hear banging and clanking.") - if(do_after(user, 40/P.toolspeed, target = src)) - if(state == 1) - to_chat(user, "You disassemble the frame.") - var/obj/item/stack/sheet/metal/M = new (loc, 5) - M.add_fingerprint(user) - qdel(src) - - else if(istype(P, /obj/item/weapon/wrench)) - if(user.is_busy()) return - to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - if(do_after(user, 40/P.toolspeed, target = src)) - if(state == 1) - to_chat(user, "You [anchored ? "un" : ""]secure [name].") - anchored = !anchored - if(2) - if(istype(P, /obj/item/weapon/wrench)) - if(user.is_busy()) return - to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - if(do_after(user, 40/P.toolspeed, target = src)) - to_chat(user, "You [anchored ? "un" : ""]secure [name].") - anchored = !anchored - - if(istype(P, /obj/item/weapon/circuitboard)) - if(!anchored) - to_chat(user, "The frame needs to be secured first!") - return - var/obj/item/weapon/circuitboard/B = P - if(B.board_type == "machine") - if(!user.drop_item()) - return - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - to_chat(user, "You add the circuit board to the frame.") - circuit = P - P.loc = src - icon_state = "box_2" - state = 3 - components = list() - req_components = circuit.req_components.Copy() - update_namelist() - update_req_desc() - else - to_chat(user, "This frame does not accept circuit boards of this type!") - if(istype(P, /obj/item/weapon/wirecutters)) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) - to_chat(user, "You remove the cables.") - state = 1 - icon_state = "box_0" - new /obj/item/stack/cable_coil/red(loc, 5) - - if(3) - if(istype(P, /obj/item/weapon/crowbar)) - playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) - state = 2 - circuit.loc = src.loc - components.Remove(circuit) - 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 - icon_state = "box_1" - - 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(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - var/obj/machinery/new_machine = new src.circuit.build_path(src.loc) - new_machine.construction() - for(var/obj/O in new_machine.component_parts) - qdel(O) - new_machine.component_parts = list() - for(var/obj/O in src) - O.loc = null - new_machine.component_parts += O - circuit.loc = null - new_machine.RefreshParts() - qdel(src) - - if(istype(P, /obj/item/weapon/storage/part_replacer) && P.contents.len && get_req_components_amt()) - var/obj/item/weapon/storage/part_replacer/replacer = P - var/list/added_components = list() - var/list/part_list = list() - - //Assemble a list of current parts, then sort them by their rating! - for(var/obj/item/weapon/stock_parts/co in replacer) - part_list += co - //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(path) in part_list)) - var/obj/item/part = (locate(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_req_desc() - return - - if(istype(P, /obj/item) && get_req_components_amt()) - for(var/I in req_components) - if(istype(P, I) && (req_components[I] > 0)) - if(istype(P, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/CP = P - var/cable_color = CP.item_color - if(CP.use(1)) - var/obj/item/stack/cable_coil/CC = new(src, 1, cable_color) - components += CC - req_components[I]-- - update_req_desc() - else - to_chat(user, "You need more cable!") - return - if(!user.drop_item()) - break - P.loc = src - components += P - req_components[I]-- - update_req_desc() - return 1 - to_chat(user, "You cannot add that to the machine!") - return 0 - - -//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/vendor - name = "circuit board (Booze-O-Mat Vendor)" - build_path = /obj/machinery/vending/boozeomat - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/vending_refill/boozeomat = 3) - -/obj/item/weapon/circuitboard/vendor/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/screwdriver)) - var/list/names = list(/obj/machinery/vending/boozeomat = "Booze-O-Mat", - /obj/machinery/vending/coffee = "Getmore Chocolate Corp", - /obj/machinery/vending/snack = "Hot Drinks", - /obj/machinery/vending/cola = "Robust Softdrinks", - /obj/machinery/vending/cigarette = "Cigarette") -// /obj/machinery/vending/autodrobe = "AutoDrobe") - - build_path = pick(names) - name = "circuit board ([names[build_path]] Vendor)" - to_chat(user, "You set the board to [names[build_path]].") - req_components = list(text2path("/obj/item/weapon/vending_refill/[copytext("[build_path]", 24)]") = 3) //Never before has i used a method as horrible as this one, im so sorry - -/obj/item/weapon/circuitboard/smes - name = "circuit board (SMES)" - build_path = /obj/machinery/power/smes - board_type = "machine" - origin_tech = "programming=4;powerstorage=5;engineering=5" - req_components = list( - /obj/item/stack/cable_coil = 5, - /obj/item/weapon/stock_parts/cell = 5, - /obj/item/weapon/stock_parts/capacitor = 1) - -/obj/item/weapon/circuitboard/emitter - name = "circuit board (Emitter)" - build_path = /obj/machinery/power/emitter - board_type = "machine" - origin_tech = "programming=4;powerstorage=5;engineering=5" - req_components = list( - /obj/item/weapon/stock_parts/micro_laser = 1, - /obj/item/weapon/stock_parts/manipulator = 1) - -/obj/item/weapon/circuitboard/power_compressor - name = "circuit board (Power Compressor)" - build_path = /obj/machinery/compressor - board_type = "machine" - origin_tech = "programming=4;powerstorage=5;engineering=4" - req_components = list( - /obj/item/stack/cable_coil = 5, - /obj/item/weapon/stock_parts/manipulator = 6) - -/obj/item/weapon/circuitboard/power_turbine - name = "circuit board (Power Turbine)" - build_path = /obj/machinery/power/turbine - board_type = "machine" - origin_tech = "programming=4;powerstorage=4;engineering=5" - req_components = list( - /obj/item/stack/cable_coil = 5, - /obj/item/weapon/stock_parts/capacitor = 6) - -/obj/item/weapon/circuitboard/mech_recharger - name = "circuit board (Mechbay Recharger)" - build_path = /obj/machinery/mech_bay_recharge_port - board_type = "machine" - origin_tech = "programming=3;powerstorage=4;engineering=4" - req_components = list( - /obj/item/stack/cable_coil = 1, - /obj/item/weapon/stock_parts/capacitor = 5) - -/obj/item/weapon/circuitboard/teleporter_hub - name = "circuit board (Teleporter Hub)" - build_path = /obj/machinery/teleport/hub - board_type = "machine" - origin_tech = "programming=3;engineering=5;bluespace=5;materials=4" - req_components = list( - /obj/item/bluespace_crystal = 3, - /obj/item/weapon/stock_parts/matter_bin = 1) - -/obj/item/weapon/circuitboard/teleporter_station - name = "circuit board (Teleporter Station)" - build_path = /obj/machinery/teleport/station - board_type = "machine" - origin_tech = "programming=4;engineering=4;bluespace=4" - req_components = list( - /obj/item/bluespace_crystal = 2, - /obj/item/weapon/stock_parts/capacitor = 2, - /obj/item/weapon/stock_parts/console_screen = 1) - -/obj/item/weapon/circuitboard/telesci_pad - name = "circuit board (Telepad)" - build_path = /obj/machinery/telepad - board_type = "machine" - origin_tech = "programming=4;engineering=3;materials=3;bluespace=4" - req_components = list( - /obj/item/bluespace_crystal = 2, - /obj/item/weapon/stock_parts/capacitor = 1, - /obj/item/stack/cable_coil = 1, - /obj/item/weapon/stock_parts/console_screen = 1) - -/obj/item/weapon/circuitboard/sleeper - name = "circuit board (Sleeper)" - build_path = /obj/machinery/sleeper - board_type = "machine" - origin_tech = "programming=3;biotech=2;engineering=3;materials=3" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/manipulator = 1, - /obj/item/stack/cable_coil = 1, - /obj/item/weapon/stock_parts/console_screen = 2) - -/obj/item/weapon/circuitboard/cryo_tube - name = "circuit board (Cryotube)" - build_path = /obj/machinery/atmospherics/components/unary/cryo_cell - board_type = "machine" - origin_tech = "programming=4;biotech=3;engineering=4" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/stack/cable_coil = 1, - /obj/item/weapon/stock_parts/console_screen = 4) - -/obj/item/weapon/circuitboard/heater - name = "circuit board (Heater)" - build_path = /obj/machinery/atmospherics/components/unary/thermomachine/heater - board_type = "machine" - origin_tech = "powerstorage=2;engineering=1)" - req_components = list( - /obj/item/stack/cable_coil = 5, - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/capacitor = 2) - -/obj/item/weapon/circuitboard/cooler - name = "circuit board (Cooler)" - build_path = /obj/machinery/atmospherics/components/unary/thermomachine/freezer - board_type = "machine" - origin_tech = "magnets=2;engineering=2" - req_components = list( - /obj/item/stack/cable_coil = 2, - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/capacitor = 2, - /obj/item/weapon/stock_parts/manipulator = 1) - -/obj/item/weapon/circuitboard/space_heater - name = "circuit board (Space Heater)" - build_path = /obj/machinery/space_heater - board_type = "machine" - origin_tech = "programming=2;engineering=2" - req_components = list( - /obj/item/weapon/stock_parts/micro_laser = 1, - /obj/item/weapon/stock_parts/capacitor = 1, - /obj/item/stack/cable_coil = 3) - -/obj/item/weapon/circuitboard/color_mixer - name = "circuit board (Color Mixer)" - build_path = /obj/machinery/color_mixer - origin_tech = "programming=2;materials=2" - req_components = list( - /obj/item/weapon/circuitboard/color_mixer = 1, - /obj/item/weapon/stock_parts/manipulator = 2, - /obj/item/stack/cable_coil = 1) - - -/obj/item/weapon/circuitboard/biogenerator - name = "circuit board (Biogenerator)" - build_path = /obj/machinery/biogenerator - board_type = "machine" - origin_tech = "programming=3;biotech=2;materials=3" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/manipulator = 1, - /obj/item/stack/cable_coil = 1, - /obj/item/weapon/stock_parts/console_screen = 1) - -/obj/item/weapon/circuitboard/hydroponics - name = "circuit board (Hydroponics Tray)" - build_path = /obj/machinery/hydroponics/constructable - board_type = "machine" - origin_tech = "programming=1;biotech=1" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 2, - /obj/item/weapon/stock_parts/manipulator = 1, - /obj/item/weapon/stock_parts/console_screen = 1) - -/obj/item/weapon/circuitboard/deepfryer - name = "circuit board (Deep Fryer)" - build_path = /obj/machinery/deepfryer - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/micro_laser = 1, - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/stack/cable_coil = 2, - /obj/item/weapon/stock_parts/console_screen = 1) - -/obj/item/weapon/circuitboard/microwave - name = "circuit board (Microwave)" - build_path = /obj/machinery/kitchen_machine/microwave - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/micro_laser = 1, - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/stack/cable_coil = 2, - /obj/item/weapon/stock_parts/console_screen = 1) - -/obj/item/weapon/circuitboard/oven - name = "circuit board (Oven)" - build_path = /obj/machinery/kitchen_machine/oven - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/micro_laser = 1, - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/stack/cable_coil = 2, - /obj/item/weapon/stock_parts/console_screen = 1) - -/obj/item/weapon/circuitboard/grill - name = "circuit board (Grill)" - build_path = /obj/machinery/kitchen_machine/grill - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/micro_laser = 1, - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/stack/cable_coil = 2, - /obj/item/weapon/stock_parts/console_screen = 1) - -/obj/item/weapon/circuitboard/candymaker - name = "circuit board (Candy)" - build_path = /obj/machinery/kitchen_machine/candymaker - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/micro_laser = 1, - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/stack/cable_coil = 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=1" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/manipulator = 1) - -/obj/item/weapon/circuitboard/processor - name = "circuit board (Food processor)" - build_path = /obj/machinery/processor - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/manipulator = 1) - -//obj/item/weapon/circuitboard/recycler -// name = "circuit board (Recycler)" -// build_path = /obj/machinery/recycler -// board_type = "machine" -// origin_tech = "programming=1" -// req_components = list( -// /obj/item/weapon/stock_parts/matter_bin = 1, -// /obj/item/weapon/stock_parts/manipulator = 1) - -/obj/item/weapon/circuitboard/seed_extractor - name = "circuit board (Seed Extractor)" - build_path = /obj/machinery/seed_extractor - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/manipulator = 1) - -/obj/item/weapon/circuitboard/smartfridge - name = "circuit board (Smartfridge)" - build_path = /obj/machinery/smartfridge - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 1) - -/obj/item/weapon/circuitboard/monkey_recycler - name = "circuit board (Monkey Recycler)" - build_path = /obj/machinery/monkey_recycler - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/manipulator = 1) - -/obj/item/weapon/circuitboard/holopad - name = "circuit board (AI Holopad)" - build_path = /obj/machinery/hologram/holopad - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/capacitor = 1) - -/obj/item/weapon/circuitboard/chem_dispenser - name = "circuit board (Portable Chem Dispenser)" - build_path = /obj/machinery/chem_dispenser/constructable - board_type = "machine" - origin_tech = "materials=4;engineering=4;programming=4;phorontech=3;biotech=3" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 2, - /obj/item/weapon/stock_parts/capacitor = 1, - /obj/item/weapon/stock_parts/manipulator = 1, - /obj/item/weapon/stock_parts/console_screen = 1, - /obj/item/weapon/stock_parts/cell = 1) - -/obj/item/weapon/circuitboard/chem_master - name = "circuit board (Chem Master 2999)" - build_path = /obj/machinery/chem_master/constructable - board_type = "machine" - origin_tech = "materials=2;programming=2;biotech=1" - req_components = list( - /obj/item/weapon/reagent_containers/glass/beaker = 2, - /obj/item/weapon/stock_parts/manipulator = 1, - /obj/item/weapon/stock_parts/console_screen = 1) - -/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=2" - 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/autolathe - board_type = "machine" - origin_tech = "engineering=2;programming=2" - 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/protolathe - board_type = "machine" - origin_tech = "engineering=2;programming=2" - 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/circuit_imprinter - name = "Circuit board (Circuit Imprinter)" - build_path = /obj/machinery/r_n_d/circuit_imprinter - board_type = "machine" - origin_tech = "engineering=2;programming=2" - 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;phorontech=3;engineering=3" - req_components = list( - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/micro_laser = 1, - /obj/item/stack/cable_coil = 2, - /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/rdserver - name = "Circuit Board (R&D Server)" - build_path = /obj/machinery/r_n_d/server - board_type = "machine" - origin_tech = "programming=3" - req_components = list( - /obj/item/stack/cable_coil = 2, - /obj/item/weapon/stock_parts/scanning_module = 1) - -/obj/item/weapon/circuitboard/mechfab - name = "Circuit board (Exosuit Fabricator)" - build_path = /obj/machinery/mecha_part_fabricator - board_type = "machine" - origin_tech = "programming=3;engineering=3" - 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/minefab - name = "Circuit board (Mining Fabricator)" - build_path = /obj/machinery/mecha_part_fabricator/mining_fabricator - board_type = "machine" - origin_tech = "powerstorage=3;programming=3;engineering=4;magnets=4;materials=4" - 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/clonepod - name = "Circuit board (Clone Pod)" - build_path = /obj/machinery/clonepod - board_type = "machine" - origin_tech = "programming=3;biotech=3" - req_components = list( - /obj/item/stack/cable_coil = 2, - /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=2;biotech=2" - 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/stack/cable_coil = 2) - -/obj/item/weapon/circuitboard/cyborgrecharger - name = "Circuit board (Cyborg Recharger)" - build_path = /obj/machinery/recharge_station - board_type = "machine" - origin_tech = "powerstorage=3;engineering=3" - req_components = list( - /obj/item/weapon/stock_parts/capacitor = 2, - /obj/item/weapon/stock_parts/cell = 1, - /obj/item/weapon/stock_parts/manipulator = 1) - -/obj/item/weapon/circuitboard/recharger - name = "circuit board (Weapon Recharger)" - build_path = /obj/machinery/recharger - board_type = "machine" - origin_tech = "powerstorage=3;engineering=3;materials=4" - req_components = list( - /obj/item/weapon/stock_parts/capacitor = 1,) - -// 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" - 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" - 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" - 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" - 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/tesla_coil - name = "circuit board (Tesla Coil)" - build_path = /obj/machinery/power/tesla_coil - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/capacitor = 1) - -/obj/item/weapon/circuitboard/grounding_rod - name = "circuit board (Grounding Rod)" - build_path = /obj/machinery/power/grounding_rod - board_type = "machine" - origin_tech = "programming=1" - req_components = list( - /obj/item/weapon/stock_parts/capacitor = 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" - 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" - 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" - 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/ore_redemption - name = "circuit board (Ore Redemption)" - build_path = /obj/machinery/mineral/ore_redemption - board_type = "machine" - origin_tech = "programming=1;engineering=2" - req_components = list( - /obj/item/weapon/stock_parts/console_screen = 1, - /obj/item/weapon/stock_parts/matter_bin = 1, - /obj/item/weapon/stock_parts/micro_laser = 1, - /obj/item/weapon/stock_parts/manipulator = 1, - /obj/item/device/assembly/igniter = 1) - -/obj/item/weapon/circuitboard/mining_equipment_vendor - name = "circuit board (Mining Equipment Vendor)" - build_path = /obj/machinery/mineral/equipment_vendor - board_type = "machine" - origin_tech = "programming=1;engineering=2" - req_components = list( - /obj/item/weapon/stock_parts/console_screen = 1, - /obj/item/weapon/stock_parts/matter_bin = 3) +//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 // user-friendly names of components + var/state = 1 + +// unfortunately, we have to instance the objects really quickly to get the names +// fortunately, this is only called once when the board is added and the items are immediately GC'd +// and none of the parts do much in their constructors +/obj/machinery/constructable_frame/proc/update_namelist() + if(!req_components) + return + + req_component_names = new() + for(var/tname in req_components) + var/path = tname + var/obj/O = new path() + req_component_names[tname] = O.name + +/obj/machinery/constructable_frame/proc/get_req_components_amt() + var/amt = 0 + for(var/path in req_components) + amt += req_components[path] + return amt + +// update description of required components remaining +/obj/machinery/constructable_frame/proc/update_req_desc() + if(!req_components || !req_component_names) + return + + var/hasContent = 0 + desc = "Requires" + for(var/i = 1 to req_components.len) + var/tname = req_components[i] + var/amt = req_components[tname] + if(amt == 0) + continue + var/use_and = i == req_components.len + desc += "[(hasContent ? (use_and ? ", and" : ",") : "")] [amt] [amt == 1 ? req_component_names[tname] : "[req_component_names[tname]]\s"]" + hasContent = 1 + + if(!hasContent) + desc = "Does not require any more components." + else + desc += "." + +/obj/machinery/constructable_frame/machine_frame/attackby(obj/item/P, mob/user) + if(P.crit_fail) + to_chat(user, "This part is faulty, you cannot add this to the machine!") + return + switch(state) + if(1) + if(istype(P, /obj/item/weapon/circuitboard)) + to_chat(user, "The frame needs wiring first!") + return + + else if(istype(P, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = P + if(C.get_amount() < 5) + to_chat(user, "You need five length of cable to wire the frame!") + return + if(user.is_busy()) return + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "You start to add cables to the frame.") + if(do_after(user, 20/P.toolspeed, target = src)) + if(state == 1) + if(!C.use(5)) + return + + to_chat(user, "You add cables to the frame.") + state = 2 + icon_state = "box_1" + + else if(istype(P, /obj/item/weapon/screwdriver) && !anchored) + if(user.is_busy()) return + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + user.visible_message("[user] disassembles the frame.", \ + "You start to disassemble the frame...", "You hear banging and clanking.") + if(do_after(user, 40/P.toolspeed, target = src)) + if(state == 1) + to_chat(user, "You disassemble the frame.") + var/obj/item/stack/sheet/metal/M = new (loc, 5) + M.add_fingerprint(user) + qdel(src) + + else if(istype(P, /obj/item/weapon/wrench)) + if(user.is_busy()) return + to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + if(do_after(user, 40/P.toolspeed, target = src)) + if(state == 1) + to_chat(user, "You [anchored ? "un" : ""]secure [name].") + anchored = !anchored + if(2) + if(istype(P, /obj/item/weapon/wrench)) + if(user.is_busy()) return + to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + if(do_after(user, 40/P.toolspeed, target = src)) + to_chat(user, "You [anchored ? "un" : ""]secure [name].") + anchored = !anchored + + if(istype(P, /obj/item/weapon/circuitboard)) + if(!anchored) + to_chat(user, "The frame needs to be secured first!") + return + var/obj/item/weapon/circuitboard/B = P + if(B.board_type == "machine") + if(!user.drop_item()) + return + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + to_chat(user, "You add the circuit board to the frame.") + circuit = P + P.loc = src + icon_state = "box_2" + state = 3 + components = list() + req_components = circuit.req_components.Copy() + update_namelist() + update_req_desc() + else + to_chat(user, "This frame does not accept circuit boards of this type!") + if(istype(P, /obj/item/weapon/wirecutters)) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) + to_chat(user, "You remove the cables.") + state = 1 + icon_state = "box_0" + new /obj/item/stack/cable_coil/red(loc, 5) + + if(3) + if(istype(P, /obj/item/weapon/crowbar)) + playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) + state = 2 + circuit.loc = src.loc + components.Remove(circuit) + 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 + icon_state = "box_1" + + 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(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + var/obj/machinery/new_machine = new src.circuit.build_path(src.loc) + new_machine.construction() + for(var/obj/O in new_machine.component_parts) + qdel(O) + new_machine.component_parts = list() + for(var/obj/O in src) + O.loc = null + new_machine.component_parts += O + circuit.loc = null + new_machine.RefreshParts() + qdel(src) + + if(istype(P, /obj/item/weapon/storage/part_replacer) && P.contents.len && get_req_components_amt()) + var/obj/item/weapon/storage/part_replacer/replacer = P + var/list/added_components = list() + var/list/part_list = list() + + //Assemble a list of current parts, then sort them by their rating! + for(var/obj/item/weapon/stock_parts/co in replacer) + part_list += co + //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(path) in part_list)) + var/obj/item/part = (locate(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_req_desc() + return + + if(istype(P, /obj/item) && get_req_components_amt()) + for(var/I in req_components) + if(istype(P, I) && (req_components[I] > 0)) + if(istype(P, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/CP = P + var/cable_color = CP.item_color + if(CP.use(1)) + var/obj/item/stack/cable_coil/CC = new(src, 1, cable_color) + components += CC + req_components[I]-- + update_req_desc() + else + to_chat(user, "You need more cable!") + return + if(!user.drop_item()) + break + P.loc = src + components += P + req_components[I]-- + update_req_desc() + return 1 + to_chat(user, "You cannot add that to the machine!") + return 0 + + +//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/vendor + name = "circuit board (Booze-O-Mat Vendor)" + build_path = /obj/machinery/vending/boozeomat + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/vending_refill/boozeomat = 3) + +/obj/item/weapon/circuitboard/vendor/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/screwdriver)) + var/list/names = list(/obj/machinery/vending/boozeomat = "Booze-O-Mat", + /obj/machinery/vending/coffee = "Getmore Chocolate Corp", + /obj/machinery/vending/snack = "Hot Drinks", + /obj/machinery/vending/cola = "Robust Softdrinks", + /obj/machinery/vending/cigarette = "Cigarette") +// /obj/machinery/vending/autodrobe = "AutoDrobe") + + build_path = pick(names) + name = "circuit board ([names[build_path]] Vendor)" + to_chat(user, "You set the board to [names[build_path]].") + req_components = list(text2path("/obj/item/weapon/vending_refill/[copytext("[build_path]", 24)]") = 3) //Never before has i used a method as horrible as this one, im so sorry + +/obj/item/weapon/circuitboard/smes + name = "circuit board (SMES)" + build_path = /obj/machinery/power/smes + board_type = "machine" + origin_tech = "programming=4;powerstorage=5;engineering=5" + req_components = list( + /obj/item/stack/cable_coil = 5, + /obj/item/weapon/stock_parts/cell = 5, + /obj/item/weapon/stock_parts/capacitor = 1) + +/obj/item/weapon/circuitboard/emitter + name = "circuit board (Emitter)" + build_path = /obj/machinery/power/emitter + board_type = "machine" + origin_tech = "programming=4;powerstorage=5;engineering=5" + req_components = list( + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/manipulator = 1) + +/obj/item/weapon/circuitboard/power_compressor + name = "circuit board (Power Compressor)" + build_path = /obj/machinery/compressor + board_type = "machine" + origin_tech = "programming=4;powerstorage=5;engineering=4" + req_components = list( + /obj/item/stack/cable_coil = 5, + /obj/item/weapon/stock_parts/manipulator = 6) + +/obj/item/weapon/circuitboard/power_turbine + name = "circuit board (Power Turbine)" + build_path = /obj/machinery/power/turbine + board_type = "machine" + origin_tech = "programming=4;powerstorage=4;engineering=5" + req_components = list( + /obj/item/stack/cable_coil = 5, + /obj/item/weapon/stock_parts/capacitor = 6) + +/obj/item/weapon/circuitboard/mech_recharger + name = "circuit board (Mechbay Recharger)" + build_path = /obj/machinery/mech_bay_recharge_port + board_type = "machine" + origin_tech = "programming=3;powerstorage=4;engineering=4" + req_components = list( + /obj/item/stack/cable_coil = 1, + /obj/item/weapon/stock_parts/capacitor = 5) + +/obj/item/weapon/circuitboard/teleporter_hub + name = "circuit board (Teleporter Hub)" + build_path = /obj/machinery/teleport/hub + board_type = "machine" + origin_tech = "programming=3;engineering=5;bluespace=5;materials=4" + req_components = list( + /obj/item/bluespace_crystal = 3, + /obj/item/weapon/stock_parts/matter_bin = 1) + +/obj/item/weapon/circuitboard/teleporter_station + name = "circuit board (Teleporter Station)" + build_path = /obj/machinery/teleport/station + board_type = "machine" + origin_tech = "programming=4;engineering=4;bluespace=4" + req_components = list( + /obj/item/bluespace_crystal = 2, + /obj/item/weapon/stock_parts/capacitor = 2, + /obj/item/weapon/stock_parts/console_screen = 1) + +/obj/item/weapon/circuitboard/telesci_pad + name = "circuit board (Telepad)" + build_path = /obj/machinery/telepad + board_type = "machine" + origin_tech = "programming=4;engineering=3;materials=3;bluespace=4" + req_components = list( + /obj/item/bluespace_crystal = 2, + /obj/item/weapon/stock_parts/capacitor = 1, + /obj/item/stack/cable_coil = 1, + /obj/item/weapon/stock_parts/console_screen = 1) + +/obj/item/weapon/circuitboard/sleeper + name = "circuit board (Sleeper)" + build_path = /obj/machinery/sleeper + board_type = "machine" + origin_tech = "programming=3;biotech=2;engineering=3;materials=3" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/stack/cable_coil = 1, + /obj/item/weapon/stock_parts/console_screen = 2) + +/obj/item/weapon/circuitboard/cryo_tube + name = "circuit board (Cryotube)" + build_path = /obj/machinery/atmospherics/components/unary/cryo_cell + board_type = "machine" + origin_tech = "programming=4;biotech=3;engineering=4" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/stack/cable_coil = 1, + /obj/item/weapon/stock_parts/console_screen = 4) + +/obj/item/weapon/circuitboard/heater + name = "circuit board (Heater)" + build_path = /obj/machinery/atmospherics/components/unary/thermomachine/heater + board_type = "machine" + origin_tech = "powerstorage=2;engineering=1)" + req_components = list( + /obj/item/stack/cable_coil = 5, + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/capacitor = 2) + +/obj/item/weapon/circuitboard/cooler + name = "circuit board (Cooler)" + build_path = /obj/machinery/atmospherics/components/unary/thermomachine/freezer + board_type = "machine" + origin_tech = "magnets=2;engineering=2" + req_components = list( + /obj/item/stack/cable_coil = 2, + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/capacitor = 2, + /obj/item/weapon/stock_parts/manipulator = 1) + +/obj/item/weapon/circuitboard/space_heater + name = "circuit board (Space Heater)" + build_path = /obj/machinery/space_heater + board_type = "machine" + origin_tech = "programming=2;engineering=2" + req_components = list( + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/capacitor = 1, + /obj/item/stack/cable_coil = 3) + +/obj/item/weapon/circuitboard/color_mixer + name = "circuit board (Color Mixer)" + build_path = /obj/machinery/color_mixer + origin_tech = "programming=2;materials=2" + req_components = list( + /obj/item/weapon/circuitboard/color_mixer = 1, + /obj/item/weapon/stock_parts/manipulator = 2, + /obj/item/stack/cable_coil = 1) + + +/obj/item/weapon/circuitboard/biogenerator + name = "circuit board (Biogenerator)" + build_path = /obj/machinery/biogenerator + board_type = "machine" + origin_tech = "programming=3;biotech=2;materials=3" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/stack/cable_coil = 1, + /obj/item/weapon/stock_parts/console_screen = 1) + +/obj/item/weapon/circuitboard/hydroponics + name = "circuit board (Hydroponics Tray)" + build_path = /obj/machinery/hydroponics/constructable + board_type = "machine" + origin_tech = "programming=1;biotech=1" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 2, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/weapon/stock_parts/console_screen = 1) + +/obj/item/weapon/circuitboard/deepfryer + name = "circuit board (Deep Fryer)" + build_path = /obj/machinery/deepfryer + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/stack/cable_coil = 2, + /obj/item/weapon/stock_parts/console_screen = 1) + +/obj/item/weapon/circuitboard/microwave + name = "circuit board (Microwave)" + build_path = /obj/machinery/kitchen_machine/microwave + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/stack/cable_coil = 2, + /obj/item/weapon/stock_parts/console_screen = 1) + +/obj/item/weapon/circuitboard/oven + name = "circuit board (Oven)" + build_path = /obj/machinery/kitchen_machine/oven + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/stack/cable_coil = 2, + /obj/item/weapon/stock_parts/console_screen = 1) + +/obj/item/weapon/circuitboard/grill + name = "circuit board (Grill)" + build_path = /obj/machinery/kitchen_machine/grill + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/stack/cable_coil = 2, + /obj/item/weapon/stock_parts/console_screen = 1) + +/obj/item/weapon/circuitboard/candymaker + name = "circuit board (Candy)" + build_path = /obj/machinery/kitchen_machine/candymaker + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/stack/cable_coil = 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=1" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/manipulator = 1) + +/obj/item/weapon/circuitboard/processor + name = "circuit board (Food processor)" + build_path = /obj/machinery/processor + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/manipulator = 1) + +//obj/item/weapon/circuitboard/recycler +// name = "circuit board (Recycler)" +// build_path = /obj/machinery/recycler +// board_type = "machine" +// origin_tech = "programming=1" +// req_components = list( +// /obj/item/weapon/stock_parts/matter_bin = 1, +// /obj/item/weapon/stock_parts/manipulator = 1) + +/obj/item/weapon/circuitboard/seed_extractor + name = "circuit board (Seed Extractor)" + build_path = /obj/machinery/seed_extractor + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/manipulator = 1) + +/obj/item/weapon/circuitboard/smartfridge + name = "circuit board (Smartfridge)" + build_path = /obj/machinery/smartfridge + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 1) + +/obj/item/weapon/circuitboard/monkey_recycler + name = "circuit board (Monkey Recycler)" + build_path = /obj/machinery/monkey_recycler + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/manipulator = 1) + +/obj/item/weapon/circuitboard/holopad + name = "circuit board (AI Holopad)" + build_path = /obj/machinery/hologram/holopad + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/capacitor = 1) + +/obj/item/weapon/circuitboard/chem_dispenser + name = "circuit board (Portable Chem Dispenser)" + build_path = /obj/machinery/chem_dispenser/constructable + board_type = "machine" + origin_tech = "materials=4;engineering=4;programming=4;phorontech=3;biotech=3" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 2, + /obj/item/weapon/stock_parts/capacitor = 1, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/weapon/stock_parts/console_screen = 1, + /obj/item/weapon/stock_parts/cell = 1) + +/obj/item/weapon/circuitboard/chem_master + name = "circuit board (Chem Master 2999)" + build_path = /obj/machinery/chem_master/constructable + board_type = "machine" + origin_tech = "materials=2;programming=2;biotech=1" + req_components = list( + /obj/item/weapon/reagent_containers/glass/beaker = 2, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/weapon/stock_parts/console_screen = 1) + +/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=2" + 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/autolathe + board_type = "machine" + origin_tech = "engineering=2;programming=2" + 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/protolathe + board_type = "machine" + origin_tech = "engineering=2;programming=2" + 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/circuit_imprinter + name = "Circuit board (Circuit Imprinter)" + build_path = /obj/machinery/r_n_d/circuit_imprinter + board_type = "machine" + origin_tech = "engineering=2;programming=2" + 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;phorontech=3;engineering=3" + req_components = list( + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/stack/cable_coil = 2, + /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/rdserver + name = "Circuit Board (R&D Server)" + build_path = /obj/machinery/r_n_d/server + board_type = "machine" + origin_tech = "programming=3" + req_components = list( + /obj/item/stack/cable_coil = 2, + /obj/item/weapon/stock_parts/scanning_module = 1) + +/obj/item/weapon/circuitboard/mechfab + name = "Circuit board (Exosuit Fabricator)" + build_path = /obj/machinery/mecha_part_fabricator + board_type = "machine" + origin_tech = "programming=3;engineering=3" + 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/minefab + name = "Circuit board (Mining Fabricator)" + build_path = /obj/machinery/mecha_part_fabricator/mining_fabricator + board_type = "machine" + origin_tech = "powerstorage=3;programming=3;engineering=4;magnets=4;materials=4" + 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/clonepod + name = "Circuit board (Clone Pod)" + build_path = /obj/machinery/clonepod + board_type = "machine" + origin_tech = "programming=3;biotech=3" + req_components = list( + /obj/item/stack/cable_coil = 2, + /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=2;biotech=2" + 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/stack/cable_coil = 2) + +/obj/item/weapon/circuitboard/cyborgrecharger + name = "Circuit board (Cyborg Recharger)" + build_path = /obj/machinery/recharge_station + board_type = "machine" + origin_tech = "powerstorage=3;engineering=3" + req_components = list( + /obj/item/weapon/stock_parts/capacitor = 2, + /obj/item/weapon/stock_parts/cell = 1, + /obj/item/weapon/stock_parts/manipulator = 1) + +/obj/item/weapon/circuitboard/recharger + name = "circuit board (Weapon Recharger)" + build_path = /obj/machinery/recharger + board_type = "machine" + origin_tech = "powerstorage=3;engineering=3;materials=4" + req_components = list( + /obj/item/weapon/stock_parts/capacitor = 1,) + +// 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" + 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" + 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" + 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" + 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/tesla_coil + name = "circuit board (Tesla Coil)" + build_path = /obj/machinery/power/tesla_coil + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/capacitor = 1) + +/obj/item/weapon/circuitboard/grounding_rod + name = "circuit board (Grounding Rod)" + build_path = /obj/machinery/power/grounding_rod + board_type = "machine" + origin_tech = "programming=1" + req_components = list( + /obj/item/weapon/stock_parts/capacitor = 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" + 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" + 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" + 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/ore_redemption + name = "circuit board (Ore Redemption)" + build_path = /obj/machinery/mineral/ore_redemption + board_type = "machine" + origin_tech = "programming=1;engineering=2" + req_components = list( + /obj/item/weapon/stock_parts/console_screen = 1, + /obj/item/weapon/stock_parts/matter_bin = 1, + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/manipulator = 1, + /obj/item/device/assembly/igniter = 1) + +/obj/item/weapon/circuitboard/mining_equipment_vendor + name = "circuit board (Mining Equipment Vendor)" + build_path = /obj/machinery/mineral/equipment_vendor + board_type = "machine" + origin_tech = "programming=1;engineering=2" + req_components = list( + /obj/item/weapon/stock_parts/console_screen = 1, + /obj/item/weapon/stock_parts/matter_bin = 3) diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 6247ea4754d3..9ed353d1efef 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -1,277 +1,277 @@ -/* -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 - -*/ - - -//Barricades, maybe there will be a metal one later... -/obj/structure/barricade/wooden - name = "wooden barricade" - desc = "This space is blocked off by a wooden barricade." - icon = 'icons/obj/structures.dmi' - icon_state = "woodenbarricade" - anchored = 1.0 - density = 1.0 - var/health = 100.0 - var/maxhealth = 100.0 - -/obj/structure/barricade/wooden/attackby(obj/item/W, mob/user) - if (istype(W, /obj/item/stack/sheet/wood)) - user.SetNextMove(CLICK_CD_INTERACT) - if (src.health < src.maxhealth) - if(user.is_busy()) return - visible_message("\red [user] begins to repair \the [src]!") - if(do_after(user,20,target = src)) - src.health = src.maxhealth - W:use(1) - visible_message("\red [user] repairs \the [src]!") - return - else - return - return - else - user.SetNextMove(CLICK_CD_MELEE) - switch(W.damtype) - if("fire") - src.health -= W.force * 1 - if("brute") - src.health -= W.force * 0.75 - else - if (src.health <= 0) - visible_message("\red The barricade is smashed apart!") - new /obj/item/stack/sheet/wood(get_turf(src)) - new /obj/item/stack/sheet/wood(get_turf(src)) - new /obj/item/stack/sheet/wood(get_turf(src)) - qdel(src) - ..() - -/obj/structure/barricade/wooden/ex_act(severity) - switch(severity) - if(1.0) - visible_message("\red The barricade is blown apart!") - qdel(src) - return - if(2.0) - src.health -= 25 - if (src.health <= 0) - visible_message("\red The barricade is blown apart!") - new /obj/item/stack/sheet/wood(get_turf(src)) - new /obj/item/stack/sheet/wood(get_turf(src)) - new /obj/item/stack/sheet/wood(get_turf(src)) - qdel(src) - return - -/obj/structure/barricade/wooden/meteorhit() - visible_message("\red The barricade is smashed apart!") - new /obj/item/stack/sheet/wood(get_turf(src)) - new /obj/item/stack/sheet/wood(get_turf(src)) - new /obj/item/stack/sheet/wood(get_turf(src)) - qdel(src) - return - -/obj/structure/barricade/wooden/blob_act() - src.health -= 25 - if (src.health <= 0) - visible_message("\red The blob eats through the barricade!") - qdel(src) - return - -/obj/structure/barricade/wooden/CanPass(atom/movable/mover, turf/target, height=0, 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 - - -//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 = 100.0 - var/maxhealth = 100.0 - var/locked = 0.0 -// req_access = list(access_maint_tunnels) - -/obj/machinery/deployable/barrier/atom_init() - . = ..() - icon_state = "barrier[locked]" - -/obj/machinery/deployable/barrier/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/card/id/)) - if (src.allowed(user)) - if (src.emagged < 2.0) - src.locked = !src.locked - src.anchored = !src.anchored - src.icon_state = "barrier[src.locked]" - if ((src.locked == 1.0) && (src.emagged < 2.0)) - to_chat(user, "Barrier lock toggled on.") - return - else if ((src.locked == 0.0) && (src.emagged < 2.0)) - to_chat(user, "Barrier lock toggled off.") - return - else - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 1, src) - s.start() - visible_message("\red BZZzZZzZZzZT") - return - return - else if (istype(W, /obj/item/weapon/card/emag)) - user.SetNextMove(CLICK_CD_MELEE) - if (src.emagged == 0) - src.emagged = 1 - src.req_access = null - 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() - visible_message("\red BZZzZZzZZzZT") - return - else if (src.emagged == 1) - src.emagged = 2 - to_chat(user, "You short out the anchoring mechanism 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() - visible_message("\red BZZzZZzZZzZT") - return - else if (istype(W, /obj/item/weapon/wrench)) - user.SetNextMove(CLICK_CD_INTERACT) - if (src.health < src.maxhealth) - src.health = src.maxhealth - src.emagged = 0 - src.req_access = list(access_security) - visible_message("\red [user] repairs \the [src]!") - return - else if (src.emagged > 0) - src.emagged = 0 - src.req_access = list(access_security) - visible_message("\red [user] repairs \the [src]!") - return - return - else - user.SetNextMove(CLICK_CD_MELEE) - switch(W.damtype) - if("fire") - src.health -= W.force * 0.75 - if("brute") - src.health -= W.force * 0.5 - else - 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/meteorhit() - src.explode() - return - -/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=0, 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("\red [src] blows apart!") - var/turf/Tsec = get_turf(src) - -/* var/obj/item/stack/rods/ =*/ - new /obj/item/stack/rods(Tsec) - - 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) +/* +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 + +*/ + + +//Barricades, maybe there will be a metal one later... +/obj/structure/barricade/wooden + name = "wooden barricade" + desc = "This space is blocked off by a wooden barricade." + icon = 'icons/obj/structures.dmi' + icon_state = "woodenbarricade" + anchored = 1.0 + density = 1.0 + var/health = 100.0 + var/maxhealth = 100.0 + +/obj/structure/barricade/wooden/attackby(obj/item/W, mob/user) + if (istype(W, /obj/item/stack/sheet/wood)) + user.SetNextMove(CLICK_CD_INTERACT) + if (src.health < src.maxhealth) + if(user.is_busy()) return + visible_message("\red [user] begins to repair \the [src]!") + if(do_after(user,20,target = src)) + src.health = src.maxhealth + W:use(1) + visible_message("\red [user] repairs \the [src]!") + return + else + return + return + else + user.SetNextMove(CLICK_CD_MELEE) + switch(W.damtype) + if("fire") + src.health -= W.force * 1 + if("brute") + src.health -= W.force * 0.75 + else + if (src.health <= 0) + visible_message("\red The barricade is smashed apart!") + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + qdel(src) + ..() + +/obj/structure/barricade/wooden/ex_act(severity) + switch(severity) + if(1.0) + visible_message("\red The barricade is blown apart!") + qdel(src) + return + if(2.0) + src.health -= 25 + if (src.health <= 0) + visible_message("\red The barricade is blown apart!") + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + qdel(src) + return + +/obj/structure/barricade/wooden/meteorhit() + visible_message("\red The barricade is smashed apart!") + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + new /obj/item/stack/sheet/wood(get_turf(src)) + qdel(src) + return + +/obj/structure/barricade/wooden/blob_act() + src.health -= 25 + if (src.health <= 0) + visible_message("\red The blob eats through the barricade!") + qdel(src) + return + +/obj/structure/barricade/wooden/CanPass(atom/movable/mover, turf/target, height=0, 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 + + +//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 = 100.0 + var/maxhealth = 100.0 + var/locked = 0.0 +// req_access = list(access_maint_tunnels) + +/obj/machinery/deployable/barrier/atom_init() + . = ..() + icon_state = "barrier[locked]" + +/obj/machinery/deployable/barrier/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/card/id/)) + if (src.allowed(user)) + if (src.emagged < 2.0) + src.locked = !src.locked + src.anchored = !src.anchored + src.icon_state = "barrier[src.locked]" + if ((src.locked == 1.0) && (src.emagged < 2.0)) + to_chat(user, "Barrier lock toggled on.") + return + else if ((src.locked == 0.0) && (src.emagged < 2.0)) + to_chat(user, "Barrier lock toggled off.") + return + else + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + visible_message("\red BZZzZZzZZzZT") + return + return + else if (istype(W, /obj/item/weapon/card/emag)) + user.SetNextMove(CLICK_CD_MELEE) + if (src.emagged == 0) + src.emagged = 1 + src.req_access = null + 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() + visible_message("\red BZZzZZzZZzZT") + return + else if (src.emagged == 1) + src.emagged = 2 + to_chat(user, "You short out the anchoring mechanism 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() + visible_message("\red BZZzZZzZZzZT") + return + else if (istype(W, /obj/item/weapon/wrench)) + user.SetNextMove(CLICK_CD_INTERACT) + if (src.health < src.maxhealth) + src.health = src.maxhealth + src.emagged = 0 + src.req_access = list(access_security) + visible_message("\red [user] repairs \the [src]!") + return + else if (src.emagged > 0) + src.emagged = 0 + src.req_access = list(access_security) + visible_message("\red [user] repairs \the [src]!") + return + return + else + user.SetNextMove(CLICK_CD_MELEE) + switch(W.damtype) + if("fire") + src.health -= W.force * 0.75 + if("brute") + src.health -= W.force * 0.5 + else + 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/meteorhit() + src.explode() + return + +/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=0, 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("\red [src] blows apart!") + var/turf/Tsec = get_turf(src) + +/* var/obj/item/stack/rods/ =*/ + new /obj/item/stack/rods(Tsec) + + 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 b6a34e73968e..f803c359f6e3 100644 --- a/code/game/machinery/door_control.dm +++ b/code/game/machinery/door_control.dm @@ -1,134 +1,134 @@ -/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 - anchored = TRUE - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - var/id = null - var/range = 10 - var/normaldoorcontrol = FALSE - var/desiredstate = 0 // Zero is closed, 1 is open. - var/specialfunctions = 1 - -/obj/machinery/door_control/allowed_fail(mob/user) - playsound(src, 'sound/items/buttonswitch.ogg', 20, 1, 1) - flick("doorctrl-denied",src) - -/obj/machinery/door_control/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/device/detective_scanner)) - return - if(istype(W, /obj/item/weapon/card/emag)) - req_access = list() - user.SetNextMove(CLICK_CD_INTERACT) - req_one_access = list() - playsound(src.loc, "sparks", 100, 1) - return src.attack_hand(user) - -/obj/machinery/door_control/attack_hand(mob/user) - . = ..() - if(.) - return - user.SetNextMove(CLICK_CD_INTERACT) - playsound(src, 'sound/items/buttonswitch.ogg', 20, 1, 1) - use_power(5) - icon_state = "doorctrl1" - - if(normaldoorcontrol) - for(var/obj/machinery/door/airlock/D in range(range)) - if(D.id_tag == src.id) - if(specialfunctions & OPEN) - if (D.density) - spawn(0) - D.open() - return - else - spawn(0) - D.close() - return - if(desiredstate == 1) - if(specialfunctions & IDSCAN) - D.aiDisabledIdScanner = 1 - if(specialfunctions & BOLTS) - D.bolt() - if(specialfunctions & SHOCK) - D.secondsElectrified = -1 - if(specialfunctions & SAFE) - D.safe = 0 - else - if(specialfunctions & IDSCAN) - D.aiDisabledIdScanner = 0 - if(specialfunctions & BOLTS) - if(!D.isAllPowerCut() && D.hasPower()) - D.unbolt() - if(specialfunctions & SHOCK) - D.secondsElectrified = 0 - if(specialfunctions & SAFE) - D.safe = 1 - - else - for(var/obj/machinery/door/poddoor/M in poddoor_list) - if (M.id == src.id) - if (M.density) - spawn( 0 ) - M.open() - return - else - spawn( 0 ) - M.close() - return - - desiredstate = !desiredstate - 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/driver_button/attackby(obj/item/weapon/W, mob/user) - - if(istype(W, /obj/item/device/detective_scanner)) - return - return src.attack_hand(user) - -/obj/machinery/driver_button/attack_hand(mob/user) - if(..() || active) - return 1 - - use_power(5) - user.SetNextMove(CLICK_CD_INTERACT) - - active = 1 - icon_state = "launcheract" - - for(var/obj/machinery/door/poddoor/M in poddoor_list) - if (M.id == src.id) - spawn( 0 ) - M.open() - return - - sleep(20) - - for(var/obj/machinery/mass_driver/M in mass_driver_list) - if(M.id == src.id) - M.drive() - - sleep(50) - - for(var/obj/machinery/door/poddoor/M in poddoor_list) - if (M.id == src.id) - spawn( 0 ) - M.close() - return - - icon_state = "launcherbtt" - active = 0 +/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 + anchored = TRUE + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + var/id = null + var/range = 10 + var/normaldoorcontrol = FALSE + var/desiredstate = 0 // Zero is closed, 1 is open. + var/specialfunctions = 1 + +/obj/machinery/door_control/allowed_fail(mob/user) + playsound(src, 'sound/items/buttonswitch.ogg', 20, 1, 1) + flick("doorctrl-denied",src) + +/obj/machinery/door_control/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/device/detective_scanner)) + return + if(istype(W, /obj/item/weapon/card/emag)) + req_access = list() + user.SetNextMove(CLICK_CD_INTERACT) + req_one_access = list() + playsound(src.loc, "sparks", 100, 1) + return src.attack_hand(user) + +/obj/machinery/door_control/attack_hand(mob/user) + . = ..() + if(.) + return + user.SetNextMove(CLICK_CD_INTERACT) + playsound(src, 'sound/items/buttonswitch.ogg', 20, 1, 1) + use_power(5) + icon_state = "doorctrl1" + + if(normaldoorcontrol) + for(var/obj/machinery/door/airlock/D in range(range)) + if(D.id_tag == src.id) + if(specialfunctions & OPEN) + if (D.density) + spawn(0) + D.open() + return + else + spawn(0) + D.close() + return + if(desiredstate == 1) + if(specialfunctions & IDSCAN) + D.aiDisabledIdScanner = 1 + if(specialfunctions & BOLTS) + D.bolt() + if(specialfunctions & SHOCK) + D.secondsElectrified = -1 + if(specialfunctions & SAFE) + D.safe = 0 + else + if(specialfunctions & IDSCAN) + D.aiDisabledIdScanner = 0 + if(specialfunctions & BOLTS) + if(!D.isAllPowerCut() && D.hasPower()) + D.unbolt() + if(specialfunctions & SHOCK) + D.secondsElectrified = 0 + if(specialfunctions & SAFE) + D.safe = 1 + + else + for(var/obj/machinery/door/poddoor/M in poddoor_list) + if (M.id == src.id) + if (M.density) + spawn( 0 ) + M.open() + return + else + spawn( 0 ) + M.close() + return + + desiredstate = !desiredstate + 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/driver_button/attackby(obj/item/weapon/W, mob/user) + + if(istype(W, /obj/item/device/detective_scanner)) + return + return src.attack_hand(user) + +/obj/machinery/driver_button/attack_hand(mob/user) + if(..() || active) + return 1 + + use_power(5) + user.SetNextMove(CLICK_CD_INTERACT) + + active = 1 + icon_state = "launcheract" + + for(var/obj/machinery/door/poddoor/M in poddoor_list) + if (M.id == src.id) + spawn( 0 ) + M.open() + return + + sleep(20) + + for(var/obj/machinery/mass_driver/M in mass_driver_list) + if(M.id == src.id) + M.drive() + + sleep(50) + + for(var/obj/machinery/door/poddoor/M in poddoor_list) + if (M.id == src.id) + spawn( 0 ) + M.close() + return + + icon_state = "launcherbtt" + active = 0 diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 02477be7f57f..0ad423efafee 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1,1166 +1,1166 @@ -#define AIRLOCK_DEFAULT 0 -#define AIRLOCK_CLOSED 1 -#define AIRLOCK_CLOSING 2 -#define AIRLOCK_OPEN 3 -#define AIRLOCK_OPENING 4 -#define AIRLOCK_DENY 5 -#define AIRLOCK_EMAG 6 -var/list/airlock_overlays = list() - -/obj/machinery/door/airlock - name = "airlock" - icon = 'icons/obj/doors/airlocks/station/public.dmi' - icon_state = "closed" - explosion_resistance = 15 - - 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 - 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 - autoclose = 1 - var/assembly_type = /obj/structure/door_assembly - var/mineral = null - var/justzap = 0 - var/safe = 1 - normalspeed = 1 - var/obj/item/weapon/airlock_electronics/electronics = null - var/hasShocked = 0 //Prevents multiple shocks from happening - var/pulseProof = 0 //#Z1 AI hacked this door after previous pulse? - var/shockedby = list() - var/close_timer_id = null - var/datum/wires/airlock/wires = null - - var/inner_material = null //material of inner filling; if its an airlock with glass, this should be set to "glass" - var/overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - - var/image/old_frame_overlay //keep those in order to prevent unnecessary updating - var/image/old_filling_overlay - var/image/old_lights_overlay - var/image/old_panel_overlay - var/image/old_weld_overlay - var/image/old_sparks_overlay - - door_open_sound = 'sound/machines/airlock/airlockToggle.ogg' - door_close_sound = 'sound/machines/airlock/airlockToggle.ogg' - var/door_deni_sound = 'sound/machines/airlock/airlockDenied.ogg' - var/door_bolt_up_sound = 'sound/machines/airlock/airlockBoltsUp.ogg' - var/door_bolt_down_sound = 'sound/machines/airlock/airlockBoltsDown.ogg' - var/door_forced_sound = 'sound/machines/airlock/airlockForced.ogg' - -/obj/machinery/door/airlock/atom_init(mapload, dir = null) - ..() - airlock_list += src - wires = new(src) - if(glass && !inner_material) - inner_material = "glass" - if(dir) - src.dir = dir - update_icon() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/door/airlock/atom_init_late() - if(closeOtherId != null) - for (var/obj/machinery/door/airlock/A in airlock_list) - if(A.closeOtherId == closeOtherId && A != src) - closeOther = A - break - -/obj/machinery/door/airlock/Destroy() - airlock_list -= src - QDEL_NULL(wires) - QDEL_NULL(electronics) - closeOther = null - return ..() - -/obj/machinery/door/airlock/process() - if(secondsElectrified > 0) - secondsElectrified-- - else - return PROCESS_KILL - -/obj/machinery/door/airlock/bumpopen(mob/living/user) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite - if(!issilicon(usr)) - if(isElectrified()) - if(!justzap) - if(shock(user, 100)) - justzap = TRUE - spawn (10) - justzap = FALSE - return - else /*if(justzap)*/ - return - else if(user.hallucination > 50 && prob(10) && !operating) - to_chat(user, "\red You feel a powerful shock course through your body!") - user.halloss += 10 - user.stunned += 10 - return - ..(user) - -/obj/machinery/door/airlock/bumpopen(mob/living/simple_animal/user) - ..(user) - -/obj/machinery/door/airlock/CanAStarPass(obj/item/weapon/card/id/ID, to_dir, caller) - return !density || (check_access(ID) && !locked && hasPower()) - -/obj/machinery/door/airlock/proc/isElectrified() - if(secondsElectrified) - return TRUE - return FALSE - -/obj/machinery/door/airlock/proc/isWireCut(wireIndex) - return wires.is_index_cut(wireIndex) - -/obj/machinery/door/airlock/proc/canAIControl() - return ((aiControlDisabled != 1) && !isAllPowerCut()); - -/obj/machinery/door/airlock/proc/canAIHack() - return (aiControlDisabled && !hackProof && !isAllPowerCut()); - -/obj/machinery/door/airlock/hasPower() - return ((!secondsMainPowerLost || !secondsBackupPowerLost) && !(stat & NOPOWER)) - -/obj/machinery/door/airlock/requiresID() - return !(isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) - -/obj/machinery/door/airlock/proc/isAllPowerCut() - if(isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - if(isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - return TRUE - return FALSE - -/obj/machinery/door/airlock/proc/regainMainPower() - if(secondsMainPowerLost > 0) - secondsMainPowerLost = 0 - -/obj/machinery/door/airlock/proc/loseMainPower() - if(secondsMainPowerLost <= 0) - secondsMainPowerLost = 60 - if(secondsBackupPowerLost < 10) - secondsBackupPowerLost = 10 - if(!spawnPowerRestoreRunning) - spawnPowerRestoreRunning = TRUE - spawn(0) - var/cont = TRUE - while (cont) - sleep(10) - cont = FALSE - if(secondsMainPowerLost > 0) - if(!isWireCut(AIRLOCK_WIRE_MAIN_POWER1) && !isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - secondsMainPowerLost -= 1 - updateDialog() - cont = TRUE - - if(secondsBackupPowerLost>0) - if(!isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) && !isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - secondsBackupPowerLost -= 1 - updateDialog() - cont = TRUE - spawnPowerRestoreRunning = FALSE - updateDialog() - -/obj/machinery/door/airlock/proc/loseBackupPower() - if(secondsBackupPowerLost < 60) - secondsBackupPowerLost = 60 - -/obj/machinery/door/airlock/proc/regainBackupPower() - if(secondsBackupPowerLost > 0) - secondsBackupPowerLost = 0 - -/obj/machinery/door/airlock/proc/bolt() - if(locked) - return - locked = 1 - playsound(src, door_bolt_down_sound, 30, 0, 3) - update_icon() - -/obj/machinery/door/airlock/proc/unbolt() - if(!locked) - return - locked = 0 - playsound(src, door_bolt_up_sound, 30, 0, 3) - update_icon() - -// 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/proc/shock(mob/user, prb) - if(!hasPower()) // 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 - sleep(10) - hasShocked = 0 - return 1 - else - return 0 - -/obj/machinery/door/airlock/update_icon(state = AIRLOCK_DEFAULT) - switch(state) - if(AIRLOCK_DEFAULT) - if(density) - state = AIRLOCK_CLOSED - else - state = AIRLOCK_OPEN - icon_state = "" - if(AIRLOCK_OPEN, AIRLOCK_CLOSED) - icon_state = "" - if(AIRLOCK_DENY, AIRLOCK_OPENING, AIRLOCK_CLOSING, AIRLOCK_EMAG) - icon_state = "nonexistenticonstate" - set_airlock_overlays(state) - -/obj/machinery/door/airlock/proc/set_airlock_overlays(state) - var/image/frame_overlay - var/image/filling_overlay - var/image/lights_overlay - var/image/panel_overlay - var/image/weld_overlay - var/image/sparks_overlay - - switch(state) - if(AIRLOCK_CLOSED) - frame_overlay = get_airlock_overlay("closed", icon) - if(inner_material) - filling_overlay = get_airlock_overlay("[inner_material]_closed", overlays_file) - else - filling_overlay = get_airlock_overlay("fill_closed", icon) - if(p_open) - panel_overlay = get_airlock_overlay("panel_closed", overlays_file) - if(welded) - weld_overlay = get_airlock_overlay("welded", overlays_file) - if(lights && hasPower()) - if(locked) - lights_overlay = get_airlock_overlay("lights_bolts", overlays_file) - else if(emergency) - lights_overlay = get_airlock_overlay("lights_emergency", overlays_file) - - if(AIRLOCK_DENY) - frame_overlay = get_airlock_overlay("closed", icon) - if(inner_material) - filling_overlay = get_airlock_overlay("[inner_material]_closed", overlays_file) - else - filling_overlay = get_airlock_overlay("fill_closed", icon) - if(p_open) - panel_overlay = get_airlock_overlay("panel_closed", overlays_file) - if(welded) - weld_overlay = get_airlock_overlay("welded", overlays_file) - lights_overlay = get_airlock_overlay("lights_denied", overlays_file) - - if(AIRLOCK_EMAG) - frame_overlay = get_airlock_overlay("closed", icon) - sparks_overlay = get_airlock_overlay("sparks", overlays_file) - if(inner_material) - filling_overlay = get_airlock_overlay("[inner_material]_closed", overlays_file) - else - filling_overlay = get_airlock_overlay("fill_closed", icon) - if(p_open) - panel_overlay = get_airlock_overlay("panel_closed", overlays_file) - if(welded) - weld_overlay = get_airlock_overlay("welded", overlays_file) - - if(AIRLOCK_CLOSING) - frame_overlay = get_airlock_overlay("closing", icon) - if(inner_material) - filling_overlay = get_airlock_overlay("[inner_material]_closing", overlays_file) - else - filling_overlay = get_airlock_overlay("fill_closing", icon) - if(lights && hasPower()) - lights_overlay = get_airlock_overlay("lights_closing", overlays_file) - if(p_open) - panel_overlay = get_airlock_overlay("panel_closing", overlays_file) - - if(AIRLOCK_OPEN) - frame_overlay = get_airlock_overlay("open", icon) - if(inner_material) - filling_overlay = get_airlock_overlay("[inner_material]_open", overlays_file) - else - filling_overlay = get_airlock_overlay("fill_open", icon) - if(p_open) - panel_overlay = get_airlock_overlay("panel_open", overlays_file) - - if(AIRLOCK_OPENING) - frame_overlay = get_airlock_overlay("opening", icon) - if(inner_material) - filling_overlay = get_airlock_overlay("[inner_material]_opening", overlays_file) - else - filling_overlay = get_airlock_overlay("fill_opening", icon) - if(lights && hasPower()) - lights_overlay = get_airlock_overlay("lights_opening", overlays_file) - if(p_open) - panel_overlay = get_airlock_overlay("panel_opening", overlays_file) - - // Doesn't used overlays.Cut() for performance reasons. - if(frame_overlay != old_frame_overlay) - overlays -= old_frame_overlay - overlays += frame_overlay - old_frame_overlay = frame_overlay - if(filling_overlay != old_filling_overlay) - overlays -= old_filling_overlay - overlays += filling_overlay - old_filling_overlay = filling_overlay - if(lights_overlay != old_lights_overlay) - if(lights_overlay) - lights_overlay.layer = LIGHTING_LAYER + 1 - lights_overlay.plane = LIGHTING_PLANE + 1 - overlays -= old_lights_overlay - overlays += lights_overlay - old_lights_overlay = lights_overlay - if(panel_overlay != old_panel_overlay) - overlays -= old_panel_overlay - overlays += panel_overlay - old_panel_overlay = panel_overlay - if(weld_overlay != old_weld_overlay) - overlays -= old_weld_overlay - overlays += weld_overlay - old_weld_overlay = weld_overlay - if(sparks_overlay != old_sparks_overlay) - if(sparks_overlay) - sparks_overlay.layer = LIGHTING_LAYER + 1 - sparks_overlay.plane = LIGHTING_PLANE + 1 - overlays -= old_sparks_overlay - overlays += sparks_overlay - old_sparks_overlay = sparks_overlay - -/proc/get_airlock_overlay(icon_state, icon_file) - var/iconkey = "[icon_state][icon_file]" - if(airlock_overlays[iconkey]) - return airlock_overlays[iconkey] - airlock_overlays[iconkey] = image(icon_file, icon_state) - return airlock_overlays[iconkey] - -/obj/machinery/door/airlock/do_animate(animation) - switch(animation) - if("opening") - update_icon(AIRLOCK_OPENING) - if("closing") - update_icon(AIRLOCK_CLOSING) - if("deny") - update_icon(AIRLOCK_DENY) - playsound(src, door_deni_sound, 40, 0, 3) - sleep(6) - update_icon(AIRLOCK_CLOSED) - icon_state = "closed" - -/obj/machinery/door/airlock/attack_ghost(mob/user) - //Separate interface for ghosts. - if(user.client.machine_interactive_ghost) - show_unified_command_interface(user) - -/obj/machinery/door/airlock/attack_ai(mob/user) -//#Z1 - if(isWireCut(AIRLOCK_WIRE_AI_CONTROL)) - to_chat(user, "Airlock AI control wire is cut. Please call the engineer or engiborg to fix this problem.") - return -//##Z1 - if(!canAIControl()) - if(canAIHack()) - hack(user) - return - else - to_chat(user, "Airlock AI control has been blocked with a firewall. Unable to hack.") - - show_unified_command_interface(user) - -//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 11 lift access override -//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 11 lift access override - -/obj/machinery/door/airlock/proc/show_unified_command_interface(mob/user) - user.set_machine(src) - var/t1 = text("Airlock Control
    \n") - if(secondsMainPowerLost > 0) - if(!isWireCut(AIRLOCK_WIRE_MAIN_POWER1) && !isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - t1 += text("Main power is offline for [] seconds.
    \n", secondsMainPowerLost) - else - t1 += text("Main power is offline indefinitely.
    \n") - else - t1 += text("Main power is online.") - - if(secondsBackupPowerLost > 0) - if(!isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) && !isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - t1 += text("Backup power is offline for [] seconds.
    \n", secondsBackupPowerLost) - else - t1 += text("Backup power is offline indefinitely.
    \n") - else if(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(isWireCut(AIRLOCK_WIRE_IDSCAN)) - t1 += text("IdScan wire is cut.
    \n") - else if(aiDisabledIdScanner) - t1 += text("IdScan disabled. Enable?
    \n", src) - else - t1 += text("IdScan enabled. Disable?
    \n", src) - - if(emergency) - t1 += text("Emergency access override is enabled. Disable?
    \n", src) - else - t1 += text("Emergency access override is disabled. Enable?
    \n", src) - - if(isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) - t1 += text("Main Power Input wire is cut.
    \n") - if(isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - t1 += text("Main Power Output wire is cut.
    \n") - if(!secondsMainPowerLost) - t1 += text("Temporarily disrupt main power?.
    \n", src) - if(!secondsBackupPowerLost) - t1 += text("Temporarily disrupt backup power?.
    \n", src) - - if(isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) - t1 += text("Backup Power Input wire is cut.
    \n") - if(isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - t1 += text("Backup Power Output wire is cut.
    \n") - - if(isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - t1 += text("Door bolt drop wire is cut.
    \n") - else if(!locked) - t1 += text("Door bolts are up. Drop them?
    \n", src) - else - t1 += text("Door bolts are down.") - if(hasPower()) - t1 += text(" Raise?
    \n", src) - else - t1 += text(" Cannot raise door bolts due to power failure.
    \n") - - if(isWireCut(AIRLOCK_WIRE_LIGHT)) - t1 += text("Door bolt lights wire is cut.
    \n") - else if(!lights) - t1 += text("Door lights are off. Enable?
    \n", src) - else - t1 += text("Door lights are on. Disable?
    \n", src) - - if(isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - t1 += text("Electrification wire is cut.
    \n") - if(secondsElectrified == -1) - t1 += text("Door is electrified indefinitely. Un-electrify it?
    \n", src) - else if(secondsElectrified>0) - t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
    \n", 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(isWireCut(AIRLOCK_WIRE_SAFETY)) - t1 += text("Door force sensors not responding.
    \n") - else if(safe) - t1 += text("Door safeties operating normally. Override?
    \n",src) - else - t1 += text("Danger. Door safeties disabled. Restore?
    \n",src) - - if(isWireCut(AIRLOCK_WIRE_SPEED)) - t1 += text("Door timing circuitry not responding.
    \n") - else if(normalspeed) - t1 += text("Door timing circuitry operating normally. Override?
    \n",src) - else - t1 += text("Warning. Door timing circuitry operating abnormally. Restore?
    \n",src) - - if(welded) - t1 += text("Door appears to have been welded shut.
    \n") - else if(!locked) - if(density) - t1 += text("Open door
    \n", src) - else - t1 += text("Close door
    \n", src) - - t1 += text("

    Close

    \n", src) - user << browse(entity_ja(t1), "window=airlock") - onclose(user, "airlock") - - -/obj/machinery/door/airlock/proc/hack(mob/user) - if(!aiHacking) - aiHacking = TRUE - spawn(20) - //TODO: Make this take a minute - to_chat(user, "Airlock AI control has been blocked. Beginning fault-detection.") - sleep(50) - if(!hack_can_continue(user)) - return - to_chat(user, "Fault confirmed: airlock control wire disabled.")//#Z1 - sleep(20) - to_chat(user, "Attempting to hack into airlock. This may take some time.") - sleep(200) - if(!hack_can_continue(user)) - return - to_chat(user, "Upload access confirmed. Loading control program into airlock software.") - sleep(170) - if(!hack_can_continue(user)) - return - to_chat(user, "Transfer complete. Forcing airlock to execute program.") - sleep(50) - //disable blocked control -//#Z1 - //aiControlDisabled = 2 - aiControlDisabled = FALSE - pulseProof = TRUE -//##Z1 - to_chat(user, "Receiving control information from airlock.") - sleep(10) - //bring up airlock dialog - aiHacking = FALSE - if (user) - attack_ai(user) - -/obj/machinery/door/airlock/proc/hack_can_continue(mob/user) - if(canAIControl()) - to_chat(user, "Alert cancelled. Airlock control has been restored without our assistance.") - aiHacking = FALSE - return FALSE - else if(!canAIHack()) - to_chat(user, "We've lost our connection! Unable to hack airlock.") - aiHacking = FALSE - return FALSE - return TRUE - -/obj/machinery/door/airlock/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if (isElectrified()) - if (istype(mover, /obj/item)) - var/obj/item/i = mover - if (i.m_amt) - 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/attack_paw(mob/user) - if(istype(user, /mob/living/carbon/alien/humanoid)) - if(welded || locked) - to_chat(user, "\red The door is sealed, it cannot be pried open.") - return - else if(!density) - return - else if(!user.is_busy(src)) - to_chat(user, "You force your claws between the doors and begin to pry them open...") - playsound(src, door_forced_sound, 30, 1, -4) - if(do_after(user,40, target = src) && src) - open(1) - return - -/obj/machinery/door/airlock/attack_animal(mob/user) - if(istype(user, /mob/living/simple_animal/hulk)) - var/mob/living/simple_animal/hulk/H = user - H.attack_hulk(src) - -/obj/machinery/door/airlock/proc/door_rupture(mob/user) - var/obj/structure/door_assembly/da = new assembly_type(loc) - da.anchored = 0 - var/target = da.loc - for(var/i in 1 to 4) - target = get_turf(get_step(target,user.dir)) - da.throw_at(target, 200, 100, spin = FALSE) - if(mineral) - da.change_mineral_airlock_type(mineral) - if(glass && da.can_insert_glass) - da.set_glass(TRUE) - da.state = ASSEMBLY_WIRED - da.created_name = name - da.update_state() - - var/obj/item/weapon/airlock_electronics/ae - ae = new/obj/item/weapon/airlock_electronics(loc) - if(!req_access) - check_access() - if(req_access.len) - ae.conf_access = req_access - else if (req_one_access.len) - ae.conf_access = req_one_access - ae.one_access = 1 - ae.loc = da - da.electronics = ae - - qdel(src) - -/obj/machinery/door/airlock/proc/hulk_break_reaction(mob/living/carbon/user) - if(!density) - return - user.SetNextMove(CLICK_CD_MELEE) - if(user.a_intent == "hurt") - if(user.hulk_scream(src, 90)) - door_rupture(user) - return - else if(locked) - to_chat(user, " The door is bolted and you need more aggressive force to get thru!") - return - var/passed = FALSE - for(var/I in get_step(user,user.dir)) - if(I == src) - passed = TRUE - break - if(!passed) - return - if(user.is_busy(src)) return - var/cur_dir = user.dir - user.visible_message("The [user] starts to force the [src] open with a bare hands!",\ - "You start forcing the [src] open with a bare hands!",\ - "You hear metal strain.") - if(do_after(user, 30, target = src) && density && user.dir == cur_dir) - user.canmove = 0 - var/turf/target = user.loc - open() - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - if(istype(target,/turf/simulated/floor)) - var/turf/simulated/floor/tile = target - tile.break_tile() - for(var/i in 1 to 2) - if(!step(user,cur_dir)) - for(var/mob/living/L in get_step(user,cur_dir)) - L.adjustBruteLoss(rand(20,60)) - break - playsound(src,'sound/weapons/thudswoosh.ogg', 50, 1) - user.visible_message("The [user] forces the [src] open with a bare hands!",\ - "You force the [src] open with a bare hands!",\ - "You hear metal strain, and a door open.") - user.canmove = 1 - close() - -/obj/machinery/door/airlock/attack_hand(mob/user) - if(ishuman(user) && prob(40) && density) - var/mob/living/carbon/human/H = user - if(H.getBrainLoss() >= 60) - playsound(src, 'sound/effects/bang.ogg', 25, 1) - if(!istype(H.head, /obj/item/clothing/head/helmet)) - visible_message(" [user] headbutts the airlock.") - var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] - H.Stun(8) - H.Weaken(5) - BP.take_damage(10, 0) - else - visible_message(" [user] headbutts the airlock. Good thing they're wearing a helmet.") - return - - if(wires.interact(user)) - return - else - if(isElectrified() && !issilicon(user) && !isobserver(user)) - if(shock(user, 100)) - return - if(HULK in user.mutations) - hulk_break_reaction(user) - return - ..() - - -/obj/machinery/door/airlock/Topic(href, href_list, var/no_window = 0) - if(href_list["close"]) - usr << browse(null, "window=airlock") - usr.unset_machine(src) - return FALSE - - . = ..(href, href_list) - if(!.) - return - - if((issilicon(usr) && canAIControl()) || isobserver(usr)) - //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, 11 lift access override - //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, 11 lift access override - if(href_list["aiDisable"]) - var/code = text2num(href_list["aiDisable"]) - switch (code) - if(1) - // Disable idscan - if(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(aiDisabledIdScanner) - to_chat(usr, "You've already disabled the IdScan feature.") - else - aiDisabledIdScanner = 1 - - if(2) - // Disrupt main power - if(!secondsMainPowerLost) - loseMainPower() - else - to_chat(usr, "Main power is already offline.") - - if(3) - // Disrupt backup power - if(!secondsBackupPowerLost) - loseBackupPower() - else - to_chat(usr, "Backup power is already offline.") - - if(4) - // Drop door bolts - if(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(!locked) - bolt() - - if(5) - // Un-electrify door - if(isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - to_chat(usr, "Can't un-electrify the airlock - The electrification wire is cut.") - else if(secondsElectrified == -1) - secondsElectrified = 0 - else if(secondsElectrified > 0) - secondsElectrified = 0 - - if(7) - // Close door - if(welded) - to_chat(usr, "The airlock has been welded shut!") - else if(locked) - to_chat(usr, "The door bolts are down!") - else - close() - - if(8) - // Safeties! We don't need no stinking safeties! - if(isWireCut(AIRLOCK_WIRE_SAFETY)) - to_chat(usr, "Control to door sensors is disabled.") - else if(safe) - safe = 0 - else - to_chat(usr, "Firmware reports safeties already overriden.") - - if(9) - // Door speed control - if(isWireCut(AIRLOCK_WIRE_SPEED)) - to_chat(usr, "Control to door timing circuitry has been severed.") - else if(normalspeed) - normalspeed = 0 - else - to_chat(usr, "Door timing circurity already accellerated.") - - if(10) - // Bolt lights - if(isWireCut(AIRLOCK_WIRE_LIGHT)) - to_chat(usr, "Control to door bolt lights has been severed.") - else if (lights) - lights = 0 - update_icon() - else - to_chat(usr, "Door bolt lights are already disabled!") - - if(11) - // Emergency access - if(emergency) - emergency = 0 - update_icon() - else - to_chat(usr, "Emergency access is already disabled!") - - else if(href_list["aiEnable"]) - var/code = text2num(href_list["aiEnable"]) - switch (code) - if(1) - // Enable idscan - if(isWireCut(AIRLOCK_WIRE_IDSCAN)) - to_chat(usr, "You can't enable IdScan - The IdScan wire has been cut.") - else if(aiDisabledIdScanner) - aiDisabledIdScanner = 0 - else - to_chat(usr, "The IdScan feature is not disabled.") - - if(4) - // Raise door bolts - if(isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - to_chat(usr, "The door bolt drop wire is cut - you can't raise the door bolts.
    \n") - else if(!locked) - to_chat(usr, "The door bolts are already up.
    \n") - else - if(hasPower()) - unbolt() - else - to_chat(usr, "Cannot raise door bolts due to power failure.
    \n") - - if(5) - // Electrify door for 30 seconds - if(isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - to_chat(usr, "The electrification wire has been cut.
    \n") - else if(secondsElectrified == -1) - to_chat(usr, "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(secondsElectrified) - to_chat(usr, "The door is already electrified. You can't re-electrify it while it's already electrified.
    \n") - else - shockedby += "\[[time_stamp()]\][usr](ckey:[usr.ckey])" - usr.attack_log += "\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]" - secondsElectrified = 30 - START_PROCESSING(SSmachine, src) - - if(6) - // Electrify door indefinitely - if(isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - to_chat(usr, "The electrification wire has been cut.
    \n") - else if(secondsElectrified == -1) - to_chat(usr, "The door is already indefinitely electrified.
    \n") - else if(secondsElectrified) - to_chat(usr, "The door is already electrified. You can't re-electrify it while it's already electrified.
    \n") - else - shockedby += "\[[time_stamp()]\][usr](ckey:[usr.ckey])" - usr.attack_log += "\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]" - secondsElectrified = -1 - - if(7) - // Open door - if(welded) - to_chat(usr, "The airlock has been welded shut!") - else if(locked) - to_chat(usr, "The door bolts are down!") - else - open() - - if (8) - // Safeties! Maybe we do need some stinking safeties! - if (isWireCut(AIRLOCK_WIRE_SAFETY)) - to_chat(usr, "Control to door sensors is disabled.") - else if (!safe) - safe = 1 - else - to_chat(usr, "Firmware reports safeties already in place.") - - if(9) - // Door speed control - if(isWireCut(AIRLOCK_WIRE_SPEED)) - to_chat(usr, "Control to door timing circuitry has been severed.") - else if (!normalspeed) - normalspeed = 1 - else - to_chat(usr, "Door timing circurity currently operating normally.") - - if(10) - // Bolt lights - if(isWireCut(AIRLOCK_WIRE_LIGHT)) - to_chat(usr, "Control to door bolt lights has been severed.") - else if (!lights) - lights = 1 - update_icon() - else - to_chat(usr, "Door bolt lights are already enabled!") - - if(11) - // Emergency access - if(!emergency) - emergency = 1 - update_icon() - else - to_chat(usr, "Emergency access is already disabled!") - - if(!no_window) - updateUsrDialog() - -/obj/machinery/door/airlock/attackby(C, mob/user) - - if(istype(C,/obj/item/weapon/changeling_hammer) && !operating && density) // yeah, hammer ignore electrify - var/obj/item/weapon/changeling_hammer/W = C - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - visible_message("[user] has punched the [src]!") - playsound(loc, 'sound/effects/grillehit.ogg', 50, 1) - if(W.use_charge(user) && prob(20)) - playsound(loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) - door_rupture(user) - return - - if(!(issilicon(user) || isobserver(user))) - if(isElectrified()) - if(shock(user, 75)) - return - if(istype(C, /obj/item/device/detective_scanner) || istype(C, /obj/item/taperoll)) - return - - add_fingerprint(user) - - if(istype(C, /obj/item/weapon/weldingtool) && !(operating > 0) && density) - var/obj/item/weapon/weldingtool/W = C - if(W.remove_fuel(0,user)) - welded = !welded - update_icon() - return - else - return - else if(istype(C, /obj/item/weapon/screwdriver)) - p_open = !p_open - update_icon() - else if(istype(C, /obj/item/weapon/wirecutters)) - return attack_hand(user) - else if(istype(C, /obj/item/device/multitool)) - return attack_hand(user) - else if(istype(C, /obj/item/device/assembly/signaler)) - return attack_hand(user) - else if(istype(C, /obj/item/weapon/pai_cable)) // -- TLE - var/obj/item/weapon/pai_cable/cable = C - cable.plugin(src, user) - else if(istype(C, /obj/item/weapon/crowbar) || istype(C, /obj/item/weapon/twohanded/fireaxe) ) - var/beingcrowbarred = null - if(istype(C, /obj/item/weapon/crowbar) ) - beingcrowbarred = 1 //derp, Agouri - else - beingcrowbarred = 0 - if( beingcrowbarred && (operating == -1 || density && welded && operating != 1 && p_open && !hasPower() && !locked) ) - if(user.is_busy(src)) return - playsound(src, '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.") - if(do_after(user,40,target = src)) - to_chat(user, "\blue You removed the airlock electronics!") - - var/obj/structure/door_assembly/da = new assembly_type(loc) - da.anchored = 1 - if(mineral) - da.change_mineral_airlock_type(mineral) - if(glass && da.can_insert_glass) - da.set_glass(TRUE) - da.state = ASSEMBLY_WIRED - da.dir = dir - da.created_name = name - da.update_state() - - var/obj/item/weapon/airlock_electronics/ae - if(!electronics) - ae = new/obj/item/weapon/airlock_electronics(loc) - if(!req_access) - check_access() - if(req_access.len) - ae.conf_access = req_access - else if (req_one_access.len) - ae.conf_access = req_one_access - ae.one_access = 1 - else - ae = electronics - electronics = null - ae.loc = loc - if(operating == -1) - ae.icon_state = "door_electronics_smoked" - ae.broken = TRUE - operating = 0 - - qdel(src) - return - else if(hasPower()) - to_chat(user, "The airlock's motors resist your efforts to force it.") - 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/twohanded/fireaxe/F = C - if(F:wielded) - spawn(0) open(1) - else - to_chat(user, "\red You need to be wielding the Fire axe to do that.") - else - spawn(0) open(1) - else - if(beingcrowbarred == 0) - var/obj/item/weapon/twohanded/fireaxe/F = C - if(F:wielded) - spawn(0) close(1) - else - to_chat(user, "\red You need to be wielding the Fire axe to do that.") - else - spawn(0) close(1) - - else if(istype(C, /obj/item/weapon/airlock_painter)) //airlock painter - change_paintjob(C, user) - else - ..() - return - -/obj/machinery/door/airlock/phoron/attackby(C, mob/user) - if(C) - ignite(is_hot(C)) - ..() - -/obj/machinery/door/airlock/proc/close_unsafe(bolt_after = FALSE) - var/temp = safe - - safe = FALSE - - if(close()) - safe = temp - if(bolt_after) - bolt() - -/obj/machinery/door/airlock/open_checks() - if(..() && !welded && !locked) - return TRUE - return FALSE - -/obj/machinery/door/airlock/close_checks() - if(..() && !welded && !locked) - if(safe) - for(var/turf/T in locs) - if(locate(/mob/living) in T) - autoclose() - return FALSE - return TRUE - return FALSE - -/obj/machinery/door/airlock/normal_open_checks() - if(hasPower() && !isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) - return TRUE - return FALSE - -/obj/machinery/door/airlock/normal_close_checks() - if(hasPower() && !isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - return TRUE - return FALSE - -/obj/machinery/door/airlock/do_open() - send_status_if_allowed() - if(closeOther != null && istype(closeOther, /obj/machinery/door/airlock/) && !closeOther.density) - closeOther.close() - if(hasPower()) - use_power(50) - ..() - autoclose() - -/obj/machinery/door/airlock/do_close() - send_status_if_allowed() - if(hasPower()) - use_power(50) - ..() - -/obj/machinery/door/airlock/do_afterclose() - for(var/turf/T in locs) - for(var/mob/living/M in T) - if(isrobot(M)) - M.adjustBruteLoss(DOOR_CRUSH_DAMAGE) - else - M.adjustBruteLoss(DOOR_CRUSH_DAMAGE) - M.SetStunned(5) - M.SetWeakened(5) - M.visible_message("[M] was crushed by the [src] door.", - "[src] door crushed you.") - - for(var/obj/structure/window/W in T) - W.ex_act(2) - - for(var/obj/effect/fluid/F in T) - qdel(F) - ..() - -/obj/machinery/door/airlock/proc/autoclose() - if(autoclose) - if(close_timer_id) - deltimer(close_timer_id) - close_timer_id = addtimer(CALLBACK(src, .proc/do_autoclose), normalspeed ? 150 : 5, TIMER_STOPPABLE) - -/obj/machinery/door/airlock/proc/do_autoclose() - close_timer_id = null - close() - -/obj/machinery/door/airlock/proc/prison_open() - unbolt() - open() - bolt() - return - -/obj/machinery/door/airlock/proc/change_paintjob(obj/item/C, mob/user) - var/obj/item/weapon/airlock_painter/W - if(istype(C, /obj/item/weapon/airlock_painter)) - W = C - else - to_chat(user, "If you see this, it means airlock/change_paintjob() was called with something other than an airlock painter. Check your code!") - return - - if(!W.can_use(user)) - return - - var/list/optionlist - if(inner_material == "glass") - optionlist = list("Public", "Public2", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance") - else - optionlist = list("Public", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance", "External", "High Security") - - var/paintjob = input(user, "Please select a paintjob for this airlock.") in optionlist - if((!in_range(src, usr) && loc != usr) || !W.use(user)) - return - switch(paintjob) - if("Public") - icon = 'icons/obj/doors/airlocks/station/public.dmi' - overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - if("Public2") - icon = 'icons/obj/doors/airlocks/station2/glass.dmi' - overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi' - if("Engineering") - icon = 'icons/obj/doors/airlocks/station/engineering.dmi' - overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - if("Atmospherics") - icon = 'icons/obj/doors/airlocks/station/atmos.dmi' - overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - if("Security") - icon = 'icons/obj/doors/airlocks/station/security.dmi' - overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - if("Command") - icon = 'icons/obj/doors/airlocks/station/command.dmi' - overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - if("Medical") - icon = 'icons/obj/doors/airlocks/station/medical.dmi' - overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - if("Research") - icon = 'icons/obj/doors/airlocks/station/research.dmi' - overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - heat_proof = glass - if("Mining") - icon = 'icons/obj/doors/airlocks/station/mining.dmi' - overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - if("Maintenance") - icon = 'icons/obj/doors/airlocks/station/maintenance.dmi' - overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - if("External") - icon = 'icons/obj/doors/airlocks/external/external.dmi' - overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi' - if("High Security") - icon = 'icons/obj/doors/airlocks/highsec/highsec.dmi' - overlays_file = 'icons/obj/doors/airlocks/highsec/overlays.dmi' - update_icon() - -/obj/structure/door_scrap - name = "Door Scrap" - desc = "Just a bunch of garbage." - var/ticker = 0 - var/icon/door = icon('icons/effects/effects.dmi',"Sliced") - //light_power = 1 - //light_color = "#cc0000" - - -/obj/structure/door_scrap/attackby(obj/O, mob/user) - if(istype(O,/obj/item/weapon/wrench)) - if(ticker >= 300) - playsound(user.loc, 'sound/items/Ratchet.ogg', 50) - user.visible_message("[user] has disassemble these scrap...") - new /obj/item/stack/sheet/metal(loc) - new /obj/item/stack/sheet/metal(loc) - qdel(src) - else - to_chat(user,"This is too hot to dismantle it") - if(prob(10)) - to_chat(user,"You accidentally drop your wrench in the flame") - qdel(O) - else - return - - -/obj/structure/door_scrap/atom_init() - . = ..() - var/image/fire_overlay = image("icon"='icons/effects/effects.dmi', "icon_state"="s_fire", "layer" = (LIGHTING_LAYER + 1)) - fire_overlay.plane = LIGHTING_PLANE + 1 - overlays += fire_overlay - START_PROCESSING(SSobj, src) - -/obj/structure/door_scrap/process() - if(ticker >= 300) - overlays.Cut() - STOP_PROCESSING(SSobj, src) - return - ticker++ - var/spot = locate(/obj/effect/fluid) in loc - if(spot) - ticker +=10 +#define AIRLOCK_DEFAULT 0 +#define AIRLOCK_CLOSED 1 +#define AIRLOCK_CLOSING 2 +#define AIRLOCK_OPEN 3 +#define AIRLOCK_OPENING 4 +#define AIRLOCK_DENY 5 +#define AIRLOCK_EMAG 6 +var/list/airlock_overlays = list() + +/obj/machinery/door/airlock + name = "airlock" + icon = 'icons/obj/doors/airlocks/station/public.dmi' + icon_state = "closed" + explosion_resistance = 15 + + 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 + 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 + autoclose = 1 + var/assembly_type = /obj/structure/door_assembly + var/mineral = null + var/justzap = 0 + var/safe = 1 + normalspeed = 1 + var/obj/item/weapon/airlock_electronics/electronics = null + var/hasShocked = 0 //Prevents multiple shocks from happening + var/pulseProof = 0 //#Z1 AI hacked this door after previous pulse? + var/shockedby = list() + var/close_timer_id = null + var/datum/wires/airlock/wires = null + + var/inner_material = null //material of inner filling; if its an airlock with glass, this should be set to "glass" + var/overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + + var/image/old_frame_overlay //keep those in order to prevent unnecessary updating + var/image/old_filling_overlay + var/image/old_lights_overlay + var/image/old_panel_overlay + var/image/old_weld_overlay + var/image/old_sparks_overlay + + door_open_sound = 'sound/machines/airlock/airlockToggle.ogg' + door_close_sound = 'sound/machines/airlock/airlockToggle.ogg' + var/door_deni_sound = 'sound/machines/airlock/airlockDenied.ogg' + var/door_bolt_up_sound = 'sound/machines/airlock/airlockBoltsUp.ogg' + var/door_bolt_down_sound = 'sound/machines/airlock/airlockBoltsDown.ogg' + var/door_forced_sound = 'sound/machines/airlock/airlockForced.ogg' + +/obj/machinery/door/airlock/atom_init(mapload, dir = null) + ..() + airlock_list += src + wires = new(src) + if(glass && !inner_material) + inner_material = "glass" + if(dir) + src.dir = dir + update_icon() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/door/airlock/atom_init_late() + if(closeOtherId != null) + for (var/obj/machinery/door/airlock/A in airlock_list) + if(A.closeOtherId == closeOtherId && A != src) + closeOther = A + break + +/obj/machinery/door/airlock/Destroy() + airlock_list -= src + QDEL_NULL(wires) + QDEL_NULL(electronics) + closeOther = null + return ..() + +/obj/machinery/door/airlock/process() + if(secondsElectrified > 0) + secondsElectrified-- + else + return PROCESS_KILL + +/obj/machinery/door/airlock/bumpopen(mob/living/user) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite + if(!issilicon(usr)) + if(isElectrified()) + if(!justzap) + if(shock(user, 100)) + justzap = TRUE + spawn (10) + justzap = FALSE + return + else /*if(justzap)*/ + return + else if(user.hallucination > 50 && prob(10) && !operating) + to_chat(user, "\red You feel a powerful shock course through your body!") + user.halloss += 10 + user.stunned += 10 + return + ..(user) + +/obj/machinery/door/airlock/bumpopen(mob/living/simple_animal/user) + ..(user) + +/obj/machinery/door/airlock/CanAStarPass(obj/item/weapon/card/id/ID, to_dir, caller) + return !density || (check_access(ID) && !locked && hasPower()) + +/obj/machinery/door/airlock/proc/isElectrified() + if(secondsElectrified) + return TRUE + return FALSE + +/obj/machinery/door/airlock/proc/isWireCut(wireIndex) + return wires.is_index_cut(wireIndex) + +/obj/machinery/door/airlock/proc/canAIControl() + return ((aiControlDisabled != 1) && !isAllPowerCut()); + +/obj/machinery/door/airlock/proc/canAIHack() + return (aiControlDisabled && !hackProof && !isAllPowerCut()); + +/obj/machinery/door/airlock/hasPower() + return ((!secondsMainPowerLost || !secondsBackupPowerLost) && !(stat & NOPOWER)) + +/obj/machinery/door/airlock/requiresID() + return !(isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) + +/obj/machinery/door/airlock/proc/isAllPowerCut() + if(isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) + if(isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) + return TRUE + return FALSE + +/obj/machinery/door/airlock/proc/regainMainPower() + if(secondsMainPowerLost > 0) + secondsMainPowerLost = 0 + +/obj/machinery/door/airlock/proc/loseMainPower() + if(secondsMainPowerLost <= 0) + secondsMainPowerLost = 60 + if(secondsBackupPowerLost < 10) + secondsBackupPowerLost = 10 + if(!spawnPowerRestoreRunning) + spawnPowerRestoreRunning = TRUE + spawn(0) + var/cont = TRUE + while (cont) + sleep(10) + cont = FALSE + if(secondsMainPowerLost > 0) + if(!isWireCut(AIRLOCK_WIRE_MAIN_POWER1) && !isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) + secondsMainPowerLost -= 1 + updateDialog() + cont = TRUE + + if(secondsBackupPowerLost>0) + if(!isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) && !isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) + secondsBackupPowerLost -= 1 + updateDialog() + cont = TRUE + spawnPowerRestoreRunning = FALSE + updateDialog() + +/obj/machinery/door/airlock/proc/loseBackupPower() + if(secondsBackupPowerLost < 60) + secondsBackupPowerLost = 60 + +/obj/machinery/door/airlock/proc/regainBackupPower() + if(secondsBackupPowerLost > 0) + secondsBackupPowerLost = 0 + +/obj/machinery/door/airlock/proc/bolt() + if(locked) + return + locked = 1 + playsound(src, door_bolt_down_sound, 30, 0, 3) + update_icon() + +/obj/machinery/door/airlock/proc/unbolt() + if(!locked) + return + locked = 0 + playsound(src, door_bolt_up_sound, 30, 0, 3) + update_icon() + +// 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/proc/shock(mob/user, prb) + if(!hasPower()) // 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 + sleep(10) + hasShocked = 0 + return 1 + else + return 0 + +/obj/machinery/door/airlock/update_icon(state = AIRLOCK_DEFAULT) + switch(state) + if(AIRLOCK_DEFAULT) + if(density) + state = AIRLOCK_CLOSED + else + state = AIRLOCK_OPEN + icon_state = "" + if(AIRLOCK_OPEN, AIRLOCK_CLOSED) + icon_state = "" + if(AIRLOCK_DENY, AIRLOCK_OPENING, AIRLOCK_CLOSING, AIRLOCK_EMAG) + icon_state = "nonexistenticonstate" + set_airlock_overlays(state) + +/obj/machinery/door/airlock/proc/set_airlock_overlays(state) + var/image/frame_overlay + var/image/filling_overlay + var/image/lights_overlay + var/image/panel_overlay + var/image/weld_overlay + var/image/sparks_overlay + + switch(state) + if(AIRLOCK_CLOSED) + frame_overlay = get_airlock_overlay("closed", icon) + if(inner_material) + filling_overlay = get_airlock_overlay("[inner_material]_closed", overlays_file) + else + filling_overlay = get_airlock_overlay("fill_closed", icon) + if(p_open) + panel_overlay = get_airlock_overlay("panel_closed", overlays_file) + if(welded) + weld_overlay = get_airlock_overlay("welded", overlays_file) + if(lights && hasPower()) + if(locked) + lights_overlay = get_airlock_overlay("lights_bolts", overlays_file) + else if(emergency) + lights_overlay = get_airlock_overlay("lights_emergency", overlays_file) + + if(AIRLOCK_DENY) + frame_overlay = get_airlock_overlay("closed", icon) + if(inner_material) + filling_overlay = get_airlock_overlay("[inner_material]_closed", overlays_file) + else + filling_overlay = get_airlock_overlay("fill_closed", icon) + if(p_open) + panel_overlay = get_airlock_overlay("panel_closed", overlays_file) + if(welded) + weld_overlay = get_airlock_overlay("welded", overlays_file) + lights_overlay = get_airlock_overlay("lights_denied", overlays_file) + + if(AIRLOCK_EMAG) + frame_overlay = get_airlock_overlay("closed", icon) + sparks_overlay = get_airlock_overlay("sparks", overlays_file) + if(inner_material) + filling_overlay = get_airlock_overlay("[inner_material]_closed", overlays_file) + else + filling_overlay = get_airlock_overlay("fill_closed", icon) + if(p_open) + panel_overlay = get_airlock_overlay("panel_closed", overlays_file) + if(welded) + weld_overlay = get_airlock_overlay("welded", overlays_file) + + if(AIRLOCK_CLOSING) + frame_overlay = get_airlock_overlay("closing", icon) + if(inner_material) + filling_overlay = get_airlock_overlay("[inner_material]_closing", overlays_file) + else + filling_overlay = get_airlock_overlay("fill_closing", icon) + if(lights && hasPower()) + lights_overlay = get_airlock_overlay("lights_closing", overlays_file) + if(p_open) + panel_overlay = get_airlock_overlay("panel_closing", overlays_file) + + if(AIRLOCK_OPEN) + frame_overlay = get_airlock_overlay("open", icon) + if(inner_material) + filling_overlay = get_airlock_overlay("[inner_material]_open", overlays_file) + else + filling_overlay = get_airlock_overlay("fill_open", icon) + if(p_open) + panel_overlay = get_airlock_overlay("panel_open", overlays_file) + + if(AIRLOCK_OPENING) + frame_overlay = get_airlock_overlay("opening", icon) + if(inner_material) + filling_overlay = get_airlock_overlay("[inner_material]_opening", overlays_file) + else + filling_overlay = get_airlock_overlay("fill_opening", icon) + if(lights && hasPower()) + lights_overlay = get_airlock_overlay("lights_opening", overlays_file) + if(p_open) + panel_overlay = get_airlock_overlay("panel_opening", overlays_file) + + // Doesn't used overlays.Cut() for performance reasons. + if(frame_overlay != old_frame_overlay) + overlays -= old_frame_overlay + overlays += frame_overlay + old_frame_overlay = frame_overlay + if(filling_overlay != old_filling_overlay) + overlays -= old_filling_overlay + overlays += filling_overlay + old_filling_overlay = filling_overlay + if(lights_overlay != old_lights_overlay) + if(lights_overlay) + lights_overlay.layer = LIGHTING_LAYER + 1 + lights_overlay.plane = LIGHTING_PLANE + 1 + overlays -= old_lights_overlay + overlays += lights_overlay + old_lights_overlay = lights_overlay + if(panel_overlay != old_panel_overlay) + overlays -= old_panel_overlay + overlays += panel_overlay + old_panel_overlay = panel_overlay + if(weld_overlay != old_weld_overlay) + overlays -= old_weld_overlay + overlays += weld_overlay + old_weld_overlay = weld_overlay + if(sparks_overlay != old_sparks_overlay) + if(sparks_overlay) + sparks_overlay.layer = LIGHTING_LAYER + 1 + sparks_overlay.plane = LIGHTING_PLANE + 1 + overlays -= old_sparks_overlay + overlays += sparks_overlay + old_sparks_overlay = sparks_overlay + +/proc/get_airlock_overlay(icon_state, icon_file) + var/iconkey = "[icon_state][icon_file]" + if(airlock_overlays[iconkey]) + return airlock_overlays[iconkey] + airlock_overlays[iconkey] = image(icon_file, icon_state) + return airlock_overlays[iconkey] + +/obj/machinery/door/airlock/do_animate(animation) + switch(animation) + if("opening") + update_icon(AIRLOCK_OPENING) + if("closing") + update_icon(AIRLOCK_CLOSING) + if("deny") + update_icon(AIRLOCK_DENY) + playsound(src, door_deni_sound, 40, 0, 3) + sleep(6) + update_icon(AIRLOCK_CLOSED) + icon_state = "closed" + +/obj/machinery/door/airlock/attack_ghost(mob/user) + //Separate interface for ghosts. + if(user.client.machine_interactive_ghost) + show_unified_command_interface(user) + +/obj/machinery/door/airlock/attack_ai(mob/user) +//#Z1 + if(isWireCut(AIRLOCK_WIRE_AI_CONTROL)) + to_chat(user, "Airlock AI control wire is cut. Please call the engineer or engiborg to fix this problem.") + return +//##Z1 + if(!canAIControl()) + if(canAIHack()) + hack(user) + return + else + to_chat(user, "Airlock AI control has been blocked with a firewall. Unable to hack.") + + show_unified_command_interface(user) + +//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 11 lift access override +//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 11 lift access override + +/obj/machinery/door/airlock/proc/show_unified_command_interface(mob/user) + user.set_machine(src) + var/t1 = text("Airlock Control
    \n") + if(secondsMainPowerLost > 0) + if(!isWireCut(AIRLOCK_WIRE_MAIN_POWER1) && !isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) + t1 += text("Main power is offline for [] seconds.
    \n", secondsMainPowerLost) + else + t1 += text("Main power is offline indefinitely.
    \n") + else + t1 += text("Main power is online.") + + if(secondsBackupPowerLost > 0) + if(!isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) && !isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) + t1 += text("Backup power is offline for [] seconds.
    \n", secondsBackupPowerLost) + else + t1 += text("Backup power is offline indefinitely.
    \n") + else if(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(isWireCut(AIRLOCK_WIRE_IDSCAN)) + t1 += text("IdScan wire is cut.
    \n") + else if(aiDisabledIdScanner) + t1 += text("IdScan disabled. Enable?
    \n", src) + else + t1 += text("IdScan enabled. Disable?
    \n", src) + + if(emergency) + t1 += text("Emergency access override is enabled. Disable?
    \n", src) + else + t1 += text("Emergency access override is disabled. Enable?
    \n", src) + + if(isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) + t1 += text("Main Power Input wire is cut.
    \n") + if(isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) + t1 += text("Main Power Output wire is cut.
    \n") + if(!secondsMainPowerLost) + t1 += text("Temporarily disrupt main power?.
    \n", src) + if(!secondsBackupPowerLost) + t1 += text("Temporarily disrupt backup power?.
    \n", src) + + if(isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) + t1 += text("Backup Power Input wire is cut.
    \n") + if(isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) + t1 += text("Backup Power Output wire is cut.
    \n") + + if(isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + t1 += text("Door bolt drop wire is cut.
    \n") + else if(!locked) + t1 += text("Door bolts are up. Drop them?
    \n", src) + else + t1 += text("Door bolts are down.") + if(hasPower()) + t1 += text(" Raise?
    \n", src) + else + t1 += text(" Cannot raise door bolts due to power failure.
    \n") + + if(isWireCut(AIRLOCK_WIRE_LIGHT)) + t1 += text("Door bolt lights wire is cut.
    \n") + else if(!lights) + t1 += text("Door lights are off. Enable?
    \n", src) + else + t1 += text("Door lights are on. Disable?
    \n", src) + + if(isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + t1 += text("Electrification wire is cut.
    \n") + if(secondsElectrified == -1) + t1 += text("Door is electrified indefinitely. Un-electrify it?
    \n", src) + else if(secondsElectrified>0) + t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
    \n", 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(isWireCut(AIRLOCK_WIRE_SAFETY)) + t1 += text("Door force sensors not responding.
    \n") + else if(safe) + t1 += text("Door safeties operating normally. Override?
    \n",src) + else + t1 += text("Danger. Door safeties disabled. Restore?
    \n",src) + + if(isWireCut(AIRLOCK_WIRE_SPEED)) + t1 += text("Door timing circuitry not responding.
    \n") + else if(normalspeed) + t1 += text("Door timing circuitry operating normally. Override?
    \n",src) + else + t1 += text("Warning. Door timing circuitry operating abnormally. Restore?
    \n",src) + + if(welded) + t1 += text("Door appears to have been welded shut.
    \n") + else if(!locked) + if(density) + t1 += text("Open door
    \n", src) + else + t1 += text("Close door
    \n", src) + + t1 += text("

    Close

    \n", src) + user << browse(entity_ja(t1), "window=airlock") + onclose(user, "airlock") + + +/obj/machinery/door/airlock/proc/hack(mob/user) + if(!aiHacking) + aiHacking = TRUE + spawn(20) + //TODO: Make this take a minute + to_chat(user, "Airlock AI control has been blocked. Beginning fault-detection.") + sleep(50) + if(!hack_can_continue(user)) + return + to_chat(user, "Fault confirmed: airlock control wire disabled.")//#Z1 + sleep(20) + to_chat(user, "Attempting to hack into airlock. This may take some time.") + sleep(200) + if(!hack_can_continue(user)) + return + to_chat(user, "Upload access confirmed. Loading control program into airlock software.") + sleep(170) + if(!hack_can_continue(user)) + return + to_chat(user, "Transfer complete. Forcing airlock to execute program.") + sleep(50) + //disable blocked control +//#Z1 + //aiControlDisabled = 2 + aiControlDisabled = FALSE + pulseProof = TRUE +//##Z1 + to_chat(user, "Receiving control information from airlock.") + sleep(10) + //bring up airlock dialog + aiHacking = FALSE + if (user) + attack_ai(user) + +/obj/machinery/door/airlock/proc/hack_can_continue(mob/user) + if(canAIControl()) + to_chat(user, "Alert cancelled. Airlock control has been restored without our assistance.") + aiHacking = FALSE + return FALSE + else if(!canAIHack()) + to_chat(user, "We've lost our connection! Unable to hack airlock.") + aiHacking = FALSE + return FALSE + return TRUE + +/obj/machinery/door/airlock/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if (isElectrified()) + if (istype(mover, /obj/item)) + var/obj/item/i = mover + if (i.m_amt) + 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/attack_paw(mob/user) + if(istype(user, /mob/living/carbon/alien/humanoid)) + if(welded || locked) + to_chat(user, "\red The door is sealed, it cannot be pried open.") + return + else if(!density) + return + else if(!user.is_busy(src)) + to_chat(user, "You force your claws between the doors and begin to pry them open...") + playsound(src, door_forced_sound, 30, 1, -4) + if(do_after(user,40, target = src) && src) + open(1) + return + +/obj/machinery/door/airlock/attack_animal(mob/user) + if(istype(user, /mob/living/simple_animal/hulk)) + var/mob/living/simple_animal/hulk/H = user + H.attack_hulk(src) + +/obj/machinery/door/airlock/proc/door_rupture(mob/user) + var/obj/structure/door_assembly/da = new assembly_type(loc) + da.anchored = 0 + var/target = da.loc + for(var/i in 1 to 4) + target = get_turf(get_step(target,user.dir)) + da.throw_at(target, 200, 100, spin = FALSE) + if(mineral) + da.change_mineral_airlock_type(mineral) + if(glass && da.can_insert_glass) + da.set_glass(TRUE) + da.state = ASSEMBLY_WIRED + da.created_name = name + da.update_state() + + var/obj/item/weapon/airlock_electronics/ae + ae = new/obj/item/weapon/airlock_electronics(loc) + if(!req_access) + check_access() + if(req_access.len) + ae.conf_access = req_access + else if (req_one_access.len) + ae.conf_access = req_one_access + ae.one_access = 1 + ae.loc = da + da.electronics = ae + + qdel(src) + +/obj/machinery/door/airlock/proc/hulk_break_reaction(mob/living/carbon/user) + if(!density) + return + user.SetNextMove(CLICK_CD_MELEE) + if(user.a_intent == "hurt") + if(user.hulk_scream(src, 90)) + door_rupture(user) + return + else if(locked) + to_chat(user, " The door is bolted and you need more aggressive force to get thru!") + return + var/passed = FALSE + for(var/I in get_step(user,user.dir)) + if(I == src) + passed = TRUE + break + if(!passed) + return + if(user.is_busy(src)) return + var/cur_dir = user.dir + user.visible_message("The [user] starts to force the [src] open with a bare hands!",\ + "You start forcing the [src] open with a bare hands!",\ + "You hear metal strain.") + if(do_after(user, 30, target = src) && density && user.dir == cur_dir) + user.canmove = 0 + var/turf/target = user.loc + open() + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + if(istype(target,/turf/simulated/floor)) + var/turf/simulated/floor/tile = target + tile.break_tile() + for(var/i in 1 to 2) + if(!step(user,cur_dir)) + for(var/mob/living/L in get_step(user,cur_dir)) + L.adjustBruteLoss(rand(20,60)) + break + playsound(src,'sound/weapons/thudswoosh.ogg', 50, 1) + user.visible_message("The [user] forces the [src] open with a bare hands!",\ + "You force the [src] open with a bare hands!",\ + "You hear metal strain, and a door open.") + user.canmove = 1 + close() + +/obj/machinery/door/airlock/attack_hand(mob/user) + if(ishuman(user) && prob(40) && density) + var/mob/living/carbon/human/H = user + if(H.getBrainLoss() >= 60) + playsound(src, 'sound/effects/bang.ogg', 25, 1) + if(!istype(H.head, /obj/item/clothing/head/helmet)) + visible_message(" [user] headbutts the airlock.") + var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] + H.Stun(8) + H.Weaken(5) + BP.take_damage(10, 0) + else + visible_message(" [user] headbutts the airlock. Good thing they're wearing a helmet.") + return + + if(wires.interact(user)) + return + else + if(isElectrified() && !issilicon(user) && !isobserver(user)) + if(shock(user, 100)) + return + if(HULK in user.mutations) + hulk_break_reaction(user) + return + ..() + + +/obj/machinery/door/airlock/Topic(href, href_list, var/no_window = 0) + if(href_list["close"]) + usr << browse(null, "window=airlock") + usr.unset_machine(src) + return FALSE + + . = ..(href, href_list) + if(!.) + return + + if((issilicon(usr) && canAIControl()) || isobserver(usr)) + //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, 11 lift access override + //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, 11 lift access override + if(href_list["aiDisable"]) + var/code = text2num(href_list["aiDisable"]) + switch (code) + if(1) + // Disable idscan + if(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(aiDisabledIdScanner) + to_chat(usr, "You've already disabled the IdScan feature.") + else + aiDisabledIdScanner = 1 + + if(2) + // Disrupt main power + if(!secondsMainPowerLost) + loseMainPower() + else + to_chat(usr, "Main power is already offline.") + + if(3) + // Disrupt backup power + if(!secondsBackupPowerLost) + loseBackupPower() + else + to_chat(usr, "Backup power is already offline.") + + if(4) + // Drop door bolts + if(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(!locked) + bolt() + + if(5) + // Un-electrify door + if(isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + to_chat(usr, "Can't un-electrify the airlock - The electrification wire is cut.") + else if(secondsElectrified == -1) + secondsElectrified = 0 + else if(secondsElectrified > 0) + secondsElectrified = 0 + + if(7) + // Close door + if(welded) + to_chat(usr, "The airlock has been welded shut!") + else if(locked) + to_chat(usr, "The door bolts are down!") + else + close() + + if(8) + // Safeties! We don't need no stinking safeties! + if(isWireCut(AIRLOCK_WIRE_SAFETY)) + to_chat(usr, "Control to door sensors is disabled.") + else if(safe) + safe = 0 + else + to_chat(usr, "Firmware reports safeties already overriden.") + + if(9) + // Door speed control + if(isWireCut(AIRLOCK_WIRE_SPEED)) + to_chat(usr, "Control to door timing circuitry has been severed.") + else if(normalspeed) + normalspeed = 0 + else + to_chat(usr, "Door timing circurity already accellerated.") + + if(10) + // Bolt lights + if(isWireCut(AIRLOCK_WIRE_LIGHT)) + to_chat(usr, "Control to door bolt lights has been severed.") + else if (lights) + lights = 0 + update_icon() + else + to_chat(usr, "Door bolt lights are already disabled!") + + if(11) + // Emergency access + if(emergency) + emergency = 0 + update_icon() + else + to_chat(usr, "Emergency access is already disabled!") + + else if(href_list["aiEnable"]) + var/code = text2num(href_list["aiEnable"]) + switch (code) + if(1) + // Enable idscan + if(isWireCut(AIRLOCK_WIRE_IDSCAN)) + to_chat(usr, "You can't enable IdScan - The IdScan wire has been cut.") + else if(aiDisabledIdScanner) + aiDisabledIdScanner = 0 + else + to_chat(usr, "The IdScan feature is not disabled.") + + if(4) + // Raise door bolts + if(isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + to_chat(usr, "The door bolt drop wire is cut - you can't raise the door bolts.
    \n") + else if(!locked) + to_chat(usr, "The door bolts are already up.
    \n") + else + if(hasPower()) + unbolt() + else + to_chat(usr, "Cannot raise door bolts due to power failure.
    \n") + + if(5) + // Electrify door for 30 seconds + if(isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + to_chat(usr, "The electrification wire has been cut.
    \n") + else if(secondsElectrified == -1) + to_chat(usr, "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(secondsElectrified) + to_chat(usr, "The door is already electrified. You can't re-electrify it while it's already electrified.
    \n") + else + shockedby += "\[[time_stamp()]\][usr](ckey:[usr.ckey])" + usr.attack_log += "\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]" + secondsElectrified = 30 + START_PROCESSING(SSmachine, src) + + if(6) + // Electrify door indefinitely + if(isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + to_chat(usr, "The electrification wire has been cut.
    \n") + else if(secondsElectrified == -1) + to_chat(usr, "The door is already indefinitely electrified.
    \n") + else if(secondsElectrified) + to_chat(usr, "The door is already electrified. You can't re-electrify it while it's already electrified.
    \n") + else + shockedby += "\[[time_stamp()]\][usr](ckey:[usr.ckey])" + usr.attack_log += "\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]" + secondsElectrified = -1 + + if(7) + // Open door + if(welded) + to_chat(usr, "The airlock has been welded shut!") + else if(locked) + to_chat(usr, "The door bolts are down!") + else + open() + + if (8) + // Safeties! Maybe we do need some stinking safeties! + if (isWireCut(AIRLOCK_WIRE_SAFETY)) + to_chat(usr, "Control to door sensors is disabled.") + else if (!safe) + safe = 1 + else + to_chat(usr, "Firmware reports safeties already in place.") + + if(9) + // Door speed control + if(isWireCut(AIRLOCK_WIRE_SPEED)) + to_chat(usr, "Control to door timing circuitry has been severed.") + else if (!normalspeed) + normalspeed = 1 + else + to_chat(usr, "Door timing circurity currently operating normally.") + + if(10) + // Bolt lights + if(isWireCut(AIRLOCK_WIRE_LIGHT)) + to_chat(usr, "Control to door bolt lights has been severed.") + else if (!lights) + lights = 1 + update_icon() + else + to_chat(usr, "Door bolt lights are already enabled!") + + if(11) + // Emergency access + if(!emergency) + emergency = 1 + update_icon() + else + to_chat(usr, "Emergency access is already disabled!") + + if(!no_window) + updateUsrDialog() + +/obj/machinery/door/airlock/attackby(C, mob/user) + + if(istype(C,/obj/item/weapon/changeling_hammer) && !operating && density) // yeah, hammer ignore electrify + var/obj/item/weapon/changeling_hammer/W = C + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + visible_message("[user] has punched the [src]!") + playsound(loc, 'sound/effects/grillehit.ogg', 50, 1) + if(W.use_charge(user) && prob(20)) + playsound(loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) + door_rupture(user) + return + + if(!(issilicon(user) || isobserver(user))) + if(isElectrified()) + if(shock(user, 75)) + return + if(istype(C, /obj/item/device/detective_scanner) || istype(C, /obj/item/taperoll)) + return + + add_fingerprint(user) + + if(istype(C, /obj/item/weapon/weldingtool) && !(operating > 0) && density) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + welded = !welded + update_icon() + return + else + return + else if(istype(C, /obj/item/weapon/screwdriver)) + p_open = !p_open + update_icon() + else if(istype(C, /obj/item/weapon/wirecutters)) + return attack_hand(user) + else if(istype(C, /obj/item/device/multitool)) + return attack_hand(user) + else if(istype(C, /obj/item/device/assembly/signaler)) + return attack_hand(user) + else if(istype(C, /obj/item/weapon/pai_cable)) // -- TLE + var/obj/item/weapon/pai_cable/cable = C + cable.plugin(src, user) + else if(istype(C, /obj/item/weapon/crowbar) || istype(C, /obj/item/weapon/twohanded/fireaxe) ) + var/beingcrowbarred = null + if(istype(C, /obj/item/weapon/crowbar) ) + beingcrowbarred = 1 //derp, Agouri + else + beingcrowbarred = 0 + if( beingcrowbarred && (operating == -1 || density && welded && operating != 1 && p_open && !hasPower() && !locked) ) + if(user.is_busy(src)) return + playsound(src, '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.") + if(do_after(user,40,target = src)) + to_chat(user, "\blue You removed the airlock electronics!") + + var/obj/structure/door_assembly/da = new assembly_type(loc) + da.anchored = 1 + if(mineral) + da.change_mineral_airlock_type(mineral) + if(glass && da.can_insert_glass) + da.set_glass(TRUE) + da.state = ASSEMBLY_WIRED + da.dir = dir + da.created_name = name + da.update_state() + + var/obj/item/weapon/airlock_electronics/ae + if(!electronics) + ae = new/obj/item/weapon/airlock_electronics(loc) + if(!req_access) + check_access() + if(req_access.len) + ae.conf_access = req_access + else if (req_one_access.len) + ae.conf_access = req_one_access + ae.one_access = 1 + else + ae = electronics + electronics = null + ae.loc = loc + if(operating == -1) + ae.icon_state = "door_electronics_smoked" + ae.broken = TRUE + operating = 0 + + qdel(src) + return + else if(hasPower()) + to_chat(user, "The airlock's motors resist your efforts to force it.") + 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/twohanded/fireaxe/F = C + if(F:wielded) + spawn(0) open(1) + else + to_chat(user, "\red You need to be wielding the Fire axe to do that.") + else + spawn(0) open(1) + else + if(beingcrowbarred == 0) + var/obj/item/weapon/twohanded/fireaxe/F = C + if(F:wielded) + spawn(0) close(1) + else + to_chat(user, "\red You need to be wielding the Fire axe to do that.") + else + spawn(0) close(1) + + else if(istype(C, /obj/item/weapon/airlock_painter)) //airlock painter + change_paintjob(C, user) + else + ..() + return + +/obj/machinery/door/airlock/phoron/attackby(C, mob/user) + if(C) + ignite(is_hot(C)) + ..() + +/obj/machinery/door/airlock/proc/close_unsafe(bolt_after = FALSE) + var/temp = safe + + safe = FALSE + + if(close()) + safe = temp + if(bolt_after) + bolt() + +/obj/machinery/door/airlock/open_checks() + if(..() && !welded && !locked) + return TRUE + return FALSE + +/obj/machinery/door/airlock/close_checks() + if(..() && !welded && !locked) + if(safe) + for(var/turf/T in locs) + if(locate(/mob/living) in T) + autoclose() + return FALSE + return TRUE + return FALSE + +/obj/machinery/door/airlock/normal_open_checks() + if(hasPower() && !isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) + return TRUE + return FALSE + +/obj/machinery/door/airlock/normal_close_checks() + if(hasPower() && !isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + return TRUE + return FALSE + +/obj/machinery/door/airlock/do_open() + send_status_if_allowed() + if(closeOther != null && istype(closeOther, /obj/machinery/door/airlock/) && !closeOther.density) + closeOther.close() + if(hasPower()) + use_power(50) + ..() + autoclose() + +/obj/machinery/door/airlock/do_close() + send_status_if_allowed() + if(hasPower()) + use_power(50) + ..() + +/obj/machinery/door/airlock/do_afterclose() + for(var/turf/T in locs) + for(var/mob/living/M in T) + if(isrobot(M)) + M.adjustBruteLoss(DOOR_CRUSH_DAMAGE) + else + M.adjustBruteLoss(DOOR_CRUSH_DAMAGE) + M.SetStunned(5) + M.SetWeakened(5) + M.visible_message("[M] was crushed by the [src] door.", + "[src] door crushed you.") + + for(var/obj/structure/window/W in T) + W.ex_act(2) + + for(var/obj/effect/fluid/F in T) + qdel(F) + ..() + +/obj/machinery/door/airlock/proc/autoclose() + if(autoclose) + if(close_timer_id) + deltimer(close_timer_id) + close_timer_id = addtimer(CALLBACK(src, .proc/do_autoclose), normalspeed ? 150 : 5, TIMER_STOPPABLE) + +/obj/machinery/door/airlock/proc/do_autoclose() + close_timer_id = null + close() + +/obj/machinery/door/airlock/proc/prison_open() + unbolt() + open() + bolt() + return + +/obj/machinery/door/airlock/proc/change_paintjob(obj/item/C, mob/user) + var/obj/item/weapon/airlock_painter/W + if(istype(C, /obj/item/weapon/airlock_painter)) + W = C + else + to_chat(user, "If you see this, it means airlock/change_paintjob() was called with something other than an airlock painter. Check your code!") + return + + if(!W.can_use(user)) + return + + var/list/optionlist + if(inner_material == "glass") + optionlist = list("Public", "Public2", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance") + else + optionlist = list("Public", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Mining", "Maintenance", "External", "High Security") + + var/paintjob = input(user, "Please select a paintjob for this airlock.") in optionlist + if((!in_range(src, usr) && loc != usr) || !W.use(user)) + return + switch(paintjob) + if("Public") + icon = 'icons/obj/doors/airlocks/station/public.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + if("Public2") + icon = 'icons/obj/doors/airlocks/station2/glass.dmi' + overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi' + if("Engineering") + icon = 'icons/obj/doors/airlocks/station/engineering.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + if("Atmospherics") + icon = 'icons/obj/doors/airlocks/station/atmos.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + if("Security") + icon = 'icons/obj/doors/airlocks/station/security.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + if("Command") + icon = 'icons/obj/doors/airlocks/station/command.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + if("Medical") + icon = 'icons/obj/doors/airlocks/station/medical.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + if("Research") + icon = 'icons/obj/doors/airlocks/station/research.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + heat_proof = glass + if("Mining") + icon = 'icons/obj/doors/airlocks/station/mining.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + if("Maintenance") + icon = 'icons/obj/doors/airlocks/station/maintenance.dmi' + overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + if("External") + icon = 'icons/obj/doors/airlocks/external/external.dmi' + overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi' + if("High Security") + icon = 'icons/obj/doors/airlocks/highsec/highsec.dmi' + overlays_file = 'icons/obj/doors/airlocks/highsec/overlays.dmi' + update_icon() + +/obj/structure/door_scrap + name = "Door Scrap" + desc = "Just a bunch of garbage." + var/ticker = 0 + var/icon/door = icon('icons/effects/effects.dmi',"Sliced") + //light_power = 1 + //light_color = "#cc0000" + + +/obj/structure/door_scrap/attackby(obj/O, mob/user) + if(istype(O,/obj/item/weapon/wrench)) + if(ticker >= 300) + playsound(user.loc, 'sound/items/Ratchet.ogg', 50) + user.visible_message("[user] has disassemble these scrap...") + new /obj/item/stack/sheet/metal(loc) + new /obj/item/stack/sheet/metal(loc) + qdel(src) + else + to_chat(user,"This is too hot to dismantle it") + if(prob(10)) + to_chat(user,"You accidentally drop your wrench in the flame") + qdel(O) + else + return + + +/obj/structure/door_scrap/atom_init() + . = ..() + var/image/fire_overlay = image("icon"='icons/effects/effects.dmi', "icon_state"="s_fire", "layer" = (LIGHTING_LAYER + 1)) + fire_overlay.plane = LIGHTING_PLANE + 1 + overlays += fire_overlay + START_PROCESSING(SSobj, src) + +/obj/structure/door_scrap/process() + if(ticker >= 300) + overlays.Cut() + STOP_PROCESSING(SSobj, src) + return + ticker++ + var/spot = locate(/obj/effect/fluid) in loc + if(spot) + ticker +=10 diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 29657e1bd1a5..2659c1803bcc 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -1,110 +1,110 @@ -/obj/item/weapon/airlock_electronics - name = "airlock electronics" - icon = 'icons/obj/doors/door_electronics.dmi' - icon_state = "door_electronics" - w_class = 2.0 //It should be tiny! -Agouri - m_amt = 50 - g_amt = 50 - - req_access = list(access_engine) - - 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 - var/broken = FALSE - - attack_self(mob/user) - if (!ishuman(user) && !istype(user,/mob/living/silicon/robot/drone)) - return ..(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) - 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(entity_ja(t1), "window=airlock_electronics") - onclose(user, "airlock") - - Topic(href, href_list) - ..() - if (usr.stat || usr.restrained() || (!ishuman(usr) && !istype(usr,/mob/living/silicon))) - return - if (href_list["close"]) - usr << browse(null, "window=airlock") - return - - if (href_list["login"]) - if(istype(usr,/mob/living/silicon)) - src.locked = 0 - src.last_configurator = usr.name - else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/device/pda)) - var/obj/item/device/pda/pda = I - I = pda.id - if (I && src.check_access(I)) - src.locked = 0 - src.last_configurator = I:registered_name - - if (locked) - return - - 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) - - proc - toggle_access(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/airlock_electronics + name = "airlock electronics" + icon = 'icons/obj/doors/door_electronics.dmi' + icon_state = "door_electronics" + w_class = 2.0 //It should be tiny! -Agouri + m_amt = 50 + g_amt = 50 + + req_access = list(access_engine) + + 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 + var/broken = FALSE + + attack_self(mob/user) + if (!ishuman(user) && !istype(user,/mob/living/silicon/robot/drone)) + return ..(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) + 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(entity_ja(t1), "window=airlock_electronics") + onclose(user, "airlock") + + Topic(href, href_list) + ..() + if (usr.stat || usr.restrained() || (!ishuman(usr) && !istype(usr,/mob/living/silicon))) + return + if (href_list["close"]) + usr << browse(null, "window=airlock") + return + + if (href_list["login"]) + if(istype(usr,/mob/living/silicon)) + src.locked = 0 + src.last_configurator = usr.name + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/pda = I + I = pda.id + if (I && src.check_access(I)) + src.locked = 0 + src.last_configurator = I:registered_name + + if (locked) + return + + 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) + + proc + toggle_access(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 87fdb287f812..a87010f33651 100644 --- a/code/game/machinery/doors/alarmlock.dm +++ b/code/game/machinery/doors/alarmlock.dm @@ -1,43 +1,43 @@ -/obj/machinery/door/airlock/alarmlock - name = "glass alarm airlock" - icon = 'icons/obj/doors/airlocks/station2/glass.dmi' - overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi' - opacity = 0 - glass = 1 - - var/datum/radio_frequency/air_connection - var/air_frequency = 1437 - autoclose = 0 - -/obj/machinery/door/airlock/alarmlock/atom_init() - . = ..() - radio_controller.remove_object(src, air_frequency) - air_connection = new - air_connection = radio_controller.add_object(src, air_frequency, RADIO_TO_AIRALARM) - open() - -/obj/machinery/door/airlock/alarmlock/Destroy() - if(radio_controller) - radio_controller.remove_object(src,air_frequency) - return ..() - -/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 (our_area.master) - our_area = our_area.master - - if(alarm_area == our_area.name) - switch(alert) - if("severe") - autoclose = 1 - close() - if("minor", "clear") - autoclose = 0 - open() +/obj/machinery/door/airlock/alarmlock + name = "glass alarm airlock" + icon = 'icons/obj/doors/airlocks/station2/glass.dmi' + overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi' + opacity = 0 + glass = 1 + + var/datum/radio_frequency/air_connection + var/air_frequency = 1437 + autoclose = 0 + +/obj/machinery/door/airlock/alarmlock/atom_init() + . = ..() + radio_controller.remove_object(src, air_frequency) + air_connection = new + air_connection = radio_controller.add_object(src, air_frequency, RADIO_TO_AIRALARM) + open() + +/obj/machinery/door/airlock/alarmlock/Destroy() + if(radio_controller) + radio_controller.remove_object(src,air_frequency) + return ..() + +/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 (our_area.master) + our_area = our_area.master + + if(alarm_area == our_area.name) + switch(alert) + if("severe") + autoclose = 1 + close() + if("minor", "clear") + autoclose = 0 + open() diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index dffd42afbc64..30011a61dd2a 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -1,369 +1,369 @@ -#define CHARS_PER_LINE 5 -#define FONT_SIZE "5pt" -#define FONT_COLOR "#09f" -#define FONT_STYLE "Arial Black" - -//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 = null // id of door it controls. - var/releasetime = 0 // when world.timeofday reaches it - release the prisoner - var/timing = 0 // 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() - var/timetoset = 0 // Used to set releasetime upon starting the timer - var/timer_activator = "Unknown" //Mob.name who activate timer - var/flag30sec = 0 //30 seconds notification flag - - maptext_height = 26 - maptext_width = 32 - -/obj/machinery/door_timer/atom_init() - ..() - pixel_x = ((dir & 3)? (0) : (dir == 4 ? 32 : -32)) - pixel_y = ((dir & 3)? (dir == 1 ? 24 : -32) : (0)) - cell_open() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/door_timer/atom_init_late() - for(var/obj/machinery/door/window/brigdoor/M in brigdoor_list) - if (M.id == id) - targets += M - - for(var/obj/machinery/flasher/F in flasher_list) - if(F.id == id) - targets += F - - for(var/obj/structure/closet/secure_closet/brig/C in closet_list) - if(C.id == id) - targets += C - - if(targets.len == 0) - stat |= BROKEN - update_icon() - -//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 -/obj/machinery/door_timer/process() - - if(stat & (NOPOWER|BROKEN)) return - if(src.timing) - - // poorly done midnight rollover - // (no seriously there's gotta be a better way to do this) - var/timeleft = timeleft() - if(timeleft > 1e5) - src.releasetime = 0 - - if(world.timeofday > (src.releasetime - 300)) //30 sec notification before release - if (!flag30sec) - flag30sec = 1 - broadcast_security_hud_message("[src.name] prisoner's sentence is ending in 30 seconds.", src) - - if(world.timeofday > src.releasetime) - broadcast_security_hud_message("[src.name] prisoner has served issued sentence. [timer_activator] is requested for the release procedure.", src) - src.timer_end() // open doors, reset timer, clear status screen - cell_open() - - src.updateUsrDialog() - src.update_icon() - - return - - -// has the door power situation changed, if so update icon. -/obj/machinery/door_timer/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. - -// power check and stop timer -/obj/machinery/door_timer/proc/timer_start(activator) - if(stat & (NOPOWER|BROKEN)) return 0 - - // Set releasetime - releasetime = world.timeofday + timetoset - if (activator) - timer_activator = activator - - return - -// Closes and locks doors -/obj/machinery/door_timer/proc/cell_close() - 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 - -//power check, set vars as default -/obj/machinery/door_timer/proc/timer_end() - if(stat & (NOPOWER|BROKEN)) return 0 - - // Reset releasetime - src.timing = 0 - flag30sec = 0 - releasetime = 0 - timer_activator = "Unknown" - - return -//Opens and unlocks door, closet -/obj/machinery/door_timer/proc/cell_open() - 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 - -// Check for releasetime timeleft -/obj/machinery/door_timer/proc/timeleft() - . = (releasetime - world.timeofday)/10 - if(. < 0) - . = 0 - -// Set timetoset -/obj/machinery/door_timer/proc/timeset(seconds) - timetoset = seconds * 10 - - if(timetoset <= 0) - timetoset = 0 - - return - -//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 -/obj/machinery/door_timer/ui_interact(mob/user) - // Used for the 'time left' display - var/second = round(timeleft() % 60) - var/minute = round((timeleft() - second) / 60) - - // Used for 'set timer' - var/setsecond = round((timetoset / 10) % 60) - var/setminute = round(((timetoset / 10) - setsecond) / 60) - - // dat - var/dat = "" - - dat += "
    Timer System:" - dat += " Door [src.id] controls
    " - - // Start/Stop timer - if (src.timing) - dat += "Stop Timer and open door
    " - else - dat += "Activate Timer and close door
    " - - // Time Left display (uses releasetime) - dat += "Time Left: [(minute ? text("[minute]:") : null)][second]
    " - dat += "
    " - - // Set Timer display (uses timetoset) - if(src.timing) - dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond] Set
    " - else - dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond]
    " - - // Controls - dat += "- - + +
    " - - // Mounted flash controls - 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" - - dat += "

    Close" - dat += "
    " - - user << browse(entity_ja(dat), "window=computer;size=400x500") - onclose(user, "computer") - - -//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 -// "change" resets the timer to the timetoset amount while the timer is counting down -// Also updates dialog window and timer icon -/obj/machinery/door_timer/Topic(href, href_list) - . = ..() - if(!.) - return - - if(!src.allowed(usr)) - return - - if(href_list["timing"]) - src.timing = text2num(href_list["timing"]) - - if(src.timing) - src.timer_start(usr.name) - cell_close() - else - src.timer_end() - cell_open() - else - if(href_list["tp"]) //adjust timer, close door if not already closed - var/tp = text2num(href_list["tp"]) - var/addtime = (timetoset / 10) - addtime += tp - addtime = min(max(round(addtime), 0), 3600) - - timeset(addtime) - - if(href_list["fc"]) - for(var/obj/machinery/flasher/F in targets) - F.flash() - - if(href_list["change"]) - src.timer_start(usr.name) - cell_close() - - src.updateUsrDialog() - src.update_icon() - - /* if(src.timing) - src.timer_start() - - else - src.timer_end() */ - - -//icon update function -// if NOPOWER, display blank -// if BROKEN, display blue screen of death icon AI uses -// if timing=true, run update display function -/obj/machinery/door_timer/update_icon() - if(stat & (NOPOWER)) - icon_state = "frame" - return - if(stat & (BROKEN)) - set_picture("ai_bsod") - return - if(src.timing) - var/disp1 = id - var/timeleft = timeleft() - var/disp2 = "[add_zero(num2text((timeleft / 60) % 60),2)]~[add_zero(num2text(timeleft % 60), 2)]" - if(length(disp2) > CHARS_PER_LINE) - disp2 = "Error" - update_display(disp1, disp2) - else - if(maptext) maptext = "" - return - - -// Adds an icon in case the screen is broken/off, stolen from status_display.dm -/obj/machinery/door_timer/proc/set_picture(state) - picture_state = state - overlays.Cut() - 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 -/obj/machinery/door_timer/proc/update_display(line1, line2) - var/new_text = {"
    [line1]
    [line2]
    "} - if(maptext != new_text) - maptext = new_text - - -//Actual string input to icon display for loop, with 5 pixel x offsets for each letter. -//Stolen from status_display -/obj/machinery/door_timer/proc/texticon(tn, px = 0, py = 0) - var/image/I = image('icons/obj/status_display.dmi', "blank") - var/len = lentext(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 = "Cell 1" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_2 - name = "Cell 2" - id = "Cell 2" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_3 - name = "Cell 3" - id = "Cell 3" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_4 - name = "Cell 4" - id = "Cell 4" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_5 - name = "Cell 5" - id = "Cell 5" - dir = 2 - pixel_y = -32 - - -/obj/machinery/door_timer/cell_6 - name = "Cell 6" - id = "Cell 6" - dir = 4 - pixel_x = 32 - -#undef FONT_SIZE -#undef FONT_COLOR -#undef FONT_STYLE -#undef CHARS_PER_LINE +#define CHARS_PER_LINE 5 +#define FONT_SIZE "5pt" +#define FONT_COLOR "#09f" +#define FONT_STYLE "Arial Black" + +//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 = null // id of door it controls. + var/releasetime = 0 // when world.timeofday reaches it - release the prisoner + var/timing = 0 // 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() + var/timetoset = 0 // Used to set releasetime upon starting the timer + var/timer_activator = "Unknown" //Mob.name who activate timer + var/flag30sec = 0 //30 seconds notification flag + + maptext_height = 26 + maptext_width = 32 + +/obj/machinery/door_timer/atom_init() + ..() + pixel_x = ((dir & 3)? (0) : (dir == 4 ? 32 : -32)) + pixel_y = ((dir & 3)? (dir == 1 ? 24 : -32) : (0)) + cell_open() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/door_timer/atom_init_late() + for(var/obj/machinery/door/window/brigdoor/M in brigdoor_list) + if (M.id == id) + targets += M + + for(var/obj/machinery/flasher/F in flasher_list) + if(F.id == id) + targets += F + + for(var/obj/structure/closet/secure_closet/brig/C in closet_list) + if(C.id == id) + targets += C + + if(targets.len == 0) + stat |= BROKEN + update_icon() + +//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 +/obj/machinery/door_timer/process() + + if(stat & (NOPOWER|BROKEN)) return + if(src.timing) + + // poorly done midnight rollover + // (no seriously there's gotta be a better way to do this) + var/timeleft = timeleft() + if(timeleft > 1e5) + src.releasetime = 0 + + if(world.timeofday > (src.releasetime - 300)) //30 sec notification before release + if (!flag30sec) + flag30sec = 1 + broadcast_security_hud_message("[src.name] prisoner's sentence is ending in 30 seconds.", src) + + if(world.timeofday > src.releasetime) + broadcast_security_hud_message("[src.name] prisoner has served issued sentence. [timer_activator] is requested for the release procedure.", src) + src.timer_end() // open doors, reset timer, clear status screen + cell_open() + + src.updateUsrDialog() + src.update_icon() + + return + + +// has the door power situation changed, if so update icon. +/obj/machinery/door_timer/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. + +// power check and stop timer +/obj/machinery/door_timer/proc/timer_start(activator) + if(stat & (NOPOWER|BROKEN)) return 0 + + // Set releasetime + releasetime = world.timeofday + timetoset + if (activator) + timer_activator = activator + + return + +// Closes and locks doors +/obj/machinery/door_timer/proc/cell_close() + 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 + +//power check, set vars as default +/obj/machinery/door_timer/proc/timer_end() + if(stat & (NOPOWER|BROKEN)) return 0 + + // Reset releasetime + src.timing = 0 + flag30sec = 0 + releasetime = 0 + timer_activator = "Unknown" + + return +//Opens and unlocks door, closet +/obj/machinery/door_timer/proc/cell_open() + 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 + +// Check for releasetime timeleft +/obj/machinery/door_timer/proc/timeleft() + . = (releasetime - world.timeofday)/10 + if(. < 0) + . = 0 + +// Set timetoset +/obj/machinery/door_timer/proc/timeset(seconds) + timetoset = seconds * 10 + + if(timetoset <= 0) + timetoset = 0 + + return + +//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 +/obj/machinery/door_timer/ui_interact(mob/user) + // Used for the 'time left' display + var/second = round(timeleft() % 60) + var/minute = round((timeleft() - second) / 60) + + // Used for 'set timer' + var/setsecond = round((timetoset / 10) % 60) + var/setminute = round(((timetoset / 10) - setsecond) / 60) + + // dat + var/dat = "" + + dat += "
    Timer System:" + dat += " Door [src.id] controls
    " + + // Start/Stop timer + if (src.timing) + dat += "Stop Timer and open door
    " + else + dat += "Activate Timer and close door
    " + + // Time Left display (uses releasetime) + dat += "Time Left: [(minute ? text("[minute]:") : null)][second]
    " + dat += "
    " + + // Set Timer display (uses timetoset) + if(src.timing) + dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond] Set
    " + else + dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond]
    " + + // Controls + dat += "- - + +
    " + + // Mounted flash controls + 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" + + dat += "

    Close" + dat += "
    " + + user << browse(entity_ja(dat), "window=computer;size=400x500") + onclose(user, "computer") + + +//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 +// "change" resets the timer to the timetoset amount while the timer is counting down +// Also updates dialog window and timer icon +/obj/machinery/door_timer/Topic(href, href_list) + . = ..() + if(!.) + return + + if(!src.allowed(usr)) + return + + if(href_list["timing"]) + src.timing = text2num(href_list["timing"]) + + if(src.timing) + src.timer_start(usr.name) + cell_close() + else + src.timer_end() + cell_open() + else + if(href_list["tp"]) //adjust timer, close door if not already closed + var/tp = text2num(href_list["tp"]) + var/addtime = (timetoset / 10) + addtime += tp + addtime = min(max(round(addtime), 0), 3600) + + timeset(addtime) + + if(href_list["fc"]) + for(var/obj/machinery/flasher/F in targets) + F.flash() + + if(href_list["change"]) + src.timer_start(usr.name) + cell_close() + + src.updateUsrDialog() + src.update_icon() + + /* if(src.timing) + src.timer_start() + + else + src.timer_end() */ + + +//icon update function +// if NOPOWER, display blank +// if BROKEN, display blue screen of death icon AI uses +// if timing=true, run update display function +/obj/machinery/door_timer/update_icon() + if(stat & (NOPOWER)) + icon_state = "frame" + return + if(stat & (BROKEN)) + set_picture("ai_bsod") + return + if(src.timing) + var/disp1 = id + var/timeleft = timeleft() + var/disp2 = "[add_zero(num2text((timeleft / 60) % 60),2)]~[add_zero(num2text(timeleft % 60), 2)]" + if(length(disp2) > CHARS_PER_LINE) + disp2 = "Error" + update_display(disp1, disp2) + else + if(maptext) maptext = "" + return + + +// Adds an icon in case the screen is broken/off, stolen from status_display.dm +/obj/machinery/door_timer/proc/set_picture(state) + picture_state = state + overlays.Cut() + 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 +/obj/machinery/door_timer/proc/update_display(line1, line2) + var/new_text = {"
    [line1]
    [line2]
    "} + if(maptext != new_text) + maptext = new_text + + +//Actual string input to icon display for loop, with 5 pixel x offsets for each letter. +//Stolen from status_display +/obj/machinery/door_timer/proc/texticon(tn, px = 0, py = 0) + var/image/I = image('icons/obj/status_display.dmi', "blank") + var/len = lentext(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 = "Cell 1" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_2 + name = "Cell 2" + id = "Cell 2" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_3 + name = "Cell 3" + id = "Cell 3" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_4 + name = "Cell 4" + id = "Cell 4" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_5 + name = "Cell 5" + id = "Cell 5" + dir = 2 + pixel_y = -32 + + +/obj/machinery/door_timer/cell_6 + name = "Cell 6" + id = "Cell 6" + dir = 4 + pixel_x = 32 + +#undef FONT_SIZE +#undef FONT_COLOR +#undef FONT_STYLE +#undef CHARS_PER_LINE diff --git a/code/game/machinery/doors/checkForMultipleDoors.dm b/code/game/machinery/doors/checkForMultipleDoors.dm index 42f313f72808..86489a47acb0 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 - return 1 +/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 diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 63ef4c68fed1..1acdbf13f78c 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -1,382 +1,382 @@ -/obj/machinery/door - name = "Door" - desc = "It opens and closes." - icon = 'icons/obj/doors/Doorint.dmi' - icon_state = "door1" - anchored = 1 - opacity = 1 - density = 1 - layer = DOOR_LAYER - power_channel = ENVIRON - var/base_layer = DOOR_LAYER - var/icon_state_open = "door0" - var/icon_state_close = "door1" - - var/secondsElectrified = 0 - var/visible = 1 - var/p_open = 0 - var/operating = 0 - var/autoclose = 0 - var/glass = 0 - var/normalspeed = 1 - var/heat_proof = 0 // For glass airlocks/opacity firedoors - var/air_properties_vary_with_direction = 0 - var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened. - var/emergency = 0 // Emergency access override - - var/door_open_sound = 'sound/machines/airlock/airlockToggle_2.ogg' - var/door_close_sound = 'sound/machines/airlock/airlockToggle_2.ogg' - - var/dock_tag - -/obj/machinery/door/atom_init() - . = ..() - if(density) - layer = base_layer + DOOR_CLOSED_MOD //Above most items if closed - explosion_resistance = initial(explosion_resistance) - update_heat_protection(get_turf(src)) - else - layer = base_layer //Under all objects if opened. 2.7 due to tables being at 2.6 - explosion_resistance = 0 - - update_nearby_tiles(need_rebuild=1) - - -/obj/machinery/door/Destroy() - density = 0 - update_nearby_tiles() - return ..() - -//process() - //return - -/obj/machinery/door/Bumped(atom/AM) - if(p_open || operating) return - if(ismob(AM)) - var/mob/M = AM - if(world.time - M.last_bumped <= 10) return //Can bump-open one airlock per second. This is to prevent shock spam. - M.last_bumped = world.time - if(!M.restrained() && !M.small) - bumpopen(M) - return - - if(istype(AM, /obj/machinery/bot)) - var/obj/machinery/bot/bot = AM - if(src.check_access(bot.botcard) || emergency) - if(density) - open() - return - - if(istype(AM, /obj/mecha)) - var/obj/mecha/mecha = AM - if(density) - if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access)) || emergency) - open() - else - do_animate("deny") - return - - if(istype(AM, /obj/structure/stool/bed/chair/wheelchair)) - var/obj/structure/stool/bed/chair/wheelchair/wheel = AM - if(density) - if((wheel.pulling && src.allowed(wheel.pulling)) || emergency) - open() - else - do_animate("deny") - return - return - - -/obj/machinery/door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group) return !block_air_zones - if(istype(mover) && mover.checkpass(PASSGLASS)) - return !opacity - return !density - - -/obj/machinery/door/proc/bumpopen(mob/user) - if(operating) return - if(user.last_airflow > world.time - vsc.airflow_delay) //Fakkit - return - src.add_fingerprint(user) - if(!src.requiresID()) - user = null - - if(density) - if(allowed(user) || emergency) - open() - else - do_animate("deny") - return - -/obj/machinery/door/meteorhit(obj/M) - src.open() - return - -/obj/machinery/door/attack_hand(mob/user) - return attackby(user, user) - -/obj/machinery/door/attack_tk(mob/user) - if(requiresID() && !allowed(null)) - return - ..() - -/obj/machinery/door/attack_ghost(mob/user) - if(IsAdminGhost(user)) - if(density) - open() - else - close() - -/obj/machinery/door/attackby(obj/item/I, mob/living/user) - if(istype(I, /obj/item/device/detective_scanner)) - return - if(src.operating) - return - if(src.density && hasPower() && (istype(I, /obj/item/weapon/card/emag)||istype(I, /obj/item/weapon/melee/energy/blade))) - update_icon(AIRLOCK_EMAG) - sleep(6) - if(!open()) - update_icon(AIRLOCK_CLOSED) - operating = -1 - return 1 - if(isrobot(user)) - return //borgs can't attack doors open because it conflicts with their AI-like interaction with them. - if(!Adjacent(user)) - user = null - if(!src.requiresID()) - user = null - user.SetNextMove(CLICK_CD_INTERACT) - if(src.allowed(user)) - if(src.density) - open() - else - close() - return - if(src.density) - do_animate("deny") - return - - -/obj/machinery/door/blob_act() - if(prob(40)) - qdel(src) - return - - -/obj/machinery/door/emp_act(severity) - if(prob(20/severity) && (istype(src,/obj/machinery/door/airlock) || istype(src,/obj/machinery/door/window)) ) - open() - 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/update_icon() - if(density) - icon_state = icon_state_close - else - icon_state = icon_state_open - - -/obj/machinery/door/proc/do_animate(animation) - switch(animation) - if("opening") - if(p_open) - flick("o_doorc0", src) - else - flick("doorc0", src) - if("closing") - if(p_open) - flick("o_doorc1", src) - else - flick("doorc1", src) - if("deny") - flick("door_deny", src) - return - - -/** - * Call this proc, if you want to open the door. - * - * Use `forced` param, if you want to open the door with - * ignoring of `normal_open_checks()` conditions. - * - * Same for `close()`. - */ - -/obj/machinery/door/proc/open(forced = FALSE) - if(!density) - return TRUE - if(open_checks(forced)) - set_operating(TRUE) - do_open() - set_operating(FALSE) - return TRUE - return FALSE - -/obj/machinery/door/proc/close(forced = FALSE) - if(density) - return TRUE - if(close_checks(forced)) - set_operating(TRUE) - do_close() - set_operating(FALSE) - return TRUE - return FALSE - - -/** - * DO NOT CALL THIS PROC DIRECTLY!!! - * - * Checks for base level conditions for door opening. - * - * If you want more conditions you can re-implement it in subtypes like that: - * > /obj/machinery/door/.../open_checks() - * > if(..() && `more conditions`) - * > return TRUE - * > return FALSE - * or in another way, but with TRUE or FALSE returning. - * - * Same for `close_checks()`. - */ - -/obj/machinery/door/proc/open_checks(forced) - if(!operating && ticker) - if(!forced) - return normal_open_checks() - return TRUE - return FALSE - -/obj/machinery/door/proc/close_checks(forced) - if(!operating && ticker) - if(!forced) - return normal_close_checks() - return TRUE - return FALSE - - -/** - * DO NOT CALL THIS PROC DIRECTLY!!! - * - * Checks for additional level conditions for door opening. - * Proc will be ignored if door was forced. - * - * If you want more conditions you can re-implement it in subtypes like that: - * > /obj/machinery/door/.../normal_open_checks() - * > if(`condition one` && `condition two`) - * > return TRUE - * > return FALSE - * or in another way, but with TRUE or FALSE returning. - * - * Same for `normal_close_checks()`. - */ - -/obj/machinery/door/proc/normal_open_checks() - return TRUE - -/obj/machinery/door/proc/normal_close_checks() - return TRUE - - -/** - * DO NOT CALL THIS PROC DIRECTLY!!! - * - * Actually the process of opening the door. - * Re-implement it in subtypes if you want another behavior. - * - * Same for `do_close()`. - */ - -/obj/machinery/door/proc/do_open() - playsound(src, door_open_sound, 50, 1) - do_animate("opening") - sleep(3) - set_opacity(FALSE) - density = FALSE - sleep(9) - layer = base_layer - explosion_resistance = 0 - update_icon() - update_nearby_tiles() - -/obj/machinery/door/proc/do_close() - playsound(src, door_close_sound, 50, 1) - do_animate("closing") - sleep(3) - density = TRUE - sleep(9) - if(visible && !glass) - set_opacity(TRUE) - layer = base_layer + DOOR_CLOSED_MOD - explosion_resistance = initial(explosion_resistance) - do_afterclose() - update_icon() - update_nearby_tiles() - - -/** - * DO NOT CALL THIS PROC DIRECTLY!!! - * - * Helps to add additional behavior for closing. - */ - -/obj/machinery/door/proc/do_afterclose() - //I shall not add a check every x ticks if a door has closed over some fire. - var/obj/fire/fire = locate() in locs - if(fire) - qdel(fire) - -/obj/machinery/door/proc/set_operating(operating) - if(operating && !src.operating) - src.operating = TRUE - else if(!operating && src.operating == 1) - src.operating = FALSE - - -/obj/machinery/door/proc/requiresID() - return 1 - -/obj/machinery/door/update_nearby_tiles(need_rebuild) - . = ..() - - if(.) - for(var/turf/simulated/turf in locs) - update_heat_protection(turf) - -/obj/machinery/door/proc/update_heat_protection(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/Move(new_loc, new_dir) - ..() - update_nearby_tiles() - -/obj/machinery/door/proc/hasPower() - return !(stat & NOPOWER) - -/obj/machinery/door/morgue - icon = 'icons/obj/doors/doormorgue.dmi' - door_open_sound = 'sound/machines/shutter_open.ogg' - door_close_sound = 'sound/machines/shutter_close.ogg' +/obj/machinery/door + name = "Door" + desc = "It opens and closes." + icon = 'icons/obj/doors/Doorint.dmi' + icon_state = "door1" + anchored = 1 + opacity = 1 + density = 1 + layer = DOOR_LAYER + power_channel = ENVIRON + var/base_layer = DOOR_LAYER + var/icon_state_open = "door0" + var/icon_state_close = "door1" + + var/secondsElectrified = 0 + var/visible = 1 + var/p_open = 0 + var/operating = 0 + var/autoclose = 0 + var/glass = 0 + var/normalspeed = 1 + var/heat_proof = 0 // For glass airlocks/opacity firedoors + var/air_properties_vary_with_direction = 0 + var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened. + var/emergency = 0 // Emergency access override + + var/door_open_sound = 'sound/machines/airlock/airlockToggle_2.ogg' + var/door_close_sound = 'sound/machines/airlock/airlockToggle_2.ogg' + + var/dock_tag + +/obj/machinery/door/atom_init() + . = ..() + if(density) + layer = base_layer + DOOR_CLOSED_MOD //Above most items if closed + explosion_resistance = initial(explosion_resistance) + update_heat_protection(get_turf(src)) + else + layer = base_layer //Under all objects if opened. 2.7 due to tables being at 2.6 + explosion_resistance = 0 + + update_nearby_tiles(need_rebuild=1) + + +/obj/machinery/door/Destroy() + density = 0 + update_nearby_tiles() + return ..() + +//process() + //return + +/obj/machinery/door/Bumped(atom/AM) + if(p_open || operating) return + if(ismob(AM)) + var/mob/M = AM + if(world.time - M.last_bumped <= 10) return //Can bump-open one airlock per second. This is to prevent shock spam. + M.last_bumped = world.time + if(!M.restrained() && !M.small) + bumpopen(M) + return + + if(istype(AM, /obj/machinery/bot)) + var/obj/machinery/bot/bot = AM + if(src.check_access(bot.botcard) || emergency) + if(density) + open() + return + + if(istype(AM, /obj/mecha)) + var/obj/mecha/mecha = AM + if(density) + if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access)) || emergency) + open() + else + do_animate("deny") + return + + if(istype(AM, /obj/structure/stool/bed/chair/wheelchair)) + var/obj/structure/stool/bed/chair/wheelchair/wheel = AM + if(density) + if((wheel.pulling && src.allowed(wheel.pulling)) || emergency) + open() + else + do_animate("deny") + return + return + + +/obj/machinery/door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group) return !block_air_zones + if(istype(mover) && mover.checkpass(PASSGLASS)) + return !opacity + return !density + + +/obj/machinery/door/proc/bumpopen(mob/user) + if(operating) return + if(user.last_airflow > world.time - vsc.airflow_delay) //Fakkit + return + src.add_fingerprint(user) + if(!src.requiresID()) + user = null + + if(density) + if(allowed(user) || emergency) + open() + else + do_animate("deny") + return + +/obj/machinery/door/meteorhit(obj/M) + src.open() + return + +/obj/machinery/door/attack_hand(mob/user) + return attackby(user, user) + +/obj/machinery/door/attack_tk(mob/user) + if(requiresID() && !allowed(null)) + return + ..() + +/obj/machinery/door/attack_ghost(mob/user) + if(IsAdminGhost(user)) + if(density) + open() + else + close() + +/obj/machinery/door/attackby(obj/item/I, mob/living/user) + if(istype(I, /obj/item/device/detective_scanner)) + return + if(src.operating) + return + if(src.density && hasPower() && (istype(I, /obj/item/weapon/card/emag)||istype(I, /obj/item/weapon/melee/energy/blade))) + update_icon(AIRLOCK_EMAG) + sleep(6) + if(!open()) + update_icon(AIRLOCK_CLOSED) + operating = -1 + return 1 + if(isrobot(user)) + return //borgs can't attack doors open because it conflicts with their AI-like interaction with them. + if(!Adjacent(user)) + user = null + if(!src.requiresID()) + user = null + user.SetNextMove(CLICK_CD_INTERACT) + if(src.allowed(user)) + if(src.density) + open() + else + close() + return + if(src.density) + do_animate("deny") + return + + +/obj/machinery/door/blob_act() + if(prob(40)) + qdel(src) + return + + +/obj/machinery/door/emp_act(severity) + if(prob(20/severity) && (istype(src,/obj/machinery/door/airlock) || istype(src,/obj/machinery/door/window)) ) + open() + 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/update_icon() + if(density) + icon_state = icon_state_close + else + icon_state = icon_state_open + + +/obj/machinery/door/proc/do_animate(animation) + switch(animation) + if("opening") + if(p_open) + flick("o_doorc0", src) + else + flick("doorc0", src) + if("closing") + if(p_open) + flick("o_doorc1", src) + else + flick("doorc1", src) + if("deny") + flick("door_deny", src) + return + + +/** + * Call this proc, if you want to open the door. + * + * Use `forced` param, if you want to open the door with + * ignoring of `normal_open_checks()` conditions. + * + * Same for `close()`. + */ + +/obj/machinery/door/proc/open(forced = FALSE) + if(!density) + return TRUE + if(open_checks(forced)) + set_operating(TRUE) + do_open() + set_operating(FALSE) + return TRUE + return FALSE + +/obj/machinery/door/proc/close(forced = FALSE) + if(density) + return TRUE + if(close_checks(forced)) + set_operating(TRUE) + do_close() + set_operating(FALSE) + return TRUE + return FALSE + + +/** + * DO NOT CALL THIS PROC DIRECTLY!!! + * + * Checks for base level conditions for door opening. + * + * If you want more conditions you can re-implement it in subtypes like that: + * > /obj/machinery/door/.../open_checks() + * > if(..() && `more conditions`) + * > return TRUE + * > return FALSE + * or in another way, but with TRUE or FALSE returning. + * + * Same for `close_checks()`. + */ + +/obj/machinery/door/proc/open_checks(forced) + if(!operating && ticker) + if(!forced) + return normal_open_checks() + return TRUE + return FALSE + +/obj/machinery/door/proc/close_checks(forced) + if(!operating && ticker) + if(!forced) + return normal_close_checks() + return TRUE + return FALSE + + +/** + * DO NOT CALL THIS PROC DIRECTLY!!! + * + * Checks for additional level conditions for door opening. + * Proc will be ignored if door was forced. + * + * If you want more conditions you can re-implement it in subtypes like that: + * > /obj/machinery/door/.../normal_open_checks() + * > if(`condition one` && `condition two`) + * > return TRUE + * > return FALSE + * or in another way, but with TRUE or FALSE returning. + * + * Same for `normal_close_checks()`. + */ + +/obj/machinery/door/proc/normal_open_checks() + return TRUE + +/obj/machinery/door/proc/normal_close_checks() + return TRUE + + +/** + * DO NOT CALL THIS PROC DIRECTLY!!! + * + * Actually the process of opening the door. + * Re-implement it in subtypes if you want another behavior. + * + * Same for `do_close()`. + */ + +/obj/machinery/door/proc/do_open() + playsound(src, door_open_sound, 50, 1) + do_animate("opening") + sleep(3) + set_opacity(FALSE) + density = FALSE + sleep(9) + layer = base_layer + explosion_resistance = 0 + update_icon() + update_nearby_tiles() + +/obj/machinery/door/proc/do_close() + playsound(src, door_close_sound, 50, 1) + do_animate("closing") + sleep(3) + density = TRUE + sleep(9) + if(visible && !glass) + set_opacity(TRUE) + layer = base_layer + DOOR_CLOSED_MOD + explosion_resistance = initial(explosion_resistance) + do_afterclose() + update_icon() + update_nearby_tiles() + + +/** + * DO NOT CALL THIS PROC DIRECTLY!!! + * + * Helps to add additional behavior for closing. + */ + +/obj/machinery/door/proc/do_afterclose() + //I shall not add a check every x ticks if a door has closed over some fire. + var/obj/fire/fire = locate() in locs + if(fire) + qdel(fire) + +/obj/machinery/door/proc/set_operating(operating) + if(operating && !src.operating) + src.operating = TRUE + else if(!operating && src.operating == 1) + src.operating = FALSE + + +/obj/machinery/door/proc/requiresID() + return 1 + +/obj/machinery/door/update_nearby_tiles(need_rebuild) + . = ..() + + if(.) + for(var/turf/simulated/turf in locs) + update_heat_protection(turf) + +/obj/machinery/door/proc/update_heat_protection(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/Move(new_loc, new_dir) + ..() + update_nearby_tiles() + +/obj/machinery/door/proc/hasPower() + return !(stat & NOPOWER) + +/obj/machinery/door/morgue + icon = 'icons/obj/doors/doormorgue.dmi' + door_open_sound = 'sound/machines/shutter_open.ogg' + door_close_sound = 'sound/machines/shutter_close.ogg' diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 635bae15bb04..4a75f3a9b75a 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -1,346 +1,346 @@ -/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 = FIREDOOR_LAYER - base_layer = FIREDOOR_LAYER - glass = 0 - door_open_sound = 'sound/machines/electric_door_open.ogg' - door_close_sound = 'sound/machines/electric_door_open.ogg' - - //These are frequenly used with windows, so make sure zones can pass. - //Generally if a firedoor is at a place where there should be a zone boundery then there will be a regular door underneath it. - block_air_zones = 0 - - var/hatch_open = 0 - var/blocked = 0 - var/nextstate = null - var/net_id - var/list/areas_added - var/list/users_to_open - var/pdiff_alert = 0 - var/pdiff = 0 - - var/lockdown = 0 // When the door has detected a problem, it locks. - var/next_process_time = 0 - 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/atom_init() - . = ..() - for(var/obj/machinery/door/firedoor/F in loc) - if(F != src) - return INITIALIZE_HINT_QDEL - var/area/A = get_area(src) - ASSERT(istype(A)) - - A.all_doors.Add(src) - areas_added = list(A) - - for(var/direction in cardinal) - A = get_area(get_step(src, direction)) - if(istype(A) && !(A in areas_added)) - A.all_doors.Add(src) - areas_added += A - - -/obj/machinery/door/firedoor/Destroy() - for(var/area/A in areas_added) - A.all_doors.Remove(src) - return ..() - - -/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!") - 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(p_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 - else - stat |= NOPOWER - return - -/obj/machinery/door/firedoor/attack_paw(mob/user) - if(istype(user, /mob/living/carbon/alien/humanoid)) - if(blocked) - to_chat(user, "\red The door is sealed, it cannot be pried open.") - return - else if(!density) - return - else if(!user.is_busy(src)) - to_chat(user, "\red You force your claws between the doors and begin to pry them open...") - playsound(src.loc, 'sound/effects/metal_creaking.ogg', 50, 0) - if (do_after(user,40,target = src) && src) - open(1) - return - -/obj/machinery/door/firedoor/attack_animal(mob/user) - if(istype(user, /mob/living/simple_animal/hulk)) - var/mob/living/simple_animal/hulk/H = user - H.attack_hulk(src) - -/obj/machinery/door/firedoor/attack_hand(mob/user) - add_fingerprint(user) - if(operating) - return//Already doing something. - - if(blocked) - to_chat(user, "\The [src] is welded solid!") - return - - if(!allowed(user)) - if(pdiff >= FIREDOOR_MAX_PRESSURE_DIFF) - to_chat(user, "Access denied.") - return - - var/alarmed = 0 - - for(var/area/A in areas_added) //Checks if there are fire alarms in any areas associated with that firedoor - if(A.fire || A.air_doors_activated) - alarmed = 1 - - var/answer = alert(user, "Would you like to [density ? "open" : "close"] this [src.name]?[ alarmed && density ? "\nNote that by doing so, you acknowledge any damages from opening this\n[src.name] as being your own fault, and you will be held accountable under the law." : ""]",\ - "\The [src]", "Yes, [density ? "open" : "close"]", "No") - if(answer == "No") - return - if(user.stat || user.stunned || user.weakened || user.paralysis || (!user.canmove && !isAI(user)) || (get_dist(src, user) > 1 && !isAI(user))) - to_chat(user, "Sorry, you must remain able bodied and close to \the [src] in order to use it.") - return - - var/needs_to_close = 0 - if(density) - if(alarmed) - needs_to_close = 1 - spawn() - open() - else - spawn() - close() - - if(needs_to_close) - spawn(50) - alarmed = 0 - for(var/area/A in areas_added) //Just in case a fire alarm is turned off while the firedoor is going through an autoclose cycle - if(A.fire || A.air_doors_activated) - alarmed = 1 - if(alarmed) - nextstate = CLOSED - close() - -/obj/machinery/door/firedoor/attackby(obj/item/weapon/C, mob/user) - 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("\red \The [user] [blocked ? "welds" : "unwelds"] \the [src] with \a [W].",\ - "You [blocked ? "weld" : "unweld"] \the [src] with \the [W].",\ - "You hear something being welded.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - update_icon() - return - - if(density && istype(C, /obj/item/weapon/screwdriver)) - hatch_open = !hatch_open - user.visible_message("[user] has [hatch_open ? "opened" : "closed"] \the [src] maintenance hatch.", - "You have [hatch_open ? "opened" : "closed"] the [src] maintenance hatch.") - update_icon() - return - - if(blocked && istype(C, /obj/item/weapon/crowbar)) - if(!hatch_open) - to_chat(user, "You must open the maintenance hatch first!") - else if(!user.is_busy(src)) - user.visible_message("[user] is removing the electronics from \the [src].", - "You start to remove the electronics from [src].") - if(do_after(user,30,target = src)) - if(blocked && density && hatch_open) - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) - user.visible_message("[user] has removed the electronics from \the [src].", - "You have removed the electronics from [src].") - - new/obj/item/weapon/airalarm_electronics(src.loc) - - var/obj/structure/firedoor_assembly/FA = new/obj/structure/firedoor_assembly(src.loc) - FA.anchored = 1 - FA.density = 1 - FA.wired = 1 - FA.update_icon() - qdel(src) - return - - if(blocked) - to_chat(user, "\red \The [src] is welded solid!") - return - - if( istype(C, /obj/item/weapon/crowbar) || ( istype(C,/obj/item/weapon/twohanded/fireaxe) && C:wielded == 1 ) ) - if(operating) - return - - if( blocked && istype(C, /obj/item/weapon/crowbar) ) - user.visible_message("\red \The [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 - if(user.is_busy(src)) return - user.visible_message("\red \The [user] starts to force \the [src] [density ? "open" : "closed"] with \a [C]!",\ - "You start forcing \the [src] [density ? "open" : "closed"] with \the [C]!",\ - "You hear metal strain.") - if(do_after(user,30,target = src)) - if( istype(C, /obj/item/weapon/crowbar) ) - if( stat & (BROKEN|NOPOWER) || !density) - user.visible_message("\red \The [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"].") - else - user.visible_message("\red \The [user] forces \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \a [C]!",\ - "You force \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \the [C]!",\ - "You hear metal strain and groan, and a door [density ? "open" : "close"].") - if(density) - spawn(0) - open() - else - spawn(0) - close() - return - - -/obj/machinery/door/firedoor/proc/latetoggle() - if(operating || stat & NOPOWER || !nextstate) - return - switch(nextstate) - if(OPEN) - nextstate = null - open() - if(CLOSED) - nextstate = null - close() - return - -/obj/machinery/door/firedoor/do_close() - ..() - layer = base_layer + FIREDOOR_CLOSED_MOD - START_PROCESSING(SSmachine, src) - latetoggle() - -/obj/machinery/door/firedoor/do_open() - ..() - layer = base_layer - if(hatch_open) - hatch_open = FALSE - visible_message("The maintenance hatch of \the [src] closes.") - update_icon() - latetoggle() - -/obj/machinery/door/firedoor/do_animate(animation) - switch(animation) - if("opening") - flick("door_opening", src) - if("closing") - flick("door_closing", src) - return - - -/obj/machinery/door/firedoor/update_icon() - overlays.Cut() - if(density) - icon_state = "door_closed" - if(hatch_open) - overlays += "hatch" - if(blocked) - overlays += "welded" - if(pdiff_alert) - overlays += "palert" - if(dir_alerts) - for(var/d in 1 to 4) - var/cdir = cardinal[d] - for(var/i in 1 to ALERT_STATES.len) - if(dir_alerts[d] & (1<<(i-1))) - overlays += new/icon(icon,"alert_[ALERT_STATES[i]]", dir=cdir) - else - icon_state = "door_open" - if(blocked) - overlays += "welded_open" - return - - // CHECK PRESSURE -/obj/machinery/door/firedoor/process() - if(density) - if(next_process_time <= world.time) - next_process_time = world.time + 100 // 10 second delays between process updates - 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.loc,list("temperature","pressure")) - var/old_alerts = dir_alerts - for(var/index in 1 to 4) - 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() - else - return PROCESS_KILL +/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 = FIREDOOR_LAYER + base_layer = FIREDOOR_LAYER + glass = 0 + door_open_sound = 'sound/machines/electric_door_open.ogg' + door_close_sound = 'sound/machines/electric_door_open.ogg' + + //These are frequenly used with windows, so make sure zones can pass. + //Generally if a firedoor is at a place where there should be a zone boundery then there will be a regular door underneath it. + block_air_zones = 0 + + var/hatch_open = 0 + var/blocked = 0 + var/nextstate = null + var/net_id + var/list/areas_added + var/list/users_to_open + var/pdiff_alert = 0 + var/pdiff = 0 + + var/lockdown = 0 // When the door has detected a problem, it locks. + var/next_process_time = 0 + 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/atom_init() + . = ..() + for(var/obj/machinery/door/firedoor/F in loc) + if(F != src) + return INITIALIZE_HINT_QDEL + var/area/A = get_area(src) + ASSERT(istype(A)) + + A.all_doors.Add(src) + areas_added = list(A) + + for(var/direction in cardinal) + A = get_area(get_step(src, direction)) + if(istype(A) && !(A in areas_added)) + A.all_doors.Add(src) + areas_added += A + + +/obj/machinery/door/firedoor/Destroy() + for(var/area/A in areas_added) + A.all_doors.Remove(src) + return ..() + + +/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!") + 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(p_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 + else + stat |= NOPOWER + return + +/obj/machinery/door/firedoor/attack_paw(mob/user) + if(istype(user, /mob/living/carbon/alien/humanoid)) + if(blocked) + to_chat(user, "\red The door is sealed, it cannot be pried open.") + return + else if(!density) + return + else if(!user.is_busy(src)) + to_chat(user, "\red You force your claws between the doors and begin to pry them open...") + playsound(src.loc, 'sound/effects/metal_creaking.ogg', 50, 0) + if (do_after(user,40,target = src) && src) + open(1) + return + +/obj/machinery/door/firedoor/attack_animal(mob/user) + if(istype(user, /mob/living/simple_animal/hulk)) + var/mob/living/simple_animal/hulk/H = user + H.attack_hulk(src) + +/obj/machinery/door/firedoor/attack_hand(mob/user) + add_fingerprint(user) + if(operating) + return//Already doing something. + + if(blocked) + to_chat(user, "\The [src] is welded solid!") + return + + if(!allowed(user)) + if(pdiff >= FIREDOOR_MAX_PRESSURE_DIFF) + to_chat(user, "Access denied.") + return + + var/alarmed = 0 + + for(var/area/A in areas_added) //Checks if there are fire alarms in any areas associated with that firedoor + if(A.fire || A.air_doors_activated) + alarmed = 1 + + var/answer = alert(user, "Would you like to [density ? "open" : "close"] this [src.name]?[ alarmed && density ? "\nNote that by doing so, you acknowledge any damages from opening this\n[src.name] as being your own fault, and you will be held accountable under the law." : ""]",\ + "\The [src]", "Yes, [density ? "open" : "close"]", "No") + if(answer == "No") + return + if(user.stat || user.stunned || user.weakened || user.paralysis || (!user.canmove && !isAI(user)) || (get_dist(src, user) > 1 && !isAI(user))) + to_chat(user, "Sorry, you must remain able bodied and close to \the [src] in order to use it.") + return + + var/needs_to_close = 0 + if(density) + if(alarmed) + needs_to_close = 1 + spawn() + open() + else + spawn() + close() + + if(needs_to_close) + spawn(50) + alarmed = 0 + for(var/area/A in areas_added) //Just in case a fire alarm is turned off while the firedoor is going through an autoclose cycle + if(A.fire || A.air_doors_activated) + alarmed = 1 + if(alarmed) + nextstate = CLOSED + close() + +/obj/machinery/door/firedoor/attackby(obj/item/weapon/C, mob/user) + 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("\red \The [user] [blocked ? "welds" : "unwelds"] \the [src] with \a [W].",\ + "You [blocked ? "weld" : "unweld"] \the [src] with \the [W].",\ + "You hear something being welded.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + update_icon() + return + + if(density && istype(C, /obj/item/weapon/screwdriver)) + hatch_open = !hatch_open + user.visible_message("[user] has [hatch_open ? "opened" : "closed"] \the [src] maintenance hatch.", + "You have [hatch_open ? "opened" : "closed"] the [src] maintenance hatch.") + update_icon() + return + + if(blocked && istype(C, /obj/item/weapon/crowbar)) + if(!hatch_open) + to_chat(user, "You must open the maintenance hatch first!") + else if(!user.is_busy(src)) + user.visible_message("[user] is removing the electronics from \the [src].", + "You start to remove the electronics from [src].") + if(do_after(user,30,target = src)) + if(blocked && density && hatch_open) + playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + user.visible_message("[user] has removed the electronics from \the [src].", + "You have removed the electronics from [src].") + + new/obj/item/weapon/airalarm_electronics(src.loc) + + var/obj/structure/firedoor_assembly/FA = new/obj/structure/firedoor_assembly(src.loc) + FA.anchored = 1 + FA.density = 1 + FA.wired = 1 + FA.update_icon() + qdel(src) + return + + if(blocked) + to_chat(user, "\red \The [src] is welded solid!") + return + + if( istype(C, /obj/item/weapon/crowbar) || ( istype(C,/obj/item/weapon/twohanded/fireaxe) && C:wielded == 1 ) ) + if(operating) + return + + if( blocked && istype(C, /obj/item/weapon/crowbar) ) + user.visible_message("\red \The [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 + if(user.is_busy(src)) return + user.visible_message("\red \The [user] starts to force \the [src] [density ? "open" : "closed"] with \a [C]!",\ + "You start forcing \the [src] [density ? "open" : "closed"] with \the [C]!",\ + "You hear metal strain.") + if(do_after(user,30,target = src)) + if( istype(C, /obj/item/weapon/crowbar) ) + if( stat & (BROKEN|NOPOWER) || !density) + user.visible_message("\red \The [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"].") + else + user.visible_message("\red \The [user] forces \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \a [C]!",\ + "You force \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \the [C]!",\ + "You hear metal strain and groan, and a door [density ? "open" : "close"].") + if(density) + spawn(0) + open() + else + spawn(0) + close() + return + + +/obj/machinery/door/firedoor/proc/latetoggle() + if(operating || stat & NOPOWER || !nextstate) + return + switch(nextstate) + if(OPEN) + nextstate = null + open() + if(CLOSED) + nextstate = null + close() + return + +/obj/machinery/door/firedoor/do_close() + ..() + layer = base_layer + FIREDOOR_CLOSED_MOD + START_PROCESSING(SSmachine, src) + latetoggle() + +/obj/machinery/door/firedoor/do_open() + ..() + layer = base_layer + if(hatch_open) + hatch_open = FALSE + visible_message("The maintenance hatch of \the [src] closes.") + update_icon() + latetoggle() + +/obj/machinery/door/firedoor/do_animate(animation) + switch(animation) + if("opening") + flick("door_opening", src) + if("closing") + flick("door_closing", src) + return + + +/obj/machinery/door/firedoor/update_icon() + overlays.Cut() + if(density) + icon_state = "door_closed" + if(hatch_open) + overlays += "hatch" + if(blocked) + overlays += "welded" + if(pdiff_alert) + overlays += "palert" + if(dir_alerts) + for(var/d in 1 to 4) + var/cdir = cardinal[d] + for(var/i in 1 to ALERT_STATES.len) + if(dir_alerts[d] & (1<<(i-1))) + overlays += new/icon(icon,"alert_[ALERT_STATES[i]]", dir=cdir) + else + icon_state = "door_open" + if(blocked) + overlays += "welded_open" + return + + // CHECK PRESSURE +/obj/machinery/door/firedoor/process() + if(density) + if(next_process_time <= world.time) + next_process_time = world.time + 100 // 10 second delays between process updates + 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.loc,list("temperature","pressure")) + var/old_alerts = dir_alerts + for(var/index in 1 to 4) + 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() + else + return PROCESS_KILL diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index ade78bdc3436..bdddf9b6c6eb 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -1,82 +1,82 @@ -/obj/machinery/door/poddoor - name = "Podlock" - desc = "Why it no open!!!" - icon = 'icons/obj/doors/blast_door.dmi' - icon_state = "pdoor1" - icon_state_open = "pdoor0" - icon_state_close = "pdoor1" - var/id = 1.0 - explosion_resistance = 25 - block_air_zones = 0 - door_open_sound = 'sound/machines/blast_door.ogg' - door_close_sound = 'sound/machines/blast_door.ogg' - -/obj/machinery/door/poddoor/cargo - icon = 'code/modules/locations/shuttles/cargo.dmi' - -/obj/machinery/door/poddoor/atom_init() - . = ..() - poddoor_list += src - if(density) - layer = base_layer + PODDOOR_CLOSED_MOD - -/obj/machinery/door/poddoor/Destroy() - poddoor_list -= src - return ..() - -/obj/machinery/door/poddoor/Bumped(atom/AM) - if(!density) - return ..() - else - return 0 - -/obj/machinery/door/poddoor/attackby(obj/item/weapon/C, mob/user) - add_fingerprint(user) - if(istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/twohanded/fireaxe) && C:wielded)) - if(!hasPower()) - open(TRUE) - -/obj/machinery/door/poddoor/normal_open_checks() - if(hasPower()) - return TRUE - return FALSE - -/obj/machinery/door/poddoor/normal_close_checks() - if(hasPower()) - return TRUE - return FALSE - -/obj/machinery/door/poddoor/do_open() - if(hasPower()) - use_power(20) - playsound(src, door_open_sound, 100, 1) - do_animate("opening") - icon_state = icon_state_open - sleep(3) - explosion_resistance = 0 - layer = base_layer - density = FALSE - set_opacity(FALSE) - update_nearby_tiles() - -/obj/machinery/door/poddoor/do_close() - if(hasPower()) - use_power(20) - playsound(src, door_close_sound, 100, 1) - do_animate("closing") - icon_state = icon_state_close - sleep(3) - explosion_resistance = initial(explosion_resistance) - layer = base_layer + PODDOOR_CLOSED_MOD - density = TRUE - set_opacity(TRUE) - do_afterclose() - update_nearby_tiles() - -/obj/machinery/door/poddoor/do_animate(animation) - switch(animation) - if("opening") - flick("pdoorc0", src) - if("closing") - flick("pdoorc1", src) - return +/obj/machinery/door/poddoor + name = "Podlock" + desc = "Why it no open!!!" + icon = 'icons/obj/doors/blast_door.dmi' + icon_state = "pdoor1" + icon_state_open = "pdoor0" + icon_state_close = "pdoor1" + var/id = 1.0 + explosion_resistance = 25 + block_air_zones = 0 + door_open_sound = 'sound/machines/blast_door.ogg' + door_close_sound = 'sound/machines/blast_door.ogg' + +/obj/machinery/door/poddoor/cargo + icon = 'code/modules/locations/shuttles/cargo.dmi' + +/obj/machinery/door/poddoor/atom_init() + . = ..() + poddoor_list += src + if(density) + layer = base_layer + PODDOOR_CLOSED_MOD + +/obj/machinery/door/poddoor/Destroy() + poddoor_list -= src + return ..() + +/obj/machinery/door/poddoor/Bumped(atom/AM) + if(!density) + return ..() + else + return 0 + +/obj/machinery/door/poddoor/attackby(obj/item/weapon/C, mob/user) + add_fingerprint(user) + if(istype(C, /obj/item/weapon/crowbar) || (istype(C, /obj/item/weapon/twohanded/fireaxe) && C:wielded)) + if(!hasPower()) + open(TRUE) + +/obj/machinery/door/poddoor/normal_open_checks() + if(hasPower()) + return TRUE + return FALSE + +/obj/machinery/door/poddoor/normal_close_checks() + if(hasPower()) + return TRUE + return FALSE + +/obj/machinery/door/poddoor/do_open() + if(hasPower()) + use_power(20) + playsound(src, door_open_sound, 100, 1) + do_animate("opening") + icon_state = icon_state_open + sleep(3) + explosion_resistance = 0 + layer = base_layer + density = FALSE + set_opacity(FALSE) + update_nearby_tiles() + +/obj/machinery/door/poddoor/do_close() + if(hasPower()) + use_power(20) + playsound(src, door_close_sound, 100, 1) + do_animate("closing") + icon_state = icon_state_close + sleep(3) + explosion_resistance = initial(explosion_resistance) + layer = base_layer + PODDOOR_CLOSED_MOD + density = TRUE + set_opacity(TRUE) + do_afterclose() + update_nearby_tiles() + +/obj/machinery/door/poddoor/do_animate(animation) + switch(animation) + if("opening") + flick("pdoorc0", src) + if("closing") + flick("pdoorc1", src) + return diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index c077d0ac4114..be710f673706 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -1,25 +1,25 @@ -/obj/machinery/door/poddoor/shutters - name = "Shutters" - icon = 'icons/obj/doors/rapid_pdoor.dmi' - icon_state = "shutter1" - icon_state_open = "shutter0" - icon_state_close = "shutter1" - door_open_sound = 'sound/machines/shutter_open.ogg' - door_close_sound = 'sound/machines/shutter_close.ogg' - -/obj/machinery/door/poddoor/shutters/atom_init() - . = ..() - layer = SHUTTERS_LAYER - -/obj/machinery/door/poddoor/shutters/do_animate(animation) - switch(animation) - if("opening") - flick("shutterc0", src) - if("closing") - flick("shutterc1", src) - return - -/obj/machinery/door/poddoor/shutters/syndi - -/obj/machinery/door/poddoor/shutters/syndi/ex_act() - return +/obj/machinery/door/poddoor/shutters + name = "Shutters" + icon = 'icons/obj/doors/rapid_pdoor.dmi' + icon_state = "shutter1" + icon_state_open = "shutter0" + icon_state_close = "shutter1" + door_open_sound = 'sound/machines/shutter_open.ogg' + door_close_sound = 'sound/machines/shutter_close.ogg' + +/obj/machinery/door/poddoor/shutters/atom_init() + . = ..() + layer = SHUTTERS_LAYER + +/obj/machinery/door/poddoor/shutters/do_animate(animation) + switch(animation) + if("opening") + flick("shutterc0", src) + if("closing") + flick("shutterc1", src) + return + +/obj/machinery/door/poddoor/shutters/syndi + +/obj/machinery/door/poddoor/shutters/syndi/ex_act() + return diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 803737dc17c3..7733ea38a531 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -1,471 +1,471 @@ -/obj/machinery/door/window - name = "interior door" - desc = "A strong door." - icon = 'icons/obj/doors/windoor.dmi' - icon_state = "left" - visible = 0.0 - flags = ON_BORDER - opacity = 0 - explosion_resistance = 5 - air_properties_vary_with_direction = 1 - door_open_sound = 'sound/machines/windowdoor.ogg' - door_close_sound = 'sound/machines/windowdoor.ogg' - var/obj/item/weapon/airlock_electronics/electronics = null - var/base_state = "left" - var/health = 150.0 //If you change this, consider changing ../door/window/brigdoor/ health at the bottom of this .dm file - -/obj/machinery/door/window/atom_init() - . = ..() - - if (req_access && req_access.len) - icon_state = "[icon_state]" - base_state = icon_state - - color = color_windows() - -/obj/machinery/door/window/Destroy() - density = 0 - update_nearby_tiles() - electronics = null - return ..() - -/obj/machinery/door/window/proc/open_and_close() - open() - if(src.check_access(null)) - sleep(50) - else //secure doors close faster - sleep(20) - close() - -/obj/machinery/door/window/update_icon() - if(density) - icon_state = base_state - else - icon_state = "[src.base_state]open" - -/obj/machinery/door/window/proc/shatter(display_message = 1) - if(!(flags & NODECONSTRUCT)) - new /obj/item/weapon/shard(loc) - new /obj/item/weapon/shard(loc) - new /obj/item/stack/rods(loc, 2) - new /obj/item/stack/cable_coil/red(loc, 2) - var/obj/item/weapon/airlock_electronics/ae - if(!electronics) - ae = new/obj/item/weapon/airlock_electronics( src.loc ) - if(!src.req_access) - src.check_access() - if(src.req_access.len) - ae.conf_access = src.req_access - else if (src.req_one_access.len) - ae.conf_access = src.req_one_access - ae.one_access = 1 - else - ae = electronics - electronics = null - ae.loc = src.loc - if(operating == -1) - ae.icon_state = "door_electronics_smoked" - ae.broken = TRUE - operating = 0 - src.density = 0 - playsound(src, "shatter", 70, 1) - if(display_message) - visible_message("[src] shatters!") - qdel(src) - -//painter -/obj/machinery/door/window/proc/change_paintjob(obj/item/C, mob/user) - var/obj/item/weapon/airlock_painter/W - if(istype(C, /obj/item/weapon/airlock_painter)) - W = C - else - return - - if(!W.can_use(user, 1)) - return - - var/new_color = input(user, "Choose color!") as color|null - if(!new_color) return - - if((!in_range(src, usr) && src.loc != usr) || !W.use(user, 1)) - return - else - color = new_color - -/obj/machinery/door/window/Bumped(atom/movable/AM) - if( operating || !src.density ) - return - if (!( ismob(AM) )) - var/obj/machinery/bot/bot = AM - if(istype(bot)) - if(src.check_access(bot.botcard)) - open_and_close() - else - do_animate("deny") - else if(istype(AM, /obj/mecha)) - var/obj/mecha/mecha = AM - if(mecha.occupant && src.allowed(mecha.occupant)) - open_and_close() - else - do_animate("deny") - return - if (!( ticker )) - return - var/mob/M = AM - if(!M.restrained()) - bumpopen(M) - return - -/obj/machinery/door/window/bumpopen(mob/user) - if( operating || !src.density ) - return - src.add_fingerprint(user) - if(!src.requiresID()) - user = null - - if(allowed(user)) - open_and_close() - else - do_animate("deny") - return - -/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target, height=0, 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 - -/obj/machinery/door/window/CanAStarPass(obj/item/weapon/card/id/ID, to_dir, caller) - return !density || (dir != to_dir) || (check_access(ID) && hasPower()) - -/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/normal_open_checks() - if(hasPower() && !emagged) - return TRUE - return FALSE - -/obj/machinery/door/window/normal_close_checks() - if(hasPower() && !emagged) - return TRUE - return FALSE - -/obj/machinery/door/window/do_open() - if(hasPower()) - use_power(15) - playsound(src, door_open_sound, 100, 1) - do_animate("opening") - icon_state = "[base_state]open" - sleep(10) - density = FALSE - block_air_zones = FALSE // We merge zones if door is open. - explosion_resistance = 0 - update_nearby_tiles() - -/obj/machinery/door/window/do_close() - if(hasPower()) - use_power(15) - playsound(src, door_close_sound, 100, 1) - do_animate("closing") - icon_state = base_state - density = TRUE - block_air_zones = TRUE - explosion_resistance = initial(explosion_resistance) - update_nearby_tiles() - -/obj/machinery/door/window/do_animate(animation) - switch(animation) - if("opening") - flick("[base_state]opening", src) - if("closing") - flick("[base_state]closing", src) - if("deny") - flick("[base_state]deny", src) - return - - -/obj/machinery/door/window/proc/take_damage(damage) - src.health = max(0, src.health - damage) - if(src.health <= 0) - shatter() - return - -/obj/machinery/door/window/bullet_act(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) - - ..() - visible_message("\red The glass door was hit by [AM].", 1) - var/tforce = 0 - if(ismob(AM)) - tforce = 40 - else - tforce = AM:throwforce - playsound(src.loc, '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/proc/attack_generic(mob/user, damage = 0) - if(src.operating) - return - user.do_attack_animation(src) - playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) - user.visible_message("[user] smashes against the [src.name].", \ - "[user] smashes against the [src.name].") - take_damage(damage) - -/obj/machinery/door/window/attack_alien(mob/user) - if(islarva(user)) - return - user.SetNextMove(CLICK_CD_MELEE) - attack_generic(user, 25) - -/obj/machinery/door/window/attack_animal(mob/user) - if(!isanimal(user)) - return - ..() - var/mob/living/simple_animal/M = user - if(M.melee_damage_upper <= 0) - return - attack_generic(M, M.melee_damage_upper) - -/obj/machinery/door/window/attack_slime(mob/living/carbon/slime/user) - if(!istype(user, /mob/living/carbon/slime/adult)) - return - user.SetNextMove(CLICK_CD_MELEE) - attack_generic(user, 25) - -/obj/machinery/door/window/attackby(obj/item/weapon/I, mob/user) - - //If it's in the process of opening/closing, ignore the click - if (src.operating == 1) - return - - if(istype(I, /obj/item/weapon/airlock_painter)) - change_paintjob(I, user) - return - - if( istype(I,/obj/item/weapon/changeling_hammer)) - var/obj/item/weapon/changeling_hammer/W = I - user.SetNextMove(CLICK_CD_MELEE) - if(W.use_charge(user, 6)) - visible_message("[user]
    has punched [src]!") - playsound(user.loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) - shatter() - return - - //Emags and ninja swords? You may pass. - if (density && ((istype(I, /obj/item/weapon/card/emag) && hasPower()) || istype(I, /obj/item/weapon/melee/energy/blade))) - flick("[src.base_state]spark", src) - user.SetNextMove(CLICK_CD_MELEE) - sleep(6) - if(istype(I, /obj/item/weapon/melee/energy/blade)) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, "sparks", 50, 1) - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - visible_message(" The glass door was sliced open by [user]!") - open(1) - return - open() - operating = -1 - return - - if(!(flags & NODECONSTRUCT)) - if(istype(I, /obj/item/weapon/screwdriver)) - if(src.density || src.operating == 1) - to_chat(user, "You need to open the [src.name] to access the maintenance panel.") - return - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - src.p_open = !( src.p_open ) - to_chat(user, "You [p_open ? "open":"close"] the maintenance panel of the [src.name].") - return - - if(istype(I, /obj/item/weapon/crowbar)) - if(p_open && !src.density) - if(user.is_busy(src)) return - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) - user.visible_message("[user] removes the electronics from the [src.name].", \ - "You start to remove electronics from the [src.name].") - if(do_after(user,40,target=src)) - if(src.p_open && !src.density && src.loc) - var/obj/structure/windoor_assembly/WA = new /obj/structure/windoor_assembly(src.loc) - switch(base_state) - if("left") - WA.icon_state = "l_windoor_assembly02" - if("right") - WA.icon_state = "r_windoor_assembly02" - if("leftsecure") - WA.icon_state = "l_secure_windoor_assembly02" - WA.secure = 1 - if("rightsecure") - WA.icon_state = "r_secure_windoor_assembly02" - WA.secure = 1 - WA.anchored = 1 - WA.state= "02" - WA.dir = src.dir - WA.ini_dir = src.dir - WA.update_icon() - WA.created_name = src.name - - to_chat(user, "You removed the airlock electronics!") - - var/obj/item/weapon/airlock_electronics/ae - if(!electronics) - ae = new/obj/item/weapon/airlock_electronics( src.loc ) - if(!req_access) - check_access() - if(req_access.len) - ae.conf_access = req_access - else if(req_one_access.len) - ae.conf_access = req_one_access - ae.one_access = 1 - else - else - ae = electronics - electronics = null - ae.loc = src.loc - - if(operating == -1) - ae.icon_state = "door_electronics_smoked" - ae.broken = TRUE - operating = 0 - - qdel(src) - return - - - //If windoor is unpowered, crowbar, fireaxe and armblade can force it. - if(istype(I, /obj/item/weapon/crowbar) || istype(I, /obj/item/weapon/twohanded/fireaxe) || istype(I, /obj/item/weapon/melee/arm_blade) ) - if(!hasPower()) - user.SetNextMove(CLICK_CD_INTERACT) - if(density) - open(1) - else - close(1) - 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)) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - if( (I.flags&NOBLUDGEON) || !I.force ) - return - var/aforce = I.force - playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) - visible_message("\red [src] was hit by [I].") - if(I.damtype == BRUTE || I.damtype == BURN) - take_damage(aforce) - 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 (src.allowed(user)) - if (src.density) - open() - else - close() - - else if (src.density) - do_animate("deny") - - return - -/obj/machinery/door/window/brigdoor - name = "Secure Door" - icon = 'icons/obj/doors/windoor.dmi' - icon_state = "leftsecure" - base_state = "leftsecure" - req_access = list(access_security) - var/id = null - health = 300.0 //Stronger doors for prison (regular window door health is 200) - -/obj/machinery/door/window/brigdoor/atom_init() - . = ..() - brigdoor_list += src - -/obj/machinery/door/window/brigdoor/Destroy() - brigdoor_list -= src - return ..() - -/obj/machinery/door/window/northleft - dir = NORTH - -/obj/machinery/door/window/eastleft - dir = EAST - -/obj/machinery/door/window/westleft - dir = WEST - -/obj/machinery/door/window/southleft - dir = SOUTH - -/obj/machinery/door/window/northright - dir = NORTH - icon_state = "right" - base_state = "right" - -/obj/machinery/door/window/eastright - dir = EAST - icon_state = "right" - base_state = "right" - -/obj/machinery/door/window/westright - dir = WEST - icon_state = "right" - base_state = "right" - -/obj/machinery/door/window/southright - dir = SOUTH - icon_state = "right" - base_state = "right" - -/obj/machinery/door/window/brigdoor/northleft - dir = NORTH - -/obj/machinery/door/window/brigdoor/eastleft - dir = EAST - -/obj/machinery/door/window/brigdoor/westleft - dir = WEST - -/obj/machinery/door/window/brigdoor/southleft - dir = SOUTH - -/obj/machinery/door/window/brigdoor/northright - dir = NORTH - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/eastright - dir = EAST - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/westright - dir = WEST - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/southright - dir = SOUTH - icon_state = "rightsecure" - base_state = "rightsecure" +/obj/machinery/door/window + name = "interior door" + desc = "A strong door." + icon = 'icons/obj/doors/windoor.dmi' + icon_state = "left" + visible = 0.0 + flags = ON_BORDER + opacity = 0 + explosion_resistance = 5 + air_properties_vary_with_direction = 1 + door_open_sound = 'sound/machines/windowdoor.ogg' + door_close_sound = 'sound/machines/windowdoor.ogg' + var/obj/item/weapon/airlock_electronics/electronics = null + var/base_state = "left" + var/health = 150.0 //If you change this, consider changing ../door/window/brigdoor/ health at the bottom of this .dm file + +/obj/machinery/door/window/atom_init() + . = ..() + + if (req_access && req_access.len) + icon_state = "[icon_state]" + base_state = icon_state + + color = color_windows() + +/obj/machinery/door/window/Destroy() + density = 0 + update_nearby_tiles() + electronics = null + return ..() + +/obj/machinery/door/window/proc/open_and_close() + open() + if(src.check_access(null)) + sleep(50) + else //secure doors close faster + sleep(20) + close() + +/obj/machinery/door/window/update_icon() + if(density) + icon_state = base_state + else + icon_state = "[src.base_state]open" + +/obj/machinery/door/window/proc/shatter(display_message = 1) + if(!(flags & NODECONSTRUCT)) + new /obj/item/weapon/shard(loc) + new /obj/item/weapon/shard(loc) + new /obj/item/stack/rods(loc, 2) + new /obj/item/stack/cable_coil/red(loc, 2) + var/obj/item/weapon/airlock_electronics/ae + if(!electronics) + ae = new/obj/item/weapon/airlock_electronics( src.loc ) + if(!src.req_access) + src.check_access() + if(src.req_access.len) + ae.conf_access = src.req_access + else if (src.req_one_access.len) + ae.conf_access = src.req_one_access + ae.one_access = 1 + else + ae = electronics + electronics = null + ae.loc = src.loc + if(operating == -1) + ae.icon_state = "door_electronics_smoked" + ae.broken = TRUE + operating = 0 + src.density = 0 + playsound(src, "shatter", 70, 1) + if(display_message) + visible_message("[src] shatters!") + qdel(src) + +//painter +/obj/machinery/door/window/proc/change_paintjob(obj/item/C, mob/user) + var/obj/item/weapon/airlock_painter/W + if(istype(C, /obj/item/weapon/airlock_painter)) + W = C + else + return + + if(!W.can_use(user, 1)) + return + + var/new_color = input(user, "Choose color!") as color|null + if(!new_color) return + + if((!in_range(src, usr) && src.loc != usr) || !W.use(user, 1)) + return + else + color = new_color + +/obj/machinery/door/window/Bumped(atom/movable/AM) + if( operating || !src.density ) + return + if (!( ismob(AM) )) + var/obj/machinery/bot/bot = AM + if(istype(bot)) + if(src.check_access(bot.botcard)) + open_and_close() + else + do_animate("deny") + else if(istype(AM, /obj/mecha)) + var/obj/mecha/mecha = AM + if(mecha.occupant && src.allowed(mecha.occupant)) + open_and_close() + else + do_animate("deny") + return + if (!( ticker )) + return + var/mob/M = AM + if(!M.restrained()) + bumpopen(M) + return + +/obj/machinery/door/window/bumpopen(mob/user) + if( operating || !src.density ) + return + src.add_fingerprint(user) + if(!src.requiresID()) + user = null + + if(allowed(user)) + open_and_close() + else + do_animate("deny") + return + +/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target, height=0, 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 + +/obj/machinery/door/window/CanAStarPass(obj/item/weapon/card/id/ID, to_dir, caller) + return !density || (dir != to_dir) || (check_access(ID) && hasPower()) + +/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/normal_open_checks() + if(hasPower() && !emagged) + return TRUE + return FALSE + +/obj/machinery/door/window/normal_close_checks() + if(hasPower() && !emagged) + return TRUE + return FALSE + +/obj/machinery/door/window/do_open() + if(hasPower()) + use_power(15) + playsound(src, door_open_sound, 100, 1) + do_animate("opening") + icon_state = "[base_state]open" + sleep(10) + density = FALSE + block_air_zones = FALSE // We merge zones if door is open. + explosion_resistance = 0 + update_nearby_tiles() + +/obj/machinery/door/window/do_close() + if(hasPower()) + use_power(15) + playsound(src, door_close_sound, 100, 1) + do_animate("closing") + icon_state = base_state + density = TRUE + block_air_zones = TRUE + explosion_resistance = initial(explosion_resistance) + update_nearby_tiles() + +/obj/machinery/door/window/do_animate(animation) + switch(animation) + if("opening") + flick("[base_state]opening", src) + if("closing") + flick("[base_state]closing", src) + if("deny") + flick("[base_state]deny", src) + return + + +/obj/machinery/door/window/proc/take_damage(damage) + src.health = max(0, src.health - damage) + if(src.health <= 0) + shatter() + return + +/obj/machinery/door/window/bullet_act(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) + + ..() + visible_message("\red The glass door was hit by [AM].", 1) + var/tforce = 0 + if(ismob(AM)) + tforce = 40 + else + tforce = AM:throwforce + playsound(src.loc, '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/proc/attack_generic(mob/user, damage = 0) + if(src.operating) + return + user.do_attack_animation(src) + playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) + user.visible_message("[user] smashes against the [src.name].", \ + "[user] smashes against the [src.name].") + take_damage(damage) + +/obj/machinery/door/window/attack_alien(mob/user) + if(islarva(user)) + return + user.SetNextMove(CLICK_CD_MELEE) + attack_generic(user, 25) + +/obj/machinery/door/window/attack_animal(mob/user) + if(!isanimal(user)) + return + ..() + var/mob/living/simple_animal/M = user + if(M.melee_damage_upper <= 0) + return + attack_generic(M, M.melee_damage_upper) + +/obj/machinery/door/window/attack_slime(mob/living/carbon/slime/user) + if(!istype(user, /mob/living/carbon/slime/adult)) + return + user.SetNextMove(CLICK_CD_MELEE) + attack_generic(user, 25) + +/obj/machinery/door/window/attackby(obj/item/weapon/I, mob/user) + + //If it's in the process of opening/closing, ignore the click + if (src.operating == 1) + return + + if(istype(I, /obj/item/weapon/airlock_painter)) + change_paintjob(I, user) + return + + if( istype(I,/obj/item/weapon/changeling_hammer)) + var/obj/item/weapon/changeling_hammer/W = I + user.SetNextMove(CLICK_CD_MELEE) + if(W.use_charge(user, 6)) + visible_message("[user]
    has punched [src]!") + playsound(user.loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) + shatter() + return + + //Emags and ninja swords? You may pass. + if (density && ((istype(I, /obj/item/weapon/card/emag) && hasPower()) || istype(I, /obj/item/weapon/melee/energy/blade))) + flick("[src.base_state]spark", src) + user.SetNextMove(CLICK_CD_MELEE) + sleep(6) + if(istype(I, /obj/item/weapon/melee/energy/blade)) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src.loc) + spark_system.start() + playsound(src.loc, "sparks", 50, 1) + playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + visible_message(" The glass door was sliced open by [user]!") + open(1) + return + open() + operating = -1 + return + + if(!(flags & NODECONSTRUCT)) + if(istype(I, /obj/item/weapon/screwdriver)) + if(src.density || src.operating == 1) + to_chat(user, "You need to open the [src.name] to access the maintenance panel.") + return + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + src.p_open = !( src.p_open ) + to_chat(user, "You [p_open ? "open":"close"] the maintenance panel of the [src.name].") + return + + if(istype(I, /obj/item/weapon/crowbar)) + if(p_open && !src.density) + if(user.is_busy(src)) return + playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + user.visible_message("[user] removes the electronics from the [src.name].", \ + "You start to remove electronics from the [src.name].") + if(do_after(user,40,target=src)) + if(src.p_open && !src.density && src.loc) + var/obj/structure/windoor_assembly/WA = new /obj/structure/windoor_assembly(src.loc) + switch(base_state) + if("left") + WA.icon_state = "l_windoor_assembly02" + if("right") + WA.icon_state = "r_windoor_assembly02" + if("leftsecure") + WA.icon_state = "l_secure_windoor_assembly02" + WA.secure = 1 + if("rightsecure") + WA.icon_state = "r_secure_windoor_assembly02" + WA.secure = 1 + WA.anchored = 1 + WA.state= "02" + WA.dir = src.dir + WA.ini_dir = src.dir + WA.update_icon() + WA.created_name = src.name + + to_chat(user, "You removed the airlock electronics!") + + var/obj/item/weapon/airlock_electronics/ae + if(!electronics) + ae = new/obj/item/weapon/airlock_electronics( src.loc ) + if(!req_access) + check_access() + if(req_access.len) + ae.conf_access = req_access + else if(req_one_access.len) + ae.conf_access = req_one_access + ae.one_access = 1 + else + else + ae = electronics + electronics = null + ae.loc = src.loc + + if(operating == -1) + ae.icon_state = "door_electronics_smoked" + ae.broken = TRUE + operating = 0 + + qdel(src) + return + + + //If windoor is unpowered, crowbar, fireaxe and armblade can force it. + if(istype(I, /obj/item/weapon/crowbar) || istype(I, /obj/item/weapon/twohanded/fireaxe) || istype(I, /obj/item/weapon/melee/arm_blade) ) + if(!hasPower()) + user.SetNextMove(CLICK_CD_INTERACT) + if(density) + open(1) + else + close(1) + 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)) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + if( (I.flags&NOBLUDGEON) || !I.force ) + return + var/aforce = I.force + playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) + visible_message("\red [src] was hit by [I].") + if(I.damtype == BRUTE || I.damtype == BURN) + take_damage(aforce) + 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 (src.allowed(user)) + if (src.density) + open() + else + close() + + else if (src.density) + do_animate("deny") + + return + +/obj/machinery/door/window/brigdoor + name = "Secure Door" + icon = 'icons/obj/doors/windoor.dmi' + icon_state = "leftsecure" + base_state = "leftsecure" + req_access = list(access_security) + var/id = null + health = 300.0 //Stronger doors for prison (regular window door health is 200) + +/obj/machinery/door/window/brigdoor/atom_init() + . = ..() + brigdoor_list += src + +/obj/machinery/door/window/brigdoor/Destroy() + brigdoor_list -= src + return ..() + +/obj/machinery/door/window/northleft + dir = NORTH + +/obj/machinery/door/window/eastleft + dir = EAST + +/obj/machinery/door/window/westleft + dir = WEST + +/obj/machinery/door/window/southleft + dir = SOUTH + +/obj/machinery/door/window/northright + dir = NORTH + icon_state = "right" + base_state = "right" + +/obj/machinery/door/window/eastright + dir = EAST + icon_state = "right" + base_state = "right" + +/obj/machinery/door/window/westright + dir = WEST + icon_state = "right" + base_state = "right" + +/obj/machinery/door/window/southright + dir = SOUTH + icon_state = "right" + base_state = "right" + +/obj/machinery/door/window/brigdoor/northleft + dir = NORTH + +/obj/machinery/door/window/brigdoor/eastleft + dir = EAST + +/obj/machinery/door/window/brigdoor/westleft + dir = WEST + +/obj/machinery/door/window/brigdoor/southleft + dir = SOUTH + +/obj/machinery/door/window/brigdoor/northright + dir = NORTH + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/eastright + dir = EAST + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/westright + dir = WEST + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/southright + dir = SOUTH + icon_state = "rightsecure" + base_state = "rightsecure" diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index 0374d42d6296..22a9a95a9a55 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -1,55 +1,55 @@ -var/list/doppler_arrays = list() - -/obj/machinery/doppler_array - name = "tachyon-doppler array" - desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array." - - -/obj/machinery/doppler_array/atom_init() - . = ..() - doppler_arrays += src - -/obj/machinery/doppler_array/Destroy() - doppler_arrays -= src - return ..() - -/obj/machinery/doppler_array/process() - return PROCESS_KILL - -/obj/machinery/doppler_array/proc/sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took) - 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],[y0]). Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range]. Temporal displacement of tachyons: [took]seconds." - - for(var/mob/O in hearers(src, null)) - O.show_message("[src] states coldly, \"[message]\"",2) - - -/obj/machinery/doppler_array/power_change() - if(stat & BROKEN) - icon_state = "[initial(icon_state)]-broken" - else - if( powered() ) - icon_state = initial(icon_state) - stat &= ~NOPOWER - else - icon_state = "[initial(icon_state)]-off" - stat |= NOPOWER +var/list/doppler_arrays = list() + +/obj/machinery/doppler_array + name = "tachyon-doppler array" + desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array." + + +/obj/machinery/doppler_array/atom_init() + . = ..() + doppler_arrays += src + +/obj/machinery/doppler_array/Destroy() + doppler_arrays -= src + return ..() + +/obj/machinery/doppler_array/process() + return PROCESS_KILL + +/obj/machinery/doppler_array/proc/sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took) + 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],[y0]). Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range]. Temporal displacement of tachyons: [took]seconds." + + for(var/mob/O in hearers(src, null)) + O.show_message("[src] states coldly, \"[message]\"",2) + + +/obj/machinery/doppler_array/power_change() + if(stat & BROKEN) + icon_state = "[initial(icon_state)]-broken" + else + if( powered() ) + icon_state = initial(icon_state) + stat &= ~NOPOWER + else + icon_state = "[initial(icon_state)]-off" + stat |= NOPOWER diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index 0ac3b43395a8..c181a6028c16 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -1,100 +1,100 @@ -/obj/machinery/embedded_controller - var/datum/computer/file/embedded_program/program - - name = "Embedded Controller" - anchored = 1 - allowed_checks = ALLOWED_CHECK_TOPIC - - var/on = 1 - -/obj/machinery/embedded_controller/radio/Destroy() - if(radio_controller) - radio_controller.remove_object(src,frequency) - if(program) - qdel(program) - 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() - updateUsrDialog() - -/obj/machinery/embedded_controller/attack_paw(mob/user) - to_chat(user, "You do not have the dexterity to use this.") - 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 - - frequency = 1379 - - unacidable = 1 - -/obj/machinery/embedded_controller/radio/atom_init() - . = ..() - 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) - -/obj/machinery/embedded_controller/radio/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/embedded_controller + var/datum/computer/file/embedded_program/program + + name = "Embedded Controller" + anchored = 1 + allowed_checks = ALLOWED_CHECK_TOPIC + + var/on = 1 + +/obj/machinery/embedded_controller/radio/Destroy() + if(radio_controller) + radio_controller.remove_object(src,frequency) + if(program) + qdel(program) + 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() + updateUsrDialog() + +/obj/machinery/embedded_controller/attack_paw(mob/user) + to_chat(user, "You do not have the dexterity to use this.") + 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 + + frequency = 1379 + + unacidable = 1 + +/obj/machinery/embedded_controller/radio/atom_init() + . = ..() + 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) + +/obj/machinery/embedded_controller/radio/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + if(frequency) + radio_connection = radio_controller.add_object(src, frequency) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 15c2b42574a3..a6951e0ae7b6 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -1,150 +1,150 @@ -// It is a gizmo that flashes a small area - -/obj/machinery/flasher - name = "Mounted flash" - desc = "A wall-mounted flashbulb device." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "mflash1" - var/id = null - var/range = 2 //this is roughly the size of brig cell - var/disable = FALSE - 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 = TRUE - -/obj/machinery/flasher/atom_init() - . = ..() - flasher_list += src - -/obj/machinery/flasher/Destroy() - flasher_list -= src - return ..() - -/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 = FALSE - base_state = "pflash" - density = TRUE - -/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, mob/user) - if (istype(W, /obj/item/weapon/wirecutters)) - add_fingerprint(user) - src.disable = !src.disable - user.SetNextMove(CLICK_CD_INTERACT) - if (src.disable) - user.visible_message("\red [user] has disconnected the [src]'s flashbulb!", "\red You disconnect the [src]'s flashbulb!") - if (!src.disable) - user.visible_message("\red [user] has connected the [src]'s flashbulb!", "\red You connect the [src]'s flashbulb!") - -//Let the AI trigger them directly. -/obj/machinery/flasher/attack_ai(mob/user) - if (anchored) - return 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(src.loc, 'sound/weapons/flash.ogg', 100, 1) - flick("[base_state]_flash", src) - src.last_flash = world.time - use_power(1000) - - for (var/mob/O in viewers(src, null)) - 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/obj/item/organ/internal/eyes/IO = H.organs_by_name[O_EYES] - if (IO.damage > IO.min_bruised_damage && prob(IO.damage + 50)) - H.flash_eyes() - IO.damage += rand(1, 5) - else - if(!O.blinded && istype(O,/mob/living)) - var/mob/living/L = O - L.flash_eyes() - - -/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) - 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, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - add_fingerprint(user) - src.anchored = !src.anchored - user.SetNextMove(CLICK_CD_INTERACT) - - if (!src.anchored) - user.show_message(text("\red [src] can now be moved.")) - src.overlays.Cut() - - else if (src.anchored) - user.show_message(text("\red [src] is now secured.")) - src.overlays += "[base_state]-s" - -/obj/machinery/flasher_button/attackby(obj/item/weapon/W, mob/user) - return attack_hand(user) - -/obj/machinery/flasher_button/attack_hand(mob/user) - if(..() || active) - return 1 - - use_power(5) - user.SetNextMove(CLICK_CD_INTERACT) - - active = 1 - icon_state = "launcheract" - - for(var/obj/machinery/flasher/M in flasher_list) - if(M.id == id) - spawn() - M.flash() - - sleep(50) - - icon_state = "launcherbtt" - active = 0 +// It is a gizmo that flashes a small area + +/obj/machinery/flasher + name = "Mounted flash" + desc = "A wall-mounted flashbulb device." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "mflash1" + var/id = null + var/range = 2 //this is roughly the size of brig cell + var/disable = FALSE + 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 = TRUE + +/obj/machinery/flasher/atom_init() + . = ..() + flasher_list += src + +/obj/machinery/flasher/Destroy() + flasher_list -= src + return ..() + +/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 = FALSE + base_state = "pflash" + density = TRUE + +/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, mob/user) + if (istype(W, /obj/item/weapon/wirecutters)) + add_fingerprint(user) + src.disable = !src.disable + user.SetNextMove(CLICK_CD_INTERACT) + if (src.disable) + user.visible_message("\red [user] has disconnected the [src]'s flashbulb!", "\red You disconnect the [src]'s flashbulb!") + if (!src.disable) + user.visible_message("\red [user] has connected the [src]'s flashbulb!", "\red You connect the [src]'s flashbulb!") + +//Let the AI trigger them directly. +/obj/machinery/flasher/attack_ai(mob/user) + if (anchored) + return 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(src.loc, 'sound/weapons/flash.ogg', 100, 1) + flick("[base_state]_flash", src) + src.last_flash = world.time + use_power(1000) + + for (var/mob/O in viewers(src, null)) + 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/obj/item/organ/internal/eyes/IO = H.organs_by_name[O_EYES] + if (IO.damage > IO.min_bruised_damage && prob(IO.damage + 50)) + H.flash_eyes() + IO.damage += rand(1, 5) + else + if(!O.blinded && istype(O,/mob/living)) + var/mob/living/L = O + L.flash_eyes() + + +/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) + 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, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + add_fingerprint(user) + src.anchored = !src.anchored + user.SetNextMove(CLICK_CD_INTERACT) + + if (!src.anchored) + user.show_message(text("\red [src] can now be moved.")) + src.overlays.Cut() + + else if (src.anchored) + user.show_message(text("\red [src] is now secured.")) + src.overlays += "[base_state]-s" + +/obj/machinery/flasher_button/attackby(obj/item/weapon/W, mob/user) + return attack_hand(user) + +/obj/machinery/flasher_button/attack_hand(mob/user) + if(..() || active) + return 1 + + use_power(5) + user.SetNextMove(CLICK_CD_INTERACT) + + active = 1 + icon_state = "launcheract" + + for(var/obj/machinery/flasher/M in flasher_list) + if(M.id == id) + spawn() + M.flash() + + sleep(50) + + icon_state = "launcherbtt" + active = 0 diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index eb72da66aacc..3b6e63ff508d 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -1,264 +1,264 @@ -/* 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" - - layer = TURF_LAYER+0.1 //Preventing mice and drones from sneaking under them. - plane = FLOOR_PLANE - - 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. - -/obj/machinery/hologram/holopad/atom_init() - . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/holopad(null) - component_parts += new /obj/item/weapon/stock_parts/capacitor(null) - RefreshParts() - -/obj/machinery/hologram/holopad/RefreshParts() - var/holograph_range = 4 - for(var/obj/item/weapon/stock_parts/capacitor/B in component_parts) - holograph_range += 1 * B.rating - holo_range = holograph_range - -/obj/machinery/hologram/holopad/attackby(obj/item/P, mob/user, params) - if(default_deconstruction_screwdriver(user, "holopad_open", "holopad0", P)) - return - - if(exchange_parts(user, P)) - return - - if(default_pry_open(P)) - return - - if(default_unfasten_wrench(user, P)) - return - - default_deconstruction_crowbar(P) - - -/obj/machinery/hologram/holopad/attack_hand(mob/user) //Carn: Hologram requests. - if(..()) - return 1 - if(!ishuman(user) && !IsAdminGhost(user)) - return 1 - user.SetNextMove(CLICK_CD_INTERACT) - 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 ai_list) - if(!AI.client || AI.stat == DEAD) - 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.setLoc(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. - - if(user.holohack) - change_holo_to_carp(user) - - src.visible_message("A holographic image of [hologram.name] flicks to life right before your eyes!") - else - to_chat(user, "\red ERROR: \black Image feed in progress.") - else - to_chat(user, "\red ERROR: \black 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_talk(mob/living/M, text, verb, datum/language/speaking) - if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something. - if(!master.say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad. - if(speaking) - text = speaking.scramble(text) - else - text = stars(text) - var/name_used = M.GetVoice() - //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only. - var/rendered - if(speaking) - rendered = "Holopad received, [name_used] [speaking.format_message(text, verb)]" - else - rendered = "Holopad received, [name_used] [verb], \"[text]\"" - master.show_message(rendered, 2) - return - -/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]"//If someone decides to right click. - hologram.desc = "Hologram of [A.name]" - hologram.set_light(2) //hologram lighting - set_light(2) //pad lighting - icon_state = "holopad1" - A.holo = src - master = A//AI is the master. - use_power = 2//Active power usage. - -/obj/machinery/hologram/holopad/proc/change_holo_to_carp(mob/living/silicon/ai/A) - hologram.icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) - hologram.name = "space carp" - hologram.desc = "Hologram of cute space carp... Wait, WHAT?" - -/obj/machinery/hologram/holopad/proc/clear_holo() -// hologram.set_light(0)//Clear lighting. //handled by the lighting controller when its ower is deleted - qdel(hologram)//Get rid of hologram. - hologram = null - if(master.holo == src) - master.holo = 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 in holo_area.master.related) - 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/meteorhit() - qdel(src) - return - -/obj/machinery/hologram/Destroy() - if(hologram) - src:clear_holo() - return ..() -/* -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" + + layer = TURF_LAYER+0.1 //Preventing mice and drones from sneaking under them. + plane = FLOOR_PLANE + + 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. + +/obj/machinery/hologram/holopad/atom_init() + . = ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/holopad(null) + component_parts += new /obj/item/weapon/stock_parts/capacitor(null) + RefreshParts() + +/obj/machinery/hologram/holopad/RefreshParts() + var/holograph_range = 4 + for(var/obj/item/weapon/stock_parts/capacitor/B in component_parts) + holograph_range += 1 * B.rating + holo_range = holograph_range + +/obj/machinery/hologram/holopad/attackby(obj/item/P, mob/user, params) + if(default_deconstruction_screwdriver(user, "holopad_open", "holopad0", P)) + return + + if(exchange_parts(user, P)) + return + + if(default_pry_open(P)) + return + + if(default_unfasten_wrench(user, P)) + return + + default_deconstruction_crowbar(P) + + +/obj/machinery/hologram/holopad/attack_hand(mob/user) //Carn: Hologram requests. + if(..()) + return 1 + if(!ishuman(user) && !IsAdminGhost(user)) + return 1 + user.SetNextMove(CLICK_CD_INTERACT) + 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 ai_list) + if(!AI.client || AI.stat == DEAD) + 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.setLoc(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. + + if(user.holohack) + change_holo_to_carp(user) + + src.visible_message("A holographic image of [hologram.name] flicks to life right before your eyes!") + else + to_chat(user, "\red ERROR: \black Image feed in progress.") + else + to_chat(user, "\red ERROR: \black 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_talk(mob/living/M, text, verb, datum/language/speaking) + if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something. + if(!master.say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad. + if(speaking) + text = speaking.scramble(text) + else + text = stars(text) + var/name_used = M.GetVoice() + //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only. + var/rendered + if(speaking) + rendered = "Holopad received, [name_used] [speaking.format_message(text, verb)]" + else + rendered = "Holopad received, [name_used] [verb], \"[text]\"" + master.show_message(rendered, 2) + return + +/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]"//If someone decides to right click. + hologram.desc = "Hologram of [A.name]" + hologram.set_light(2) //hologram lighting + set_light(2) //pad lighting + icon_state = "holopad1" + A.holo = src + master = A//AI is the master. + use_power = 2//Active power usage. + +/obj/machinery/hologram/holopad/proc/change_holo_to_carp(mob/living/silicon/ai/A) + hologram.icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) + hologram.name = "space carp" + hologram.desc = "Hologram of cute space carp... Wait, WHAT?" + +/obj/machinery/hologram/holopad/proc/clear_holo() +// hologram.set_light(0)//Clear lighting. //handled by the lighting controller when its ower is deleted + qdel(hologram)//Get rid of hologram. + hologram = null + if(master.holo == src) + master.holo = 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 in holo_area.master.related) + 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/meteorhit() + qdel(src) + return + +/obj/machinery/hologram/Destroy() + if(hologram) + src:clear_holo() + return ..() +/* +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 d17e67bbeff9..9e6008e6f340 100644 --- a/code/game/machinery/hydroponics.dm +++ b/code/game/machinery/hydroponics.dm @@ -1,1012 +1,1012 @@ -#define HYDRO_RATING_MULTIPLIER 0.35 - -/obj/machinery/hydroponics - name = "hydroponics tray" - icon = 'icons/obj/hydroponics/equipment.dmi' - icon_state = "hydrotray" - density = TRUE - anchored = 1 - interact_offline = TRUE - pixel_y = 8 - - var/waterlevel = 100 //The amount of water in the tray (max 100) - var/maxwater = 100 //The maximum amount of water in the tray - var/nutrilevel = 10 //The amount of nutrient in the tray (max 10) - var/maxnutri = 10 //The maximum nutrient of water in the tray - 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 = FALSE //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 = FALSE //Is it occupied? - var/harvest = FALSE //Ready to harvest? - var/obj/item/seeds/myseed = null //The currently planted seed - var/rating = 1 - var/unwrenchable = TRUE - -/obj/machinery/hydroponics/constructable - name = "hydroponics tray" - icon = 'icons/obj/hydroponics/equipment.dmi' - icon_state = "hydrotray3" - -/obj/machinery/hydroponics/constructable/atom_init() - . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/hydroponics(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/weapon/stock_parts/console_screen(null) - RefreshParts() - -/obj/machinery/hydroponics/constructable/RefreshParts() - var/tmp_capacity = 0 - for (var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) - tmp_capacity += M.rating - for (var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - rating = M.rating - maxwater = tmp_capacity * 50 // Up to 300 - maxnutri = tmp_capacity * 5 // Up to 30 - waterlevel = maxwater - nutrilevel = 3 - -/obj/machinery/hydroponics/Destroy() - if(myseed) - qdel(myseed) - myseed = null - return ..() - -/obj/machinery/hydroponics/constructable/attackby(obj/item/I, mob/user) - if(default_deconstruction_screwdriver(user, "hydrotray3", "hydrotray3", I)) - return - - if(exchange_parts(user, I)) - return - - if(default_pry_open(I)) - return - - if(default_unfasten_wrench(user, I)) - return - - if(istype(I, /obj/item/weapon/crowbar)) - if(anchored == 2) - to_chat(user, "Unscrew the hoses first!") - return - default_deconstruction_crowbar(I, 1) - ..() - -/obj/machinery/hydroponics/bullet_act(obj/item/projectile/P) //Works with the Somatoray to modify plant variables. - if(!planted) - ..() - return - if(istype(P, /obj/item/projectile/energy/floramut)) - mutate() - else if(istype(P, /obj/item/projectile/energy/florayield)) - if(myseed.yield == 0)//Oh god don't divide by zero you'll doom us all. - adjustSYield(1 * rating) - else if(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... - adjustSYield(1 * rating) - else - ..() - return - -/obj/machinery/hydroponics/CanPass(atom/movable/mover, turf/target, height = 0, air_group = 0) - if(air_group || (height == 0)) - return TRUE - - if(istype(mover) && mover.checkpass(PASSTABLE)) - return TRUE - else - return FALSE - -/obj/machinery/hydroponics/process() - - var/needs_update = FALSE // Checks if the icon needs updating so we don't redraw empty trays every time - - 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 - needs_update = TRUE - -//Nutrients////////////////////////////////////////////////////////////// - // Nutrients deplete slowly - if(prob(50)) - adjustNutri(-1 / rating * HYDRO_SPEED_MULTIPLIER) - - // Lack of nutrients hurts non-weeds - if(nutrilevel <= 0 && myseed.plant_type != 1) - adjustHealth(-rand(1,3) * HYDRO_SPEED_MULTIPLIER) - -//Water////////////////////////////////////////////////////////////////// - // Drink random amount of water - adjustWater(-rand(1,6) / rating * HYDRO_SPEED_MULTIPLIER) - - // If the plant is dry, it loses health pretty fast, unless mushroom - if(waterlevel <= 10 && myseed.plant_type != 2) - adjustHealth(-rand(0,1) / rating * HYDRO_SPEED_MULTIPLIER) - if(waterlevel <= 0) - adjustHealth(-rand(0,2) / rating * HYDRO_SPEED_MULTIPLIER) - - // Sufficient water level and nutrient level = plant healthy - else if(waterlevel > 10 && nutrilevel > 0) - adjustHealth(rand(1,2) / rating * HYDRO_SPEED_MULTIPLIER) - if(prob(5)) //5 percent chance the weed population will increase - adjustWeeds(1 / rating * 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) - adjustHealth(-1 / rating * HYDRO_SPEED_MULTIPLIER) - adjustToxic(-rand(1,10) / rating * HYDRO_SPEED_MULTIPLIER) - else if(toxic >= 80) // I don't think it ever gets here tbh unless above is commented out - adjustHealth(-3) - adjustToxic(-rand(1,10) / rating * HYDRO_SPEED_MULTIPLIER) - -//Pests & Weeds////////////////////////////////////////////////////////// - - else if(pestlevel >= 5) - adjustHealth(-1 / rating * HYDRO_SPEED_MULTIPLIER) - - // If it's a weed, it doesn't stunt the growth - if(weedlevel >= 5 && myseed.plant_type != 1 ) - adjustHealth(-1 / rating * HYDRO_SPEED_MULTIPLIER) - - -//Health & Age/////////////////////////////////////////////////////////// - - // Plant dies if health <= 0 - if(health <= 0) - plantdies() - adjustWeeds(1 / rating * HYDRO_SPEED_MULTIPLIER) // Weeds flourish - - // If the plant is too old, lose health fast - if(age > myseed.lifespan) - adjustHealth(-rand(1,5) / rating * HYDRO_SPEED_MULTIPLIER) - - // Harvest code - if(age > myseed.production && (age - lastproduce) > myseed.production && (!harvest && !dead)) - nutrimentMutation() - if(myseed && myseed.yield != -1) // Unharvestable shouldn't be harvested - harvest = TRUE - else - lastproduce = age - if(prob(5)) // On each tick, there's a 5 percent chance the pest population will increase - adjustPests(1 / rating * HYDRO_SPEED_MULTIPLIER) - else - if(waterlevel > 10 && nutrilevel > 0 && prob(10)) // If there's no plant, the percentage chance is 10% - adjustWeeds(1 / rating * HYDRO_SPEED_MULTIPLIER) - - // 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 - needs_update = TRUE - if (needs_update) - update_icon() - return - -/obj/machinery/hydroponics/proc/nutrimentMutation() - if (mutmod == 0) - return - if (mutmod == 1) - if(prob(80)) //80% - mutate() - else if(prob(75)) //15% - hardmutate() - return - if (mutmod == 2) - if(prob(50)) //50% - mutate() - else if(prob(50)) //25% - hardmutate() - else if(prob(50)) //12.5% - mutatespecie() - return - return - -/obj/machinery/hydroponics/update_icon() - //Refreshes the icon and sets the luminosity - overlays.Cut() - - UpdateDescription() - - if(planted) - var/image/I - if(dead) - I = image(icon = myseed.hydroponictray_icon_path, icon_state = "[myseed.species]-dead") - else if(harvest) - if(myseed.plant_type == 2) // Shrooms don't have a -harvest graphic - I = image(icon = myseed.hydroponictray_icon_path, icon_state = "[myseed.species]-grow[myseed.growthstages]") - else - I = image(icon = myseed.hydroponictray_icon_path, 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 - I = image(icon = myseed.hydroponictray_icon_path, 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 - I = image(icon = myseed.hydroponictray_icon_path, icon_state = "[myseed.species]-grow[myseed.growthstages]") // Same - overlays += I - - if(waterlevel <= 10) - overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_lowwater3") - if(nutrilevel <= 2) - overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_lownutri3") - if(health <= (myseed.endurance / 2)) - overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_lowhealth3") - if(weedlevel >= 5 || pestlevel >= 5 || toxic >= 40) - overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_alert3") - if(harvest) - overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_harvest3") - - if(istype(myseed,/obj/item/seeds/glowshroom)) - set_light(round(myseed.potency/10)) - else - set_light(0) - - return - -/obj/machinery/hydroponics/proc/UpdateDescription() - desc = null - if (planted) - desc = "[src] has [myseed.plantname] planted." - if (dead) - desc += " It's dead." - else if (harvest) - desc += " It's ready to harvest." - -/obj/machinery/hydroponics/proc/weedinvasion() // If a weed growth is sufficient, this happens. - dead = FALSE - var/oldPlantName - if(myseed) // In case there's nothing in the tray beforehand - oldPlantName = myseed.plantname - qdel(myseed) - else - oldPlantName = "Empty tray" - 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) - myseed = new /obj/item/seeds/towermycelium - if(4 to 5) - myseed = new /obj/item/seeds/plumpmycelium - else - myseed = new /obj/item/seeds/weeds - planted = TRUE - age = 0 - health = myseed.endurance - lastcycle = world.time - harvest = FALSE - weedlevel = 0 // Reset - pestlevel = 0 // Reset - update_icon() - visible_message("[oldPlantName] overtaken by [myseed.plantname].") - return - - -/obj/machinery/hydroponics/proc/mutate(lifemut = 2, endmut = 5, productmut = 1, yieldmut = 2, potmut = 25) // Mutates the current seed - if(!planted) - return - adjustSLife(rand(-lifemut,lifemut)) - adjustSEnd(rand(-endmut,endmut)) - adjustSProduct(rand(-productmut,productmut)) - adjustSYield(rand(-yieldmut,yieldmut)) - adjustSPot(rand(-potmut,potmut)) - return - - -obj/machinery/hydroponics/proc/hardmutate() // Strongly mutates the current seed. - mutate(4, 10, 2, 4, 50) - -obj/machinery/hydroponics/proc/mutatespecie() // Mutagent produced a new plant! - if(!planted || dead) - return - - var/oldPlantName = myseed.plantname - if(myseed.mutatelist.len > 0) - var/mutantseed = pick(myseed.mutatelist) - qdel(myseed) - myseed = new mutantseed - else - return - - dead = FALSE - hardmutate() - planted = TRUE - age = 0 - health = myseed.endurance - lastcycle = world.time - harvest = FALSE - weedlevel = 0 // Reset - - sleep(5) // Wait a while - update_icon() - visible_message("[oldPlantName] suddenly mutated into [myseed.plantname]!") - - -/obj/machinery/hydroponics/proc/mutateweed() // If the weeds gets the mutagent instead. Mind you, this pretty much destroys the old plant - if (weedlevel > 5) - if(myseed) - 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 = FALSE - hardmutate() - planted = TRUE - age = 0 - health = myseed.endurance - lastcycle = world.time - harvest = FALSE - weedlevel = 0 // Reset - - sleep(5) // Wait a while - update_icon() - 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() - health = 0 - harvest = FALSE - pestlevel = 0 // Pests die - if(!dead) - update_icon() - dead = TRUE - - -/obj/machinery/hydroponics/proc/mutatepest() - if(pestlevel > 5) - visible_message("The pests seem to behave oddly...") - for(var/i in 1 to 3) - new /obj/effect/spider/spiderling(loc) - else - to_chat(usr, "The pests seem to behave oddly, but quickly settle down...") - - -/obj/machinery/hydroponics/attackby(obj/item/O, mob/user) - if(istype(O, /obj/item/nutrient)) - var/obj/item/nutrient/myNut = O - user.remove_from_mob(O) - nutrilevel = 10 - yieldmod = myNut.yieldmod - mutmod = myNut.mutmod - to_chat(user, "You replace the nutrient solution in [src].") - qdel(O) - update_icon() - - else if(istype(O, /obj/item/weapon/reagent_containers) ) // Syringe stuff (and other reagent containers now too) - var/obj/item/weapon/reagent_containers/reagent_source = O - var/datum/reagents/S = new /datum/reagents() - - S.my_atom = src - - var/obj/target = myseed ? myseed.plantname : src - - if(istype(reagent_source, /obj/item/weapon/reagent_containers/syringe)) - var/obj/item/weapon/reagent_containers/syringe/syr = reagent_source - if(syr.mode != 1) - to_chat(user, "You can't get any extract out of this plant.") - return - if(!reagent_source.reagents.total_volume) - to_chat(user, "[reagent_source] is empty.") - return TRUE - - if(istype(reagent_source, /obj/item/weapon/reagent_containers/food/snacks) || istype(reagent_source, /obj/item/weapon/reagent_containers/pill)) - visible_message("[user] composts [reagent_source], spreading it through [target].") - reagent_source.reagents.trans_to(S,reagent_source.reagents.total_volume) - qdel(reagent_source) - else - reagent_source.reagents.trans_to(S,reagent_source.amount_per_transfer_from_this) - if(istype(reagent_source, /obj/item/weapon/reagent_containers/syringe/)) - var/obj/item/weapon/reagent_containers/syringe/syr = reagent_source - visible_message("[user] injects [target] with [syr].") - if(syr.reagents.total_volume <= 0) - syr.mode = 0 - syr.update_icon() - else if(istype(reagent_source, /obj/item/weapon/reagent_containers/spray/)) - visible_message("[user] sprays [target] with [reagent_source].") - playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - else if(reagent_source.amount_per_transfer_from_this) // Droppers, cans, beakers, what have you. - visible_message("[user] uses [reagent_source] on [target].") - - // Beakers, bottles, buckets, etc. Can't use is_open_container though. - if(istype(reagent_source, /obj/item/weapon/reagent_containers/glass/)) - playsound(loc, 'sound/effects/slosh.ogg', 25, 1) - - // There needs to be a good amount of mutagen to actually work - if(S.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() - if(21 to 41) - to_chat(user, "The plants don't seem to react...") - if(11 to 20) - mutateweed() - if(1 to 10) - mutatepest() - else - to_chat(user, "Nothing happens...") - - // Antitoxin binds shit pretty well. So the tox goes significantly down - if(S.has_reagent("anti_toxin", 1)) - adjustToxic(-round(S.get_reagent_amount("anti_toxin")*2)) - - // NIGGA, YOU JUST WENT ON FULL RETARD. - if(S.has_reagent("toxin", 1)) - adjustToxic(round(S.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.has_reagent("milk", 1)) - adjustNutri(round(S.get_reagent_amount("milk")*0.1)) - adjustWater(round(S.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.has_reagent("beer", 1)) - adjustHealth(-round(S.get_reagent_amount("beer")*0.05)) - adjustNutri(round(S.get_reagent_amount("beer")*0.25)) - adjustWater(round(S.get_reagent_amount("beer")*0.7)) - - // You're an idiot for thinking that one of the most corrosive and deadly gasses would be beneficial - if(S.has_reagent("fluorine", 1)) - adjustHealth(-round(S.get_reagent_amount("fluorine")*2)) - adjustToxic(round(S.get_reagent_amount("flourine")*2.5)) - adjustWater(-round(S.get_reagent_amount("flourine")*0.5)) - adjustWeeds(-rand(1,4)) - - // You're an idiot for thinking that one of the most corrosive and deadly gasses would be beneficial - if(S.has_reagent("chlorine", 1)) - adjustHealth(-round(S.get_reagent_amount("chlorine")*1)) - adjustToxic(round(S.get_reagent_amount("chlorine")*1.5)) - adjustWater(-round(S.get_reagent_amount("chlorine")*0.5)) - adjustWeeds(-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.has_reagent("phosphorus", 1)) - adjustHealth(-round(S.get_reagent_amount("phosphorus")*0.75)) - adjustNutri(round(S.get_reagent_amount("phosphorus")*0.1)) - adjustWater(-round(S.get_reagent_amount("phosphorus")*0.5)) - adjustWeeds(-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.has_reagent("sugar", 1)) - adjustWeeds(rand(1,2)) - adjustPests(rand(1,2)) - adjustNutri(round(S.get_reagent_amount("sugar")*0.1)) - - // It is water! - if(S.has_reagent("water", 1)) - adjustWater(round(S.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.has_reagent("holywater", 1)) - adjustWater(round(S.get_reagent_amount("holywater")*1)) - adjustHealth(round(S.get_reagent_amount("holywater")*0.1)) - - // Unholy water, Mostly the same, but it also damages the plant. - if(S.has_reagent("unholywater", 1)) - adjustWater(round(S.get_reagent_amount("unholywater"))) - adjustToxic(round(S.get_reagent_amount("unholywater")*0.1)) - adjustPests(rand(1,4)) - - // 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.has_reagent("sodawater", 1)) - adjustWater(round(S.get_reagent_amount("sodawater")*1)) - adjustHealth(round(S.get_reagent_amount("sodawater")*0.1)) - adjustNutri(round(S.get_reagent_amount("sodawater")*0.1)) - - // Man, you guys are retards - if(S.has_reagent("sacid", 1)) - adjustHealth(-round(S.get_reagent_amount("sacid")*1)) - adjustToxic(round(S.get_reagent_amount("sacid")*1.5)) - adjustWeeds(-rand(1,2)) - - // SERIOUSLY - if(S.has_reagent("pacid", 1)) - adjustHealth(-round(S.get_reagent_amount("pacid")*2)) - adjustToxic(round(S.get_reagent_amount("pacid")*3)) - adjustWeeds(-rand(1,4)) - - // Plant-B-Gone is just as bad - if(S.has_reagent("plantbgone", 1)) - adjustHealth(-round(S.get_reagent_amount("plantbgone")*2)) - adjustToxic(-round(S.get_reagent_amount("plantbgone")*3)) - adjustWeeds(-rand(4,8)) - - // Healing - if(S.has_reagent("cryoxadone", 1)) - adjustHealth(round(S.get_reagent_amount("cryoxadone")*3)) - adjustToxic(-round(S.get_reagent_amount("cryoxadone")*3)) - - // Ammonia is bad ass. - if(S.has_reagent("ammonia", 1)) - adjustHealth(round(S.get_reagent_amount("ammonia")*0.5)) - adjustNutri(round(S.get_reagent_amount("ammonia")*1)) - - // This is more bad ass, and pests get hurt by the corrosive nature of it, not the plant. - if(S.has_reagent("diethylamine", 1)) - adjustHealth(round(S.get_reagent_amount("diethylamine")*1)) - adjustNutri(round(S.get_reagent_amount("diethylamine")*2)) - adjustPests(-rand(1,2)) - - // Compost, effectively - if(S.has_reagent("nutriment", 1)) - adjustHealth(round(S.get_reagent_amount("nutriment")*0.5)) - adjustNutri(round(S.get_reagent_amount("nutriment")*1)) - - // Poor man's mutagen. - if(S.has_reagent("radium", 1)) - adjustHealth(-round(S.get_reagent_amount("radium")*1.5)) - adjustToxic(round(S.get_reagent_amount("radium")*2)) - if(S.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() - if(21 to 41) - to_chat(user, "The plants don't seem to react...") - if(11 to 20) - mutateweed() - if(1 to 10) - mutatepest() - else - to_chat(user, "Nothing happens...") - - // The best stuff there is. For testing/debugging. - if(S.has_reagent("adminordrazine", 1)) - adjustWater(round(S.get_reagent_amount("adminordrazine")*1)) - adjustHealth(round(S.get_reagent_amount("adminordrazine")*1)) - adjustNutri(round(S.get_reagent_amount("adminordrazine")*1)) - adjustPests(-rand(1,5)) - adjustWeeds(-rand(1,5)) - if(S.has_reagent("adminordrazine", 5)) - switch(rand(100)) - if(66 to 100) - mutatespecie() - if(33 to 65) - mutateweed() - if(1 to 32) - mutatepest() - else - to_chat(user, "Nothing happens...") - - S.clear_reagents() - qdel(S) - update_icon() - return TRUE - - else if ( istype(O, /obj/item/seeds/) ) - if(!planted) - user.remove_from_mob(O) - to_chat(user, "You plant the [O.name]") - dead = FALSE - myseed = O - planted = TRUE - 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) - update_icon() - - else - to_chat(user, "[src] already has seeds in it!") - - else if (istype(O, /obj/item/device/plant_analyzer)) - if(planted && myseed) - to_chat(user, "*** [myseed.plantname] ***")//Carn: now reports the plants growing, not the seeds. - to_chat(user, "-Plant Age: \blue [age]") - to_chat(user, "-Plant Endurance: \blue [myseed.endurance]") - to_chat(user, "-Plant Lifespan: \blue [myseed.lifespan]") - if(myseed.yield != -1) - to_chat(user, "-Plant Yield: \blue [myseed.yield]") - to_chat(user, "-Plant Production: \blue [myseed.production]") - if(myseed.potency != -1) - to_chat(user, "-Plant Potency: \blue [myseed.potency]") - to_chat(user, "-Weed level: \blue [weedlevel]/10") - to_chat(user, "-Pest level: \blue [pestlevel]/10") - to_chat(user, "-Toxicity level: \blue [toxic]/100") - to_chat(user, "-Water level: [waterlevel]/[maxwater]") - to_chat(user, "-Nutrition level: [nutrilevel]/[maxnutri]") - to_chat(user, "") - else - to_chat(user, "No plant found.") - to_chat(user, "-Weed level: \blue [weedlevel]/10") - to_chat(user, "-Pest level: \blue [pestlevel]/10") - to_chat(user, "-Toxicity level: \blue [toxic]/100") - to_chat(user, "-Water level: [waterlevel]/[maxwater]") - to_chat(user, "-Nutrition level: [nutrilevel]/[maxnutri]") - to_chat(user, "") - - else if (istype(O, /obj/item/weapon/minihoe)) - if(weedlevel > 0) - user.visible_message("[user] uproots the weeds.", "You remove the weeds from [src].") - weedlevel = 0 - update_icon() - 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.remove_from_mob(O) - adjustToxic(myWKiller.toxicity) - adjustWeeds(-myWKiller.WeedKillStr) - to_chat(user, "You apply the weedkiller solution into [src].") - playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - qdel(O) - update_icon() - - 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) - score["stuffharvested"]++ - - else if(istype(O, /obj/item/weapon/wrench) && unwrenchable) - if(anchored == 2) - to_chat(user, "Unscrew the hoses first!") - return - - if(!anchored && !isinspace()) - playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) - anchored = 1 - to_chat(user, "You wrench [src] in place.") - else if(anchored) - playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) - anchored = 0 - to_chat(user, "You unwrench [src].") - - else if(istype(O, /obj/item/weapon/wirecutters) && unwrenchable) - - if(anchored) - if(anchored == 2) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) - anchored = 1 - to_chat(user, "You snip \the [src]'s hoses.") - - else if(anchored == 1) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) - anchored = 2 - to_chat(user, "You reconnect \the [src]'s hoses.") - - update_icon() - - else if ( istype(O, /obj/item/weapon/pestspray) ) - var/obj/item/pestkiller/myPKiller = O - user.remove_from_mob(O) - adjustToxic(myPKiller.toxicity) - adjustPests(-myPKiller.PestKillStr) - to_chat(user, "You apply the pestkiller solution into [src].") - playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - qdel(O) - update_icon() - else if(istype(O, /obj/item/apiary)) - if(planted) - to_chat(user, "\red The hydroponics tray is already occupied!") - else - user.remove_from_mob() - qdel(O) - - var/obj/machinery/apiary/A = new(src.loc) - A.icon = src.icon - A.icon_state = src.icon_state - A.hydrotray_type = src.type - qdel(src) - return - -/obj/machinery/hydroponics/attack_tk(mob/user) - if(harvest) - myseed.harvest(src) - else if(dead) - planted = FALSE - dead = FALSE - to_chat(user, text("You remove the dead plant from the [src].")) - qdel(myseed) - update_icon() - -/obj/machinery/hydroponics/attack_hand(mob/user) - . = ..() - if(.) - return - if(issilicon(user))//AI doesn't know what is planted - return TRUE - if(harvest) - if(!in_range(src, user)) - return TRUE - myseed.harvest() - else if(dead) - planted = FALSE - dead = FALSE - to_chat(user, "You remove the dead plant from [src].") - qdel(myseed) - update_icon() - else - if(planted && !dead) - to_chat(user, "[src] has [myseed.plantname] planted.") - if(health <= (myseed.endurance / 2)) - to_chat(user, "The plant looks unhealthy.") - else - to_chat(user, "[src] is empty.") - to_chat(user, "Water: [waterlevel]/[maxwater]") - to_chat(user, "Nutrient: [nutrilevel]/[maxnutri]") - if(weedlevel >= 5) // Visual aid for those blind - to_chat(user, "[src] is filled with weeds!") - if(pestlevel >= 5) // Visual aid for those blind - to_chat(user, "[src] is filled with tiny worms!") - to_chat(user, "")// Empty line for readability. - -/obj/item/seeds/proc/getYield() - var/obj/machinery/hydroponics/parent = loc - if (parent.yieldmod == 0) - return min(yield, 1)//1 if above zero, 0 otherwise - return (yield * parent.yieldmod) - -/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 - var/list/result = list() - var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc //needed for TK - while(t_amount < getYield()) - var/obj/item/weapon/reagent_containers/food/snacks/grown/t_prod = new produce(output_loc, potency) - result.Add(t_prod) // 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++ - if(getYield() >= 1) - score["stuffharvested"]++ - - parent.update_tray() - return result - -/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) - new/obj/item/stack/tile/grass(user.loc, t_yield) - - parent.update_tray() - -/obj/item/seeds/gibtomato/harvest(mob/user = usr) - var/produce = text2path(productname) - var/obj/machinery/hydroponics/parent = loc - 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 - var/t_amount = 0 - - while ( t_amount < (yield * parent.yieldmod )) - var/obj/item/weapon/grown/t_prod = new produce(user.loc, potency) - 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) - t_prod.plant_type = plant_type - t_amount++ - - parent.update_tray() - -/obj/item/seeds/deathnettleseed/harvest(mob/user = usr) //COPYPOASTAAAA - var/produce = text2path(productname) - var/obj/machinery/hydroponics/parent = loc - var/t_amount = 0 - - while (t_amount < (yield * parent.yieldmod)) - var/obj/item/weapon/grown/t_prod = new produce(user.loc, potency) - 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) - 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 - 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 = FALSE - lastproduce = age - if(istype(myseed,/obj/item/seeds/replicapod/)) - to_chat(user, "You harvest from the [myseed.plantname].") - else if(myseed.getYield() <= 0) - to_chat(user, "You fail to harvest anything useful!") - else - to_chat(user, "You harvest [myseed.getYield()] items from the [myseed.plantname].") - if(myseed.oneharvest) - qdel(myseed) - planted = FALSE - dead = FALSE - update_icon() - -/// Tray Setters - The following procs adjust the tray or plants variables, and make sure that the stat doesn't go out of bounds./// -/obj/machinery/hydroponics/proc/adjustNutri(adjustamt) - nutrilevel += adjustamt - nutrilevel = max(nutrilevel, 0) - nutrilevel = min(nutrilevel, maxnutri) - -/obj/machinery/hydroponics/proc/adjustWater(adjustamt) - waterlevel += adjustamt - waterlevel = max(waterlevel, 0) - waterlevel = min(waterlevel, maxwater) - if(adjustamt > 0) - adjustToxic(-round(adjustamt / 4))//Toxicity dilutation code. The more water you put in, the lesser the toxin concentration. - -/obj/machinery/hydroponics/proc/adjustHealth(adjustamt) - if(planted && !dead) - health += adjustamt - health = max(health, 0) - health = min(health, myseed.endurance) - -/obj/machinery/hydroponics/proc/adjustToxic(adjustamt) - toxic += adjustamt - toxic = max(toxic, 0) - toxic = min(toxic, 100) - -/obj/machinery/hydroponics/proc/adjustPests(adjustamt) - pestlevel += adjustamt - pestlevel = max(pestlevel, 0) - pestlevel = min(pestlevel, 10) - -/obj/machinery/hydroponics/proc/adjustWeeds(adjustamt) - weedlevel += adjustamt - weedlevel = max(weedlevel, 0) - pestlevel = min(pestlevel, 10) - -/// Seed Setters /// -/obj/machinery/hydroponics/proc/adjustSYield(adjustamt)//0,10 - if(myseed.yield != -1) // Unharvestable shouldn't suddenly turn harvestable - myseed.yield += adjustamt - myseed.yield = max(myseed.yield, 0) - myseed.yield = min(myseed.yield, 10) - if(myseed.yield <= 0 && myseed.plant_type == 2) - myseed.yield = 1 // Mushrooms always have a minimum yield of 1. - -/obj/machinery/hydroponics/proc/adjustSLife(adjustamt)//10,100 - myseed.lifespan += adjustamt - myseed.lifespan = max(myseed.lifespan, 10) - myseed.lifespan = min(myseed.lifespan, 100) - -/obj/machinery/hydroponics/proc/adjustSEnd(adjustamt)//10,100 - myseed.endurance += adjustamt - myseed.endurance = max(myseed.endurance, 10) - myseed.endurance = min(myseed.endurance, 100) - -/obj/machinery/hydroponics/proc/adjustSProduct(adjustamt)//2,10 - myseed.production += adjustamt - myseed.production = max(myseed.endurance, 2) - myseed.production = min(myseed.endurance, 10) - -/obj/machinery/hydroponics/proc/adjustSPot(adjustamt)//0,100 - if(myseed.potency != -1) //Not all plants have a potency - myseed.potency += adjustamt - myseed.potency = max(myseed.potency, 0) - myseed.potency = min(myseed.potency, 100) - -/////////////////////////////////////////////////////////////////////////////// -/obj/machinery/hydroponics/soil - name = "soil" - icon = 'icons/obj/hydroponics/equipment.dmi' - icon_state = "soil" - density = FALSE - use_power = FALSE - unwrenchable = FALSE - -/obj/machinery/hydroponics/soil/update_icon()//as a regular tray but without overlays under it (awter level, nutri, weeds, etc) - overlays.Cut() - - UpdateDescription() - - if(planted) - if(dead) - overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-dead") - else if(harvest) - if(myseed.plant_type == 2) // Shrooms don't have a -harvest graphic - overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-grow[myseed.growthstages]") - else - overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-harvest") - else if(age < myseed.maturation) - var/t_growthstate = ((age / myseed.maturation) * myseed.growthstages ) - overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-grow[round(t_growthstate)]") - lastproduce = age - else - overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-grow[myseed.growthstages]") - - if(!luminosity) - if(istype(myseed,/obj/item/seeds/glowshroom)) - set_light(round(myseed.potency/10)) - else - set_light(0) - return - -/obj/machinery/hydroponics/soil/attackby(obj/item/O, mob/user) - ..() - if(istype(O, /obj/item/weapon/shovel)) - to_chat(user, "You clear up [src]!") - qdel(src) - -#undef HYDRO_RATING_MULTIPLIER +#define HYDRO_RATING_MULTIPLIER 0.35 + +/obj/machinery/hydroponics + name = "hydroponics tray" + icon = 'icons/obj/hydroponics/equipment.dmi' + icon_state = "hydrotray" + density = TRUE + anchored = 1 + interact_offline = TRUE + pixel_y = 8 + + var/waterlevel = 100 //The amount of water in the tray (max 100) + var/maxwater = 100 //The maximum amount of water in the tray + var/nutrilevel = 10 //The amount of nutrient in the tray (max 10) + var/maxnutri = 10 //The maximum nutrient of water in the tray + 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 = FALSE //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 = FALSE //Is it occupied? + var/harvest = FALSE //Ready to harvest? + var/obj/item/seeds/myseed = null //The currently planted seed + var/rating = 1 + var/unwrenchable = TRUE + +/obj/machinery/hydroponics/constructable + name = "hydroponics tray" + icon = 'icons/obj/hydroponics/equipment.dmi' + icon_state = "hydrotray3" + +/obj/machinery/hydroponics/constructable/atom_init() + . = ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/hydroponics(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + RefreshParts() + +/obj/machinery/hydroponics/constructable/RefreshParts() + var/tmp_capacity = 0 + for (var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) + tmp_capacity += M.rating + for (var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + rating = M.rating + maxwater = tmp_capacity * 50 // Up to 300 + maxnutri = tmp_capacity * 5 // Up to 30 + waterlevel = maxwater + nutrilevel = 3 + +/obj/machinery/hydroponics/Destroy() + if(myseed) + qdel(myseed) + myseed = null + return ..() + +/obj/machinery/hydroponics/constructable/attackby(obj/item/I, mob/user) + if(default_deconstruction_screwdriver(user, "hydrotray3", "hydrotray3", I)) + return + + if(exchange_parts(user, I)) + return + + if(default_pry_open(I)) + return + + if(default_unfasten_wrench(user, I)) + return + + if(istype(I, /obj/item/weapon/crowbar)) + if(anchored == 2) + to_chat(user, "Unscrew the hoses first!") + return + default_deconstruction_crowbar(I, 1) + ..() + +/obj/machinery/hydroponics/bullet_act(obj/item/projectile/P) //Works with the Somatoray to modify plant variables. + if(!planted) + ..() + return + if(istype(P, /obj/item/projectile/energy/floramut)) + mutate() + else if(istype(P, /obj/item/projectile/energy/florayield)) + if(myseed.yield == 0)//Oh god don't divide by zero you'll doom us all. + adjustSYield(1 * rating) + else if(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... + adjustSYield(1 * rating) + else + ..() + return + +/obj/machinery/hydroponics/CanPass(atom/movable/mover, turf/target, height = 0, air_group = 0) + if(air_group || (height == 0)) + return TRUE + + if(istype(mover) && mover.checkpass(PASSTABLE)) + return TRUE + else + return FALSE + +/obj/machinery/hydroponics/process() + + var/needs_update = FALSE // Checks if the icon needs updating so we don't redraw empty trays every time + + 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 + needs_update = TRUE + +//Nutrients////////////////////////////////////////////////////////////// + // Nutrients deplete slowly + if(prob(50)) + adjustNutri(-1 / rating * HYDRO_SPEED_MULTIPLIER) + + // Lack of nutrients hurts non-weeds + if(nutrilevel <= 0 && myseed.plant_type != 1) + adjustHealth(-rand(1,3) * HYDRO_SPEED_MULTIPLIER) + +//Water////////////////////////////////////////////////////////////////// + // Drink random amount of water + adjustWater(-rand(1,6) / rating * HYDRO_SPEED_MULTIPLIER) + + // If the plant is dry, it loses health pretty fast, unless mushroom + if(waterlevel <= 10 && myseed.plant_type != 2) + adjustHealth(-rand(0,1) / rating * HYDRO_SPEED_MULTIPLIER) + if(waterlevel <= 0) + adjustHealth(-rand(0,2) / rating * HYDRO_SPEED_MULTIPLIER) + + // Sufficient water level and nutrient level = plant healthy + else if(waterlevel > 10 && nutrilevel > 0) + adjustHealth(rand(1,2) / rating * HYDRO_SPEED_MULTIPLIER) + if(prob(5)) //5 percent chance the weed population will increase + adjustWeeds(1 / rating * 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) + adjustHealth(-1 / rating * HYDRO_SPEED_MULTIPLIER) + adjustToxic(-rand(1,10) / rating * HYDRO_SPEED_MULTIPLIER) + else if(toxic >= 80) // I don't think it ever gets here tbh unless above is commented out + adjustHealth(-3) + adjustToxic(-rand(1,10) / rating * HYDRO_SPEED_MULTIPLIER) + +//Pests & Weeds////////////////////////////////////////////////////////// + + else if(pestlevel >= 5) + adjustHealth(-1 / rating * HYDRO_SPEED_MULTIPLIER) + + // If it's a weed, it doesn't stunt the growth + if(weedlevel >= 5 && myseed.plant_type != 1 ) + adjustHealth(-1 / rating * HYDRO_SPEED_MULTIPLIER) + + +//Health & Age/////////////////////////////////////////////////////////// + + // Plant dies if health <= 0 + if(health <= 0) + plantdies() + adjustWeeds(1 / rating * HYDRO_SPEED_MULTIPLIER) // Weeds flourish + + // If the plant is too old, lose health fast + if(age > myseed.lifespan) + adjustHealth(-rand(1,5) / rating * HYDRO_SPEED_MULTIPLIER) + + // Harvest code + if(age > myseed.production && (age - lastproduce) > myseed.production && (!harvest && !dead)) + nutrimentMutation() + if(myseed && myseed.yield != -1) // Unharvestable shouldn't be harvested + harvest = TRUE + else + lastproduce = age + if(prob(5)) // On each tick, there's a 5 percent chance the pest population will increase + adjustPests(1 / rating * HYDRO_SPEED_MULTIPLIER) + else + if(waterlevel > 10 && nutrilevel > 0 && prob(10)) // If there's no plant, the percentage chance is 10% + adjustWeeds(1 / rating * HYDRO_SPEED_MULTIPLIER) + + // 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 + needs_update = TRUE + if (needs_update) + update_icon() + return + +/obj/machinery/hydroponics/proc/nutrimentMutation() + if (mutmod == 0) + return + if (mutmod == 1) + if(prob(80)) //80% + mutate() + else if(prob(75)) //15% + hardmutate() + return + if (mutmod == 2) + if(prob(50)) //50% + mutate() + else if(prob(50)) //25% + hardmutate() + else if(prob(50)) //12.5% + mutatespecie() + return + return + +/obj/machinery/hydroponics/update_icon() + //Refreshes the icon and sets the luminosity + overlays.Cut() + + UpdateDescription() + + if(planted) + var/image/I + if(dead) + I = image(icon = myseed.hydroponictray_icon_path, icon_state = "[myseed.species]-dead") + else if(harvest) + if(myseed.plant_type == 2) // Shrooms don't have a -harvest graphic + I = image(icon = myseed.hydroponictray_icon_path, icon_state = "[myseed.species]-grow[myseed.growthstages]") + else + I = image(icon = myseed.hydroponictray_icon_path, 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 + I = image(icon = myseed.hydroponictray_icon_path, 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 + I = image(icon = myseed.hydroponictray_icon_path, icon_state = "[myseed.species]-grow[myseed.growthstages]") // Same + overlays += I + + if(waterlevel <= 10) + overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_lowwater3") + if(nutrilevel <= 2) + overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_lownutri3") + if(health <= (myseed.endurance / 2)) + overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_lowhealth3") + if(weedlevel >= 5 || pestlevel >= 5 || toxic >= 40) + overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_alert3") + if(harvest) + overlays += image('icons/obj/hydroponics/equipment.dmi', icon_state = "over_harvest3") + + if(istype(myseed,/obj/item/seeds/glowshroom)) + set_light(round(myseed.potency/10)) + else + set_light(0) + + return + +/obj/machinery/hydroponics/proc/UpdateDescription() + desc = null + if (planted) + desc = "[src] has [myseed.plantname] planted." + if (dead) + desc += " It's dead." + else if (harvest) + desc += " It's ready to harvest." + +/obj/machinery/hydroponics/proc/weedinvasion() // If a weed growth is sufficient, this happens. + dead = FALSE + var/oldPlantName + if(myseed) // In case there's nothing in the tray beforehand + oldPlantName = myseed.plantname + qdel(myseed) + else + oldPlantName = "Empty tray" + 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) + myseed = new /obj/item/seeds/towermycelium + if(4 to 5) + myseed = new /obj/item/seeds/plumpmycelium + else + myseed = new /obj/item/seeds/weeds + planted = TRUE + age = 0 + health = myseed.endurance + lastcycle = world.time + harvest = FALSE + weedlevel = 0 // Reset + pestlevel = 0 // Reset + update_icon() + visible_message("[oldPlantName] overtaken by [myseed.plantname].") + return + + +/obj/machinery/hydroponics/proc/mutate(lifemut = 2, endmut = 5, productmut = 1, yieldmut = 2, potmut = 25) // Mutates the current seed + if(!planted) + return + adjustSLife(rand(-lifemut,lifemut)) + adjustSEnd(rand(-endmut,endmut)) + adjustSProduct(rand(-productmut,productmut)) + adjustSYield(rand(-yieldmut,yieldmut)) + adjustSPot(rand(-potmut,potmut)) + return + + +obj/machinery/hydroponics/proc/hardmutate() // Strongly mutates the current seed. + mutate(4, 10, 2, 4, 50) + +obj/machinery/hydroponics/proc/mutatespecie() // Mutagent produced a new plant! + if(!planted || dead) + return + + var/oldPlantName = myseed.plantname + if(myseed.mutatelist.len > 0) + var/mutantseed = pick(myseed.mutatelist) + qdel(myseed) + myseed = new mutantseed + else + return + + dead = FALSE + hardmutate() + planted = TRUE + age = 0 + health = myseed.endurance + lastcycle = world.time + harvest = FALSE + weedlevel = 0 // Reset + + sleep(5) // Wait a while + update_icon() + visible_message("[oldPlantName] suddenly mutated into [myseed.plantname]!") + + +/obj/machinery/hydroponics/proc/mutateweed() // If the weeds gets the mutagent instead. Mind you, this pretty much destroys the old plant + if (weedlevel > 5) + if(myseed) + 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 = FALSE + hardmutate() + planted = TRUE + age = 0 + health = myseed.endurance + lastcycle = world.time + harvest = FALSE + weedlevel = 0 // Reset + + sleep(5) // Wait a while + update_icon() + 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() + health = 0 + harvest = FALSE + pestlevel = 0 // Pests die + if(!dead) + update_icon() + dead = TRUE + + +/obj/machinery/hydroponics/proc/mutatepest() + if(pestlevel > 5) + visible_message("The pests seem to behave oddly...") + for(var/i in 1 to 3) + new /obj/effect/spider/spiderling(loc) + else + to_chat(usr, "The pests seem to behave oddly, but quickly settle down...") + + +/obj/machinery/hydroponics/attackby(obj/item/O, mob/user) + if(istype(O, /obj/item/nutrient)) + var/obj/item/nutrient/myNut = O + user.remove_from_mob(O) + nutrilevel = 10 + yieldmod = myNut.yieldmod + mutmod = myNut.mutmod + to_chat(user, "You replace the nutrient solution in [src].") + qdel(O) + update_icon() + + else if(istype(O, /obj/item/weapon/reagent_containers) ) // Syringe stuff (and other reagent containers now too) + var/obj/item/weapon/reagent_containers/reagent_source = O + var/datum/reagents/S = new /datum/reagents() + + S.my_atom = src + + var/obj/target = myseed ? myseed.plantname : src + + if(istype(reagent_source, /obj/item/weapon/reagent_containers/syringe)) + var/obj/item/weapon/reagent_containers/syringe/syr = reagent_source + if(syr.mode != 1) + to_chat(user, "You can't get any extract out of this plant.") + return + if(!reagent_source.reagents.total_volume) + to_chat(user, "[reagent_source] is empty.") + return TRUE + + if(istype(reagent_source, /obj/item/weapon/reagent_containers/food/snacks) || istype(reagent_source, /obj/item/weapon/reagent_containers/pill)) + visible_message("[user] composts [reagent_source], spreading it through [target].") + reagent_source.reagents.trans_to(S,reagent_source.reagents.total_volume) + qdel(reagent_source) + else + reagent_source.reagents.trans_to(S,reagent_source.amount_per_transfer_from_this) + if(istype(reagent_source, /obj/item/weapon/reagent_containers/syringe/)) + var/obj/item/weapon/reagent_containers/syringe/syr = reagent_source + visible_message("[user] injects [target] with [syr].") + if(syr.reagents.total_volume <= 0) + syr.mode = 0 + syr.update_icon() + else if(istype(reagent_source, /obj/item/weapon/reagent_containers/spray/)) + visible_message("[user] sprays [target] with [reagent_source].") + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + else if(reagent_source.amount_per_transfer_from_this) // Droppers, cans, beakers, what have you. + visible_message("[user] uses [reagent_source] on [target].") + + // Beakers, bottles, buckets, etc. Can't use is_open_container though. + if(istype(reagent_source, /obj/item/weapon/reagent_containers/glass/)) + playsound(loc, 'sound/effects/slosh.ogg', 25, 1) + + // There needs to be a good amount of mutagen to actually work + if(S.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() + if(21 to 41) + to_chat(user, "The plants don't seem to react...") + if(11 to 20) + mutateweed() + if(1 to 10) + mutatepest() + else + to_chat(user, "Nothing happens...") + + // Antitoxin binds shit pretty well. So the tox goes significantly down + if(S.has_reagent("anti_toxin", 1)) + adjustToxic(-round(S.get_reagent_amount("anti_toxin")*2)) + + // NIGGA, YOU JUST WENT ON FULL RETARD. + if(S.has_reagent("toxin", 1)) + adjustToxic(round(S.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.has_reagent("milk", 1)) + adjustNutri(round(S.get_reagent_amount("milk")*0.1)) + adjustWater(round(S.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.has_reagent("beer", 1)) + adjustHealth(-round(S.get_reagent_amount("beer")*0.05)) + adjustNutri(round(S.get_reagent_amount("beer")*0.25)) + adjustWater(round(S.get_reagent_amount("beer")*0.7)) + + // You're an idiot for thinking that one of the most corrosive and deadly gasses would be beneficial + if(S.has_reagent("fluorine", 1)) + adjustHealth(-round(S.get_reagent_amount("fluorine")*2)) + adjustToxic(round(S.get_reagent_amount("flourine")*2.5)) + adjustWater(-round(S.get_reagent_amount("flourine")*0.5)) + adjustWeeds(-rand(1,4)) + + // You're an idiot for thinking that one of the most corrosive and deadly gasses would be beneficial + if(S.has_reagent("chlorine", 1)) + adjustHealth(-round(S.get_reagent_amount("chlorine")*1)) + adjustToxic(round(S.get_reagent_amount("chlorine")*1.5)) + adjustWater(-round(S.get_reagent_amount("chlorine")*0.5)) + adjustWeeds(-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.has_reagent("phosphorus", 1)) + adjustHealth(-round(S.get_reagent_amount("phosphorus")*0.75)) + adjustNutri(round(S.get_reagent_amount("phosphorus")*0.1)) + adjustWater(-round(S.get_reagent_amount("phosphorus")*0.5)) + adjustWeeds(-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.has_reagent("sugar", 1)) + adjustWeeds(rand(1,2)) + adjustPests(rand(1,2)) + adjustNutri(round(S.get_reagent_amount("sugar")*0.1)) + + // It is water! + if(S.has_reagent("water", 1)) + adjustWater(round(S.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.has_reagent("holywater", 1)) + adjustWater(round(S.get_reagent_amount("holywater")*1)) + adjustHealth(round(S.get_reagent_amount("holywater")*0.1)) + + // Unholy water, Mostly the same, but it also damages the plant. + if(S.has_reagent("unholywater", 1)) + adjustWater(round(S.get_reagent_amount("unholywater"))) + adjustToxic(round(S.get_reagent_amount("unholywater")*0.1)) + adjustPests(rand(1,4)) + + // 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.has_reagent("sodawater", 1)) + adjustWater(round(S.get_reagent_amount("sodawater")*1)) + adjustHealth(round(S.get_reagent_amount("sodawater")*0.1)) + adjustNutri(round(S.get_reagent_amount("sodawater")*0.1)) + + // Man, you guys are retards + if(S.has_reagent("sacid", 1)) + adjustHealth(-round(S.get_reagent_amount("sacid")*1)) + adjustToxic(round(S.get_reagent_amount("sacid")*1.5)) + adjustWeeds(-rand(1,2)) + + // SERIOUSLY + if(S.has_reagent("pacid", 1)) + adjustHealth(-round(S.get_reagent_amount("pacid")*2)) + adjustToxic(round(S.get_reagent_amount("pacid")*3)) + adjustWeeds(-rand(1,4)) + + // Plant-B-Gone is just as bad + if(S.has_reagent("plantbgone", 1)) + adjustHealth(-round(S.get_reagent_amount("plantbgone")*2)) + adjustToxic(-round(S.get_reagent_amount("plantbgone")*3)) + adjustWeeds(-rand(4,8)) + + // Healing + if(S.has_reagent("cryoxadone", 1)) + adjustHealth(round(S.get_reagent_amount("cryoxadone")*3)) + adjustToxic(-round(S.get_reagent_amount("cryoxadone")*3)) + + // Ammonia is bad ass. + if(S.has_reagent("ammonia", 1)) + adjustHealth(round(S.get_reagent_amount("ammonia")*0.5)) + adjustNutri(round(S.get_reagent_amount("ammonia")*1)) + + // This is more bad ass, and pests get hurt by the corrosive nature of it, not the plant. + if(S.has_reagent("diethylamine", 1)) + adjustHealth(round(S.get_reagent_amount("diethylamine")*1)) + adjustNutri(round(S.get_reagent_amount("diethylamine")*2)) + adjustPests(-rand(1,2)) + + // Compost, effectively + if(S.has_reagent("nutriment", 1)) + adjustHealth(round(S.get_reagent_amount("nutriment")*0.5)) + adjustNutri(round(S.get_reagent_amount("nutriment")*1)) + + // Poor man's mutagen. + if(S.has_reagent("radium", 1)) + adjustHealth(-round(S.get_reagent_amount("radium")*1.5)) + adjustToxic(round(S.get_reagent_amount("radium")*2)) + if(S.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() + if(21 to 41) + to_chat(user, "The plants don't seem to react...") + if(11 to 20) + mutateweed() + if(1 to 10) + mutatepest() + else + to_chat(user, "Nothing happens...") + + // The best stuff there is. For testing/debugging. + if(S.has_reagent("adminordrazine", 1)) + adjustWater(round(S.get_reagent_amount("adminordrazine")*1)) + adjustHealth(round(S.get_reagent_amount("adminordrazine")*1)) + adjustNutri(round(S.get_reagent_amount("adminordrazine")*1)) + adjustPests(-rand(1,5)) + adjustWeeds(-rand(1,5)) + if(S.has_reagent("adminordrazine", 5)) + switch(rand(100)) + if(66 to 100) + mutatespecie() + if(33 to 65) + mutateweed() + if(1 to 32) + mutatepest() + else + to_chat(user, "Nothing happens...") + + S.clear_reagents() + qdel(S) + update_icon() + return TRUE + + else if ( istype(O, /obj/item/seeds/) ) + if(!planted) + user.remove_from_mob(O) + to_chat(user, "You plant the [O.name]") + dead = FALSE + myseed = O + planted = TRUE + 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) + update_icon() + + else + to_chat(user, "[src] already has seeds in it!") + + else if (istype(O, /obj/item/device/plant_analyzer)) + if(planted && myseed) + to_chat(user, "*** [myseed.plantname] ***")//Carn: now reports the plants growing, not the seeds. + to_chat(user, "-Plant Age: \blue [age]") + to_chat(user, "-Plant Endurance: \blue [myseed.endurance]") + to_chat(user, "-Plant Lifespan: \blue [myseed.lifespan]") + if(myseed.yield != -1) + to_chat(user, "-Plant Yield: \blue [myseed.yield]") + to_chat(user, "-Plant Production: \blue [myseed.production]") + if(myseed.potency != -1) + to_chat(user, "-Plant Potency: \blue [myseed.potency]") + to_chat(user, "-Weed level: \blue [weedlevel]/10") + to_chat(user, "-Pest level: \blue [pestlevel]/10") + to_chat(user, "-Toxicity level: \blue [toxic]/100") + to_chat(user, "-Water level: [waterlevel]/[maxwater]") + to_chat(user, "-Nutrition level: [nutrilevel]/[maxnutri]") + to_chat(user, "") + else + to_chat(user, "No plant found.") + to_chat(user, "-Weed level: \blue [weedlevel]/10") + to_chat(user, "-Pest level: \blue [pestlevel]/10") + to_chat(user, "-Toxicity level: \blue [toxic]/100") + to_chat(user, "-Water level: [waterlevel]/[maxwater]") + to_chat(user, "-Nutrition level: [nutrilevel]/[maxnutri]") + to_chat(user, "") + + else if (istype(O, /obj/item/weapon/minihoe)) + if(weedlevel > 0) + user.visible_message("[user] uproots the weeds.", "You remove the weeds from [src].") + weedlevel = 0 + update_icon() + 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.remove_from_mob(O) + adjustToxic(myWKiller.toxicity) + adjustWeeds(-myWKiller.WeedKillStr) + to_chat(user, "You apply the weedkiller solution into [src].") + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + qdel(O) + update_icon() + + 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) + score["stuffharvested"]++ + + else if(istype(O, /obj/item/weapon/wrench) && unwrenchable) + if(anchored == 2) + to_chat(user, "Unscrew the hoses first!") + return + + if(!anchored && !isinspace()) + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + anchored = 1 + to_chat(user, "You wrench [src] in place.") + else if(anchored) + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + anchored = 0 + to_chat(user, "You unwrench [src].") + + else if(istype(O, /obj/item/weapon/wirecutters) && unwrenchable) + + if(anchored) + if(anchored == 2) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) + anchored = 1 + to_chat(user, "You snip \the [src]'s hoses.") + + else if(anchored == 1) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) + anchored = 2 + to_chat(user, "You reconnect \the [src]'s hoses.") + + update_icon() + + else if ( istype(O, /obj/item/weapon/pestspray) ) + var/obj/item/pestkiller/myPKiller = O + user.remove_from_mob(O) + adjustToxic(myPKiller.toxicity) + adjustPests(-myPKiller.PestKillStr) + to_chat(user, "You apply the pestkiller solution into [src].") + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + qdel(O) + update_icon() + else if(istype(O, /obj/item/apiary)) + if(planted) + to_chat(user, "\red The hydroponics tray is already occupied!") + else + user.remove_from_mob() + qdel(O) + + var/obj/machinery/apiary/A = new(src.loc) + A.icon = src.icon + A.icon_state = src.icon_state + A.hydrotray_type = src.type + qdel(src) + return + +/obj/machinery/hydroponics/attack_tk(mob/user) + if(harvest) + myseed.harvest(src) + else if(dead) + planted = FALSE + dead = FALSE + to_chat(user, text("You remove the dead plant from the [src].")) + qdel(myseed) + update_icon() + +/obj/machinery/hydroponics/attack_hand(mob/user) + . = ..() + if(.) + return + if(issilicon(user))//AI doesn't know what is planted + return TRUE + if(harvest) + if(!in_range(src, user)) + return TRUE + myseed.harvest() + else if(dead) + planted = FALSE + dead = FALSE + to_chat(user, "You remove the dead plant from [src].") + qdel(myseed) + update_icon() + else + if(planted && !dead) + to_chat(user, "[src] has [myseed.plantname] planted.") + if(health <= (myseed.endurance / 2)) + to_chat(user, "The plant looks unhealthy.") + else + to_chat(user, "[src] is empty.") + to_chat(user, "Water: [waterlevel]/[maxwater]") + to_chat(user, "Nutrient: [nutrilevel]/[maxnutri]") + if(weedlevel >= 5) // Visual aid for those blind + to_chat(user, "[src] is filled with weeds!") + if(pestlevel >= 5) // Visual aid for those blind + to_chat(user, "[src] is filled with tiny worms!") + to_chat(user, "")// Empty line for readability. + +/obj/item/seeds/proc/getYield() + var/obj/machinery/hydroponics/parent = loc + if (parent.yieldmod == 0) + return min(yield, 1)//1 if above zero, 0 otherwise + return (yield * parent.yieldmod) + +/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 + var/list/result = list() + var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc //needed for TK + while(t_amount < getYield()) + var/obj/item/weapon/reagent_containers/food/snacks/grown/t_prod = new produce(output_loc, potency) + result.Add(t_prod) // 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++ + if(getYield() >= 1) + score["stuffharvested"]++ + + parent.update_tray() + return result + +/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) + new/obj/item/stack/tile/grass(user.loc, t_yield) + + parent.update_tray() + +/obj/item/seeds/gibtomato/harvest(mob/user = usr) + var/produce = text2path(productname) + var/obj/machinery/hydroponics/parent = loc + 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 + var/t_amount = 0 + + while ( t_amount < (yield * parent.yieldmod )) + var/obj/item/weapon/grown/t_prod = new produce(user.loc, potency) + 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) + t_prod.plant_type = plant_type + t_amount++ + + parent.update_tray() + +/obj/item/seeds/deathnettleseed/harvest(mob/user = usr) //COPYPOASTAAAA + var/produce = text2path(productname) + var/obj/machinery/hydroponics/parent = loc + var/t_amount = 0 + + while (t_amount < (yield * parent.yieldmod)) + var/obj/item/weapon/grown/t_prod = new produce(user.loc, potency) + 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) + 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 + 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 = FALSE + lastproduce = age + if(istype(myseed,/obj/item/seeds/replicapod/)) + to_chat(user, "You harvest from the [myseed.plantname].") + else if(myseed.getYield() <= 0) + to_chat(user, "You fail to harvest anything useful!") + else + to_chat(user, "You harvest [myseed.getYield()] items from the [myseed.plantname].") + if(myseed.oneharvest) + qdel(myseed) + planted = FALSE + dead = FALSE + update_icon() + +/// Tray Setters - The following procs adjust the tray or plants variables, and make sure that the stat doesn't go out of bounds./// +/obj/machinery/hydroponics/proc/adjustNutri(adjustamt) + nutrilevel += adjustamt + nutrilevel = max(nutrilevel, 0) + nutrilevel = min(nutrilevel, maxnutri) + +/obj/machinery/hydroponics/proc/adjustWater(adjustamt) + waterlevel += adjustamt + waterlevel = max(waterlevel, 0) + waterlevel = min(waterlevel, maxwater) + if(adjustamt > 0) + adjustToxic(-round(adjustamt / 4))//Toxicity dilutation code. The more water you put in, the lesser the toxin concentration. + +/obj/machinery/hydroponics/proc/adjustHealth(adjustamt) + if(planted && !dead) + health += adjustamt + health = max(health, 0) + health = min(health, myseed.endurance) + +/obj/machinery/hydroponics/proc/adjustToxic(adjustamt) + toxic += adjustamt + toxic = max(toxic, 0) + toxic = min(toxic, 100) + +/obj/machinery/hydroponics/proc/adjustPests(adjustamt) + pestlevel += adjustamt + pestlevel = max(pestlevel, 0) + pestlevel = min(pestlevel, 10) + +/obj/machinery/hydroponics/proc/adjustWeeds(adjustamt) + weedlevel += adjustamt + weedlevel = max(weedlevel, 0) + pestlevel = min(pestlevel, 10) + +/// Seed Setters /// +/obj/machinery/hydroponics/proc/adjustSYield(adjustamt)//0,10 + if(myseed.yield != -1) // Unharvestable shouldn't suddenly turn harvestable + myseed.yield += adjustamt + myseed.yield = max(myseed.yield, 0) + myseed.yield = min(myseed.yield, 10) + if(myseed.yield <= 0 && myseed.plant_type == 2) + myseed.yield = 1 // Mushrooms always have a minimum yield of 1. + +/obj/machinery/hydroponics/proc/adjustSLife(adjustamt)//10,100 + myseed.lifespan += adjustamt + myseed.lifespan = max(myseed.lifespan, 10) + myseed.lifespan = min(myseed.lifespan, 100) + +/obj/machinery/hydroponics/proc/adjustSEnd(adjustamt)//10,100 + myseed.endurance += adjustamt + myseed.endurance = max(myseed.endurance, 10) + myseed.endurance = min(myseed.endurance, 100) + +/obj/machinery/hydroponics/proc/adjustSProduct(adjustamt)//2,10 + myseed.production += adjustamt + myseed.production = max(myseed.endurance, 2) + myseed.production = min(myseed.endurance, 10) + +/obj/machinery/hydroponics/proc/adjustSPot(adjustamt)//0,100 + if(myseed.potency != -1) //Not all plants have a potency + myseed.potency += adjustamt + myseed.potency = max(myseed.potency, 0) + myseed.potency = min(myseed.potency, 100) + +/////////////////////////////////////////////////////////////////////////////// +/obj/machinery/hydroponics/soil + name = "soil" + icon = 'icons/obj/hydroponics/equipment.dmi' + icon_state = "soil" + density = FALSE + use_power = FALSE + unwrenchable = FALSE + +/obj/machinery/hydroponics/soil/update_icon()//as a regular tray but without overlays under it (awter level, nutri, weeds, etc) + overlays.Cut() + + UpdateDescription() + + if(planted) + if(dead) + overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-dead") + else if(harvest) + if(myseed.plant_type == 2) // Shrooms don't have a -harvest graphic + overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-grow[myseed.growthstages]") + else + overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-harvest") + else if(age < myseed.maturation) + var/t_growthstate = ((age / myseed.maturation) * myseed.growthstages ) + overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-grow[round(t_growthstate)]") + lastproduce = age + else + overlays += image(icon = myseed.hydroponictray_icon_path, icon_state="[myseed.species]-grow[myseed.growthstages]") + + if(!luminosity) + if(istype(myseed,/obj/item/seeds/glowshroom)) + set_light(round(myseed.potency/10)) + else + set_light(0) + return + +/obj/machinery/hydroponics/soil/attackby(obj/item/O, mob/user) + ..() + if(istype(O, /obj/item/weapon/shovel)) + to_chat(user, "You clear up [src]!") + qdel(src) + +#undef HYDRO_RATING_MULTIPLIER diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index de3684e33ae5..d5ce439bb0a1 100755 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -1,140 +1,140 @@ -/obj/machinery/igniter - name = "igniter" - desc = "It's useful for igniting flammable items." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "igniter1" - plane = FLOOR_PLANE - anchored = TRUE - use_power = 1 - idle_power_usage = 2 - active_power_usage = 4 - var/id = null - var/on = TRUE - -/obj/machinery/igniter/attack_hand(mob/user) - . = ..() - if(.) - return - user.SetNextMove(CLICK_CD_INTERACT) - use_power(50) - on = !on - icon_state = text("igniter[]", on) - -/obj/machinery/igniter/process() //ugh why is this even in process()? - if (on && !(stat & NOPOWER)) - var/turf/location = src.loc - if (isturf(location)) - location.hotspot_expose(1000, 500) - return 1 - -/obj/machinery/igniter/atom_init() - . = ..() - icon_state = "igniter[on]" - -/obj/machinery/igniter/power_change() - if(!( stat & NOPOWER) ) - icon_state = "igniter[src.on]" - else - icon_state = "igniter0" - -// 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 = null - var/disable = 0 - var/last_spark = 0 - var/base_state = "migniter" - anchored = 1 - -/obj/machinery/sparker/power_change() - if ( powered() && disable == 0 ) - stat &= ~NOPOWER - icon_state = "[base_state]" - else - stat |= ~NOPOWER - icon_state = "[base_state]-p" - -/obj/machinery/sparker/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/device/detective_scanner)) - return - if (istype(W, /obj/item/weapon/screwdriver)) - add_fingerprint(user) - src.disable = !src.disable - user.SetNextMove(CLICK_CD_INTERACT) - if (src.disable) - user.visible_message("\red [user] has disabled the [src]!", "\red You disable the connection to the [src].") - icon_state = "[base_state]-d" - if (!src.disable) - user.visible_message("\red [user] has reconnected the [src]!", "\red 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 (anchored) - return ignite() - else - return - -/obj/machinery/sparker/proc/ignite() - if (!powered()) - return - - if (disable || (last_spark && world.time < 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() - last_spark = world.time - use_power(1000) - var/turf/location = loc - if (isturf(location)) - location.hotspot_expose(1000, 500) - return 1 - -/obj/machinery/sparker/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - ..(severity) - return - ignite() - ..(severity) - -/obj/machinery/ignition_switch/attackby(obj/item/weapon/W, mob/user) - return attack_hand(user) - -/obj/machinery/ignition_switch/attack_hand(mob/user) - . = ..() - if(.) - return - if(active) - return 1 - - use_power(5) - user.SetNextMove(CLICK_CD_INTERACT) - - active = 1 - icon_state = "launcheract" - - for(var/obj/machinery/sparker/M in machines) - if (M.id == id) - spawn(0) - M.ignite() - - for(var/obj/machinery/igniter/M in machines) - if(M.id == id) - use_power(50) - M.on = !M.on - M.icon_state = text("igniter[]", M.on) - - sleep(50) - - icon_state = "launcherbtt" - active = 0 +/obj/machinery/igniter + name = "igniter" + desc = "It's useful for igniting flammable items." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "igniter1" + plane = FLOOR_PLANE + anchored = TRUE + use_power = 1 + idle_power_usage = 2 + active_power_usage = 4 + var/id = null + var/on = TRUE + +/obj/machinery/igniter/attack_hand(mob/user) + . = ..() + if(.) + return + user.SetNextMove(CLICK_CD_INTERACT) + use_power(50) + on = !on + icon_state = text("igniter[]", on) + +/obj/machinery/igniter/process() //ugh why is this even in process()? + if (on && !(stat & NOPOWER)) + var/turf/location = src.loc + if (isturf(location)) + location.hotspot_expose(1000, 500) + return 1 + +/obj/machinery/igniter/atom_init() + . = ..() + icon_state = "igniter[on]" + +/obj/machinery/igniter/power_change() + if(!( stat & NOPOWER) ) + icon_state = "igniter[src.on]" + else + icon_state = "igniter0" + +// 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 = null + var/disable = 0 + var/last_spark = 0 + var/base_state = "migniter" + anchored = 1 + +/obj/machinery/sparker/power_change() + if ( powered() && disable == 0 ) + stat &= ~NOPOWER + icon_state = "[base_state]" + else + stat |= ~NOPOWER + icon_state = "[base_state]-p" + +/obj/machinery/sparker/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/device/detective_scanner)) + return + if (istype(W, /obj/item/weapon/screwdriver)) + add_fingerprint(user) + src.disable = !src.disable + user.SetNextMove(CLICK_CD_INTERACT) + if (src.disable) + user.visible_message("\red [user] has disabled the [src]!", "\red You disable the connection to the [src].") + icon_state = "[base_state]-d" + if (!src.disable) + user.visible_message("\red [user] has reconnected the [src]!", "\red 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 (anchored) + return ignite() + else + return + +/obj/machinery/sparker/proc/ignite() + if (!powered()) + return + + if (disable || (last_spark && world.time < 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() + last_spark = world.time + use_power(1000) + var/turf/location = loc + if (isturf(location)) + location.hotspot_expose(1000, 500) + return 1 + +/obj/machinery/sparker/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + ignite() + ..(severity) + +/obj/machinery/ignition_switch/attackby(obj/item/weapon/W, mob/user) + return attack_hand(user) + +/obj/machinery/ignition_switch/attack_hand(mob/user) + . = ..() + if(.) + return + if(active) + return 1 + + use_power(5) + user.SetNextMove(CLICK_CD_INTERACT) + + active = 1 + icon_state = "launcheract" + + for(var/obj/machinery/sparker/M in machines) + if (M.id == id) + spawn(0) + M.ignite() + + for(var/obj/machinery/igniter/M in machines) + if(M.id == id) + use_power(50) + M.on = !M.on + M.icon_state = text("igniter[]", M.on) + + sleep(50) + + icon_state = "launcherbtt" + active = 0 diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 41c0d4d934ea..0c080031bf80 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -1,176 +1,176 @@ -/obj/machinery/iv_drip - name = "\improper IV drip" - icon = 'icons/obj/iv_drip.dmi' - icon_state = "iv_drip" - anchored = 0 - density = 0 - interact_offline = TRUE - var/mob/living/carbon/human/attached = null - var/mode = 1 // 1 is injecting, 0 is taking blood. - var/obj/item/weapon/reagent_containers/beaker = null - - -/obj/machinery/iv_drip/atom_init() - . = ..() - update_icon() - -/obj/machinery/iv_drip/update_icon() - if(attached) - if(mode) - icon_state = "injecting" - else - icon_state = "donating" - else - if(mode) - icon_state = "injectidle" - else - icon_state = "donateidle" - - overlays = null - - if(beaker) - if(attached) - overlays += "beakeractive" - else - overlays += "beakeridle" - if(beaker.reagents.total_volume) - var/image/filling = image('icons/obj/iv_drip.dmi', src, "reagent") - - var/percent = round((beaker.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(beaker.reagents.reagent_list) - overlays += filling - -/obj/machinery/iv_drip/MouseDrop(over_object, src_location, over_location) - ..() - if(!iscarbon(usr) && !isrobot(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) - 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, mob/user) - if (istype(W, /obj/item/weapon/reagent_containers)) - if(!isnull(src.beaker)) - to_chat(user, "There is already a reagent container loaded!") - return - - user.drop_item() - W.loc = 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(BP_R_ARM , BP_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(istype(src.beaker, /obj/item/weapon/reagent_containers/blood)) - // speed up transfer on blood packs - 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(NOCLONE in T.mutations) - return - - if(T.species && T.species.flags[NO_BLOOD]) - 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_ai(mob/user) - if(IsAdminGhost(user)) - return ..() - -/obj/machinery/iv_drip/attack_hand(mob/user) - . = ..() - if(.) - return - - if(beaker) - beaker.loc = get_turf(src) - beaker = null - update_icon() - -/obj/machinery/iv_drip/verb/toggle_mode() - set name = "Toggle Mode" - set category = "Object" - set src in oview(1) - - if(isliving(usr) && usr.stat != DEAD) - mode = !mode - to_chat(usr, "The IV drip is now [mode ? "injecting" : "taking blood"].") - -/obj/machinery/iv_drip/examine(mob/user) - ..() - if(src in oview(2, user)) - to_chat(user, "The IV drip 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, "[attached ? attached : "No one"] is attached.") +/obj/machinery/iv_drip + name = "\improper IV drip" + icon = 'icons/obj/iv_drip.dmi' + icon_state = "iv_drip" + anchored = 0 + density = 0 + interact_offline = TRUE + var/mob/living/carbon/human/attached = null + var/mode = 1 // 1 is injecting, 0 is taking blood. + var/obj/item/weapon/reagent_containers/beaker = null + + +/obj/machinery/iv_drip/atom_init() + . = ..() + update_icon() + +/obj/machinery/iv_drip/update_icon() + if(attached) + if(mode) + icon_state = "injecting" + else + icon_state = "donating" + else + if(mode) + icon_state = "injectidle" + else + icon_state = "donateidle" + + overlays = null + + if(beaker) + if(attached) + overlays += "beakeractive" + else + overlays += "beakeridle" + if(beaker.reagents.total_volume) + var/image/filling = image('icons/obj/iv_drip.dmi', src, "reagent") + + var/percent = round((beaker.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(beaker.reagents.reagent_list) + overlays += filling + +/obj/machinery/iv_drip/MouseDrop(over_object, src_location, over_location) + ..() + if(!iscarbon(usr) && !isrobot(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) + 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, mob/user) + if (istype(W, /obj/item/weapon/reagent_containers)) + if(!isnull(src.beaker)) + to_chat(user, "There is already a reagent container loaded!") + return + + user.drop_item() + W.loc = 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(BP_R_ARM , BP_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(istype(src.beaker, /obj/item/weapon/reagent_containers/blood)) + // speed up transfer on blood packs + 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(NOCLONE in T.mutations) + return + + if(T.species && T.species.flags[NO_BLOOD]) + 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_ai(mob/user) + if(IsAdminGhost(user)) + return ..() + +/obj/machinery/iv_drip/attack_hand(mob/user) + . = ..() + if(.) + return + + if(beaker) + beaker.loc = get_turf(src) + beaker = null + update_icon() + +/obj/machinery/iv_drip/verb/toggle_mode() + set name = "Toggle Mode" + set category = "Object" + set src in oview(1) + + if(isliving(usr) && usr.stat != DEAD) + mode = !mode + to_chat(usr, "The IV drip is now [mode ? "injecting" : "taking blood"].") + +/obj/machinery/iv_drip/examine(mob/user) + ..() + if(src in oview(2, user)) + to_chat(user, "The IV drip 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, "[attached ? attached : "No one"] is attached.") diff --git a/code/game/machinery/kitchen/deep_fryer.dm b/code/game/machinery/kitchen/deep_fryer.dm index efa621bf5a0f..5e3a0aa648e3 100644 --- a/code/game/machinery/kitchen/deep_fryer.dm +++ b/code/game/machinery/kitchen/deep_fryer.dm @@ -1,105 +1,105 @@ -/obj/machinery/deepfryer - name = "deep fryer" - desc = "Deep fried everything." - icon = 'icons/obj/kitchen.dmi' - icon_state = "fryer_off" - layer = 2.9 - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 5 - interact_offline = TRUE - var/on = FALSE //Is it deep frying already? - var/obj/item/frying = null //What's being fried RIGHT NOW? - var/fry_time = 0.0 - - -/obj/machinery/deepfryer/atom_init() - . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/deepfryer(null) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(null) - RefreshParts() - -/obj/machinery/deepfryer/Destroy() - frying = null - return ..() - -/obj/machinery/deepfryer/examine(mob/user) - ..() - if(frying) - switch(fry_time) - if(0 to 15) - to_chat(user, "You can make out lightly-fried [frying] in the oil.") - if(16 to 49) - to_chat(user, "You can make out fried [frying] in the oil.") - if(50 to 59) - to_chat(user, "You can make out deep-fried [frying] in the oil.") - if(60 to INFINITY) - to_chat(user, "You fucked up, man.") - -/obj/machinery/deepfryer/attackby(obj/item/I, mob/user) - if(!anchored) - if(istype(I, /obj/item/weapon/wrench)) - default_unfasten_wrench(user, I) - return - if(on) - to_chat(user, "[src] is still active!") - return - if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/deepfryholder)) - to_chat(user, "You cannot doublefry.") - return - else if(istype(I, /obj/item/weapon/wrench)) - if(alert(user,"How do you want to use [I]?","You think...","Unfasten","Cook") == "Unfasten") - default_unfasten_wrench(user, I) - return - if (ishuman(user) && !(I.flags & DROPDEL)) - to_chat(user, "You put [I] into [src].") - on = TRUE - user.drop_item() - frying = I - frying.loc = src - icon_state = "fryer_on" - - -/obj/machinery/deepfryer/process() - ..() - if(frying) - fry_time++ - if(fry_time == 30) - playsound(src, "sound/machines/ding.ogg", 50, 1) - visible_message("[src] dings!") - else if (fry_time == 60) - visible_message("[src] emits an acrid smell!") - -/obj/machinery/deepfryer/attack_hand(mob/user) - . = ..() - if(.) - return - - if(frying) - to_chat(user, "You eject [frying] from [src].") - var/obj/item/weapon/reagent_containers/food/snacks/deepfryholder/S = new(loc) - S.appearance = frying.appearance - S.desc = frying.desc - switch(fry_time) - if(0 to 15) - S.color = rgb(166,103,54) - S.name = "lightly-fried [frying.name]" - if(16 to 49) - S.color = rgb(103,63,24) - S.name = "fried [frying.name]" - if(50 to 59) - S.color = rgb(63, 23, 4) - S.name = "deep-fried [frying.name]" - if(60 to INFINITY) - S.color = rgb(33,19,9) - S.name = "burned down mess" - S.desc = "A heavily fried...something. Who can tell anymore?" - S.filling_color = S.color - qdel(frying) - icon_state = "fryer_off" - user.put_in_hands(S) - frying = null - on = FALSE - fry_time = 0 +/obj/machinery/deepfryer + name = "deep fryer" + desc = "Deep fried everything." + icon = 'icons/obj/kitchen.dmi' + icon_state = "fryer_off" + layer = 2.9 + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 5 + interact_offline = TRUE + var/on = FALSE //Is it deep frying already? + var/obj/item/frying = null //What's being fried RIGHT NOW? + var/fry_time = 0.0 + + +/obj/machinery/deepfryer/atom_init() + . = ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/deepfryer(null) + component_parts += new /obj/item/weapon/stock_parts/micro_laser(null) + RefreshParts() + +/obj/machinery/deepfryer/Destroy() + frying = null + return ..() + +/obj/machinery/deepfryer/examine(mob/user) + ..() + if(frying) + switch(fry_time) + if(0 to 15) + to_chat(user, "You can make out lightly-fried [frying] in the oil.") + if(16 to 49) + to_chat(user, "You can make out fried [frying] in the oil.") + if(50 to 59) + to_chat(user, "You can make out deep-fried [frying] in the oil.") + if(60 to INFINITY) + to_chat(user, "You fucked up, man.") + +/obj/machinery/deepfryer/attackby(obj/item/I, mob/user) + if(!anchored) + if(istype(I, /obj/item/weapon/wrench)) + default_unfasten_wrench(user, I) + return + if(on) + to_chat(user, "[src] is still active!") + return + if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/deepfryholder)) + to_chat(user, "You cannot doublefry.") + return + else if(istype(I, /obj/item/weapon/wrench)) + if(alert(user,"How do you want to use [I]?","You think...","Unfasten","Cook") == "Unfasten") + default_unfasten_wrench(user, I) + return + if (ishuman(user) && !(I.flags & DROPDEL)) + to_chat(user, "You put [I] into [src].") + on = TRUE + user.drop_item() + frying = I + frying.loc = src + icon_state = "fryer_on" + + +/obj/machinery/deepfryer/process() + ..() + if(frying) + fry_time++ + if(fry_time == 30) + playsound(src, "sound/machines/ding.ogg", 50, 1) + visible_message("[src] dings!") + else if (fry_time == 60) + visible_message("[src] emits an acrid smell!") + +/obj/machinery/deepfryer/attack_hand(mob/user) + . = ..() + if(.) + return + + if(frying) + to_chat(user, "You eject [frying] from [src].") + var/obj/item/weapon/reagent_containers/food/snacks/deepfryholder/S = new(loc) + S.appearance = frying.appearance + S.desc = frying.desc + switch(fry_time) + if(0 to 15) + S.color = rgb(166,103,54) + S.name = "lightly-fried [frying.name]" + if(16 to 49) + S.color = rgb(103,63,24) + S.name = "fried [frying.name]" + if(50 to 59) + S.color = rgb(63, 23, 4) + S.name = "deep-fried [frying.name]" + if(60 to INFINITY) + S.color = rgb(33,19,9) + S.name = "burned down mess" + S.desc = "A heavily fried...something. Who can tell anymore?" + S.filling_color = S.color + qdel(frying) + icon_state = "fryer_off" + user.put_in_hands(S) + frying = null + on = FALSE + fry_time = 0 diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index 1fc9254c3b60..c6ab6a05d27e 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -1,238 +1,238 @@ - -/obj/machinery/gibber - name = "Gibber" - desc = "The name isn't descriptive enough?" - icon = 'icons/obj/kitchen.dmi' - icon_state = "grinder" - density = TRUE - anchored = TRUE - use_power = 1 - idle_power_usage = 2 - active_power_usage = 500 - var/operating = FALSE //Is it on? - var/dirty = FALSE // Does it need cleaning? - var/gibtime = 80 // Time from starting until meat appears - var/gib_throw_dir // Direction to spit meat and gibs in. - var/meat_produced = 0 - var/ignore_clothing = 0 - -//auto-gibs anything that bumps into it -/obj/machinery/gibber/autogibber - var/turf/input_plate - -/obj/machinery/gibber/autogibber/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/gibber/autogibber/atom_init_late() - 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) - log_misc("a [src] didn't find an input plate.") - -/obj/machinery/gibber/autogibber/Bumped(atom/A) - if(!input_plate) return - - if(ismob(A)) - var/mob/M = A - - if(M.loc == input_plate) - M.loc = src - M.gib() - - -/obj/machinery/gibber/atom_init() - . = ..() - overlays += image('icons/obj/kitchen.dmi', "grjam") - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/gibber(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - RefreshParts() - -/obj/machinery/gibber/RefreshParts() - var/gib_time = initial(gibtime) - for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) - meat_produced += 3 * B.rating - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - gib_time -= 5 * M.rating - gibtime = gib_time - if(M.rating >= 2) - ignore_clothing = 1 - -/obj/machinery/gibber/update_icon() - overlays.Cut() - 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/container_resist() - go_out() - -/obj/machinery/gibber/attack_hand(mob/user) - . = ..() - if(.) - return - user.SetNextMove(CLICK_CD_INTERACT) - if(operating) - to_chat(user, "The gibber is locked and running, wait for it to finish.") - return 1 - else - startgibbing(user) - -/obj/machinery/gibber/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/weapon/grab)) - src.add_fingerprint(user) - var/obj/item/weapon/grab/G = W - move_into_gibber(user, G.affecting) - qdel(G) - - if(default_deconstruction_screwdriver(user, "grinder_open", "grinder", W)) - return - - if(exchange_parts(user, W)) - return - - if(default_pry_open(W)) - return - - if(default_unfasten_wrench(user, W)) - return - - -/obj/machinery/gibber/MouseDrop_T(mob/target, mob/user) - if(!iscarbon(user) && !isrobot(user)) - return - if(user.stat || user.restrained()) - return - move_into_gibber(user,target) - -/obj/machinery/gibber/proc/move_into_gibber(mob/user,mob/living/victim) - - if(src.occupant) - to_chat(user, "The gibber is full, empty it first!") - return - - if(operating) - to_chat(user, "The gibber is locked and running, wait for it to finish.") - return - - if(!(iscarbon(victim)) && !(istype(victim, /mob/living/simple_animal)) ) - to_chat(user, "This is not suitable for the gibber!") - return - - if(victim.abiotic(1) && !ignore_clothing) - to_chat(user, "Subject may not have abiotic items on.") - return - if(user.is_busy(src)) return - user.visible_message("\red [user] starts to put [victim] into the gibber!") - src.add_fingerprint(user) - if(do_after(user, 30, target = src) && victim.Adjacent(src) && user.Adjacent(src) && victim.Adjacent(user) && !occupant) - user.visible_message("\red [user] stuffs [victim] into the gibber!") - if(victim.client) - victim.client.perspective = EYE_PERSPECTIVE - victim.client.eye = src - victim.loc = src - src.occupant = victim - update_icon() - -/obj/machinery/gibber/verb/eject() - set category = "Object" - set name = "Empty Gibber" - set src in oview(1) - - if (usr.stat != CONSCIOUS) - return - src.go_out() - add_fingerprint(usr) - return - -/obj/machinery/gibber/proc/go_out() - if(operating || !src.occupant) - 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 - update_icon() - return - - -/obj/machinery/gibber/proc/startgibbing(mob/user) - if(src.operating) - return - if(!src.occupant) - visible_message("You hear a loud metallic grinding sound.") - return - use_power(1000) - visible_message("You hear a loud squelchy grinding sound.") - src.operating = 1 - update_icon() - var/offset = prob(50) ? -2 : 2 - animate(src, pixel_x = pixel_x + offset, time = gibtime / 100, loop = gibtime) //start shaking - playsound(src.loc, 'sound/effects/gibber.ogg', 100, 1) - - var/slab_name = occupant.name - var/slab_count = 3 - var/slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat - var/slab_nutrition = occupant.get_nutrition() / 15 - - // Some mobs have specific meat item types. - if(ishuman(occupant)) - slab_name = occupant.real_name - slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat/human - else if(ismonkey(occupant)) - slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat/monkey - - // Small mobs don't give as much nutrition. - if(occupant.small) - slab_nutrition *= 0.5 - slab_nutrition /= slab_count - - spawn(gibtime) - if(iscarbon(occupant)) - for(var/i=1 to slab_count) - var/obj/item/weapon/reagent_containers/food/snacks/meat/new_meat = new slab_type(get_turf(get_step(src, 8))) - new_meat.name = "[slab_name] [new_meat.name]" - new_meat.reagents.add_reagent("nutriment", slab_nutrition) - - if(occupant.reagents) - occupant.reagents.trans_to(new_meat, round(occupant.reagents.total_volume/slab_count, 1)) - - occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" //One shall not simply gib a mob unnoticed! - user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]" - msg_admin_attack("[user.name] ([user.ckey]) gibbed [src.occupant] ([src.occupant.ckey]) (JMP)") - - occupant.ghostize(bancheck = TRUE) - - operating = 0 - occupant.gib() - qdel(src.occupant) - occupant = null - - playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) - operating = 0 - for (var/obj/item/thing in contents) - thing.loc = get_turf(thing) // Drop it onto the turf for throwing. - thing.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) // Being pelted with bits of meat and bone would hurt. - - pixel_x = initial(pixel_x) //return to it's spot after shaking - update_icon() - - + +/obj/machinery/gibber + name = "Gibber" + desc = "The name isn't descriptive enough?" + icon = 'icons/obj/kitchen.dmi' + icon_state = "grinder" + density = TRUE + anchored = TRUE + use_power = 1 + idle_power_usage = 2 + active_power_usage = 500 + var/operating = FALSE //Is it on? + var/dirty = FALSE // Does it need cleaning? + var/gibtime = 80 // Time from starting until meat appears + var/gib_throw_dir // Direction to spit meat and gibs in. + var/meat_produced = 0 + var/ignore_clothing = 0 + +//auto-gibs anything that bumps into it +/obj/machinery/gibber/autogibber + var/turf/input_plate + +/obj/machinery/gibber/autogibber/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/gibber/autogibber/atom_init_late() + 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) + log_misc("a [src] didn't find an input plate.") + +/obj/machinery/gibber/autogibber/Bumped(atom/A) + if(!input_plate) return + + if(ismob(A)) + var/mob/M = A + + if(M.loc == input_plate) + M.loc = src + M.gib() + + +/obj/machinery/gibber/atom_init() + . = ..() + overlays += image('icons/obj/kitchen.dmi', "grjam") + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/gibber(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + RefreshParts() + +/obj/machinery/gibber/RefreshParts() + var/gib_time = initial(gibtime) + for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) + meat_produced += 3 * B.rating + for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + gib_time -= 5 * M.rating + gibtime = gib_time + if(M.rating >= 2) + ignore_clothing = 1 + +/obj/machinery/gibber/update_icon() + overlays.Cut() + 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/container_resist() + go_out() + +/obj/machinery/gibber/attack_hand(mob/user) + . = ..() + if(.) + return + user.SetNextMove(CLICK_CD_INTERACT) + if(operating) + to_chat(user, "The gibber is locked and running, wait for it to finish.") + return 1 + else + startgibbing(user) + +/obj/machinery/gibber/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/grab)) + src.add_fingerprint(user) + var/obj/item/weapon/grab/G = W + move_into_gibber(user, G.affecting) + qdel(G) + + if(default_deconstruction_screwdriver(user, "grinder_open", "grinder", W)) + return + + if(exchange_parts(user, W)) + return + + if(default_pry_open(W)) + return + + if(default_unfasten_wrench(user, W)) + return + + +/obj/machinery/gibber/MouseDrop_T(mob/target, mob/user) + if(!iscarbon(user) && !isrobot(user)) + return + if(user.stat || user.restrained()) + return + move_into_gibber(user,target) + +/obj/machinery/gibber/proc/move_into_gibber(mob/user,mob/living/victim) + + if(src.occupant) + to_chat(user, "The gibber is full, empty it first!") + return + + if(operating) + to_chat(user, "The gibber is locked and running, wait for it to finish.") + return + + if(!(iscarbon(victim)) && !(istype(victim, /mob/living/simple_animal)) ) + to_chat(user, "This is not suitable for the gibber!") + return + + if(victim.abiotic(1) && !ignore_clothing) + to_chat(user, "Subject may not have abiotic items on.") + return + if(user.is_busy(src)) return + user.visible_message("\red [user] starts to put [victim] into the gibber!") + src.add_fingerprint(user) + if(do_after(user, 30, target = src) && victim.Adjacent(src) && user.Adjacent(src) && victim.Adjacent(user) && !occupant) + user.visible_message("\red [user] stuffs [victim] into the gibber!") + if(victim.client) + victim.client.perspective = EYE_PERSPECTIVE + victim.client.eye = src + victim.loc = src + src.occupant = victim + update_icon() + +/obj/machinery/gibber/verb/eject() + set category = "Object" + set name = "Empty Gibber" + set src in oview(1) + + if (usr.stat != CONSCIOUS) + return + src.go_out() + add_fingerprint(usr) + return + +/obj/machinery/gibber/proc/go_out() + if(operating || !src.occupant) + 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 + update_icon() + return + + +/obj/machinery/gibber/proc/startgibbing(mob/user) + if(src.operating) + return + if(!src.occupant) + visible_message("You hear a loud metallic grinding sound.") + return + use_power(1000) + visible_message("You hear a loud squelchy grinding sound.") + src.operating = 1 + update_icon() + var/offset = prob(50) ? -2 : 2 + animate(src, pixel_x = pixel_x + offset, time = gibtime / 100, loop = gibtime) //start shaking + playsound(src.loc, 'sound/effects/gibber.ogg', 100, 1) + + var/slab_name = occupant.name + var/slab_count = 3 + var/slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat + var/slab_nutrition = occupant.get_nutrition() / 15 + + // Some mobs have specific meat item types. + if(ishuman(occupant)) + slab_name = occupant.real_name + slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat/human + else if(ismonkey(occupant)) + slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat/monkey + + // Small mobs don't give as much nutrition. + if(occupant.small) + slab_nutrition *= 0.5 + slab_nutrition /= slab_count + + spawn(gibtime) + if(iscarbon(occupant)) + for(var/i=1 to slab_count) + var/obj/item/weapon/reagent_containers/food/snacks/meat/new_meat = new slab_type(get_turf(get_step(src, 8))) + new_meat.name = "[slab_name] [new_meat.name]" + new_meat.reagents.add_reagent("nutriment", slab_nutrition) + + if(occupant.reagents) + occupant.reagents.trans_to(new_meat, round(occupant.reagents.total_volume/slab_count, 1)) + + occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" //One shall not simply gib a mob unnoticed! + user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]" + msg_admin_attack("[user.name] ([user.ckey]) gibbed [src.occupant] ([src.occupant.ckey]) (JMP)") + + occupant.ghostize(bancheck = TRUE) + + operating = 0 + occupant.gib() + qdel(src.occupant) + occupant = null + + playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) + operating = 0 + for (var/obj/item/thing in contents) + thing.loc = get_turf(thing) // Drop it onto the turf for throwing. + thing.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) // Being pelted with bits of meat and bone would hurt. + + pixel_x = initial(pixel_x) //return to it's spot after shaking + update_icon() + + diff --git a/code/game/machinery/kitchen/juicer.dm b/code/game/machinery/kitchen/juicer.dm index 4a9be077c7a5..d22d4fbceb98 100644 --- a/code/game/machinery/kitchen/juicer.dm +++ b/code/game/machinery/kitchen/juicer.dm @@ -1,163 +1,163 @@ - -/obj/machinery/juicer - name = "Juicer" - icon = 'icons/obj/kitchen.dmi' - icon_state = "juicer1" - layer = 2.9 - density = 1 - anchored = 0 - use_power = 1 - idle_power_usage = 5 - active_power_usage = 100 - pass_flags = PASSTABLE - var/obj/item/weapon/reagent_containers/beaker = null - var/global/list/allowed_items = list ( - /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/grapes = "grapejuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = "poisonberryjuice", - ) - -/obj/machinery/juicer/atom_init() - 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(obj/item/O, mob/user) - if(default_unfasten_wrench(user, O)) - return - if (istype(O,/obj/item/weapon/reagent_containers/glass) || \ - istype(O,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass)) - if (beaker) - return 1 - else - user.remove_from_mob(O) - O.loc = 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 - user.remove_from_mob(O) - O.loc = src - src.updateUsrDialog() - return 0 - -/obj/machinery/juicer/attack_ai(mob/user) - if(IsAdminGhost(user)) - return ..() - return 0 - -/obj/machinery/juicer/ui_interact(mob/user) // 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[entity_ja(dat)]", "window=juicer") - onclose(user, "juicer") - - -/obj/machinery/juicer/Topic(href, href_list) - . = ..() - if(!.) - return - - switch(href_list["action"]) - if ("juice") - juice() - if ("detach") - detach() - - src.updateUsrDialog() - -/obj/machinery/juicer/verb/detach() - set category = "Object" - set name = "Detach Beaker from the juicer" - set src in oview(1) - if (usr.stat != CONSCIOUS) - 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(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(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(src.loc, '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) - if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) - break - -/obj/structure/closet/crate/juice/PopulateContents() - new/obj/machinery/juicer(src) - for (var/i in 1 to 3) - 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 = 1 + anchored = 0 + use_power = 1 + idle_power_usage = 5 + active_power_usage = 100 + pass_flags = PASSTABLE + var/obj/item/weapon/reagent_containers/beaker = null + var/global/list/allowed_items = list ( + /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/grapes = "grapejuice", + /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = "poisonberryjuice", + ) + +/obj/machinery/juicer/atom_init() + 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(obj/item/O, mob/user) + if(default_unfasten_wrench(user, O)) + return + if (istype(O,/obj/item/weapon/reagent_containers/glass) || \ + istype(O,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass)) + if (beaker) + return 1 + else + user.remove_from_mob(O) + O.loc = 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 + user.remove_from_mob(O) + O.loc = src + src.updateUsrDialog() + return 0 + +/obj/machinery/juicer/attack_ai(mob/user) + if(IsAdminGhost(user)) + return ..() + return 0 + +/obj/machinery/juicer/ui_interact(mob/user) // 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[entity_ja(dat)]", "window=juicer") + onclose(user, "juicer") + + +/obj/machinery/juicer/Topic(href, href_list) + . = ..() + if(!.) + return + + switch(href_list["action"]) + if ("juice") + juice() + if ("detach") + detach() + + src.updateUsrDialog() + +/obj/machinery/juicer/verb/detach() + set category = "Object" + set name = "Detach Beaker from the juicer" + set src in oview(1) + if (usr.stat != CONSCIOUS) + 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(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(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(src.loc, '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) + if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) + break + +/obj/structure/closet/crate/juice/PopulateContents() + new/obj/machinery/juicer(src) + for (var/i in 1 to 3) + 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/processor.dm b/code/game/machinery/kitchen/processor.dm index 2ec528e1f297..1ad348d97cb9 100644 --- a/code/game/machinery/kitchen/processor.dm +++ b/code/game/machinery/kitchen/processor.dm @@ -1,202 +1,202 @@ -/obj/machinery/processor - name = "Food Processor" - icon = 'icons/obj/kitchen.dmi' - icon_state = "processor" - layer = 2.9 - density = TRUE - anchored = TRUE - use_power = 1 - idle_power_usage = 5 - active_power_usage = 50 - var/broken = FALSE - var/processing = FALSE - var/rating_speed = 1 - var/rating_amount = 1 - -/obj/machinery/processor/atom_init() - . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/processor(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - RefreshParts() - -/obj/machinery/processor/RefreshParts() - for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) - rating_amount = B.rating - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - rating_speed = M.rating - -/datum/food_processor_process - var/input - var/output - var/time = 40 - -/datum/food_processor_process/proc/process_food(loc, what, obj/machinery/processor/processor) - if (output && loc && processor) - for(var/i = 0, i < processor.rating_amount, i++) - new output(loc) - if (what) - qdel(what) - - /* objs */ -/datum/food_processor_process/meat - input = /obj/item/weapon/reagent_containers/food/snacks/meat - output = /obj/item/weapon/reagent_containers/food/snacks/rawmeatball - -/datum/food_processor_process/meat2 - input = /obj/item/weapon/syntiflesh - output = /obj/item/weapon/reagent_containers/food/snacks/rawmeatball - -/datum/food_processor_process/potato - input = /obj/item/weapon/reagent_containers/food/snacks/grown/potato - output = /obj/item/weapon/reagent_containers/food/snacks/rawsticks - -/datum/food_processor_process/carrot - input = /obj/item/weapon/reagent_containers/food/snacks/grown/carrot - output = /obj/item/weapon/reagent_containers/food/snacks/carrotfries - -/datum/food_processor_process/soybeans - input = /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans - output = /obj/item/weapon/reagent_containers/food/snacks/soydope - -/datum/food_processor_process/wheat - input = /obj/item/weapon/reagent_containers/food/snacks/grown/wheat - output = /obj/item/weapon/reagent_containers/food/condiment/flour - -/datum/food_processor_process/spaghetti - input = /obj/item/weapon/reagent_containers/food/snacks/dough - output = /obj/item/weapon/reagent_containers/food/snacks/spagetti - - /* mobs */ -/datum/food_processor_process/mob/process_food(loc, what, processor) - ..() - -//datum/food_processor_process/mob/slime/process_food(loc, what, obj/machinery/processor/processor) -// var/mob/living/simple_animal/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 + processor.rating_amount, i++) -// new S.coretype(loc) -// feedback_add_details("slime_core_harvested","[replacetext(S.colour," ","_")]") -// ..() - -/datum/food_processor_process/mob/slime - input = /mob/living/carbon/slime - output = /obj/item/weapon/reagent_containers/glass/beaker/slime - -/datum/food_processor_process/mob/monkey - input = /mob/living/carbon/monkey - output = null - -/datum/food_processor_process/mob/monkey/process_food(loc, what, processor) - var/mob/living/carbon/monkey/O = what - if (O.client) //grief-proof - O.loc = loc - O.visible_message("\blue Suddenly [O] jumps out from the processor!", \ - "You jump out from the processor", \ - "You hear chimp") - 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 - ..() - - - -/obj/machinery/processor/proc/select_recipe(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/attackby(obj/item/O, mob/user) - if(processing) - to_chat(user, "\red The processor is in the process of processing.") - return 1 - if(default_deconstruction_screwdriver(user, "processor1", "processor", O)) - return - - if(exchange_parts(user, O)) - return - - if(default_pry_open(O)) - return - - if(default_unfasten_wrench(user, O)) - return - - default_deconstruction_crowbar(O) - - if(contents.len > 0) //TODO: several items at once? several different items? - to_chat(user, "\red Something is already in the processing chamber.") - return 1 - var/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, "\red That probably won't blend.") - return 1 - user.visible_message("[user] put [what] into [src].", \ - "You put the [what] into [src].") - user.drop_item() - what:loc = src - return - -/obj/machinery/processor/attack_hand(mob/user) - . = ..() - if(.) - return - if(processing) - to_chat(user, "\red The processor is in the process of processing.") - return 1 - if(contents.len == 0) - to_chat(user, "\red The processor is empty.") - return 1 - user.SetNextMove(CLICK_CD_INTERACT) - processing = TRUE - user.visible_message("[user] turns on [src].", \ - "You turn on [src].", \ - "You hear a food processor.") - playsound(loc, 'sound/machines/blender.ogg', 35, 1) - use_power(500) - var/total_time = 0 - for(var/O in contents) - var/datum/food_processor_process/P = select_recipe(O) - if (!P) - log_admin("DEBUG: [O] in processor havent suitable recipe. How do you put it in?") //-rastaf0 // DEAR GOD THIS BURNS MY EYES HAVE YOU EVER LOOKED IN AN ENGLISH DICTONARY BEFORE IN YOUR LIFE AAAAAAAAAAAAAAAAAAAAA - Iamgoofball - continue - total_time += P.time - sleep(total_time / rating_speed) - for(var/O in contents) - var/datum/food_processor_process/P = select_recipe(O) - if (!P) - log_admin("DEBUG: [O] in processor havent suitable recipe. How do you put it in?") //-rastaf0 - continue - P.process_food(loc, O, src) - processing = FALSE - visible_message("\blue \the [src] finished processing.", \ - "You hear the food processor stopping/") +/obj/machinery/processor + name = "Food Processor" + icon = 'icons/obj/kitchen.dmi' + icon_state = "processor" + layer = 2.9 + density = TRUE + anchored = TRUE + use_power = 1 + idle_power_usage = 5 + active_power_usage = 50 + var/broken = FALSE + var/processing = FALSE + var/rating_speed = 1 + var/rating_amount = 1 + +/obj/machinery/processor/atom_init() + . = ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/processor(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + RefreshParts() + +/obj/machinery/processor/RefreshParts() + for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) + rating_amount = B.rating + for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + rating_speed = M.rating + +/datum/food_processor_process + var/input + var/output + var/time = 40 + +/datum/food_processor_process/proc/process_food(loc, what, obj/machinery/processor/processor) + if (output && loc && processor) + for(var/i = 0, i < processor.rating_amount, i++) + new output(loc) + if (what) + qdel(what) + + /* objs */ +/datum/food_processor_process/meat + input = /obj/item/weapon/reagent_containers/food/snacks/meat + output = /obj/item/weapon/reagent_containers/food/snacks/rawmeatball + +/datum/food_processor_process/meat2 + input = /obj/item/weapon/syntiflesh + output = /obj/item/weapon/reagent_containers/food/snacks/rawmeatball + +/datum/food_processor_process/potato + input = /obj/item/weapon/reagent_containers/food/snacks/grown/potato + output = /obj/item/weapon/reagent_containers/food/snacks/rawsticks + +/datum/food_processor_process/carrot + input = /obj/item/weapon/reagent_containers/food/snacks/grown/carrot + output = /obj/item/weapon/reagent_containers/food/snacks/carrotfries + +/datum/food_processor_process/soybeans + input = /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans + output = /obj/item/weapon/reagent_containers/food/snacks/soydope + +/datum/food_processor_process/wheat + input = /obj/item/weapon/reagent_containers/food/snacks/grown/wheat + output = /obj/item/weapon/reagent_containers/food/condiment/flour + +/datum/food_processor_process/spaghetti + input = /obj/item/weapon/reagent_containers/food/snacks/dough + output = /obj/item/weapon/reagent_containers/food/snacks/spagetti + + /* mobs */ +/datum/food_processor_process/mob/process_food(loc, what, processor) + ..() + +//datum/food_processor_process/mob/slime/process_food(loc, what, obj/machinery/processor/processor) +// var/mob/living/simple_animal/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 + processor.rating_amount, i++) +// new S.coretype(loc) +// feedback_add_details("slime_core_harvested","[replacetext(S.colour," ","_")]") +// ..() + +/datum/food_processor_process/mob/slime + input = /mob/living/carbon/slime + output = /obj/item/weapon/reagent_containers/glass/beaker/slime + +/datum/food_processor_process/mob/monkey + input = /mob/living/carbon/monkey + output = null + +/datum/food_processor_process/mob/monkey/process_food(loc, what, processor) + var/mob/living/carbon/monkey/O = what + if (O.client) //grief-proof + O.loc = loc + O.visible_message("\blue Suddenly [O] jumps out from the processor!", \ + "You jump out from the processor", \ + "You hear chimp") + 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 + ..() + + + +/obj/machinery/processor/proc/select_recipe(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/attackby(obj/item/O, mob/user) + if(processing) + to_chat(user, "\red The processor is in the process of processing.") + return 1 + if(default_deconstruction_screwdriver(user, "processor1", "processor", O)) + return + + if(exchange_parts(user, O)) + return + + if(default_pry_open(O)) + return + + if(default_unfasten_wrench(user, O)) + return + + default_deconstruction_crowbar(O) + + if(contents.len > 0) //TODO: several items at once? several different items? + to_chat(user, "\red Something is already in the processing chamber.") + return 1 + var/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, "\red That probably won't blend.") + return 1 + user.visible_message("[user] put [what] into [src].", \ + "You put the [what] into [src].") + user.drop_item() + what:loc = src + return + +/obj/machinery/processor/attack_hand(mob/user) + . = ..() + if(.) + return + if(processing) + to_chat(user, "\red The processor is in the process of processing.") + return 1 + if(contents.len == 0) + to_chat(user, "\red The processor is empty.") + return 1 + user.SetNextMove(CLICK_CD_INTERACT) + processing = TRUE + user.visible_message("[user] turns on [src].", \ + "You turn on [src].", \ + "You hear a food processor.") + playsound(loc, 'sound/machines/blender.ogg', 35, 1) + use_power(500) + var/total_time = 0 + for(var/O in contents) + var/datum/food_processor_process/P = select_recipe(O) + if (!P) + log_admin("DEBUG: [O] in processor havent suitable recipe. How do you put it in?") //-rastaf0 // DEAR GOD THIS BURNS MY EYES HAVE YOU EVER LOOKED IN AN ENGLISH DICTONARY BEFORE IN YOUR LIFE AAAAAAAAAAAAAAAAAAAAA - Iamgoofball + continue + total_time += P.time + sleep(total_time / rating_speed) + for(var/O in contents) + var/datum/food_processor_process/P = select_recipe(O) + if (!P) + log_admin("DEBUG: [O] in processor havent suitable recipe. How do you put it in?") //-rastaf0 + continue + P.process_food(loc, O, src) + processing = FALSE + visible_message("\blue \the [src] finished processing.", \ + "You hear the food processor stopping/") diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm index c35890c949c0..95a3b7618178 100644 --- a/code/game/machinery/kitchen/smartfridge.dm +++ b/code/game/machinery/kitchen/smartfridge.dm @@ -1,369 +1,369 @@ -/* 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 - allowed_checks = ALLOWED_CHECK_NONE - var/max_n_of_items = 1500 - var/icon_on = "smartfridge" - var/icon_off = "smartfridge-off" - var/icon_panel = "smartfridge-panel" - var/list/item_quants = list() - var/ispowered = 1 //starts powered - var/isbroken = 0 - var/seconds_electrified = 0; - var/shoot_inventory = 0 - var/locked = 0 - var/datum/wires/smartfridge/wires = null - -/obj/machinery/smartfridge/atom_init() - . = ..() - wires = new(src) - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/smartfridge(null, type) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - RefreshParts() - -/obj/machinery/smartfridge/Destroy() - QDEL_NULL(wires) - return ..() - -/obj/machinery/smartfridge/construction() - for(var/datum/A in contents) - qdel(A) - -/obj/machinery/smartfridge/deconstruction() - for(var/atom/movable/A in contents) - A.loc = loc - -/obj/machinery/smartfridge/RefreshParts() - for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) - max_n_of_items = 1500 * B.rating - -/obj/machinery/smartfridge/proc/accept_check(obj/item/O) - if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/) || istype(O,/obj/item/seeds/)) - return 1 - return 0 - -/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" - -/obj/machinery/smartfridge/seeds/accept_check(obj/item/O) - if(istype(O,/obj/item/seeds/)) - return 1 - return 0 - -/obj/machinery/smartfridge/chemistry - name = "smart chemical storage" - desc = "A refrigerated storage unit for medicine storage." - -/obj/machinery/smartfridge/chemistry/accept_check(obj/item/O) - if(istype(O,/obj/item/weapon/storage/pill_bottle)) - return TRUE - if(!istype(O,/obj/item/weapon/reagent_containers)) - return FALSE - if(istype(O,/obj/item/weapon/reagent_containers/pill)) // empty pill prank ok - return TRUE - if(!O.reagents || !O.reagents.reagent_list.len) // other empty containers not accepted - return FALSE - if(istype(O,/obj/item/weapon/reagent_containers/syringe) || istype(O,/obj/item/weapon/reagent_containers/glass/bottle) || istype(O,/obj/item/weapon/reagent_containers/glass/beaker) || istype(O,/obj/item/weapon/reagent_containers/spray)) - return TRUE - return FALSE - -/obj/machinery/smartfridge/secure/extract - name = "\improper Slime Extract Storage" - desc = "A refrigerated storage unit for slime extracts." - req_access_txt = "47" - -/obj/machinery/smartfridge/secure/extract/accept_check(obj/item/O) - if(istype(O,/obj/item/slime_extract)) - return 1 - return 0 - -/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_txt = "5;33" - -/obj/machinery/smartfridge/secure/medbay/accept_check(obj/item/O) - if(istype(O,/obj/item/weapon/reagent_containers/glass/)) - return 1 - if(istype(O,/obj/item/weapon/storage/pill_bottle/)) - return 1 - if(istype(O,/obj/item/weapon/reagent_containers/pill/)) - return 1 - return 0 - -/obj/machinery/smartfridge/secure/virology - name = "\improper Refrigerated Virus Storage" - desc = "A refrigerated storage unit for storing viral material." - req_access_txt = "39" - icon_state = "smartfridge_virology" - icon_on = "smartfridge_virology" - icon_off = "smartfridge_virology-off" - -/obj/machinery/smartfridge/secure/virology/accept_check(obj/item/O) - if(istype(O,/obj/item/weapon/reagent_containers/glass/beaker/vial/)) - return 1 - if(istype(O,/obj/item/weapon/virusdish/)) - return 1 - return 0 - -/obj/machinery/smartfridge/chemistry/virology - name = "\improper Smart Virus Storage" - desc = "A refrigerated storage unit for volatile sample storage." - - -/obj/machinery/smartfridge/drinks - name = "\improper Drink Showcase" - desc = "A refrigerated storage unit for tasty tasty alcohol." - -/obj/machinery/smartfridge/drinks/accept_check(obj/item/O) - if(istype(O,/obj/item/weapon/reagent_containers/glass) || istype(O,/obj/item/weapon/reagent_containers/food/drinks) || istype(O,/obj/item/weapon/reagent_containers/food/condiment)) - return 1 - -/obj/machinery/smartfridge/process() - if(!src.ispowered) - return - if(src.seconds_electrified > 0) - src.seconds_electrified-- - if(src.shoot_inventory && prob(2)) - src.throw_item() - -/obj/machinery/smartfridge/power_change() - if( powered() ) - src.ispowered = 1 - stat &= ~NOPOWER - if(!isbroken) - icon_state = icon_on - else - spawn(rand(0, 15)) - src.ispowered = 0 - stat |= NOPOWER - if(!isbroken) - icon_state = icon_off - -/******************* -* Item Adding -********************/ - -/obj/machinery/smartfridge/attackby(obj/item/O, mob/user) - if(default_deconstruction_screwdriver(user, "smartfridge_open", "smartfridge", O)) - return - - if(exchange_parts(user, O)) - return - - if(default_pry_open(O)) - return - - if(default_unfasten_wrench(user, O)) - power_change() - return - - default_deconstruction_crowbar(O) - - if(istype(O, /obj/item/weapon/screwdriver)) - panel_open = !panel_open - to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") - overlays.Cut() - if(panel_open) - overlays += image(icon, icon_panel) - nanomanager.update_uis(src) - return - - if(is_wire_tool(O) && panel_open && wires.interact(user)) - return - - if(!src.ispowered) - to_chat(user, "\The [src] is unpowered and useless.") - return - - if(accept_check(O)) - if(contents.len >= max_n_of_items) - to_chat(user, "\The [src] is full.") - return - else - user.remove_from_mob(O) - O.loc = src - if(item_quants[O.name]) - item_quants[O.name]++ - else - item_quants[O.name] = 1 - user.visible_message("[user] has added \the [O] to \the [src].", \ - "You add \the [O] to \the [src].") - - nanomanager.update_uis(src) - - else if(istype(O, /obj/item/weapon/storage)) // fastload from userstorage - var/obj/item/weapon/storage/S = O - var/item_loaded = 0 - for(var/obj/I in S.contents) - if(accept_check(I)) - if(contents.len >= max_n_of_items) - to_chat(user, "\The [src] is full.") - return - else - S.remove_from_storage(I,src) - if(item_quants[I.name]) - item_quants[I.name]++ - else - item_quants[I.name] = 1 - item_loaded++ - - if(item_loaded) - user.visible_message( \ - "[user] loads \the [src] with \the [S].", \ - "You load \the [src] with \the [S].") - if(S.contents.len > 0) - to_chat(user, "Some items are refused.") - - nanomanager.update_uis(src) - return - else - to_chat(user, "\The [src] smartly refuses [O].") - return - -/obj/machinery/smartfridge/secure/attackby(obj/item/O, mob/user) - if (istype(O, /obj/item/weapon/card/emag)) - emagged = 1 - locked = -1 - to_chat(user, "You short out the product lock on [src].") - return - - ..() - -/obj/machinery/smartfridge/attack_ai(mob/user) - if(IsAdminGhost(user)) - return ..() - return 0 - -/obj/machinery/smartfridge/attack_hand(mob/user) - if(!issilicon(user) && !isobserver(user) && seconds_electrified) - if(shock(user, 100)) - return - - return ..() - -/******************* -* SmartFridge Menu -********************/ - -/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null) - var/is_secure = istype(src,/obj/machinery/smartfridge/secure) - - var/data[0] - data["contents"] = null - data["electrified"] = seconds_electrified > 0 - data["shoot_inventory"] = shoot_inventory - data["locked"] = locked - data["secure"] = is_secure - - var/list/items[0] - for (var/i=1 to length(item_quants)) - var/K = item_quants[i] - var/count = item_quants[K] - if (count > 0) - items.Add(list(list("display_name" = html_encode(capitalize(K)), "vend" = i, "quantity" = count))) - - if (items.len > 0) - data["contents"] = items - - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) - if (!ui) - ui = new(user, src, ui_key, "smartfridge.tmpl", src.name, 400, 500) - ui.set_initial_data(data) - ui.open() - -/obj/machinery/smartfridge/Topic(href, href_list) - . = ..() - if(!.) - return - - var/mob/user = usr - var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") - - if (href_list["close"]) - user.unset_machine() - ui.close() - return FALSE - - if (href_list["vend"]) - var/index = text2num(href_list["vend"]) - var/amount = text2num(href_list["amount"]) - var/K = item_quants[index] - var/count = item_quants[K] - - // Sanity check, there are probably ways to press the button when it shouldn't be possible. - if(count > 0) - item_quants[K] = max(count - amount, 0) - - var/i = amount - for(var/obj/O in contents) - if (O.name == K) - O.loc = loc - i-- - if (i <= 0) - return TRUE - - return TRUE - -/obj/machinery/smartfridge/proc/throw_item() - var/obj/throw_item = null - var/mob/living/target = locate() in view(7,src) - if(!target) - return 0 - - for (var/O in item_quants) - if(item_quants[O] <= 0) //Try to use a record that actually has something to dump. - continue - - item_quants[O]-- - for(var/obj/T in contents) - if(T.name == O) - T.loc = src.loc - throw_item = T - break - break - if(!throw_item) - return 0 - throw_item.throw_at(target,16,3,src) - src.visible_message("\red [src] launches [throw_item.name] at [target.name]!") - return 1 - -/obj/machinery/smartfridge/proc/shock(mob/user, prb) - if(!ispowered) return 0 - if(!prob(prb)) return 0 - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - - return electrocute_mob(user, get_area(src), src, 0.7) - -/************************ -* Secure SmartFridges -*************************/ - -/obj/machinery/smartfridge/secure/Topic(href, href_list) - . = ..() - if(!.) - return - if (!allowed(usr) && !emagged && locked != -1 && href_list["vend"]) - to_chat(usr, "\red Access denied.") - return FALSE +/* 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 + allowed_checks = ALLOWED_CHECK_NONE + var/max_n_of_items = 1500 + var/icon_on = "smartfridge" + var/icon_off = "smartfridge-off" + var/icon_panel = "smartfridge-panel" + var/list/item_quants = list() + var/ispowered = 1 //starts powered + var/isbroken = 0 + var/seconds_electrified = 0; + var/shoot_inventory = 0 + var/locked = 0 + var/datum/wires/smartfridge/wires = null + +/obj/machinery/smartfridge/atom_init() + . = ..() + wires = new(src) + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/smartfridge(null, type) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + RefreshParts() + +/obj/machinery/smartfridge/Destroy() + QDEL_NULL(wires) + return ..() + +/obj/machinery/smartfridge/construction() + for(var/datum/A in contents) + qdel(A) + +/obj/machinery/smartfridge/deconstruction() + for(var/atom/movable/A in contents) + A.loc = loc + +/obj/machinery/smartfridge/RefreshParts() + for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) + max_n_of_items = 1500 * B.rating + +/obj/machinery/smartfridge/proc/accept_check(obj/item/O) + if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/) || istype(O,/obj/item/seeds/)) + return 1 + return 0 + +/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" + +/obj/machinery/smartfridge/seeds/accept_check(obj/item/O) + if(istype(O,/obj/item/seeds/)) + return 1 + return 0 + +/obj/machinery/smartfridge/chemistry + name = "smart chemical storage" + desc = "A refrigerated storage unit for medicine storage." + +/obj/machinery/smartfridge/chemistry/accept_check(obj/item/O) + if(istype(O,/obj/item/weapon/storage/pill_bottle)) + return TRUE + if(!istype(O,/obj/item/weapon/reagent_containers)) + return FALSE + if(istype(O,/obj/item/weapon/reagent_containers/pill)) // empty pill prank ok + return TRUE + if(!O.reagents || !O.reagents.reagent_list.len) // other empty containers not accepted + return FALSE + if(istype(O,/obj/item/weapon/reagent_containers/syringe) || istype(O,/obj/item/weapon/reagent_containers/glass/bottle) || istype(O,/obj/item/weapon/reagent_containers/glass/beaker) || istype(O,/obj/item/weapon/reagent_containers/spray)) + return TRUE + return FALSE + +/obj/machinery/smartfridge/secure/extract + name = "\improper Slime Extract Storage" + desc = "A refrigerated storage unit for slime extracts." + req_access_txt = "47" + +/obj/machinery/smartfridge/secure/extract/accept_check(obj/item/O) + if(istype(O,/obj/item/slime_extract)) + return 1 + return 0 + +/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_txt = "5;33" + +/obj/machinery/smartfridge/secure/medbay/accept_check(obj/item/O) + if(istype(O,/obj/item/weapon/reagent_containers/glass/)) + return 1 + if(istype(O,/obj/item/weapon/storage/pill_bottle/)) + return 1 + if(istype(O,/obj/item/weapon/reagent_containers/pill/)) + return 1 + return 0 + +/obj/machinery/smartfridge/secure/virology + name = "\improper Refrigerated Virus Storage" + desc = "A refrigerated storage unit for storing viral material." + req_access_txt = "39" + icon_state = "smartfridge_virology" + icon_on = "smartfridge_virology" + icon_off = "smartfridge_virology-off" + +/obj/machinery/smartfridge/secure/virology/accept_check(obj/item/O) + if(istype(O,/obj/item/weapon/reagent_containers/glass/beaker/vial/)) + return 1 + if(istype(O,/obj/item/weapon/virusdish/)) + return 1 + return 0 + +/obj/machinery/smartfridge/chemistry/virology + name = "\improper Smart Virus Storage" + desc = "A refrigerated storage unit for volatile sample storage." + + +/obj/machinery/smartfridge/drinks + name = "\improper Drink Showcase" + desc = "A refrigerated storage unit for tasty tasty alcohol." + +/obj/machinery/smartfridge/drinks/accept_check(obj/item/O) + if(istype(O,/obj/item/weapon/reagent_containers/glass) || istype(O,/obj/item/weapon/reagent_containers/food/drinks) || istype(O,/obj/item/weapon/reagent_containers/food/condiment)) + return 1 + +/obj/machinery/smartfridge/process() + if(!src.ispowered) + return + if(src.seconds_electrified > 0) + src.seconds_electrified-- + if(src.shoot_inventory && prob(2)) + src.throw_item() + +/obj/machinery/smartfridge/power_change() + if( powered() ) + src.ispowered = 1 + stat &= ~NOPOWER + if(!isbroken) + icon_state = icon_on + else + spawn(rand(0, 15)) + src.ispowered = 0 + stat |= NOPOWER + if(!isbroken) + icon_state = icon_off + +/******************* +* Item Adding +********************/ + +/obj/machinery/smartfridge/attackby(obj/item/O, mob/user) + if(default_deconstruction_screwdriver(user, "smartfridge_open", "smartfridge", O)) + return + + if(exchange_parts(user, O)) + return + + if(default_pry_open(O)) + return + + if(default_unfasten_wrench(user, O)) + power_change() + return + + default_deconstruction_crowbar(O) + + if(istype(O, /obj/item/weapon/screwdriver)) + panel_open = !panel_open + to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") + overlays.Cut() + if(panel_open) + overlays += image(icon, icon_panel) + nanomanager.update_uis(src) + return + + if(is_wire_tool(O) && panel_open && wires.interact(user)) + return + + if(!src.ispowered) + to_chat(user, "\The [src] is unpowered and useless.") + return + + if(accept_check(O)) + if(contents.len >= max_n_of_items) + to_chat(user, "\The [src] is full.") + return + else + user.remove_from_mob(O) + O.loc = src + if(item_quants[O.name]) + item_quants[O.name]++ + else + item_quants[O.name] = 1 + user.visible_message("[user] has added \the [O] to \the [src].", \ + "You add \the [O] to \the [src].") + + nanomanager.update_uis(src) + + else if(istype(O, /obj/item/weapon/storage)) // fastload from userstorage + var/obj/item/weapon/storage/S = O + var/item_loaded = 0 + for(var/obj/I in S.contents) + if(accept_check(I)) + if(contents.len >= max_n_of_items) + to_chat(user, "\The [src] is full.") + return + else + S.remove_from_storage(I,src) + if(item_quants[I.name]) + item_quants[I.name]++ + else + item_quants[I.name] = 1 + item_loaded++ + + if(item_loaded) + user.visible_message( \ + "[user] loads \the [src] with \the [S].", \ + "You load \the [src] with \the [S].") + if(S.contents.len > 0) + to_chat(user, "Some items are refused.") + + nanomanager.update_uis(src) + return + else + to_chat(user, "\The [src] smartly refuses [O].") + return + +/obj/machinery/smartfridge/secure/attackby(obj/item/O, mob/user) + if (istype(O, /obj/item/weapon/card/emag)) + emagged = 1 + locked = -1 + to_chat(user, "You short out the product lock on [src].") + return + + ..() + +/obj/machinery/smartfridge/attack_ai(mob/user) + if(IsAdminGhost(user)) + return ..() + return 0 + +/obj/machinery/smartfridge/attack_hand(mob/user) + if(!issilicon(user) && !isobserver(user) && seconds_electrified) + if(shock(user, 100)) + return + + return ..() + +/******************* +* SmartFridge Menu +********************/ + +/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null) + var/is_secure = istype(src,/obj/machinery/smartfridge/secure) + + var/data[0] + data["contents"] = null + data["electrified"] = seconds_electrified > 0 + data["shoot_inventory"] = shoot_inventory + data["locked"] = locked + data["secure"] = is_secure + + var/list/items[0] + for (var/i=1 to length(item_quants)) + var/K = item_quants[i] + var/count = item_quants[K] + if (count > 0) + items.Add(list(list("display_name" = html_encode(capitalize(K)), "vend" = i, "quantity" = count))) + + if (items.len > 0) + data["contents"] = items + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + ui = new(user, src, ui_key, "smartfridge.tmpl", src.name, 400, 500) + ui.set_initial_data(data) + ui.open() + +/obj/machinery/smartfridge/Topic(href, href_list) + . = ..() + if(!.) + return + + var/mob/user = usr + var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") + + if (href_list["close"]) + user.unset_machine() + ui.close() + return FALSE + + if (href_list["vend"]) + var/index = text2num(href_list["vend"]) + var/amount = text2num(href_list["amount"]) + var/K = item_quants[index] + var/count = item_quants[K] + + // Sanity check, there are probably ways to press the button when it shouldn't be possible. + if(count > 0) + item_quants[K] = max(count - amount, 0) + + var/i = amount + for(var/obj/O in contents) + if (O.name == K) + O.loc = loc + i-- + if (i <= 0) + return TRUE + + return TRUE + +/obj/machinery/smartfridge/proc/throw_item() + var/obj/throw_item = null + var/mob/living/target = locate() in view(7,src) + if(!target) + return 0 + + for (var/O in item_quants) + if(item_quants[O] <= 0) //Try to use a record that actually has something to dump. + continue + + item_quants[O]-- + for(var/obj/T in contents) + if(T.name == O) + T.loc = src.loc + throw_item = T + break + break + if(!throw_item) + return 0 + throw_item.throw_at(target,16,3,src) + src.visible_message("\red [src] launches [throw_item.name] at [target.name]!") + return 1 + +/obj/machinery/smartfridge/proc/shock(mob/user, prb) + if(!ispowered) return 0 + if(!prob(prb)) return 0 + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + + return electrocute_mob(user, get_area(src), src, 0.7) + +/************************ +* Secure SmartFridges +*************************/ + +/obj/machinery/smartfridge/secure/Topic(href, href_list) + . = ..() + if(!.) + return + if (!allowed(usr) && !emagged && locked != -1 && href_list["vend"]) + to_chat(usr, "\red Access denied.") + return FALSE diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index 3145d927afe5..bda47a02dc2b 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -1,81 +1,81 @@ -// the light switch -// can have multiple per area -// can also operate on non-loc area through "otherarea" var -/obj/machinery/light_switch - name = "light switch" - desc = "It turns lights on and off. What are you, simple?" - icon = 'icons/obj/power.dmi' - icon_state = "light1" - anchored = TRUE - var/on = TRUE - var/area/area = null - var/otherarea = null - // luminosity = 1 - -/obj/machinery/light_switch/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/light_switch/atom_init_late() - area = loc.loc - - if(otherarea) - area = locate(text2path("/area/[otherarea]")) - - if(!name) - name = "light switch ([area.name])" - - on = area.lightswitch - updateicon() - - - -/obj/machinery/light_switch/proc/updateicon() - if(stat & NOPOWER) - icon_state = "light-p" - else - if(on) - icon_state = "light1" - else - icon_state = "light0" - -/obj/machinery/light_switch/examine(mob/user) - ..() - if(src in oview(1, user)) - to_chat(user, "A light switch. It is [on? "on" : "off"].") - -/obj/machinery/light_switch/attack_hand(mob/user) - . = ..() - if(.) - return - - on = !on - user.SetNextMove(CLICK_CD_INTERACT) - playsound(src, 'sound/items/buttonclick.ogg', 20, 1, 1) - - for(var/area/A in area.master.related) - A.lightswitch = on - A.updateicon() - - for(var/obj/machinery/light_switch/L in A) - L.on = on - L.updateicon() - - area.master.power_change() - -/obj/machinery/light_switch/power_change() - - if(!otherarea) - 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) +// the light switch +// can have multiple per area +// can also operate on non-loc area through "otherarea" var +/obj/machinery/light_switch + name = "light switch" + desc = "It turns lights on and off. What are you, simple?" + icon = 'icons/obj/power.dmi' + icon_state = "light1" + anchored = TRUE + var/on = TRUE + var/area/area = null + var/otherarea = null + // luminosity = 1 + +/obj/machinery/light_switch/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/light_switch/atom_init_late() + area = loc.loc + + if(otherarea) + area = locate(text2path("/area/[otherarea]")) + + if(!name) + name = "light switch ([area.name])" + + on = area.lightswitch + updateicon() + + + +/obj/machinery/light_switch/proc/updateicon() + if(stat & NOPOWER) + icon_state = "light-p" + else + if(on) + icon_state = "light1" + else + icon_state = "light0" + +/obj/machinery/light_switch/examine(mob/user) + ..() + if(src in oview(1, user)) + to_chat(user, "A light switch. It is [on? "on" : "off"].") + +/obj/machinery/light_switch/attack_hand(mob/user) + . = ..() + if(.) + return + + on = !on + user.SetNextMove(CLICK_CD_INTERACT) + playsound(src, 'sound/items/buttonclick.ogg', 20, 1, 1) + + for(var/area/A in area.master.related) + A.lightswitch = on + A.updateicon() + + for(var/obj/machinery/light_switch/L in A) + L.on = on + L.updateicon() + + area.master.power_change() + +/obj/machinery/light_switch/power_change() + + if(!otherarea) + 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) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index d25ec1d6c69c..222f31867518 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -1,485 +1,485 @@ -/* -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, autocalled) 'modules/power/power.dm' - Deducts 'amount' from the power channel 'chan' of the area that contains the object. - If it's autocalled then everything is normal, if something else calls use_power we are going to - need to recalculate the power two ticks in a row. - - 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 -*/ - -/obj/machinery - name = "machinery" - icon = 'icons/obj/stationobjs.dmi' - layer = DEFAULT_MACHINERY_LAYER - 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 = null //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/panel_open = 0 - var/state_open = 0 - var/mob/living/occupant = null - var/unsecuring_tool = /obj/item/weapon/wrench - var/interact_open = FALSE // Can the machine be interacted with when in maint/when the panel is open. - var/interact_offline = 0 // Can the machine be interacted with while de-powered. - var/allowed_checks = ALLOWED_CHECK_EVERYWHERE // should machine call allowed() in attack_hand(). See machinery/turretid for example. - var/frequency = 0 - var/datum/radio_frequency/radio_connection - var/radio_filter_out - var/radio_filter_in - -/obj/machinery/atom_init() - . = ..() - machines += src - START_PROCESSING(SSmachine, src) - power_change() - -/obj/machinery/Destroy() - if(frequency) - set_frequency(null) - machines -= src - STOP_PROCESSING(SSmachine, src) - - dropContents() - return ..() - -/obj/machinery/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) - -/obj/machinery/proc/locate_machinery() - return - -/obj/machinery/process()//If you dont use process or power why are you here - return PROCESS_KILL - -/obj/machinery/proc/process_atmos()//If you dont use process 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(loc) - pulse2.icon = 'icons/effects/effects.dmi' - pulse2.icon_state = "empdisable" - pulse2.name = "emp sparks" - pulse2.anchored = 1 - pulse2.dir = pick(cardinal) - - QDEL_IN(pulse2, 10) - ..() - -/obj/machinery/proc/open_machine() - state_open = 1 - density = 0 - dropContents() - update_icon() - updateUsrDialog() - -/obj/machinery/proc/dropContents() - var/turf/T = get_turf(src) - for(var/atom/movable/AM in contents) - AM.forceMove(T) - if(isliving(AM)) - var/mob/living/L = AM - if(L.client) - L.client.eye = L - L.client.perspective = MOB_PERSPECTIVE - occupant = null - -/obj/machinery/proc/close_machine(mob/living/target = null) - state_open = 0 - density = 1 - if(!target) - for(var/mob/living/carbon/C in loc) - if(C.buckled) - continue - else - target = C - if(target && !target.buckled) - if(target.client) - target.client.perspective = EYE_PERSPECTIVE - target.client.eye = src - occupant = target - target.loc = src - target.stop_pulling() - if(target.pulledby) - target.pulledby.stop_pulling() - updateUsrDialog() - update_icon() - -/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) - -//sets the use_power var and then forces an area power update @ 7e65984ae2ec4e7eaaecc8da0bfa75642c3489c7 bay12 -/obj/machinery/proc/update_use_power(new_use_power, force_update = 0) - if ((new_use_power == use_power) && !force_update) - return //don't need to do anything - - use_power = new_use_power - - //force area power update - //use_power() forces an area power update on the next tick so have to pass the correct power amount for this tick - if (use_power >= 2) - use_power(active_power_usage) - else if (use_power == 1) - use_power(idle_power_usage) - else - use_power(0) - -/obj/machinery/proc/auto_use_power() - if(!powered(power_channel)) - return 0 - if(src.use_power == 1) - use_power(idle_power_usage,power_channel, 1) - else if(src.use_power >= 2) - use_power(active_power_usage,power_channel, 1) - return 1 - -//By default, we check everything. -//But sometimes, we need to override this check. -/obj/machinery/proc/is_operational_topic() - return !((stat & (NOPOWER|BROKEN|MAINT|EMPED)) || (panel_open && !interact_open)) - -/obj/machinery/Topic(href, href_list) - ..() - - if(usr.can_use_topic(src) != STATUS_INTERACTIVE || !is_operational_topic()) - usr.unset_machine(src) - return FALSE - - if(!can_mob_interact(usr)) - return FALSE - - if((allowed_checks & ALLOWED_CHECK_TOPIC) && !emagged && !allowed(usr)) - allowed_fail(usr) - to_chat(usr, "Access Denied.") - return FALSE - - usr.set_machine(src) - add_fingerprint(usr) - - var/area/A = get_area(src) - A.master.powerupdate = 1 - - return TRUE - -/obj/machinery/proc/is_operational() - return !(stat & (NOPOWER|BROKEN|MAINT)) - -/obj/machinery/proc/issilicon_allowed(mob/living/silicon/S) - if(istype(S) && allowed(S)) - return TRUE - return FALSE - -/obj/machinery/proc/is_interactable() - if((stat & (NOPOWER|BROKEN)) && !interact_offline) - return FALSE - if(panel_open && !interact_open) - return FALSE - return TRUE - -/obj/machinery/proc/allowed_fail(mob/user) // incase you want to add something special when allowed fails. - return - -//////////////////////////////////////////////////////////////////////////////////////////// - -/obj/machinery/interact(mob/user) - if(issilicon(user) || isobserver(user)) - add_hiddenprint(user) - else if(isliving(user)) - add_fingerprint(user) - if(ui_interact(user) != -1) - user.set_machine(src) - -/obj/machinery/attack_ai(mob/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 attack_hand(user) - else - return attack_hand(user) - -/obj/machinery/attack_paw(mob/user) - return attack_hand(user) - -// set_machine must be 0 if clicking the machinery doesn't bring up a dialog -/obj/machinery/attack_hand(mob/user) - if ((user.lying || user.stat) && !IsAdminGhost(user)) - return 1 - if(!is_interactable()) - return 1 - if (!(ishuman(user) || issilicon(user) || ismonkey(user) || isalienqueen(user) || IsAdminGhost(user))) - to_chat(user, "You don't have the dexterity to do this!") - return 1 - if (!can_mob_interact(user)) - return 1 - if(hasvar(src, "wires")) // Lets close wires window if panel is closed. - var/datum/wires/DW = vars["wires"] // Wires and machinery that uses this feature actually should be refactored. - if(istype(DW) && !DW.can_use(user)) // Many of them do not use panel_open var. - DW.Topic("close=1", list("close"="1")) - if((allowed_checks & ALLOWED_CHECK_A_HAND) && !emagged && !allowed(user)) - allowed_fail(user) - to_chat(user, "Access Denied.") - return 1 - - var/area/A = get_area(src) - A.master.powerupdate = 1 // <- wtf is this var and its comments... - - interact(user) - return 0 - -/obj/machinery/CheckParts(list/parts_list) - ..() - RefreshParts() - -/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/default_pry_open(obj/item/weapon/crowbar/C) - . = !(state_open || panel_open || is_operational() || (flags & NODECONSTRUCT)) && istype(C) - if(.) - playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) - visible_message("[usr] pry open \the [src].", "You pry open \the [src].") - open_machine() - return 1 - -/obj/machinery/proc/default_deconstruction_crowbar(obj/item/weapon/crowbar/C, ignore_panel = 0) - . = istype(C) && (panel_open || ignore_panel) && !(flags & NODECONSTRUCT) - if(.) - deconstruction() - playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) - var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(loc) - transfer_fingerprints_to(M) - M.state = 2 - M.icon_state = "box_1" - for(var/obj/item/I in component_parts) - if(I.reliability != 100 && crit_fail) - I.crit_fail = 1 - I.loc = loc - qdel(src) - -/obj/machinery/proc/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/weapon/screwdriver/S) - if(istype(S) && !(flags & NODECONSTRUCT)) - playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(!panel_open) - panel_open = 1 - icon_state = icon_state_open - to_chat(user, "You open the maintenance hatch of [src].") - else - panel_open = 0 - icon_state = icon_state_closed - to_chat(user, "You close the maintenance hatch of [src].") - return 1 - return 0 - -/obj/machinery/proc/default_change_direction_wrench(mob/user, obj/item/weapon/wrench/W) - if(panel_open && istype(W)) - playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) - dir = turn(dir,-90) - to_chat(user, "You rotate [src].") - return 1 - return 0 - -/obj/proc/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20) - if(istype(W) && !(flags & NODECONSTRUCT)) - if(user.is_busy()) return - to_chat(user, "You begin [anchored ? "un" : ""]securing [name]...") - playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, time/W.toolspeed, target = src)) - to_chat(user, "You [anchored ? "un" : ""]secure [name].") - anchored = !anchored - playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1) - return 1 - return 0 - -/obj/machinery/proc/exchange_parts(mob/user, obj/item/weapon/storage/part_replacer/W) - var/shouldplaysound = 0 - if(istype(W) && component_parts) - if(panel_open || W.works_from_distance) - var/obj/item/weapon/circuitboard/CB = locate(/obj/item/weapon/circuitboard) in component_parts - var/P - if(W.works_from_distance) - to_chat(user, "Following parts detected in the machine:") - for(var/var/obj/item/C in component_parts) - to_chat(user, " [C.name]") - for(var/obj/item/weapon/stock_parts/A in component_parts) - for(var/D in CB.req_components) - if(ispath(A.type, D)) - P = D - break - for(var/obj/item/weapon/stock_parts/B in W.contents) - if(istype(B, P) && istype(A, P)) - if(B.rating > A.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 - -/obj/machinery/proc/display_parts(mob/user) - to_chat(user, "Following parts detected in the machine:") - for(var/obj/item/C in component_parts) - to_chat(user, "[bicon(C)] [C.name]") - -//called on machinery construction (i.e from frame to machinery) but not on initialization -/obj/machinery/proc/construction() - return - -//called on deconstruction before the final deletion -/obj/machinery/proc/deconstruction() - return - -/obj/machinery/proc/state(msg) - for(var/mob/O in hearers(src, null)) - O.show_message("[bicon(src)] [msg]", 2) - -/obj/machinery/proc/ping(text=null) - if (!text) - text = "\The [src] pings." - - state(text, "blue") - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - -/obj/machinery/tesla_act(power) - ..() - if(prob(85)) - emp_act(2) - else if(prob(50)) - ex_act(3) - else if(prob(90)) - ex_act(2) - else - ex_act(1) +/* +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, autocalled) 'modules/power/power.dm' + Deducts 'amount' from the power channel 'chan' of the area that contains the object. + If it's autocalled then everything is normal, if something else calls use_power we are going to + need to recalculate the power two ticks in a row. + + 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 +*/ + +/obj/machinery + name = "machinery" + icon = 'icons/obj/stationobjs.dmi' + layer = DEFAULT_MACHINERY_LAYER + 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 = null //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/panel_open = 0 + var/state_open = 0 + var/mob/living/occupant = null + var/unsecuring_tool = /obj/item/weapon/wrench + var/interact_open = FALSE // Can the machine be interacted with when in maint/when the panel is open. + var/interact_offline = 0 // Can the machine be interacted with while de-powered. + var/allowed_checks = ALLOWED_CHECK_EVERYWHERE // should machine call allowed() in attack_hand(). See machinery/turretid for example. + var/frequency = 0 + var/datum/radio_frequency/radio_connection + var/radio_filter_out + var/radio_filter_in + +/obj/machinery/atom_init() + . = ..() + machines += src + START_PROCESSING(SSmachine, src) + power_change() + +/obj/machinery/Destroy() + if(frequency) + set_frequency(null) + machines -= src + STOP_PROCESSING(SSmachine, src) + + dropContents() + return ..() + +/obj/machinery/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) + +/obj/machinery/proc/locate_machinery() + return + +/obj/machinery/process()//If you dont use process or power why are you here + return PROCESS_KILL + +/obj/machinery/proc/process_atmos()//If you dont use process 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(loc) + pulse2.icon = 'icons/effects/effects.dmi' + pulse2.icon_state = "empdisable" + pulse2.name = "emp sparks" + pulse2.anchored = 1 + pulse2.dir = pick(cardinal) + + QDEL_IN(pulse2, 10) + ..() + +/obj/machinery/proc/open_machine() + state_open = 1 + density = 0 + dropContents() + update_icon() + updateUsrDialog() + +/obj/machinery/proc/dropContents() + var/turf/T = get_turf(src) + for(var/atom/movable/AM in contents) + AM.forceMove(T) + if(isliving(AM)) + var/mob/living/L = AM + if(L.client) + L.client.eye = L + L.client.perspective = MOB_PERSPECTIVE + occupant = null + +/obj/machinery/proc/close_machine(mob/living/target = null) + state_open = 0 + density = 1 + if(!target) + for(var/mob/living/carbon/C in loc) + if(C.buckled) + continue + else + target = C + if(target && !target.buckled) + if(target.client) + target.client.perspective = EYE_PERSPECTIVE + target.client.eye = src + occupant = target + target.loc = src + target.stop_pulling() + if(target.pulledby) + target.pulledby.stop_pulling() + updateUsrDialog() + update_icon() + +/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) + +//sets the use_power var and then forces an area power update @ 7e65984ae2ec4e7eaaecc8da0bfa75642c3489c7 bay12 +/obj/machinery/proc/update_use_power(new_use_power, force_update = 0) + if ((new_use_power == use_power) && !force_update) + return //don't need to do anything + + use_power = new_use_power + + //force area power update + //use_power() forces an area power update on the next tick so have to pass the correct power amount for this tick + if (use_power >= 2) + use_power(active_power_usage) + else if (use_power == 1) + use_power(idle_power_usage) + else + use_power(0) + +/obj/machinery/proc/auto_use_power() + if(!powered(power_channel)) + return 0 + if(src.use_power == 1) + use_power(idle_power_usage,power_channel, 1) + else if(src.use_power >= 2) + use_power(active_power_usage,power_channel, 1) + return 1 + +//By default, we check everything. +//But sometimes, we need to override this check. +/obj/machinery/proc/is_operational_topic() + return !((stat & (NOPOWER|BROKEN|MAINT|EMPED)) || (panel_open && !interact_open)) + +/obj/machinery/Topic(href, href_list) + ..() + + if(usr.can_use_topic(src) != STATUS_INTERACTIVE || !is_operational_topic()) + usr.unset_machine(src) + return FALSE + + if(!can_mob_interact(usr)) + return FALSE + + if((allowed_checks & ALLOWED_CHECK_TOPIC) && !emagged && !allowed(usr)) + allowed_fail(usr) + to_chat(usr, "Access Denied.") + return FALSE + + usr.set_machine(src) + add_fingerprint(usr) + + var/area/A = get_area(src) + A.master.powerupdate = 1 + + return TRUE + +/obj/machinery/proc/is_operational() + return !(stat & (NOPOWER|BROKEN|MAINT)) + +/obj/machinery/proc/issilicon_allowed(mob/living/silicon/S) + if(istype(S) && allowed(S)) + return TRUE + return FALSE + +/obj/machinery/proc/is_interactable() + if((stat & (NOPOWER|BROKEN)) && !interact_offline) + return FALSE + if(panel_open && !interact_open) + return FALSE + return TRUE + +/obj/machinery/proc/allowed_fail(mob/user) // incase you want to add something special when allowed fails. + return + +//////////////////////////////////////////////////////////////////////////////////////////// + +/obj/machinery/interact(mob/user) + if(issilicon(user) || isobserver(user)) + add_hiddenprint(user) + else if(isliving(user)) + add_fingerprint(user) + if(ui_interact(user) != -1) + user.set_machine(src) + +/obj/machinery/attack_ai(mob/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 attack_hand(user) + else + return attack_hand(user) + +/obj/machinery/attack_paw(mob/user) + return attack_hand(user) + +// set_machine must be 0 if clicking the machinery doesn't bring up a dialog +/obj/machinery/attack_hand(mob/user) + if ((user.lying || user.stat) && !IsAdminGhost(user)) + return 1 + if(!is_interactable()) + return 1 + if (!(ishuman(user) || issilicon(user) || ismonkey(user) || isalienqueen(user) || IsAdminGhost(user))) + to_chat(user, "You don't have the dexterity to do this!") + return 1 + if (!can_mob_interact(user)) + return 1 + if(hasvar(src, "wires")) // Lets close wires window if panel is closed. + var/datum/wires/DW = vars["wires"] // Wires and machinery that uses this feature actually should be refactored. + if(istype(DW) && !DW.can_use(user)) // Many of them do not use panel_open var. + DW.Topic("close=1", list("close"="1")) + if((allowed_checks & ALLOWED_CHECK_A_HAND) && !emagged && !allowed(user)) + allowed_fail(user) + to_chat(user, "Access Denied.") + return 1 + + var/area/A = get_area(src) + A.master.powerupdate = 1 // <- wtf is this var and its comments... + + interact(user) + return 0 + +/obj/machinery/CheckParts(list/parts_list) + ..() + RefreshParts() + +/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/default_pry_open(obj/item/weapon/crowbar/C) + . = !(state_open || panel_open || is_operational() || (flags & NODECONSTRUCT)) && istype(C) + if(.) + playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) + visible_message("[usr] pry open \the [src].", "You pry open \the [src].") + open_machine() + return 1 + +/obj/machinery/proc/default_deconstruction_crowbar(obj/item/weapon/crowbar/C, ignore_panel = 0) + . = istype(C) && (panel_open || ignore_panel) && !(flags & NODECONSTRUCT) + if(.) + deconstruction() + playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) + var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(loc) + transfer_fingerprints_to(M) + M.state = 2 + M.icon_state = "box_1" + for(var/obj/item/I in component_parts) + if(I.reliability != 100 && crit_fail) + I.crit_fail = 1 + I.loc = loc + qdel(src) + +/obj/machinery/proc/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/weapon/screwdriver/S) + if(istype(S) && !(flags & NODECONSTRUCT)) + playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1) + if(!panel_open) + panel_open = 1 + icon_state = icon_state_open + to_chat(user, "You open the maintenance hatch of [src].") + else + panel_open = 0 + icon_state = icon_state_closed + to_chat(user, "You close the maintenance hatch of [src].") + return 1 + return 0 + +/obj/machinery/proc/default_change_direction_wrench(mob/user, obj/item/weapon/wrench/W) + if(panel_open && istype(W)) + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + dir = turn(dir,-90) + to_chat(user, "You rotate [src].") + return 1 + return 0 + +/obj/proc/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20) + if(istype(W) && !(flags & NODECONSTRUCT)) + if(user.is_busy()) return + to_chat(user, "You begin [anchored ? "un" : ""]securing [name]...") + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, time/W.toolspeed, target = src)) + to_chat(user, "You [anchored ? "un" : ""]secure [name].") + anchored = !anchored + playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1) + return 1 + return 0 + +/obj/machinery/proc/exchange_parts(mob/user, obj/item/weapon/storage/part_replacer/W) + var/shouldplaysound = 0 + if(istype(W) && component_parts) + if(panel_open || W.works_from_distance) + var/obj/item/weapon/circuitboard/CB = locate(/obj/item/weapon/circuitboard) in component_parts + var/P + if(W.works_from_distance) + to_chat(user, "Following parts detected in the machine:") + for(var/var/obj/item/C in component_parts) + to_chat(user, " [C.name]") + for(var/obj/item/weapon/stock_parts/A in component_parts) + for(var/D in CB.req_components) + if(ispath(A.type, D)) + P = D + break + for(var/obj/item/weapon/stock_parts/B in W.contents) + if(istype(B, P) && istype(A, P)) + if(B.rating > A.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 + +/obj/machinery/proc/display_parts(mob/user) + to_chat(user, "Following parts detected in the machine:") + for(var/obj/item/C in component_parts) + to_chat(user, "[bicon(C)] [C.name]") + +//called on machinery construction (i.e from frame to machinery) but not on initialization +/obj/machinery/proc/construction() + return + +//called on deconstruction before the final deletion +/obj/machinery/proc/deconstruction() + return + +/obj/machinery/proc/state(msg) + for(var/mob/O in hearers(src, null)) + O.show_message("[bicon(src)] [msg]", 2) + +/obj/machinery/proc/ping(text=null) + if (!text) + text = "\The [src] pings." + + state(text, "blue") + playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) + +/obj/machinery/tesla_act(power) + ..() + if(prob(85)) + emp_act(2) + else if(prob(50)) + ex_act(3) + else if(prob(90)) + ex_act(2) + else + ex_act(1) diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index bb65e89b143c..913fef8693e9 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -1,384 +1,384 @@ -// 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 - -/obj/machinery/magnetic_module/atom_init() - . = ..() - var/turf/T = loc - hide(T.intact) - center = T - radio_controller.add_object(src, freq, RADIO_MAGNETS) - INVOKE_ASYNC(src, .proc/magnetic_process) - - // update the invisibility and icon -/obj/machinery/magnetic_module/hide(intact) - invisibility = intact ? 101 : 0 - updateicon() - - // update the icon_state -/obj/machinery/magnetic_module/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]" - -/obj/machinery/magnetic_module/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) - - -/obj/machinery/magnetic_module/proc/Cmd(command, 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() - - -/obj/machinery/magnetic_module/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) - qdel(src) - */ - - updateicon() - - -/obj/machinery/magnetic_module/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.flags & CONDUCT)) - 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_module/Destroy() - if(radio_controller) - radio_controller.remove_object(src, freq) - return ..() - -/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 - 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 - - - - -/obj/machinery/magnetic_controller/atom_init() - . = ..() - - if(autolink) - for(var/obj/machinery/magnetic_module/M in machines) - if(M.freq == frequency && M.code == code) - magnets.Add(M) - - radio_connection = radio_controller.add_object(src, frequency, RADIO_MAGNETS) - - if(path) // check for default path - filter_path() // renders rpath - - -/obj/machinery/magnetic_controller/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) - - -/obj/machinery/magnetic_controller/ui_interact(mob/user) - 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] +
    " - - dat += "
    Speed: - [speed] +
    " - dat += "Path: {[path]}
    " - dat += "Moving: [moving ? "Enabled":"Disabled"]" - - user << browse(entity_ja(dat), "window=magnet;size=400x500") - onclose(user, "magnet") - -/obj/machinery/magnetic_controller/Topic(href, href_list) - . = ..() - if(!.) - return - - if(href_list["radio-op"]) - - // Prepare signal beforehand, because this is a radio operation - var/datum/signal/signal = new - 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 = sanitize_safe(input(usr, "Please define a new path!",,input_default(path)) as text|null) - 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() - -/obj/machinery/magnetic_controller/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 = new - 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) - 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 - - -/obj/machinery/magnetic_controller/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 to maximum_character) // 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 - -/obj/machinery/magnetic_controller/Destroy() - if(radio_controller) - radio_controller.remove_object(src, frequency) - return ..() +// 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 + +/obj/machinery/magnetic_module/atom_init() + . = ..() + var/turf/T = loc + hide(T.intact) + center = T + radio_controller.add_object(src, freq, RADIO_MAGNETS) + INVOKE_ASYNC(src, .proc/magnetic_process) + + // update the invisibility and icon +/obj/machinery/magnetic_module/hide(intact) + invisibility = intact ? 101 : 0 + updateicon() + + // update the icon_state +/obj/machinery/magnetic_module/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]" + +/obj/machinery/magnetic_module/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) + + +/obj/machinery/magnetic_module/proc/Cmd(command, 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() + + +/obj/machinery/magnetic_module/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) + qdel(src) + */ + + updateicon() + + +/obj/machinery/magnetic_module/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.flags & CONDUCT)) + 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_module/Destroy() + if(radio_controller) + radio_controller.remove_object(src, freq) + return ..() + +/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 + 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 + + + + +/obj/machinery/magnetic_controller/atom_init() + . = ..() + + if(autolink) + for(var/obj/machinery/magnetic_module/M in machines) + if(M.freq == frequency && M.code == code) + magnets.Add(M) + + radio_connection = radio_controller.add_object(src, frequency, RADIO_MAGNETS) + + if(path) // check for default path + filter_path() // renders rpath + + +/obj/machinery/magnetic_controller/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) + + +/obj/machinery/magnetic_controller/ui_interact(mob/user) + 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] +
    " + + dat += "
    Speed: - [speed] +
    " + dat += "Path: {[path]}
    " + dat += "Moving: [moving ? "Enabled":"Disabled"]" + + user << browse(entity_ja(dat), "window=magnet;size=400x500") + onclose(user, "magnet") + +/obj/machinery/magnetic_controller/Topic(href, href_list) + . = ..() + if(!.) + return + + if(href_list["radio-op"]) + + // Prepare signal beforehand, because this is a radio operation + var/datum/signal/signal = new + 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 = sanitize_safe(input(usr, "Please define a new path!",,input_default(path)) as text|null) + 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() + +/obj/machinery/magnetic_controller/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 = new + 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) + 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 + + +/obj/machinery/magnetic_controller/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 to maximum_character) // 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 + +/obj/machinery/magnetic_controller/Destroy() + if(radio_controller) + radio_controller.remove_object(src, frequency) + return ..() diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index 5e094e8cc353..489ba88d62a5 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -1,48 +1,48 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/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 - - var/power = 1.0 - var/code = 1.0 - var/id = 1.0 - 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/atom_init() - . = ..() - mass_driver_list += src - -/obj/machinery/mass_driver/Destroy() - mass_driver_list -= src - return ..() - -/obj/machinery/mass_driver/proc/drive(amount) - if(stat & (BROKEN|NOPOWER)) - return - use_power(500) - var/O_limit - 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) - for(var/mob/M in hearers(src, null)) - to_chat(M, "\blue The mass driver lets out a screech, it mustn't be able to handle any more items.") - break - use_power(500) - O.throw_at(target, drive_range * power, power) - flick("mass_driver1", src) - return - -/obj/machinery/mass_driver/emp_act(severity) - if(stat & (BROKEN|NOPOWER)) - return - drive() - ..(severity) +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/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 + + var/power = 1.0 + var/code = 1.0 + var/id = 1.0 + 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/atom_init() + . = ..() + mass_driver_list += src + +/obj/machinery/mass_driver/Destroy() + mass_driver_list -= src + return ..() + +/obj/machinery/mass_driver/proc/drive(amount) + if(stat & (BROKEN|NOPOWER)) + return + use_power(500) + var/O_limit + 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) + for(var/mob/M in hearers(src, null)) + to_chat(M, "\blue The mass driver lets out a screech, it mustn't be able to handle any more items.") + break + use_power(500) + O.throw_at(target, drive_range * power, power) + flick("mass_driver1", src) + return + +/obj/machinery/mass_driver/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + return + drive() + ..(severity) diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index ac727199a23c..747ba0e5c20c 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -1,226 +1,226 @@ -// 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 - interact_offline = TRUE - - var/open = 0 // true if cover is open - 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) - -/obj/machinery/navbeacon/atom_init() - . = ..() - set_codes() - var/turf/T = loc - hide(T.intact) - radio_controller.add_object(src, freq, RADIO_NAVBEACONS) - -/obj/machinery/navbeacon/Destroy() - if(radio_controller) - radio_controller.remove_object(src, freq) - return ..() - - // set the transponder codes assoc list from codes_txt -/obj/machinery/navbeacon/proc/set_codes() - if(!codes_txt) - return - - codes = new() - - var/list/entries = splittext(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 -/obj/machinery/navbeacon/hide(intact) - invisibility = intact ? 101 : 0 - updateicon() - - // update the icon_state -/obj/machinery/navbeacon/proc/updateicon() - var/state="navbeacon[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 -/obj/machinery/navbeacon/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 - -/obj/machinery/navbeacon/proc/post_signal() - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) - return - - var/datum/signal/signal = new() - 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) - - -/obj/machinery/navbeacon/attackby(obj/item/I, mob/user) - var/turf/T = loc - if(T.intact) - return // prevent intraction when T-scanner revealed - - if(istype(I, /obj/item/weapon/screwdriver)) - open = !open - user.SetNextMove(CLICK_CD_RAPID) - - user.visible_message("[user] [open ? "opens" : "closes"] the beacon's cover.", "You [open ? "open" : "close"] the beacon's cover.") - - updateicon() - - else if (istype(I, /obj/item/weapon/card/id)||istype(I, /obj/item/device/pda)) - if(open) - if (src.allowed(user)) - src.locked = !src.locked - to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]") - else - to_chat(user, "\red Access denied.") - updateDialog() - else - to_chat(user, "You must open the cover first!") - return - -/obj/machinery/navbeacon/attack_paw() - return - -/obj/machinery/navbeacon/ui_interact(mob/user) - var/ai = isAI(user) || isobserver(user) - - var/turf/T = loc - if(T.intact) - return // prevent intraction when T-scanner revealed - - if(!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) - t += "
        • [key] ... [codes[key]]" - t += " (edit)" - t += " (delete)
          " - t += "(add new)
          " - t+= "
            " - - user << browse(entity_ja(t), "window=navbeacon") - onclose(user, "navbeacon") - -/obj/machinery/navbeacon/Topic(href, href_list) - . = ..() - if(!. || ((!open || locked) && !issilicon(usr) && !isobserver(usr))) - return FALSE - - if (href_list["freq"]) - freq = sanitize_frequency(freq + text2num(href_list["freq"])) - - else if(href_list["locedit"]) - var/newloc = sanitize_safe(input("Enter New Location", "Navigation Beacon", input_default(location)) as text|null) - if(newloc) - location = newloc - - else if(href_list["edit"]) - var/codekey = href_list["code"] - - var/newkey = sanitize_safe(input("Enter Transponder Code Key", "Navigation Beacon", input_default(codekey)) as text|null) - if(!newkey) - return FALSE - - var/codeval = codes[codekey] - var/newval = sanitize_safe(input("Enter Transponder Code Value", "Navigation Beacon", input_default(codeval)) as text|null) - if(!newval) - return FALSE - - codes.Remove(codekey) - codes[newkey] = newval - - updateDialog() - - else if(href_list["delete"]) - var/codekey = href_list["code"] - codes.Remove(codekey) - - else if(href_list["add"]) - var/newkey = sanitize(input("Enter New Transponder Code Key", "Navigation Beacon") as text|null) - if(!newkey) - return FALSE - - var/newval = sanitize(input("Enter New Transponder Code Value", "Navigation Beacon") as text|null) - if(!newval) - return FALSE - - if(!codes) - codes = new() - - codes[newkey] = newval - - updateDialog() +// 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 + interact_offline = TRUE + + var/open = 0 // true if cover is open + 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) + +/obj/machinery/navbeacon/atom_init() + . = ..() + set_codes() + var/turf/T = loc + hide(T.intact) + radio_controller.add_object(src, freq, RADIO_NAVBEACONS) + +/obj/machinery/navbeacon/Destroy() + if(radio_controller) + radio_controller.remove_object(src, freq) + return ..() + + // set the transponder codes assoc list from codes_txt +/obj/machinery/navbeacon/proc/set_codes() + if(!codes_txt) + return + + codes = new() + + var/list/entries = splittext(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 +/obj/machinery/navbeacon/hide(intact) + invisibility = intact ? 101 : 0 + updateicon() + + // update the icon_state +/obj/machinery/navbeacon/proc/updateicon() + var/state="navbeacon[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 +/obj/machinery/navbeacon/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 + +/obj/machinery/navbeacon/proc/post_signal() + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) + return + + var/datum/signal/signal = new() + 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) + + +/obj/machinery/navbeacon/attackby(obj/item/I, mob/user) + var/turf/T = loc + if(T.intact) + return // prevent intraction when T-scanner revealed + + if(istype(I, /obj/item/weapon/screwdriver)) + open = !open + user.SetNextMove(CLICK_CD_RAPID) + + user.visible_message("[user] [open ? "opens" : "closes"] the beacon's cover.", "You [open ? "open" : "close"] the beacon's cover.") + + updateicon() + + else if (istype(I, /obj/item/weapon/card/id)||istype(I, /obj/item/device/pda)) + if(open) + if (src.allowed(user)) + src.locked = !src.locked + to_chat(user, "Controls are now [src.locked ? "locked." : "unlocked."]") + else + to_chat(user, "\red Access denied.") + updateDialog() + else + to_chat(user, "You must open the cover first!") + return + +/obj/machinery/navbeacon/attack_paw() + return + +/obj/machinery/navbeacon/ui_interact(mob/user) + var/ai = isAI(user) || isobserver(user) + + var/turf/T = loc + if(T.intact) + return // prevent intraction when T-scanner revealed + + if(!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) + t += "
                • [key] ... [codes[key]]" + t += " (edit)" + t += " (delete)
                  " + t += "(add new)
                  " + t+= "
                    " + + user << browse(entity_ja(t), "window=navbeacon") + onclose(user, "navbeacon") + +/obj/machinery/navbeacon/Topic(href, href_list) + . = ..() + if(!. || ((!open || locked) && !issilicon(usr) && !isobserver(usr))) + return FALSE + + if (href_list["freq"]) + freq = sanitize_frequency(freq + text2num(href_list["freq"])) + + else if(href_list["locedit"]) + var/newloc = sanitize_safe(input("Enter New Location", "Navigation Beacon", input_default(location)) as text|null) + if(newloc) + location = newloc + + else if(href_list["edit"]) + var/codekey = href_list["code"] + + var/newkey = sanitize_safe(input("Enter Transponder Code Key", "Navigation Beacon", input_default(codekey)) as text|null) + if(!newkey) + return FALSE + + var/codeval = codes[codekey] + var/newval = sanitize_safe(input("Enter Transponder Code Value", "Navigation Beacon", input_default(codeval)) as text|null) + if(!newval) + return FALSE + + codes.Remove(codekey) + codes[newkey] = newval + + updateDialog() + + else if(href_list["delete"]) + var/codekey = href_list["code"] + codes.Remove(codekey) + + else if(href_list["add"]) + var/newkey = sanitize(input("Enter New Transponder Code Key", "Navigation Beacon") as text|null) + if(!newkey) + return FALSE + + var/newval = sanitize(input("Enter New Transponder Code Value", "Navigation Beacon") as text|null) + if(!newval) + return FALSE + + if(!codes) + codes = new() + + codes[newkey] = newval + + updateDialog() diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm index 1e1f843fa1f3..c26d5b154afe 100644 --- a/code/game/machinery/overview.dm +++ b/code/game/machinery/overview.dm @@ -1,362 +1,362 @@ -//#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(mob/user) - - 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; i
                    [message]" + + screen = 6 + Console.set_light(2) + messages += "Message sent to [dpt]
                    [message]" + else + for (var/mob/O in hearers(4, src.loc)) + O.show_message(text("[bicon(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) //choose priority + 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 FALSE + 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 + + updateUsrDialog() + + //err... hacking code, which has no reason for existing... but anyway... it's supposed to unlock priority 3 messanging on that console (EXTREME priority...) the code for that actually exists. +/obj/machinery/requests_console/attackby(obj/item/weapon/O, mob/user) + /* + if (istype(O, /obj/item/weapon/crowbar)) + if(open) + open = 0 + icon_state="req_comp0" + else + open = 1 + if(hackState == 0) + icon_state="req_comp_open" + else if(hackState == 1) + icon_state="req_comp_rewired" + if (istype(O, /obj/item/weapon/screwdriver)) + if(open) + if(hackState == 0) + hackState = 1 + icon_state="req_comp_rewired" + else if(hackState == 1) + hackState = 0 + icon_state="req_comp_open" + else + to_chat(user, "You can't do much with that.")*/ + + if (istype(O, /obj/item/weapon/card/id)) + if(screen == 9) + var/obj/item/weapon/card/id/T = O + msgVerified = text("Verified by [T.registered_name] ([T.assignment])") + updateUsrDialog() + if(screen == 10) + var/obj/item/weapon/card/id/ID = O + if (access_RC_announce in ID.GetAccess()) + announceAuth = 1 + else + announceAuth = 0 + to_chat(user, "\red 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 diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm index 04f0d6e82201..3e809f8ee221 100644 --- a/code/game/machinery/robot_fabricator.dm +++ b/code/game/machinery/robot_fabricator.dm @@ -1,134 +1,134 @@ -/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 - allowed_checks = ALLOWED_CHECK_TOPIC - -/obj/machinery/robotic_fabricator/attackby(obj/item/O, mob/user) - if (istype(O, /obj/item/stack/sheet/metal)) - var/obj/item/stack/sheet/metal/M = O - if (src.metal_amount < 150000.0) - var/count = 0 - src.overlays += "fab-load-metal" - spawn(15) - if(!M.get_amount()) - return - while(metal_amount < 150000 && M.use(1)) - src.metal_amount += M.m_amt /*O:height * O:width * O:length * 100000.0*/ - count++ - - to_chat(user, "You insert [count] metal sheet\s into the fabricator.") - 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/ui_interact(user) - var/dat - - 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[entity_ja(dat)]", "window=robot_fabricator") - onclose(user, "robot_fabricator") - -/obj/machinery/robotic_fabricator/Topic(href, href_list) - . = ..() - if(!.) - return - - 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" - - 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" - - updateUsrDialog() +/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 + allowed_checks = ALLOWED_CHECK_TOPIC + +/obj/machinery/robotic_fabricator/attackby(obj/item/O, mob/user) + if (istype(O, /obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/M = O + if (src.metal_amount < 150000.0) + var/count = 0 + src.overlays += "fab-load-metal" + spawn(15) + if(!M.get_amount()) + return + while(metal_amount < 150000 && M.use(1)) + src.metal_amount += M.m_amt /*O:height * O:width * O:length * 100000.0*/ + count++ + + to_chat(user, "You insert [count] metal sheet\s into the fabricator.") + 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/ui_interact(user) + var/dat + + 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[entity_ja(dat)]", "window=robot_fabricator") + onclose(user, "robot_fabricator") + +/obj/machinery/robotic_fabricator/Topic(href, href_list) + . = ..() + if(!.) + return + + 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" + + 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" + + updateUsrDialog() diff --git a/code/game/machinery/seed_extractor.dm b/code/game/machinery/seed_extractor.dm index 96830792c402..42df6194fbc6 100644 --- a/code/game/machinery/seed_extractor.dm +++ b/code/game/machinery/seed_extractor.dm @@ -1,97 +1,97 @@ -/obj/machinery/seed_extractor - name = "seed extractor" - desc = "Extracts and bags seeds from produce." - icon = 'icons/obj/hydroponics/equipment.dmi' - icon_state = "sextractor" - density = 1 - anchored = 1 - var/max_seeds = 1000 - var/seed_multiplier = 1 - -/obj/machinery/seed_extractor/atom_init() - . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/seed_extractor(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - RefreshParts() - -/obj/machinery/seed_extractor/RefreshParts() - for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) - max_seeds = 1000 * B.rating - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - seed_multiplier = M.rating - - -/obj/machinery/seed_extractor/attackby(obj/item/O, mob/user) - - if(default_deconstruction_screwdriver(user, "sextractor_open", "sextractor", O)) - return - - if(exchange_parts(user, O)) - return - - if(default_pry_open(O)) - return - - if(default_unfasten_wrench(user, O)) - return - - default_deconstruction_crowbar(O) - - if(istype(O, /obj/item/weapon/organ)) - var/obj/item/weapon/organ/IO = O - if(IO.specie == DIONA) - to_chat(user, "You extract some seeds from the [IO.name].") - var/t_amount = 0 - var/t_max = rand(1,4) - for(var/I in t_amount to t_max) - new /obj/item/seeds/replicapod(loc) - qdel(IO) - - if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/)) - var/obj/item/weapon/reagent_containers/food/snacks/grown/F = O - user.drop_item() - to_chat(user, "You extract some seeds from the [F.name].") - var/seed = text2path(F.seed) - var/t_amount = 0 - var/t_max = rand(1,4) - while(t_amount < t_max) - var/obj/item/seeds/t_prod = new seed(loc) - t_prod.species = F.species - t_prod.lifespan = F.lifespan - t_prod.endurance = F.endurance - t_prod.maturation = F.maturation - t_prod.production = F.production - t_prod.yield = F.yield - t_prod.potency = F.potency - t_amount++ - qdel(O) - - else if(istype(O, /obj/item/weapon/grown/)) - var/obj/item/weapon/grown/F = O - user.drop_item() - to_chat(user, "You extract some seeds from the [F.name].") - var/seed = text2path(F.seed) - var/t_amount = 0 - var/t_max = rand(1,4) - while(t_amount < t_max) - var/obj/item/seeds/t_prod = new seed(loc) - t_prod.species = F.species - t_prod.lifespan = F.lifespan - t_prod.endurance = F.endurance - t_prod.maturation = F.maturation - t_prod.production = F.production - t_prod.yield = F.yield - t_prod.potency = F.potency - t_amount++ - qdel(O) - - else if(istype(O, /obj/item/stack/tile/grass)) - var/obj/item/stack/tile/grass/S = O - if(!S.use(1)) - return - to_chat(user, "You extract some seeds from the [S.name].") - new /obj/item/seeds/grassseed(loc) - - return +/obj/machinery/seed_extractor + name = "seed extractor" + desc = "Extracts and bags seeds from produce." + icon = 'icons/obj/hydroponics/equipment.dmi' + icon_state = "sextractor" + density = 1 + anchored = 1 + var/max_seeds = 1000 + var/seed_multiplier = 1 + +/obj/machinery/seed_extractor/atom_init() + . = ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/seed_extractor(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + RefreshParts() + +/obj/machinery/seed_extractor/RefreshParts() + for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts) + max_seeds = 1000 * B.rating + for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + seed_multiplier = M.rating + + +/obj/machinery/seed_extractor/attackby(obj/item/O, mob/user) + + if(default_deconstruction_screwdriver(user, "sextractor_open", "sextractor", O)) + return + + if(exchange_parts(user, O)) + return + + if(default_pry_open(O)) + return + + if(default_unfasten_wrench(user, O)) + return + + default_deconstruction_crowbar(O) + + if(istype(O, /obj/item/weapon/organ)) + var/obj/item/weapon/organ/IO = O + if(IO.specie == DIONA) + to_chat(user, "You extract some seeds from the [IO.name].") + var/t_amount = 0 + var/t_max = rand(1,4) + for(var/I in t_amount to t_max) + new /obj/item/seeds/replicapod(loc) + qdel(IO) + + if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/)) + var/obj/item/weapon/reagent_containers/food/snacks/grown/F = O + user.drop_item() + to_chat(user, "You extract some seeds from the [F.name].") + var/seed = text2path(F.seed) + var/t_amount = 0 + var/t_max = rand(1,4) + while(t_amount < t_max) + var/obj/item/seeds/t_prod = new seed(loc) + t_prod.species = F.species + t_prod.lifespan = F.lifespan + t_prod.endurance = F.endurance + t_prod.maturation = F.maturation + t_prod.production = F.production + t_prod.yield = F.yield + t_prod.potency = F.potency + t_amount++ + qdel(O) + + else if(istype(O, /obj/item/weapon/grown/)) + var/obj/item/weapon/grown/F = O + user.drop_item() + to_chat(user, "You extract some seeds from the [F.name].") + var/seed = text2path(F.seed) + var/t_amount = 0 + var/t_max = rand(1,4) + while(t_amount < t_max) + var/obj/item/seeds/t_prod = new seed(loc) + t_prod.species = F.species + t_prod.lifespan = F.lifespan + t_prod.endurance = F.endurance + t_prod.maturation = F.maturation + t_prod.production = F.production + t_prod.yield = F.yield + t_prod.potency = F.potency + t_amount++ + qdel(O) + + else if(istype(O, /obj/item/stack/tile/grass)) + var/obj/item/stack/tile/grass/S = O + if(!S.use(1)) + return + to_chat(user, "You extract some seeds from the [S.name].") + new /obj/item/seeds/grassseed(loc) + + return diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index 5615b0631fa1..8158d9f947f7 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -1,629 +1,629 @@ -/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 - var/const/max_health = 200 - var/health = max_health //The shield can only take so much beating (prevents perma-prisons) - -/obj/machinery/shield/atom_init() - dir = pick(1,2,3,4) - . = ..() - update_nearby_tiles(need_rebuild = 1) - -/obj/machinery/shield/Destroy() - opacity = 0 - density = 0 - update_nearby_tiles() - return ..() - -/obj/machinery/shield/CanPass(atom/movable/mover, turf/target, height, air_group) - if(!height || air_group) return 0 - else return ..() - -/obj/machinery/shield/attackby(obj/item/weapon/W, mob/user) - 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(src.loc, 'sound/effects/EMPulse.ogg', 75, 1) - - user.SetNextMove(CLICK_CD_MELEE) - if (src.health <= 0) - visible_message("\blue The [src] dissipates!") - qdel(src) - return - - opacity = 1 - spawn(20) if(src) opacity = 0 - - ..() - -/obj/machinery/shield/meteorhit() - src.health -= max_health*0.75 //3/4 health as damage - - if(src.health <= 0) - visible_message("\blue The [src] dissipates!") - qdel(src) - return - - opacity = 1 - spawn(20) if(src) opacity = 0 - return - -/obj/machinery/shield/bullet_act(obj/item/projectile/Proj) - health -= Proj.damage - ..() - if(health <=0) - visible_message("\blue The [src] dissipates!") - 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) - return - -/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) - //Let everyone know we've been hit! - visible_message("\red [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(src.loc, 'sound/effects/EMPulse.ogg', 100, 1) - - //Handle the destruction of the shield - if (src.health <= 0) - visible_message("\blue The [src] dissipates!") - 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 = TRUE - opacity = FALSE - anchored = FALSE - req_access = list(access_engine) - var/const/max_health = 100 - var/health = max_health - var/active = FALSE - var/malfunction = FALSE //Malfunction causes parts of the shield to slowly dissapate - var/list/deployed_shields = list() - var/is_open = FALSE //Whether or not the wires are exposed - var/locked = FALSE - -/obj/machinery/shieldgen/Destroy() - for(var/obj/machinery/shield/shield_tile in deployed_shields) - deployed_shields -= shield_tile - qdel(shield_tile) - return ..() - - -/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)) - - return - -/obj/machinery/shieldgen/proc/checkhp() - if(health <= 30) - src.malfunction = 1 - if(health <= 0) - qdel(src) - update_icon() - return - -/obj/machinery/shieldgen/meteorhit(obj/O) - src.health -= max_health*0.25 //A quarter of the machine's health - if (prob(5)) - src.malfunction = 1 - src.checkhp() - return - -/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() - return - -/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_hand(mob/user) - . = ..() - if(.) - return - if(locked && !IsAdminGhost(user)) - to_chat(user, "The machine is locked, you are unable to use it.") - return 1 - if(is_open) - to_chat(user, "The panel must be closed before operating this machine.") - return 1 - user.SetNextMove(CLICK_CD_INTERACT) - if (src.active) - user.visible_message("\blue [bicon(src)] [user] deactivated the shield generator.", \ - "\blue [bicon(src)] You deactivate the shield generator.", \ - "You hear heavy droning fade out.") - src.shields_down() - else - if(anchored) - user.visible_message("\blue [bicon(src)] [user] activated the shield generator.", \ - "\blue [bicon(src)] You activate the shield generator.", \ - "You hear heavy droning.") - src.shields_up() - else - to_chat(user, "The device must first be secured to the floor.") - -/obj/machinery/shieldgen/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/card/emag)) - malfunction = 1 - user.SetNextMove(CLICK_CD_MELEE) - update_icon() - - else if(istype(W, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) - if(is_open) - to_chat(user, "\blue You close the panel.") - is_open = 0 - else - to_chat(user, "\blue You open the panel and expose the wiring.") - is_open = 1 - - else if(istype(W, /obj/item/stack/cable_coil) && malfunction && is_open) - var/obj/item/stack/cable_coil/coil = W - if(user.is_busy(src)) return - to_chat(user, "\blue You begin to replace the wires.") - //if(do_after(user, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage - if(do_after(user, 30, target = src)) - if(QDELETED(src) || !coil.use(1)) - return - - health = max_health - malfunction = 0 - to_chat(user, "\blue You repair the [src]!") - update_icon() - - else if(istype(W, /obj/item/weapon/wrench)) - if(locked) - to_chat(user, "The bolts are covered, unlocking this would retract the covers.") - return - if(anchored) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - to_chat(user, "\blue You unsecure the [src] from the floor!") - if(active) - to_chat(user, "\blue The [src] shuts off!") - src.shields_down() - anchored = 0 - else - if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - to_chat(user, "\blue You secure the [src] to the floor!") - anchored = 1 - - - else 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 - to_chat(user, "\red Access denied.") - - else - ..() - - -/obj/machinery/shieldgen/update_icon() - if(active) - src.icon_state = malfunction ? "shieldonbr":"shieldon" - else - src.icon_state = malfunction ? "shieldoffbr":"shieldoff" - return - -////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 = FALSE - density = TRUE - req_access = list(access_teleporter, access_xenoarch) - flags = CONDUCT - use_power = 0 - var/active = FALSE - var/power = 0 - var/state = 0 - var/steps = 0 - var/last_check = 0 - var/check_delay = 10 - var/recalc = 0 - var/locked = TRUE - var/destroyed = FALSE - var/obj/structure/cable/attached // the attached cable - var/storedpower = 0 - -/obj/machinery/shieldwallgen/proc/power() - if(!anchored) - power = 0 - return 0 - var/turf/T = src.loc - - 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.newload += shieldload //uses powernet power. -// message_admins("[PN.load]", 1) -// use_power(250) //uses APC power - -/obj/machinery/shieldwallgen/attack_hand(mob/user) - . = ..() - if(.) - return - if(state != 1) - to_chat(user, "\red The shield generator needs to be firmly secured to the floor first.") - return 1 - if(src.locked && !issilicon(user) && !IsAdminGhost(user)) - to_chat(user, "\red The controls are locked!") - return 1 - if(power != 1) - to_chat(user, "\red The shield generator needs to be powered by wire underneath.") - return 1 - - user.SetNextMove(CLICK_CD_INTERACT) - if(src.active >= 1) - 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.") - for(var/dir in list(1,2,4,8)) src.cleanup(dir) - 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.") - -/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(!src.state == 1) - 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("\red The [src.name] shuts down due to lack of power!", \ - "You hear heavy droning fade out") - icon_state = "Shield_Gen" - src.active = 0 - for(var/dir in list(1,2,4,8)) src.cleanup(dir) - -/obj/machinery/shieldwallgen/proc/setup_field(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/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/weapon/wrench)) - if(active) - to_chat(user, "Turn off the field generator first.") - return - - else if(state == 0) - state = 1 - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - to_chat(user, "You secure the external reinforcing bolts to the floor.") - src.anchored = 1 - return - - else if(state == 1) - state = 0 - playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) - to_chat(user, "You undo the external reinforcing bolts.") - src.anchored = 0 - 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, "Controls are now [src.locked ? "locked." : "unlocked."]") - else - to_chat(user, "\red Access denied.") - - else - src.add_fingerprint(user) - visible_message("\red The [src.name] has been hit with \the [W.name] by [user.name]!") - user.SetNextMove(CLICK_CD_MELEE) - -/obj/machinery/shieldwallgen/proc/cleanup(NSEW) - var/obj/machinery/shieldwall/F - var/obj/machinery/shieldwallgen/G - var/turf/T = src.loc - var/turf/T2 = src.loc - - for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for fields - T = get_step(T2, NSEW) - T2 = T - if(locate(/obj/machinery/shieldwall) in T) - F = (locate(/obj/machinery/shieldwall) in T) - qdel(F) - - if(locate(/obj/machinery/shieldwallgen) in T) - G = (locate(/obj/machinery/shieldwallgen) in T) - if(!G.active) - break - -/obj/machinery/shieldwallgen/Destroy() - src.cleanup(1) - src.cleanup(2) - src.cleanup(4) - src.cleanup(8) - attached = null - return ..() - -/obj/machinery/shieldwallgen/bullet_act(obj/item/projectile/Proj) - storedpower -= Proj.damage - ..() - return - - -//////////////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 - light_range = 3 - var/needs_power = 0 - var/active = 1 -// var/power = 10 - var/delay = 5 - var/last_active - var/mob/U - var/obj/machinery/shieldwallgen/gen_primary - var/obj/machinery/shieldwallgen/gen_secondary - -/obj/machinery/shieldwall/atom_init(mapload, obj/machinery/shieldwallgen/A, obj/machinery/shieldwallgen/B) - . = ..() - gen_primary = A - gen_secondary = B - if(A && B) - needs_power = 1 - -/obj/machinery/shieldwall/attack_hand(mob/user) - 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(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 - ..() - return - - -/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 - return - - -/obj/machinery/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group || (height==0)) return 1 - - if(istype(mover) && mover.checkpass(PASSGLASS)) - return prob(20) - else - if (istype(mover, /obj/item/projectile)) - return prob(10) - else - return !src.density +/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 + var/const/max_health = 200 + var/health = max_health //The shield can only take so much beating (prevents perma-prisons) + +/obj/machinery/shield/atom_init() + dir = pick(1,2,3,4) + . = ..() + update_nearby_tiles(need_rebuild = 1) + +/obj/machinery/shield/Destroy() + opacity = 0 + density = 0 + update_nearby_tiles() + return ..() + +/obj/machinery/shield/CanPass(atom/movable/mover, turf/target, height, air_group) + if(!height || air_group) return 0 + else return ..() + +/obj/machinery/shield/attackby(obj/item/weapon/W, mob/user) + 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(src.loc, 'sound/effects/EMPulse.ogg', 75, 1) + + user.SetNextMove(CLICK_CD_MELEE) + if (src.health <= 0) + visible_message("\blue The [src] dissipates!") + qdel(src) + return + + opacity = 1 + spawn(20) if(src) opacity = 0 + + ..() + +/obj/machinery/shield/meteorhit() + src.health -= max_health*0.75 //3/4 health as damage + + if(src.health <= 0) + visible_message("\blue The [src] dissipates!") + qdel(src) + return + + opacity = 1 + spawn(20) if(src) opacity = 0 + return + +/obj/machinery/shield/bullet_act(obj/item/projectile/Proj) + health -= Proj.damage + ..() + if(health <=0) + visible_message("\blue The [src] dissipates!") + 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) + return + +/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) + //Let everyone know we've been hit! + visible_message("\red [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(src.loc, 'sound/effects/EMPulse.ogg', 100, 1) + + //Handle the destruction of the shield + if (src.health <= 0) + visible_message("\blue The [src] dissipates!") + 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 = TRUE + opacity = FALSE + anchored = FALSE + req_access = list(access_engine) + var/const/max_health = 100 + var/health = max_health + var/active = FALSE + var/malfunction = FALSE //Malfunction causes parts of the shield to slowly dissapate + var/list/deployed_shields = list() + var/is_open = FALSE //Whether or not the wires are exposed + var/locked = FALSE + +/obj/machinery/shieldgen/Destroy() + for(var/obj/machinery/shield/shield_tile in deployed_shields) + deployed_shields -= shield_tile + qdel(shield_tile) + return ..() + + +/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)) + + return + +/obj/machinery/shieldgen/proc/checkhp() + if(health <= 30) + src.malfunction = 1 + if(health <= 0) + qdel(src) + update_icon() + return + +/obj/machinery/shieldgen/meteorhit(obj/O) + src.health -= max_health*0.25 //A quarter of the machine's health + if (prob(5)) + src.malfunction = 1 + src.checkhp() + return + +/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() + return + +/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_hand(mob/user) + . = ..() + if(.) + return + if(locked && !IsAdminGhost(user)) + to_chat(user, "The machine is locked, you are unable to use it.") + return 1 + if(is_open) + to_chat(user, "The panel must be closed before operating this machine.") + return 1 + user.SetNextMove(CLICK_CD_INTERACT) + if (src.active) + user.visible_message("\blue [bicon(src)] [user] deactivated the shield generator.", \ + "\blue [bicon(src)] You deactivate the shield generator.", \ + "You hear heavy droning fade out.") + src.shields_down() + else + if(anchored) + user.visible_message("\blue [bicon(src)] [user] activated the shield generator.", \ + "\blue [bicon(src)] You activate the shield generator.", \ + "You hear heavy droning.") + src.shields_up() + else + to_chat(user, "The device must first be secured to the floor.") + +/obj/machinery/shieldgen/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/card/emag)) + malfunction = 1 + user.SetNextMove(CLICK_CD_MELEE) + update_icon() + + else if(istype(W, /obj/item/weapon/screwdriver)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + if(is_open) + to_chat(user, "\blue You close the panel.") + is_open = 0 + else + to_chat(user, "\blue You open the panel and expose the wiring.") + is_open = 1 + + else if(istype(W, /obj/item/stack/cable_coil) && malfunction && is_open) + var/obj/item/stack/cable_coil/coil = W + if(user.is_busy(src)) return + to_chat(user, "\blue You begin to replace the wires.") + //if(do_after(user, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage + if(do_after(user, 30, target = src)) + if(QDELETED(src) || !coil.use(1)) + return + + health = max_health + malfunction = 0 + to_chat(user, "\blue You repair the [src]!") + update_icon() + + else if(istype(W, /obj/item/weapon/wrench)) + if(locked) + to_chat(user, "The bolts are covered, unlocking this would retract the covers.") + return + if(anchored) + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + to_chat(user, "\blue You unsecure the [src] from the floor!") + if(active) + to_chat(user, "\blue The [src] shuts off!") + src.shields_down() + anchored = 0 + else + if(istype(get_turf(src), /turf/space)) return //No wrenching these in space! + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + to_chat(user, "\blue You secure the [src] to the floor!") + anchored = 1 + + + else 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 + to_chat(user, "\red Access denied.") + + else + ..() + + +/obj/machinery/shieldgen/update_icon() + if(active) + src.icon_state = malfunction ? "shieldonbr":"shieldon" + else + src.icon_state = malfunction ? "shieldoffbr":"shieldoff" + return + +////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 = FALSE + density = TRUE + req_access = list(access_teleporter, access_xenoarch) + flags = CONDUCT + use_power = 0 + var/active = FALSE + var/power = 0 + var/state = 0 + var/steps = 0 + var/last_check = 0 + var/check_delay = 10 + var/recalc = 0 + var/locked = TRUE + var/destroyed = FALSE + var/obj/structure/cable/attached // the attached cable + var/storedpower = 0 + +/obj/machinery/shieldwallgen/proc/power() + if(!anchored) + power = 0 + return 0 + var/turf/T = src.loc + + 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.newload += shieldload //uses powernet power. +// message_admins("[PN.load]", 1) +// use_power(250) //uses APC power + +/obj/machinery/shieldwallgen/attack_hand(mob/user) + . = ..() + if(.) + return + if(state != 1) + to_chat(user, "\red The shield generator needs to be firmly secured to the floor first.") + return 1 + if(src.locked && !issilicon(user) && !IsAdminGhost(user)) + to_chat(user, "\red The controls are locked!") + return 1 + if(power != 1) + to_chat(user, "\red The shield generator needs to be powered by wire underneath.") + return 1 + + user.SetNextMove(CLICK_CD_INTERACT) + if(src.active >= 1) + 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.") + for(var/dir in list(1,2,4,8)) src.cleanup(dir) + 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.") + +/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(!src.state == 1) + 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("\red The [src.name] shuts down due to lack of power!", \ + "You hear heavy droning fade out") + icon_state = "Shield_Gen" + src.active = 0 + for(var/dir in list(1,2,4,8)) src.cleanup(dir) + +/obj/machinery/shieldwallgen/proc/setup_field(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/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/wrench)) + if(active) + to_chat(user, "Turn off the field generator first.") + return + + else if(state == 0) + state = 1 + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + to_chat(user, "You secure the external reinforcing bolts to the floor.") + src.anchored = 1 + return + + else if(state == 1) + state = 0 + playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) + to_chat(user, "You undo the external reinforcing bolts.") + src.anchored = 0 + 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, "Controls are now [src.locked ? "locked." : "unlocked."]") + else + to_chat(user, "\red Access denied.") + + else + src.add_fingerprint(user) + visible_message("\red The [src.name] has been hit with \the [W.name] by [user.name]!") + user.SetNextMove(CLICK_CD_MELEE) + +/obj/machinery/shieldwallgen/proc/cleanup(NSEW) + var/obj/machinery/shieldwall/F + var/obj/machinery/shieldwallgen/G + var/turf/T = src.loc + var/turf/T2 = src.loc + + for(var/dist = 0, dist <= 9, dist += 1) // checks out to 8 tiles away for fields + T = get_step(T2, NSEW) + T2 = T + if(locate(/obj/machinery/shieldwall) in T) + F = (locate(/obj/machinery/shieldwall) in T) + qdel(F) + + if(locate(/obj/machinery/shieldwallgen) in T) + G = (locate(/obj/machinery/shieldwallgen) in T) + if(!G.active) + break + +/obj/machinery/shieldwallgen/Destroy() + src.cleanup(1) + src.cleanup(2) + src.cleanup(4) + src.cleanup(8) + attached = null + return ..() + +/obj/machinery/shieldwallgen/bullet_act(obj/item/projectile/Proj) + storedpower -= Proj.damage + ..() + return + + +//////////////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 + light_range = 3 + var/needs_power = 0 + var/active = 1 +// var/power = 10 + var/delay = 5 + var/last_active + var/mob/U + var/obj/machinery/shieldwallgen/gen_primary + var/obj/machinery/shieldwallgen/gen_secondary + +/obj/machinery/shieldwall/atom_init(mapload, obj/machinery/shieldwallgen/A, obj/machinery/shieldwallgen/B) + . = ..() + gen_primary = A + gen_secondary = B + if(A && B) + needs_power = 1 + +/obj/machinery/shieldwall/attack_hand(mob/user) + 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(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 + ..() + return + + +/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 + return + + +/obj/machinery/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group || (height==0)) return 1 + + 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 7ca970d57b1f..549f0c8fe056 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -1,302 +1,302 @@ -#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 - -/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 - - frequency = 1435 // radio frequency - var/supply_display = 0 // true if a supply shuttle display - - var/friendc = 0 // track if Friend Computer mode - - maptext_height = 26 - maptext_width = 32 - - // new display - // register for radio system - -/obj/machinery/status_display/atom_init() - . = ..() - status_display_list += src - radio_controller.add_object(src, frequency) - -/obj/machinery/status_display/Destroy() - status_display_list -= src - if(radio_controller) - radio_controller.remove_object(src,frequency) - return ..() - -/obj/machinery/status_display/process() - if(stat & NOPOWER) - remove_display() - return - update() - -/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 - - if(mode == 3 && overlays.len) //Why we must update diplay if picture is already set? - return - - if(overlays.len && !friendc || mode == 4) - overlays.Cut() - - switch(mode) - if(0) //blank - remove_display() - if(1) //emergency shuttle timer - if(SSshuttle.online) - var/line1 - var/line2 = get_shuttle_timer() - if(SSshuttle.location == 1) - line1 = "-ETD-" - else - line1 = "-ETA-" - if(length(line2) > CHARS_PER_LINE) - line2 = "Error!" - update_display(line1, line2) - else - remove_display() - if(2) //custom messages - var/line1 - var/line2 - - if(!index1) - line1 = message1 - else - line1 = copytext(message1+"|"+message1, index1, index1+CHARS_PER_LINE) - var/message1_len = length(message1) - index1 += SCROLL_SPEED - if(index1 > message1_len) - index1 -= message1_len - - if(!index2) - line2 = message2 - else - line2 = copytext(message2+"|"+message2, index2, index2+CHARS_PER_LINE) - var/message2_len = length(message2) - index2 += SCROLL_SPEED - if(index2 > message2_len) - index2 -= message2_len - update_display(line1, line2) - if(4) // supply shuttle timer - var/line1 = "SUPPLY" - var/line2 - if(SSshuttle.moving) - line2 = get_SSshuttle_timer() - if(lentext(line2) > CHARS_PER_LINE) - line2 = "Error" - else - if(SSshuttle.at_station) - line2 = "Docked" - else - line1 = "" - update_display(line1, line2) - -/obj/machinery/status_display/examine(mob/user) - ..() - switch(mode) - if(1,2,4) - to_chat(user, "The display says:
                    [message1]
                    [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 = SSshuttle.timeleft() - if(timeleft) - return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]" - return "" - -/obj/machinery/status_display/proc/get_SSshuttle_timer() - if(SSshuttle.moving) - var/timeleft = round((SSshuttle.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.Cut() - 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 - - update() - - -/obj/machinery/ai_status_display - icon = 'icons/obj/status_display.dmi' - icon_state = "frame" - name = "AI display" - anchored = 1 - density = 0 - - 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/atom_init() - . = ..() - ai_status_display_list += src - -/obj/machinery/ai_status_display/Destroy() - ai_status_display_list -= src - return ..() - -/obj/machinery/ai_status_display/process() - if(stat & NOPOWER) - overlays.Cut() - 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() - - if(mode==0) //Blank - overlays.Cut() - return - - if(mode==1) // AI emoticon - switch(emotion) - if("Very Happy") - set_picture("ai_veryhappy") - if("Happy") - set_picture("ai_happy") - if("Neutral") - set_picture("ai_neutral") - if("Unsure") - set_picture("ai_unsure") - if("Confused") - set_picture("ai_confused") - if("Sad") - set_picture("ai_sad") - if("BSOD") - set_picture("ai_bsod") - if("Blank") - set_picture("ai_off") - if("Problems?") - set_picture("ai_trollface") - if("Awesome") - set_picture("ai_awesome") - if("Dorfy") - set_picture("ai_urist") - if("Facepalm") - set_picture("ai_facepalm") - if("Friend Computer") - set_picture("ai_friend") - if("HAL") - set_picture("ai_hal") - - return - - if(mode==2) // BSOD - set_picture("ai_bsod") - return - - -/obj/machinery/ai_status_display/proc/set_picture(state) - picture_state = state - if(overlays.len) - overlays.Cut() - overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) - -#undef CHARS_PER_LINE -#undef FONT_SIZE -#undef FONT_COLOR -#undef FONT_STYLE -#undef SCROLL_SPEED +#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 + +/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 + + frequency = 1435 // radio frequency + var/supply_display = 0 // true if a supply shuttle display + + var/friendc = 0 // track if Friend Computer mode + + maptext_height = 26 + maptext_width = 32 + + // new display + // register for radio system + +/obj/machinery/status_display/atom_init() + . = ..() + status_display_list += src + radio_controller.add_object(src, frequency) + +/obj/machinery/status_display/Destroy() + status_display_list -= src + if(radio_controller) + radio_controller.remove_object(src,frequency) + return ..() + +/obj/machinery/status_display/process() + if(stat & NOPOWER) + remove_display() + return + update() + +/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 + + if(mode == 3 && overlays.len) //Why we must update diplay if picture is already set? + return + + if(overlays.len && !friendc || mode == 4) + overlays.Cut() + + switch(mode) + if(0) //blank + remove_display() + if(1) //emergency shuttle timer + if(SSshuttle.online) + var/line1 + var/line2 = get_shuttle_timer() + if(SSshuttle.location == 1) + line1 = "-ETD-" + else + line1 = "-ETA-" + if(length(line2) > CHARS_PER_LINE) + line2 = "Error!" + update_display(line1, line2) + else + remove_display() + if(2) //custom messages + var/line1 + var/line2 + + if(!index1) + line1 = message1 + else + line1 = copytext(message1+"|"+message1, index1, index1+CHARS_PER_LINE) + var/message1_len = length(message1) + index1 += SCROLL_SPEED + if(index1 > message1_len) + index1 -= message1_len + + if(!index2) + line2 = message2 + else + line2 = copytext(message2+"|"+message2, index2, index2+CHARS_PER_LINE) + var/message2_len = length(message2) + index2 += SCROLL_SPEED + if(index2 > message2_len) + index2 -= message2_len + update_display(line1, line2) + if(4) // supply shuttle timer + var/line1 = "SUPPLY" + var/line2 + if(SSshuttle.moving) + line2 = get_SSshuttle_timer() + if(lentext(line2) > CHARS_PER_LINE) + line2 = "Error" + else + if(SSshuttle.at_station) + line2 = "Docked" + else + line1 = "" + update_display(line1, line2) + +/obj/machinery/status_display/examine(mob/user) + ..() + switch(mode) + if(1,2,4) + to_chat(user, "The display says:
                    [message1]
                    [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 = SSshuttle.timeleft() + if(timeleft) + return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]" + return "" + +/obj/machinery/status_display/proc/get_SSshuttle_timer() + if(SSshuttle.moving) + var/timeleft = round((SSshuttle.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.Cut() + 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 + + update() + + +/obj/machinery/ai_status_display + icon = 'icons/obj/status_display.dmi' + icon_state = "frame" + name = "AI display" + anchored = 1 + density = 0 + + 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/atom_init() + . = ..() + ai_status_display_list += src + +/obj/machinery/ai_status_display/Destroy() + ai_status_display_list -= src + return ..() + +/obj/machinery/ai_status_display/process() + if(stat & NOPOWER) + overlays.Cut() + 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() + + if(mode==0) //Blank + overlays.Cut() + return + + if(mode==1) // AI emoticon + switch(emotion) + if("Very Happy") + set_picture("ai_veryhappy") + if("Happy") + set_picture("ai_happy") + if("Neutral") + set_picture("ai_neutral") + if("Unsure") + set_picture("ai_unsure") + if("Confused") + set_picture("ai_confused") + if("Sad") + set_picture("ai_sad") + if("BSOD") + set_picture("ai_bsod") + if("Blank") + set_picture("ai_off") + if("Problems?") + set_picture("ai_trollface") + if("Awesome") + set_picture("ai_awesome") + if("Dorfy") + set_picture("ai_urist") + if("Facepalm") + set_picture("ai_facepalm") + if("Friend Computer") + set_picture("ai_friend") + if("HAL") + set_picture("ai_hal") + + return + + if(mode==2) // BSOD + set_picture("ai_bsod") + return + + +/obj/machinery/ai_status_display/proc/set_picture(state) + picture_state = state + if(overlays.len) + overlays.Cut() + overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) + +#undef CHARS_PER_LINE +#undef FONT_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 3abe6c21918c..9048c4c887d4 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -1,564 +1,564 @@ -////////////////////////////////////// -// 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 = "suitstorage000000100" //order is: [has helmet][has suit][has human][is open][is locked][is UV cycling][is powered][is dirty/broken] [is superUVcycling] - anchored = 1 - density = 1 - var/mob/living/carbon/human/OCCUPANT = null - var/obj/item/clothing/suit/space/SUIT = null - var/SUIT_TYPE = null - var/obj/item/clothing/head/helmet/space/HELMET = null - var/HELMET_TYPE = null - var/obj/item/clothing/mask/MASK = null //All the stuff that's gonna be stored insiiiiiiiiiiiiiiiiiiide, nyoro~n - 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/ispowered = 1 //starts powered - var/isbroken = 0 - var/issuperUV = 0 - var/panelopen = 0 - var/safetieson = 1 - var/cycletime_left = 0 - - -//The units themselves///////////////// - -/obj/machinery/suit_storage_unit/standard_unit - SUIT_TYPE = /obj/item/clothing/suit/space/globose - HELMET_TYPE = /obj/item/clothing/head/helmet/space/globose - MASK_TYPE = /obj/item/clothing/mask/breath - -/obj/machinery/suit_storage_unit/syndicate_unit - SUIT_TYPE = /obj/item/clothing/suit/space/rig/syndi - HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/syndi - MASK_TYPE = /obj/item/clothing/mask/gas/syndicate - -/obj/machinery/suit_storage_unit/science - SUIT_TYPE = /obj/item/clothing/suit/space/globose/science - HELMET_TYPE = /obj/item/clothing/head/helmet/space/globose/science - MASK_TYPE = /obj/item/clothing/mask/breath - -/obj/machinery/suit_storage_unit/atom_init() - . = ..() - if(SUIT_TYPE) - SUIT = new SUIT_TYPE(src) - if(HELMET_TYPE) - HELMET = new HELMET_TYPE(src) - if(MASK_TYPE) - MASK = new MASK_TYPE(src) - update_icon() - -/obj/machinery/suit_storage_unit/update_icon() - var/hashelmet = 0 - var/hassuit = 0 - var/hashuman = 0 - if(HELMET) - hashelmet = 1 - if(SUIT) - hassuit = 1 - if(OCCUPANT) - hashuman = 1 - icon_state = text("suitstorage[][][][][][][][][]",hashelmet,hassuit,hashuman,src.isopen,src.islocked,src.isUV,src.ispowered,src.isbroken,src.issuperUV) - - -/obj/machinery/suit_storage_unit/power_change() - if( powered() ) - src.ispowered = 1 - stat &= ~NOPOWER - src.update_icon() - else - spawn(rand(0, 15)) - src.ispowered = 0 - stat |= NOPOWER - src.islocked = 0 - src.isopen = 1 - src.dump_everything() - 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/ui_interact(mob/user) - var/dat - - if(src.panelopen) //The maintenance panel is open. Time for some shady stuff - dat+= "Suit storage unit: Maintenance panel" - dat+= "Maintenance panel controls
                    " - dat+= "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.

                    " - 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(entity_ja(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. - dat += "Suit storage unit" - dat+= "Unit is cauterising contents with selected UV ray intensity. Please wait.
                    " - //dat+= "Cycle end in: [src.cycletimeleft()] seconds. " - //user << browse(entity_ja(dat), "window=ssu_cycling_panel;size=400x500") - //onclose(user, "ssu_cycling_panel") - - else - if(!src.isbroken) - dat+= "Suit storage unit" - dat+= "U-Stor-It Suit Storage Unit, model DS1900
                    " - dat+= "Welcome to the Unit control panel.
                    " - 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) - if(src.OCCUPANT) - dat+= "
                    WARNING: Biological entity detected inside the Unit's storage. Please remove.
                    " - dat+= "Eject extra load" - 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(entity_ja(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. - dat+= "Suit storage unit" - dat+= "Unit chamber is too contaminated to continue usage. Please call for a qualified individual to perform maintenance.

                    " - dat+= text("
                    Close control panel", user) - //user << browse(entity_ja(dat), "window=suit_storage_unit;size=400x500") - //onclose(user, "suit_storage_unit") - - user << browse(entity_ja(dat), "window=suit_storage_unit;size=400x500") - onclose(user, "suit_storage_unit") - - -/obj/machinery/suit_storage_unit/Topic(href, href_list) //I fucking HATE this proc - . = ..() - if(!.) - return - - if (href_list["toggleUV"]) - src.toggleUV(usr) - else if (href_list["togglesafeties"]) - src.togglesafeties(usr) - else if (href_list["dispense_helmet"]) - src.dispense_helmet(usr) - else if (href_list["dispense_suit"]) - src.dispense_suit(usr) - else if (href_list["dispense_mask"]) - src.dispense_mask(usr) - else if (href_list["toggle_open"]) - src.toggle_open(usr) - else if (href_list["toggle_lock"]) - src.toggle_lock(usr) - else if (href_list["start_UV"]) - src.start_UV(usr) - else if (href_list["eject_guy"]) - src.eject_occupant(usr) - - src.updateUsrDialog() - src.update_icon() - - -/obj/machinery/suit_storage_unit/proc/toggleUV(mob/user) -// var/protected = 0 -// var/mob/living/carbon/human/H = user - if(!src.panelopen) - 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(src.loc, "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) -// var/protected = 0 -// var/mob/living/carbon/human/H = user - if(!src.panelopen) //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(src.loc, "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) - 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) - if(!src.SUIT) - return - else - src.SUIT.loc = src.loc - src.SUIT = null - return - - -/obj/machinery/suit_storage_unit/proc/dispense_mask(mob/user) - if(!src.MASK) - return - else - src.MASK.loc = src.loc - src.MASK = 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.OCCUPANT) - src.eject_occupant(OCCUPANT) - return - - -/obj/machinery/suit_storage_unit/proc/toggle_open(mob/user) - 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) - 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) - 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 && !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_bodypart_damage(0, burndamage) - OCCUPANT.emote("scream",,, 1) - else - var/burndamage = rand(6,10) - OCCUPANT.take_bodypart_damage(0, burndamage) - OCCUPANT.emote("scream",,, 1) - if(i==3) //End of the cycle - if(!src.issuperUV) - if(src.HELMET) - HELMET.clean_blood() - if(src.SUIT) - SUIT.clean_blood() - if(src.MASK) - MASK.clean_blood() - else //It was supercycling, destroy everything - if(src.HELMET) - src.HELMET = null - if(src.SUIT) - src.SUIT = null - if(src.MASK) - src.MASK = 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.", 3) - src.isbroken = 1 - 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() - return - -/* spawn(200) //Let's clean dat shit after 20 secs //Eh, this doesn't work - if(src.HELMET) - HELMET.clean_blood() - if(src.SUIT) - SUIT.clean_blood() - if(src.MASK) - MASK.clean_blood() - src.isUV = 0 //Cycle ends - src.update_icon() - src.updateUsrDialog() - - var/i - for(i=0,i<4,i++) //Gradually give the guy inside some damaged based on the intensity - spawn(50) - if(src.OCCUPANT) - if(src.issuperUV) - OCCUPANT.take_bodypart_damage(0, 40) - to_chat(user, "Test. You gave him 40 damage") - else - OCCUPANT.take_bodypart_damage(0, 8) - to_chat(user, "Test. You gave him 8 damage") - return*/ - - -/obj/machinery/suit_storage_unit/proc/cycletimeleft() - if(src.cycletime_left >= 1) - src.cycletime_left-- - return src.cycletime_left - - -/obj/machinery/suit_storage_unit/proc/eject_occupant(mob/user) - 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/container_resist() - var/mob/living/user = usr - if(islocked) - if(user.is_busy()) return - user.next_move = world.time + 100 - user.last_special = world.time + 100 - var/breakout_time = 2 - to_chat(user, "You start kicking against the doors to escape! (This will take about [breakout_time] minutes.)") - visible_message("You see [user] kicking against the doors of the [src]!") - if(do_after(user,(breakout_time*60*10),target=src)) - if(!user || user.stat != CONSCIOUS || user.loc != src || isopen || !islocked) - return - else - isopen = 1 - islocked = 0 - visible_message("[user] successfully broke out of [src]!") - else - return - eject_occupant(user) - add_fingerprint(user) - updateUsrDialog() - 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.stat != CONSCIOUS) - return - if (!src.isopen) - to_chat(usr, "The unit's doors are shut.") - return - if (!src.ispowered || src.isbroken) - to_chat(usr, "The unit is not operational.") - return - if ( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) ) - to_chat(usr, "It's too cluttered inside for you to fit in!") - return - if(usr.is_busy()) return - visible_message("[usr] starts squeezing into the suit storage unit!", 3) - if(do_after(usr, 10, target = src)) - 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) -// qdel(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/attackby(obj/item/I, mob/user) - if(!src.ispowered) - return - if(istype(I, /obj/item/weapon/screwdriver)) - src.panelopen = !src.panelopen - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) - to_chat(user, text("You [] the unit's maintenance panel.",(src.panelopen ? "open up" : "close") )) - src.updateUsrDialog() - return - if ( istype(I, /obj/item/weapon/grab) ) - var/obj/item/weapon/grab/G = I - if( !(ismob(G.affecting)) ) - return - user.SetNextMove(CLICK_CD_MELEE) - if (!src.isopen) - to_chat(usr, "The unit's doors are shut.") - return - if (!src.ispowered || src.isbroken) - to_chat(usr, "The unit is not operational.") - return - if ( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) ) //Unit needs to be absolutely empty - to_chat(user, "The unit's storage area is too cluttered.") - return - if(user.is_busy()) return - visible_message("[user] starts putting [G.affecting.name] into the Suit Storage Unit.", 3) - if(do_after(user, 20, target = src)) - 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) - 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 - to_chat(user, "You load the [S.name] into the storage compartment.") - user.drop_item() - S.loc = src - 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 - to_chat(user, "You load the [H.name] into the storage compartment.") - user.drop_item() - H.loc = src - 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 - to_chat(user, "You load the [M.name] into the storage compartment.") - user.drop_item() - M.loc = src - src.MASK = M - src.update_icon() - src.updateUsrDialog() - return - src.update_icon() - src.updateUsrDialog() - return - - -/obj/machinery/suit_storage_unit/attack_paw(mob/user) - to_chat(user, "The console controls are far too complicated for your tiny brain!") - return +////////////////////////////////////// +// 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 = "suitstorage000000100" //order is: [has helmet][has suit][has human][is open][is locked][is UV cycling][is powered][is dirty/broken] [is superUVcycling] + anchored = 1 + density = 1 + var/mob/living/carbon/human/OCCUPANT = null + var/obj/item/clothing/suit/space/SUIT = null + var/SUIT_TYPE = null + var/obj/item/clothing/head/helmet/space/HELMET = null + var/HELMET_TYPE = null + var/obj/item/clothing/mask/MASK = null //All the stuff that's gonna be stored insiiiiiiiiiiiiiiiiiiide, nyoro~n + 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/ispowered = 1 //starts powered + var/isbroken = 0 + var/issuperUV = 0 + var/panelopen = 0 + var/safetieson = 1 + var/cycletime_left = 0 + + +//The units themselves///////////////// + +/obj/machinery/suit_storage_unit/standard_unit + SUIT_TYPE = /obj/item/clothing/suit/space/globose + HELMET_TYPE = /obj/item/clothing/head/helmet/space/globose + MASK_TYPE = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/syndicate_unit + SUIT_TYPE = /obj/item/clothing/suit/space/rig/syndi + HELMET_TYPE = /obj/item/clothing/head/helmet/space/rig/syndi + MASK_TYPE = /obj/item/clothing/mask/gas/syndicate + +/obj/machinery/suit_storage_unit/science + SUIT_TYPE = /obj/item/clothing/suit/space/globose/science + HELMET_TYPE = /obj/item/clothing/head/helmet/space/globose/science + MASK_TYPE = /obj/item/clothing/mask/breath + +/obj/machinery/suit_storage_unit/atom_init() + . = ..() + if(SUIT_TYPE) + SUIT = new SUIT_TYPE(src) + if(HELMET_TYPE) + HELMET = new HELMET_TYPE(src) + if(MASK_TYPE) + MASK = new MASK_TYPE(src) + update_icon() + +/obj/machinery/suit_storage_unit/update_icon() + var/hashelmet = 0 + var/hassuit = 0 + var/hashuman = 0 + if(HELMET) + hashelmet = 1 + if(SUIT) + hassuit = 1 + if(OCCUPANT) + hashuman = 1 + icon_state = text("suitstorage[][][][][][][][][]",hashelmet,hassuit,hashuman,src.isopen,src.islocked,src.isUV,src.ispowered,src.isbroken,src.issuperUV) + + +/obj/machinery/suit_storage_unit/power_change() + if( powered() ) + src.ispowered = 1 + stat &= ~NOPOWER + src.update_icon() + else + spawn(rand(0, 15)) + src.ispowered = 0 + stat |= NOPOWER + src.islocked = 0 + src.isopen = 1 + src.dump_everything() + 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/ui_interact(mob/user) + var/dat + + if(src.panelopen) //The maintenance panel is open. Time for some shady stuff + dat+= "Suit storage unit: Maintenance panel" + dat+= "Maintenance panel controls
                    " + dat+= "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.

                    " + 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(entity_ja(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. + dat += "Suit storage unit" + dat+= "Unit is cauterising contents with selected UV ray intensity. Please wait.
                    " + //dat+= "Cycle end in: [src.cycletimeleft()] seconds. " + //user << browse(entity_ja(dat), "window=ssu_cycling_panel;size=400x500") + //onclose(user, "ssu_cycling_panel") + + else + if(!src.isbroken) + dat+= "Suit storage unit" + dat+= "U-Stor-It Suit Storage Unit, model DS1900
                    " + dat+= "Welcome to the Unit control panel.
                    " + 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) + if(src.OCCUPANT) + dat+= "
                    WARNING: Biological entity detected inside the Unit's storage. Please remove.
                    " + dat+= "Eject extra load" + 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(entity_ja(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. + dat+= "Suit storage unit" + dat+= "Unit chamber is too contaminated to continue usage. Please call for a qualified individual to perform maintenance.

                    " + dat+= text("
                    Close control panel", user) + //user << browse(entity_ja(dat), "window=suit_storage_unit;size=400x500") + //onclose(user, "suit_storage_unit") + + user << browse(entity_ja(dat), "window=suit_storage_unit;size=400x500") + onclose(user, "suit_storage_unit") + + +/obj/machinery/suit_storage_unit/Topic(href, href_list) //I fucking HATE this proc + . = ..() + if(!.) + return + + if (href_list["toggleUV"]) + src.toggleUV(usr) + else if (href_list["togglesafeties"]) + src.togglesafeties(usr) + else if (href_list["dispense_helmet"]) + src.dispense_helmet(usr) + else if (href_list["dispense_suit"]) + src.dispense_suit(usr) + else if (href_list["dispense_mask"]) + src.dispense_mask(usr) + else if (href_list["toggle_open"]) + src.toggle_open(usr) + else if (href_list["toggle_lock"]) + src.toggle_lock(usr) + else if (href_list["start_UV"]) + src.start_UV(usr) + else if (href_list["eject_guy"]) + src.eject_occupant(usr) + + src.updateUsrDialog() + src.update_icon() + + +/obj/machinery/suit_storage_unit/proc/toggleUV(mob/user) +// var/protected = 0 +// var/mob/living/carbon/human/H = user + if(!src.panelopen) + 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(src.loc, "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) +// var/protected = 0 +// var/mob/living/carbon/human/H = user + if(!src.panelopen) //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(src.loc, "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) + 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) + if(!src.SUIT) + return + else + src.SUIT.loc = src.loc + src.SUIT = null + return + + +/obj/machinery/suit_storage_unit/proc/dispense_mask(mob/user) + if(!src.MASK) + return + else + src.MASK.loc = src.loc + src.MASK = 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.OCCUPANT) + src.eject_occupant(OCCUPANT) + return + + +/obj/machinery/suit_storage_unit/proc/toggle_open(mob/user) + 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) + 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) + 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 && !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_bodypart_damage(0, burndamage) + OCCUPANT.emote("scream",,, 1) + else + var/burndamage = rand(6,10) + OCCUPANT.take_bodypart_damage(0, burndamage) + OCCUPANT.emote("scream",,, 1) + if(i==3) //End of the cycle + if(!src.issuperUV) + if(src.HELMET) + HELMET.clean_blood() + if(src.SUIT) + SUIT.clean_blood() + if(src.MASK) + MASK.clean_blood() + else //It was supercycling, destroy everything + if(src.HELMET) + src.HELMET = null + if(src.SUIT) + src.SUIT = null + if(src.MASK) + src.MASK = 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.", 3) + src.isbroken = 1 + 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() + return + +/* spawn(200) //Let's clean dat shit after 20 secs //Eh, this doesn't work + if(src.HELMET) + HELMET.clean_blood() + if(src.SUIT) + SUIT.clean_blood() + if(src.MASK) + MASK.clean_blood() + src.isUV = 0 //Cycle ends + src.update_icon() + src.updateUsrDialog() + + var/i + for(i=0,i<4,i++) //Gradually give the guy inside some damaged based on the intensity + spawn(50) + if(src.OCCUPANT) + if(src.issuperUV) + OCCUPANT.take_bodypart_damage(0, 40) + to_chat(user, "Test. You gave him 40 damage") + else + OCCUPANT.take_bodypart_damage(0, 8) + to_chat(user, "Test. You gave him 8 damage") + return*/ + + +/obj/machinery/suit_storage_unit/proc/cycletimeleft() + if(src.cycletime_left >= 1) + src.cycletime_left-- + return src.cycletime_left + + +/obj/machinery/suit_storage_unit/proc/eject_occupant(mob/user) + 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/container_resist() + var/mob/living/user = usr + if(islocked) + if(user.is_busy()) return + user.next_move = world.time + 100 + user.last_special = world.time + 100 + var/breakout_time = 2 + to_chat(user, "You start kicking against the doors to escape! (This will take about [breakout_time] minutes.)") + visible_message("You see [user] kicking against the doors of the [src]!") + if(do_after(user,(breakout_time*60*10),target=src)) + if(!user || user.stat != CONSCIOUS || user.loc != src || isopen || !islocked) + return + else + isopen = 1 + islocked = 0 + visible_message("[user] successfully broke out of [src]!") + else + return + eject_occupant(user) + add_fingerprint(user) + updateUsrDialog() + 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.stat != CONSCIOUS) + return + if (!src.isopen) + to_chat(usr, "The unit's doors are shut.") + return + if (!src.ispowered || src.isbroken) + to_chat(usr, "The unit is not operational.") + return + if ( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) ) + to_chat(usr, "It's too cluttered inside for you to fit in!") + return + if(usr.is_busy()) return + visible_message("[usr] starts squeezing into the suit storage unit!", 3) + if(do_after(usr, 10, target = src)) + 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) +// qdel(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/attackby(obj/item/I, mob/user) + if(!src.ispowered) + return + if(istype(I, /obj/item/weapon/screwdriver)) + src.panelopen = !src.panelopen + playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + to_chat(user, text("You [] the unit's maintenance panel.",(src.panelopen ? "open up" : "close") )) + src.updateUsrDialog() + return + if ( istype(I, /obj/item/weapon/grab) ) + var/obj/item/weapon/grab/G = I + if( !(ismob(G.affecting)) ) + return + user.SetNextMove(CLICK_CD_MELEE) + if (!src.isopen) + to_chat(usr, "The unit's doors are shut.") + return + if (!src.ispowered || src.isbroken) + to_chat(usr, "The unit is not operational.") + return + if ( (src.OCCUPANT) || (src.HELMET) || (src.SUIT) ) //Unit needs to be absolutely empty + to_chat(user, "The unit's storage area is too cluttered.") + return + if(user.is_busy()) return + visible_message("[user] starts putting [G.affecting.name] into the Suit Storage Unit.", 3) + if(do_after(user, 20, target = src)) + 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) + 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 + to_chat(user, "You load the [S.name] into the storage compartment.") + user.drop_item() + S.loc = src + 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 + to_chat(user, "You load the [H.name] into the storage compartment.") + user.drop_item() + H.loc = src + 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 + to_chat(user, "You load the [M.name] into the storage compartment.") + user.drop_item() + M.loc = src + src.MASK = M + src.update_icon() + src.updateUsrDialog() + return + src.update_icon() + src.updateUsrDialog() + return + + +/obj/machinery/suit_storage_unit/attack_paw(mob/user) + to_chat(user, "The console controls are far too complicated for your tiny brain!") + return diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm index 036ec45df689..0b1c8dac4376 100644 --- a/code/game/machinery/syndicatebeacon.dm +++ b/code/game/machinery/syndicatebeacon.dm @@ -1,236 +1,236 @@ -//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 - use_power = 0 - - var/temptext = "" - var/selfdestructing = 0 - var/charges = 1 - -/obj/machinery/syndicate_beacon/attack_ghost(mob/user) //Not needed, but showing of truncated string is not good - return - -/obj/machinery/syndicate_beacon/ui_interact(mob/user) - var/dat = "Scanning [pick("retina pattern", "voice print", "fingerprints", "dna sequence")]...
                    Identity confirmed,
                    " - if(ishuman(user) || isAI(user)) - 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(entity_ja(dat), "window=syndbeacon") - onclose(user, "syndbeacon") - -/obj/machinery/syndicate_beacon/is_operational_topic() - return TRUE - -/obj/machinery/syndicate_beacon/Topic(href, href_list) - . = ..() - if(!.) - return - - 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 phoron 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.name] ([N.ckey]) has accepted a traitor objective from a syndicate beacon. (JMP)") - - 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.updateUsrDialog() - - -/obj/machinery/syndicate_beacon/proc/selfdestruct() - selfdestructing = 1 - spawn() explosion(src.loc, rand(3,8), rand(1,3), 1, 10) - - - -#define SCREWED 32 - -/obj/machinery/singularity_beacon //not the best place for it but it's a hack job anyway -- Urist - name = "ominous beacon" - desc = "This looks suspicious..." - icon = 'icons/obj/singularity.dmi' - icon_state = "beacon" - anchored = FALSE - density = TRUE - layer = MOB_LAYER - 0.1 //so people can't hide it and it's REALLY OBVIOUS - stat = 0 - use_power = 0 - - var/active = 0 //It doesn't use up power, so use_power wouldn't really suit it - var/icontype = "beacon" - var/obj/structure/cable/attached = null - - -/obj/machinery/singularity_beacon/proc/Activate(mob/user = null) - if(!checkWirePower()) - if(user) - to_chat(user, "\blue The connected wire doesn't have enough current.") - return 1 - for(var/obj/singularity/singulo in poi_list) - if(singulo.z == z) - singulo.target = src - icon_state = "[icontype]1" - active = 1 - if(user) - to_chat(user, "\blue You activate the beacon.") - - -/obj/machinery/singularity_beacon/proc/Deactivate(mob/user = null) - for(var/obj/singularity/singulo in poi_list) - if(singulo.target == src) - singulo.target = null - icon_state = "[icontype]0" - active = 0 - if(user) - to_chat(user, "\blue You deactivate the beacon.") - - -/obj/machinery/singularity_beacon/attack_ai(mob/user) - if(IsAdminGhost(user)) - return ..() - -/obj/machinery/singularity_beacon/attack_hand(mob/user) - . = ..() - if(.) - return 1 - user.SetNextMove(CLICK_CD_INTERACT) - if(stat & SCREWED) - return active ? Deactivate(user) : Activate(user) - else - to_chat(user, "\red You need to screw the beacon to the floor first!") - return 1 - - -/obj/machinery/singularity_beacon/attackby(obj/item/weapon/W, mob/user) - if(istype(W,/obj/item/weapon/screwdriver)) - if(active) - to_chat(user, "\red You need to deactivate the beacon first!") - return - - if(stat & SCREWED) - stat &= ~SCREWED - anchored = 0 - to_chat(user, "\blue You unscrew the beacon from the floor.") - attached = null - return - else - var/turf/T = loc - if(isturf(T) && !T.intact) - attached = locate() in T - if(!attached) - to_chat(user, "This device must be placed over an exposed cable.") - return - stat |= SCREWED - anchored = 1 - to_chat(user, "\blue You screw the beacon to the floor and attach the cable.") - return - ..() - return - - -/obj/machinery/singularity_beacon/Destroy() - if(active) - Deactivate() - return ..() - - /* - * 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 - */ -/obj/machinery/singularity_beacon/proc/checkWirePower() - if(!attached) - return 0 - var/datum/powernet/PN = attached.get_powernet() - if(!PN) - return 0 - if(PN.avail < 1500) - return 0 - return 1 - -/obj/machinery/singularity_beacon/process() - if(!active) - return - else - if(!checkWirePower()) - Deactivate() - return - - -/obj/machinery/singularity_beacon/syndicate - icontype = "beaconsynd" - icon_state = "beaconsynd0" - -#undef SCREWED +//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 + use_power = 0 + + var/temptext = "" + var/selfdestructing = 0 + var/charges = 1 + +/obj/machinery/syndicate_beacon/attack_ghost(mob/user) //Not needed, but showing of truncated string is not good + return + +/obj/machinery/syndicate_beacon/ui_interact(mob/user) + var/dat = "Scanning [pick("retina pattern", "voice print", "fingerprints", "dna sequence")]...
                    Identity confirmed,
                    " + if(ishuman(user) || isAI(user)) + 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(entity_ja(dat), "window=syndbeacon") + onclose(user, "syndbeacon") + +/obj/machinery/syndicate_beacon/is_operational_topic() + return TRUE + +/obj/machinery/syndicate_beacon/Topic(href, href_list) + . = ..() + if(!.) + return + + 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 phoron 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.name] ([N.ckey]) has accepted a traitor objective from a syndicate beacon. (JMP)") + + 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.updateUsrDialog() + + +/obj/machinery/syndicate_beacon/proc/selfdestruct() + selfdestructing = 1 + spawn() explosion(src.loc, rand(3,8), rand(1,3), 1, 10) + + + +#define SCREWED 32 + +/obj/machinery/singularity_beacon //not the best place for it but it's a hack job anyway -- Urist + name = "ominous beacon" + desc = "This looks suspicious..." + icon = 'icons/obj/singularity.dmi' + icon_state = "beacon" + anchored = FALSE + density = TRUE + layer = MOB_LAYER - 0.1 //so people can't hide it and it's REALLY OBVIOUS + stat = 0 + use_power = 0 + + var/active = 0 //It doesn't use up power, so use_power wouldn't really suit it + var/icontype = "beacon" + var/obj/structure/cable/attached = null + + +/obj/machinery/singularity_beacon/proc/Activate(mob/user = null) + if(!checkWirePower()) + if(user) + to_chat(user, "\blue The connected wire doesn't have enough current.") + return 1 + for(var/obj/singularity/singulo in poi_list) + if(singulo.z == z) + singulo.target = src + icon_state = "[icontype]1" + active = 1 + if(user) + to_chat(user, "\blue You activate the beacon.") + + +/obj/machinery/singularity_beacon/proc/Deactivate(mob/user = null) + for(var/obj/singularity/singulo in poi_list) + if(singulo.target == src) + singulo.target = null + icon_state = "[icontype]0" + active = 0 + if(user) + to_chat(user, "\blue You deactivate the beacon.") + + +/obj/machinery/singularity_beacon/attack_ai(mob/user) + if(IsAdminGhost(user)) + return ..() + +/obj/machinery/singularity_beacon/attack_hand(mob/user) + . = ..() + if(.) + return 1 + user.SetNextMove(CLICK_CD_INTERACT) + if(stat & SCREWED) + return active ? Deactivate(user) : Activate(user) + else + to_chat(user, "\red You need to screw the beacon to the floor first!") + return 1 + + +/obj/machinery/singularity_beacon/attackby(obj/item/weapon/W, mob/user) + if(istype(W,/obj/item/weapon/screwdriver)) + if(active) + to_chat(user, "\red You need to deactivate the beacon first!") + return + + if(stat & SCREWED) + stat &= ~SCREWED + anchored = 0 + to_chat(user, "\blue You unscrew the beacon from the floor.") + attached = null + return + else + var/turf/T = loc + if(isturf(T) && !T.intact) + attached = locate() in T + if(!attached) + to_chat(user, "This device must be placed over an exposed cable.") + return + stat |= SCREWED + anchored = 1 + to_chat(user, "\blue You screw the beacon to the floor and attach the cable.") + return + ..() + return + + +/obj/machinery/singularity_beacon/Destroy() + if(active) + Deactivate() + return ..() + + /* + * 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 + */ +/obj/machinery/singularity_beacon/proc/checkWirePower() + if(!attached) + return 0 + var/datum/powernet/PN = attached.get_powernet() + if(!PN) + return 0 + if(PN.avail < 1500) + return 0 + return 1 + +/obj/machinery/singularity_beacon/process() + if(!active) + return + else + if(!checkWirePower()) + Deactivate() + return + + +/obj/machinery/singularity_beacon/syndicate + icontype = "beaconsynd" + icon_state = "beaconsynd0" + +#undef SCREWED diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 391fabd37eab..db7ee1231dd5 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -1,227 +1,227 @@ -// ### 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", "common", "command", "engineering", "security", - "receiverA", "receiverB", "broadcasterA", "broadcasterB") - -/obj/machinery/telecomms/hub/preset_cent - id = "CentComm Hub" - network = "tcommsat" - heatgen = 0 - autolinkers = list("hub_cent", "c_relay", "s_relay", "m_relay", "r_relay", - "centcomm", "receiverCent", "broadcasterCent") - -//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) // science, medical, supply - - -//--PRESET RIGHT--// - -/obj/machinery/telecomms/receiver/preset_right - id = "Receiver B" - network = "tcommsat" - autolinkers = list("receiverB") // link to relay - freq_listening = list(1353, 1357, 1359) //command, engineering, security - - //Common and other radio frequencies for people to freely use -/obj/machinery/telecomms/receiver/preset_right/atom_init() - for(var/i = 1441, i < 1489, i += 2) - freq_listening |= i - . = ..() - -/obj/machinery/telecomms/receiver/preset_cent - id = "CentComm Receiver" - network = "tcommsat" - heatgen = 0 - autolinkers = list("receiverCent") - freq_listening = list(1345, 1341) - - -//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) - autolinkers = list("processor2", "supply") - -/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(1357) - autolinkers = list("processor4", "engineering", "common") - -/obj/machinery/telecomms/bus/preset_four/atom_init() - for(var/i = 1441, i < 1489, i += 2) - freq_listening |= i - . = ..() - -/obj/machinery/telecomms/bus/preset_cent - id = "CentComm Bus" - network = "tcommsat" - freq_listening = list(1345, 1341) - heatgen = 0 - autolinkers = list("processorCent", "centcomm") - -//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_cent - id = "CentComm Processor" - network = "tcommsat" - heatgen = 0 - autolinkers = list("processorCent") - -//Servers - -/obj/machinery/telecomms/server/presets - - network = "tcommsat" - -/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") - -/obj/machinery/telecomms/server/presets/common - id = "Common Server" - freq_listening = list() - autolinkers = list("common") - - //Common and other radio frequencies for people to freely use - // 1441 to 1489 -/obj/machinery/telecomms/server/presets/common/atom_init() - for(var/i = 1441, i < 1489, i += 2) - freq_listening |= i - . = ..() - -/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") - -/obj/machinery/telecomms/server/presets/centcomm - id = "CentComm Server" - freq_listening = list(1345, 1341) - heatgen = 0 - autolinkers = list("centcomm") - - -//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_cent - id = "CentComm Broadcaster" - network = "tcommsat" - heatgen = 0 - autolinkers = list("broadcasterCent") +// ### 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", "common", "command", "engineering", "security", + "receiverA", "receiverB", "broadcasterA", "broadcasterB") + +/obj/machinery/telecomms/hub/preset_cent + id = "CentComm Hub" + network = "tcommsat" + heatgen = 0 + autolinkers = list("hub_cent", "c_relay", "s_relay", "m_relay", "r_relay", + "centcomm", "receiverCent", "broadcasterCent") + +//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) // science, medical, supply + + +//--PRESET RIGHT--// + +/obj/machinery/telecomms/receiver/preset_right + id = "Receiver B" + network = "tcommsat" + autolinkers = list("receiverB") // link to relay + freq_listening = list(1353, 1357, 1359) //command, engineering, security + + //Common and other radio frequencies for people to freely use +/obj/machinery/telecomms/receiver/preset_right/atom_init() + for(var/i = 1441, i < 1489, i += 2) + freq_listening |= i + . = ..() + +/obj/machinery/telecomms/receiver/preset_cent + id = "CentComm Receiver" + network = "tcommsat" + heatgen = 0 + autolinkers = list("receiverCent") + freq_listening = list(1345, 1341) + + +//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) + autolinkers = list("processor2", "supply") + +/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(1357) + autolinkers = list("processor4", "engineering", "common") + +/obj/machinery/telecomms/bus/preset_four/atom_init() + for(var/i = 1441, i < 1489, i += 2) + freq_listening |= i + . = ..() + +/obj/machinery/telecomms/bus/preset_cent + id = "CentComm Bus" + network = "tcommsat" + freq_listening = list(1345, 1341) + heatgen = 0 + autolinkers = list("processorCent", "centcomm") + +//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_cent + id = "CentComm Processor" + network = "tcommsat" + heatgen = 0 + autolinkers = list("processorCent") + +//Servers + +/obj/machinery/telecomms/server/presets + + network = "tcommsat" + +/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") + +/obj/machinery/telecomms/server/presets/common + id = "Common Server" + freq_listening = list() + autolinkers = list("common") + + //Common and other radio frequencies for people to freely use + // 1441 to 1489 +/obj/machinery/telecomms/server/presets/common/atom_init() + for(var/i = 1441, i < 1489, i += 2) + freq_listening |= i + . = ..() + +/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") + +/obj/machinery/telecomms/server/presets/centcomm + id = "CentComm Server" + freq_listening = list(1345, 1341) + heatgen = 0 + autolinkers = list("centcomm") + + +//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_cent + id = "CentComm Broadcaster" + network = "tcommsat" + heatgen = 0 + autolinkers = list("broadcasterCent") diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 0b6852c85388..011ca1bb84f5 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -1,619 +1,619 @@ -//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. -*/ - -/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 - - if(!on) - return - //world << "[src] ([src.id]) - [signal.debug_print()]" - 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(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 = new - 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"], - "mobtype" = signal.data["mobtype"], - "realname" = signal.data["realname"], - "name" = signal.data["name"], - "job" = signal.data["job"], - "key" = signal.data["key"], - "vmessage" = signal.data["vmessage"], - "vname" = signal.data["vname"], - "vmask" = signal.data["vmask"], - "compression" = signal.data["compression"], - "message" = signal.data["message"], - "connection" = signal.data["connection"], - "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"], - "verb" = signal.data["verb"], - "language" = signal.data["language"] - ) - - // Keep the "original" signal constant - if(!signal.data["original"]) - copy.data["original"] = signal - else - copy.data["original"] = signal.data["original"] - - else - qdel(copy) - - - 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/atom_init() - 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 - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/telecomms/atom_init_late() - 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 - return ..() - -// Used in auto linking -/obj/machinery/telecomms/proc/add_link(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)) - for(var/x in autolinkers) - if(T.autolinkers.Find(x)) - if(src != T) - links |= T - -/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 = between(0, integrity, 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() - - var/transfer_moles = 0.25 * env.total_moles - - var/datum/gas_mixture/removed = env.remove(transfer_moles) - - if(removed) - - var/heat_produced = idle_power_usage //obviously can't produce more heat than the machine draws from it's power source - if (traffic <= 0) - heat_produced *= 0.30 //if idle, produce less heat. - - removed.add_thermal_energy(heat_produced) - - 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) - - if(!on) // has to be on to receive messages - return - if(!signal) - return - if(!check_receive_level(signal)) - return - - 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 - -/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/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 - -/obj/machinery/telecomms/server/atom_init() - . = ..() - server_radio = new() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/telecomms/server(null) - component_parts += new /obj/item/weapon/stock_parts/subspace/filter(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/stack/cable_coil/random(null, 1) - RefreshParts() - -/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["vmessage"] = signal.data["message"] - log.parameters["vname"] = signal.data["vname"] - log.parameters["message"] = signal.data["message"] - log.parameters["name"] = signal.data["name"] - log.parameters["realname"] = signal.data["realname"] - - if(!isnewplayer(M) && 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.parameters["vname"] = Gibberish(signal.data["vname"], 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)])" - - 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/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(content, 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. +*/ + +/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 + + if(!on) + return + //world << "[src] ([src.id]) - [signal.debug_print()]" + 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(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 = new + 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"], + "mobtype" = signal.data["mobtype"], + "realname" = signal.data["realname"], + "name" = signal.data["name"], + "job" = signal.data["job"], + "key" = signal.data["key"], + "vmessage" = signal.data["vmessage"], + "vname" = signal.data["vname"], + "vmask" = signal.data["vmask"], + "compression" = signal.data["compression"], + "message" = signal.data["message"], + "connection" = signal.data["connection"], + "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"], + "verb" = signal.data["verb"], + "language" = signal.data["language"] + ) + + // Keep the "original" signal constant + if(!signal.data["original"]) + copy.data["original"] = signal + else + copy.data["original"] = signal.data["original"] + + else + qdel(copy) + + + 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/atom_init() + 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 + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/telecomms/atom_init_late() + 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 + return ..() + +// Used in auto linking +/obj/machinery/telecomms/proc/add_link(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)) + for(var/x in autolinkers) + if(T.autolinkers.Find(x)) + if(src != T) + links |= T + +/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 = between(0, integrity, 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() + + var/transfer_moles = 0.25 * env.total_moles + + var/datum/gas_mixture/removed = env.remove(transfer_moles) + + if(removed) + + var/heat_produced = idle_power_usage //obviously can't produce more heat than the machine draws from it's power source + if (traffic <= 0) + heat_produced *= 0.30 //if idle, produce less heat. + + removed.add_thermal_energy(heat_produced) + + 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) + + if(!on) // has to be on to receive messages + return + if(!signal) + return + if(!check_receive_level(signal)) + return + + 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 + +/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/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 + +/obj/machinery/telecomms/server/atom_init() + . = ..() + server_radio = new() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/telecomms/server(null) + component_parts += new /obj/item/weapon/stock_parts/subspace/filter(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/stack/cable_coil/random(null, 1) + RefreshParts() + +/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["vmessage"] = signal.data["message"] + log.parameters["vname"] = signal.data["vname"] + log.parameters["message"] = signal.data["message"] + log.parameters["name"] = signal.data["name"] + log.parameters["realname"] = signal.data["realname"] + + if(!isnewplayer(M) && 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.parameters["vname"] = Gibberish(signal.data["vname"], 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)])" + + 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/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(content, 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 b645e65e12b7..b83fc7edcb70 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -1,55 +1,55 @@ -/obj/machinery/transformer - name = "Automatic Robotic Factory 5000" - desc = "A large metalic machine with an entrance and an exit. A sign on the side reads, 'human go in, robot come out', human must be lying down and alive." - icon = 'icons/obj/recycling.dmi' - icon_state = "separator-AO1" - layer = MOB_LAYER+1 // Overhead - anchored = 1 - density = 1 - var/transform_dead = 0 - var/transform_standing = 0 - -/obj/machinery/transformer/atom_init() - // On us - . = ..() - new /obj/machinery/conveyor(loc, WEST, 1) - -/obj/machinery/transformer/Bumped(atom/movable/AM) - 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 - transform(AM) - -/obj/machinery/transformer/proc/transform(mob/living/carbon/human/H) - if(stat & (BROKEN|NOPOWER)) - return - if(!transform_dead && H.stat == DEAD) - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - return - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) - use_power(5000) // Use a lot of power. - var/mob/living/silicon/robot = H.Robotize() - robot.lying = 1 - spawn(50) // So he can't jump out the gate right away. - playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) - if(robot) - robot.lying = 0 - -/obj/machinery/transformer/conveyor/atom_init() - . = ..() - 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(east, WEST, 1) - - // West - var/turf/west = locate(T.x - 1, T.y, T.z) - if(istype(west, /turf/simulated/floor)) - new /obj/machinery/conveyor(west, WEST, 1) +/obj/machinery/transformer + name = "Automatic Robotic Factory 5000" + desc = "A large metalic machine with an entrance and an exit. A sign on the side reads, 'human go in, robot come out', human must be lying down and alive." + icon = 'icons/obj/recycling.dmi' + icon_state = "separator-AO1" + layer = MOB_LAYER+1 // Overhead + anchored = 1 + density = 1 + var/transform_dead = 0 + var/transform_standing = 0 + +/obj/machinery/transformer/atom_init() + // On us + . = ..() + new /obj/machinery/conveyor(loc, WEST, 1) + +/obj/machinery/transformer/Bumped(atom/movable/AM) + 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 + transform(AM) + +/obj/machinery/transformer/proc/transform(mob/living/carbon/human/H) + if(stat & (BROKEN|NOPOWER)) + return + if(!transform_dead && H.stat == DEAD) + playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + return + playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + use_power(5000) // Use a lot of power. + var/mob/living/silicon/robot = H.Robotize() + robot.lying = 1 + spawn(50) // So he can't jump out the gate right away. + playsound(src.loc, 'sound/machines/ping.ogg', 50, 0) + if(robot) + robot.lying = 0 + +/obj/machinery/transformer/conveyor/atom_init() + . = ..() + 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(east, WEST, 1) + + // West + var/turf/west = locate(T.x - 1, T.y, T.z) + if(istype(west, /turf/simulated/floor)) + new /obj/machinery/conveyor(west, WEST, 1) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index a86447c17418..a145047d285e 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1,1207 +1,1207 @@ -/datum/data/vending_product - var/product_name = "generic" - var/product_path = null - var/amount = 0 - var/max_amount = 0 - var/price = 0 - var/display_color = "blue" - - - -/obj/machinery/vending - name = "Vendomat" - desc = "A generic vending machine." - icon = 'icons/obj/vending.dmi' - icon_state = "generic" - var/light_range_on = 3 - var/light_power_on = 1 - layer = 2.9 - anchored = 1 - density = 1 - allowed_checks = ALLOWED_CHECK_NONE - 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/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 = 1 //Stop spouting those godawful pitches! - var/extended_inventory = 0 //can we access the hidden inventory? - var/obj/item/weapon/coin/coin - var/obj/item/weapon/vending_refill/refill_canister = null //The type of refill canisters used by this machine. - - var/check_accounts = 1 // 1 = requires PIN and checks accounts. 0 = You slide an ID, it vends, SPACE COMMUNISM! - var/obj/item/weapon/spacecash/ewallet/ewallet - var/datum/wires/vending/wires = null - var/scan_id = TRUE - - -/obj/machinery/vending/atom_init() - . = ..() - wires = new(src) - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/vendor(null) - - slogan_list = splittext(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. - last_slogan = world.time + rand(0, slogan_delay) - - build_inventory(products) - //Add hidden inventory - build_inventory(contraband, 1) - build_inventory(premium, 0, 1) - power_change() - -/obj/machinery/vending/Destroy() - QDEL_NULL(wires) - QDEL_NULL(coin) - return ..() - -/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)) - spawn(0) - src.malfunction() - return - return - else - return - -/obj/machinery/vending/blob_act() - if (prob(50)) - spawn(0) - src.malfunction() - qdel(src) - return - - return - -/obj/machinery/vending/proc/build_inventory(list/productlist,hidden=0,req_coin=0) - 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 /datum/data/vending_product() - - R.product_path = typepath - R.amount = amount - R.max_amount = amount - R.price = price - R.display_color = pick("red","orange","green") - - if(hidden) - hidden_records += R - else if(req_coin) - coin_records += R - else - product_records += R - - var/atom/temp = typepath - R.product_name = initial(temp.name) -// world << "Added: [R.product_name]] - [R.amount] - [R.product_path]" - return - -/obj/machinery/vending/proc/refill_inventory(obj/item/weapon/vending_refill/refill, datum/data/vending_product/machine, mob/user) //Restocking from TG - var/total = 0 - - var/to_restock = 0 - for(var/datum/data/vending_product/machine_content in machine) - to_restock += machine_content.max_amount - machine_content.amount - - if(to_restock <= refill.charges) - for(var/datum/data/vending_product/machine_content in machine) - if(machine_content.amount != machine_content.max_amount) - to_chat(usr, "[machine_content.max_amount - machine_content.amount] of [machine_content.product_name]") - machine_content.amount = machine_content.max_amount - refill.charges -= to_restock - total = to_restock - else - var/tmp_charges = refill.charges - for(var/datum/data/vending_product/machine_content in machine) - var/restock = ceil(((machine_content.max_amount - machine_content.amount) / to_restock) * tmp_charges) - if(restock > refill.charges) - restock = refill.charges - machine_content.amount += restock - refill.charges -= restock - total += restock - if(restock) - to_chat(usr, "[restock] of [machine_content.product_name]") - if(refill.charges == 0) //due to rounding, we ran out of refill charges, exit. - break - return total - -/obj/machinery/vending/attackby(obj/item/weapon/W, mob/user) - if(panel_open) - if(default_unfasten_wrench(user, W, time = 60)) - return - - if(istype(W, /obj/item/weapon/crowbar)) - default_deconstruction_crowbar(W) - - if (istype(W, /obj/item/weapon/card/emag)) - src.emagged = 1 - to_chat(user, "You short out the product lock on [src]") - return - - else if(istype(W, /obj/item/weapon/screwdriver) && anchored) - src.panel_open = !src.panel_open - to_chat(user, "You [src.panel_open ? "open" : "close"] the maintenance panel.") - src.overlays.Cut() - if(src.panel_open) - src.overlays += image(src.icon, "[initial(icon_state)]-panel") - src.updateUsrDialog() - - return - else if(is_wire_tool(W) && panel_open && wires.interact(user)) - return - - else if(istype(W, /obj/item/weapon/coin) && premium.len > 0) - user.drop_item() - W.loc = src - coin = W - to_chat(user, "\blue You insert the [W] into the [src]") - return - - else if(istype(W, /obj/item/weapon/wrench)) //unwrenching vendomats - var/turf/T = user.loc - if(user.is_busy(src)) return - to_chat(user, "You begin [anchored ? "unwrenching" : "wrenching"] the [src].") - playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user, 40, target = src)) - if( !istype(src, /obj/machinery/vending) || !user || !W || !T ) return - if( user.loc == T && user.get_active_hand() == W ) - anchored = !anchored - to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].") - if (!(src.anchored & powered())) - src.icon_state = "[initial(icon_state)]-off" - stat |= NOPOWER - set_light(0) - else - icon_state = initial(icon_state) - stat &= ~NOPOWER - set_light(light_range_on, light_power_on) - - else if(currently_vending && istype(W, /obj/item/device/pda) && W.GetID()) - var/obj/item/weapon/card/I = W.GetID() - scan_card(I) - - else if(currently_vending && istype(W, /obj/item/weapon/card)) - var/obj/item/weapon/card/I = W - scan_card(I) - - else if(istype(W, refill_canister) && refill_canister != null) - if(stat & (BROKEN|NOPOWER)) - to_chat(user, "It does nothing.") - else if(panel_open) - //if the panel is open we attempt to refill the machine - var/obj/item/weapon/vending_refill/canister = W - if(canister.charges == 0) - to_chat(user, "This [canister.name] is empty!") - else - var/transfered = refill_inventory(canister,product_records,user) - if(transfered) - to_chat(user, "You loaded [transfered] items in \the [name].") - else - to_chat(user, "The [name] is fully stocked.") - return; - else - to_chat(user, "You should probably unscrew the service panel first.") - - else if (istype(W, /obj/item/weapon/spacecash/ewallet)) - user.drop_item() - W.loc = src - ewallet = W - to_chat(user, "\blue You insert the [W] into the [src]") - - else if(src.panel_open) - for(var/datum/data/vending_product/R in product_records) - if(istype(W, R.product_path)) - stock(R, user) - qdel(W) - else - ..() - -/obj/machinery/vending/default_deconstruction_crowbar(obj/item/O) - var/list/all_products = product_records + hidden_records + coin_records - for(var/datum/data/vending_product/machine_content in all_products) - while(machine_content.amount !=0) - var/safety = 0 //to avoid infinite loop - for(var/obj/item/weapon/vending_refill/VR in component_parts) - safety++ - if(VR.charges < initial(VR.charges)) - VR.charges++ - machine_content.amount-- - if(!machine_content.amount) - break - else - safety-- - if(safety <= 0) - break - ..() - -/obj/machinery/vending/proc/scan_card(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(check_accounts) - if(vendor_account) - var/datum/money_account/D = get_account(C.associated_account_number) - var/attempt_pin = 0 - if(D) - if(D.security_level > 0) - attempt_pin = input("Enter pin code", "Vendor transaction") as num - if(attempt_pin) - D = attempt_account_access(C.associated_account_number, attempt_pin, 2) - if(D) - var/transaction_amount = currently_vending.price - if(transaction_amount <= D.money) - - //transfer the money - D.money -= transaction_amount - vendor_account.money += transaction_amount - - //create entries in the two account transaction logs - var/datum/transaction/T = new() - T.target_name = "[vendor_account.owner_name] (via [src.name])" - T.purpose = "Purchase of [currently_vending.product_name]" - if(transaction_amount > 0) - T.amount = "([transaction_amount])" - else - T.amount = "[transaction_amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - D.transaction_log.Add(T) - // - T = new() - T.target_name = D.owner_name - T.purpose = "Purchase of [currently_vending.product_name]" - T.amount = "[transaction_amount]" - T.source_terminal = src.name - T.date = current_date_string - T.time = worldtime2text() - vendor_account.transaction_log.Add(T) - - // Vend the item - src.vend(src.currently_vending, usr) - currently_vending = null - else - to_chat(usr, "[bicon(src)]You don't have that much money!") - else - to_chat(usr, "[bicon(src)]You entered wrong account PIN!") - else - to_chat(usr, "[bicon(src)]Unable to find your money account!") - else - to_chat(usr, "[bicon(src)]Unable to access account. Check security settings and try again.") - else - //Just Vend it. - src.vend(src.currently_vending, usr) - currently_vending = null - else - to_chat(usr, "[bicon(src)]Unable to access vendor account. Please record the machine ID and call CentComm Support.") - -/obj/machinery/vending/ui_interact(mob/user) - if(seconds_electrified && !issilicon(user) && !isobserver(user)) - if(shock(user, 100)) - return - - var/vendorname = name //import the machine's name - - if(currently_vending) - var/dat - dat += "You have selected [currently_vending.product_name].
                    Please swipe your ID to pay for the article.

                    " - dat += "Cancel" - var/datum/browser/popup = new(user, "window=vending", "[vendorname]", 400, 550) - popup.set_content(dat) - popup.open() - return - - var/dat - dat += "

                    Select an item

                    " - dat += "
                    " - - if (product_records.len == 0) - dat += "No product loaded!" - - else - dat += "
                      " - - dat += print_recors(product_records) - if(extended_inventory) - dat += print_recors(hidden_records) - if(coin) - dat += print_recors(coin_records) - - dat += "
                    " - dat += "
                    " - - if (premium.len > 0) - dat += "Coin slot: [coin ? coin : "No coin inserted"] Remove
                    " - - if (ewallet) - dat += "Charge card's credits: [ewallet ? ewallet.worth : "No charge card inserted"] (Remove)

                    " - - var/datum/browser/popup = new(user, "window=vending", "[vendorname]", 450, 500) - popup.set_content(dat) - popup.open() - -/obj/machinery/vending/proc/print_recors(list/record) - var/dat - for (var/datum/data/vending_product/R in record) - dat += "
                  • " - if (R.amount > 0) - dat += " Vend" - else - dat += " SOLD OUT" - dat += "[R.product_name]:" - dat += " [R.amount] " - if(R.price) - dat += " (Price: [R.price])" - dat += "
                  • " - return dat - -/obj/machinery/vending/Topic(href, href_list) - . = ..() - if(!.) - return - - if(href_list["remove_coin"] && !issilicon(usr) && !isobserver(usr)) - if(!coin) - to_chat(usr, "There is no coin in this machine.") - return FALSE - - coin.loc = loc - if(!usr.get_active_hand()) - usr.put_in_hands(coin) - to_chat(usr, "\blue You remove the [coin] from the [src]") - coin = null - - else if(href_list["remove_ewallet"] && !issilicon(usr) && !isobserver(usr)) - if (!ewallet) - to_chat(usr, "There is no charge card in this machine.") - return - ewallet.loc = loc - if(!usr.get_active_hand()) - usr.put_in_hands(ewallet) - to_chat(usr, "\blue You remove the [ewallet] from the [src]") - ewallet = null - - else if (href_list["vend"] && vend_ready && !currently_vending) - - if(isrobot(usr)) - var/mob/living/silicon/robot/R = usr - if(!(R.module && istype(R.module,/obj/item/weapon/robot_module/butler) )) - to_chat(usr, "\red The vending machine refuses to interface with you, as you are not in its target demographic!") - return FALSE - else if(issilicon(usr)) - to_chat(usr, "\red The vending machine refuses to interface with you, as you are not in its target demographic!") - return FALSE - - 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 FALSE - - var/datum/data/vending_product/R = locate(href_list["vend"]) - if (!R || !istype(R) || !R.product_path || R.amount <= 0) - return FALSE - - if(R.price == null || isobserver(usr)) //Centcomm buys somethin at himself? Nope, because they can just take this - src.vend(R, usr) - else - if (ewallet) - if (R.price <= ewallet.worth) - ewallet.worth -= R.price - src.vend(R, usr) - else - to_chat(usr, "\red The ewallet doesn't have enough money to pay for that.") - src.currently_vending = R - src.updateUsrDialog() - else - src.currently_vending = R - src.updateUsrDialog() - return - - else if (href_list["cancel_buying"]) - src.currently_vending = null - src.updateUsrDialog() - return - - src.updateUsrDialog() - -/obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user) - if (!allowed(user) && !emagged && scan_id) //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 (R in coin_records) - if(!coin) - to_chat(user, "\blue You need to insert a coin to get this item.") - return - if(coin.string_attached) - if(prob(50)) - to_chat(user, "\blue You successfully pull the coin out before the [src] could swallow it.") - else - to_chat(user, "\blue You weren't able to pull the coin out fast enough, the machine ate it, string and all.") - QDEL_NULL(coin) - else - QDEL_NULL(coin) - - 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)) - playsound(src, 'sound/items/vending.ogg', 50, 1, 1) - src.vend_ready = 1 - return - - src.updateUsrDialog() - -/obj/machinery/vending/proc/stock(datum/data/vending_product/R, mob/user) - if(src.panel_open) - to_chat(user, "\blue You stock the [src] with \a [R.product_name]") - R.amount++ - - 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(2)) - src.throw_item() - - return - -/obj/machinery/vending/proc/speak(message) - if(stat & NOPOWER) - return - - if (!message) - return - - for(var/mob/O in hearers(src, null)) - O.show_message("[src] beeps, \"[message]\"",2) - return - -/obj/machinery/vending/power_change() - if(stat & BROKEN) - icon_state = "[initial(icon_state)]-broken" - set_light(0) - else - if( powered() & src.anchored ) - icon_state = initial(icon_state) - stat &= ~NOPOWER - set_light(light_range_on, light_power_on) - else - spawn(rand(0, 15)) - src.icon_state = "[initial(icon_state)]-off" - stat |= NOPOWER - set_light(0) - -//Oh no we're malfunctioning! Dump out some product and break. -/obj/machinery/vending/proc/malfunction() - for(var/datum/data/vending_product/R in src.product_records) - if (R.amount <= 0) //Try to use a record that actually has something to dump. - continue - var/dump_path = R.product_path - if (!dump_path) - continue - - while(R.amount>0) - new dump_path(src.loc) - R.amount-- - continue - - 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/obj/throw_item = null - var/mob/living/target = locate() in view(7,src) - if(!target) - return 0 - - for(var/datum/data/vending_product/R in src.product_records) - if (R.amount <= 0) //Try to use a record that actually has something to dump. - continue - var/dump_path = R.product_path - if (!dump_path) - continue - - R.amount-- - throw_item = new dump_path(src.loc) - break - if (!throw_item) - return 0 - throw_item.throw_at(target, 16, 3) - visible_message("[src] launches [throw_item.name] at [target.name]!") - return 1 - -/obj/machinery/vending/proc/shock(mob/user, prb) - 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 (electrocute_mob(user, get_area(src), src, 0.7)) - return 1 - else - 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/phoron;/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" - light_color = "#77beda" - 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/tequilla = 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/bottle/beer = 6, - /obj/item/weapon/reagent_containers/food/drinks/bottle/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/cans/tonic = 8, - /obj/item/weapon/reagent_containers/food/drinks/cans/cola = 8, /obj/item/weapon/reagent_containers/food/drinks/cans/sodawater = 15, - /obj/item/weapon/reagent_containers/food/drinks/flask/barflask = 2, /obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask = 2, - /obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 30,/obj/item/weapon/reagent_containers/food/drinks/ice = 9, - /obj/item/weapon/reagent_containers/food/drinks/bottle/melonliquor = 2,/obj/item/weapon/reagent_containers/food/drinks/bottle/bluecuracao = 2, - /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe = 2,/obj/item/weapon/reagent_containers/food/drinks/bottle/grenadine = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/champagne = 5) - contraband = list(/obj/item/weapon/reagent_containers/food/drinks/tea = 10) - vend_delay = 15 - 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" - refill_canister = /obj/item/weapon/vending_refill/boozeomat - -/obj/machinery/vending/assist - 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) - product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!" - -/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" - light_color = "#b88b2e" - 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) - refill_canister = /obj/item/weapon/vending_refill/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!;Twice the calories for half the price!" - 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" - light_color = "#d00023" - products = list(/obj/item/weapon/reagent_containers/food/snacks/candy/candybar = 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) - contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6) - prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy/candybar = 1,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 5,/obj/item/weapon/reagent_containers/food/snacks/chips = 1, - /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 2,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 1,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 1, - /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1) - refill_canister = /obj/item/weapon/vending_refill/snack - -/obj/machinery/vending/chinese - name = "\improper Mr. Chang" - desc = "A self-serving Chinese food machine, for all your Chinese food needs." - product_slogans = "Taste 5000 years of culture!" - icon_state = "snack" - light_color = "#d00023" - products = list(/obj/item/weapon/reagent_containers/food/snacks/chinese/chowmein = 6, /obj/item/weapon/reagent_containers/food/snacks/chinese/tao = 6, /obj/item/weapon/reagent_containers/food/snacks/chinese/sweetsourchickenball = 6, /obj/item/weapon/reagent_containers/food/snacks/chinese/newdles = 6, - /obj/item/weapon/reagent_containers/food/snacks/chinese/rice = 6, /obj/item/weapon/kitchen/utensil/fork/sticks = 18) - prices = list(/obj/item/weapon/reagent_containers/food/snacks/chinese/chowmein = 50, /obj/item/weapon/reagent_containers/food/snacks/chinese/tao = 50, /obj/item/weapon/reagent_containers/food/snacks/chinese/sweetsourchickenball = 50, /obj/item/weapon/reagent_containers/food/snacks/chinese/newdles = 50, - /obj/item/weapon/reagent_containers/food/snacks/chinese/rice = 50, /obj/item/weapon/kitchen/utensil/fork/sticks = 1) - refill_canister = /obj/item/weapon/vending_refill/snack - -/obj/machinery/vending/cola - name = "Robust Softdrinks" - desc = "A softdrink vendor provided by Robust Industries, LLC." - icon_state = "Cola_Machine" - light_color = "#315ab4" - product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!" - 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/cans/cola = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 10, - /obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 10, - /obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 10, - /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10, /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10) - contraband = list(/obj/item/weapon/reagent_containers/food/drinks/cans/thirteenloko = 5) - prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 1, - /obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 1, - /obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 2,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 1, - /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1) - -//This one's from bay12 -/obj/machinery/vending/cart - name = "PTech" - desc = "Cartridges for PDAs." - product_slogans = "Carts to go!" - icon_state = "cart" - light_color = "#dddddd" - 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/science = 10,/obj/item/device/pda/heads = 10, - /obj/item/weapon/cartridge/captain = 3,/obj/item/weapon/cartridge/quartermaster = 10) - - -/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." - vend_delay = 34 - icon_state = "cigs" - light_color = "#dddddd" - products = list(/obj/item/weapon/storage/fancy/cigarettes = 10, /obj/item/weapon/storage/fancy/cigarettes/menthol = 5, /obj/item/weapon/storage/box/matches = 10, /obj/item/weapon/lighter/random = 4, /obj/item/clothing/mask/ecig = 4) - contraband = list(/obj/item/weapon/lighter/zippo = 4) - premium = list(/obj/item/clothing/mask/cigarette/cigar/havana = 2) - prices = list(/obj/item/weapon/storage/fancy/cigarettes = 20, /obj/item/weapon/storage/fancy/cigarettes/menthol = 30, /obj/item/weapon/storage/box/matches = 10, /obj/item/weapon/lighter/random = 15, /obj/item/clothing/mask/ecig = 40) - refill_canister = /obj/item/weapon/vending_refill/cigarette - -/obj/machinery/vending/medical - name = "NanoMed Plus" - desc = "Medical drug dispenser." - icon_state = "med" - icon_deny = "med-deny" - light_color = "#e6fff2" - 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/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, - /obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 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/dylovene = 6) - - -//This one's from bay12 -/obj/machinery/vending/phoronresearch - name = "Toximate 3000" - desc = "All the fine parts you need in one vending machine!" - products = list(/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) - -/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" - light_power_on = 1 - light_color = "#e6fff2" - 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/hypospray/autoinjector = 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) - -/obj/machinery/vending/wallmed2 - name = "NanoMed" - desc = "Wall-mounted Medical Equipment dispenser." - icon_state = "wallmed" - light_power_on = 1 - light_color = "#e6fff2" - 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/hypospray/autoinjector = 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) - -/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" - light_color = "#f1f8ff" - 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) - contraband = list(/obj/item/clothing/glasses/sunglasses = 2,/obj/item/weapon/storage/fancy/donut_box = 2,/obj/item/device/flashlight/seclite = 4) - -/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" - light_color = "#34ff7b" - icon_deny = "nutri-deny" - products = list(/obj/item/nutrient/ez = 45,/obj/item/nutrient/l4z = 25,/obj/item/nutrient/rh = 15,/obj/item/weapon/pestspray = 20, - /obj/item/weapon/reagent_containers/syringe = 5,/obj/item/weapon/storage/bag/plants = 5) - premium = list(/obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10,/obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5) - -/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" - light_color = "#34ff7b" - products = list(/obj/item/seeds/ambrosiavulgarisseed = 3,/obj/item/seeds/appleseed = 3,/obj/item/seeds/bananaseed = 3,/obj/item/seeds/berryseed = 3, - /obj/item/seeds/cabbageseed = 3,/obj/item/seeds/carrotseed = 3,/obj/item/seeds/cherryseed = 3,/obj/item/seeds/chantermycelium = 3, - /obj/item/seeds/chiliseed = 3,/obj/item/seeds/cocoapodseed = 3,/obj/item/seeds/cornseed = 3,/obj/item/seeds/replicapod = 3, - /obj/item/seeds/eggplantseed = 3,/obj/item/seeds/grapeseed = 3,/obj/item/seeds/grassseed = 3,/obj/item/seeds/lemonseed = 3, - /obj/item/seeds/limeseed = 3,/obj/item/seeds/orangeseed = 3,/obj/item/seeds/plastiseed = 3,/obj/item/seeds/potatoseed = 3, - /obj/item/seeds/poppyseed = 3,/obj/item/seeds/pumpkinseed = 3,/obj/item/seeds/riceseed= 3,/obj/item/seeds/soyaseed = 3, - /obj/item/seeds/sunflowerseed = 3,/obj/item/seeds/tomatoseed = 3,/obj/item/seeds/towermycelium = 3,/obj/item/seeds/watermelonseed = 3, - /obj/item/seeds/wheatseed = 3,/obj/item/seeds/whitebeetseed = 3) - contraband = list(/obj/item/seeds/amanitamycelium = 2,/obj/item/seeds/glowshroom = 2,/obj/item/seeds/libertymycelium = 2,/obj/item/seeds/mtearseed = 2, - /obj/item/seeds/nettleseed = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/shandseed = 2,) - premium = list(/obj/item/toy/waterflower = 1) - - -/obj/machinery/vending/magivend - name = "MagiVend" - desc = "A magic vending machine." - icon_state = "MagiVend" - light_color = "#97429a" - 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/shoes/sandal = 1,/obj/item/weapon/staff = 2, /obj/item/device/modkit/wizard/skrell = 1, - /obj/item/device/modkit/wizard/unathi = 1, /obj/item/device/modkit/wizard/tajaran = 1, /obj/item/clothing/head/wizard/redhood = 1, /obj/item/clothing/head/wizard/bluehood = 1, - /obj/item/clothing/suit/wizrobe/wiz_blue = 1, /obj/item/clothing/suit/wizrobe/wiz_red = 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 - -/obj/machinery/vending/weirdomat - name = "Weird-O-Mat" - desc = "A marvel, on the brink of technobabble and pixie fiction." - icon_state = "MagiVend" - light_color = "#97429a" - products = list(/obj/item/weapon/occult_pinpointer = 3, - /obj/item/device/occult_scanner = 3, - /obj/item/clothing/mask/gas/owl_mask = 3, - /obj/item/clothing/mask/pig = 3, - /obj/item/clothing/mask/horsehead = 3, - /obj/item/clothing/mask/cowmask = 3, - /obj/item/clothing/mask/chicken = 3, - /obj/item/weapon/kitchenknife/plastic = 3) - prices = list(/obj/item/weapon/occult_pinpointer = 400, - /obj/item/device/occult_scanner = 400, - /obj/item/clothing/mask/gas/owl_mask = 250, - /obj/item/clothing/mask/pig = 250, - /obj/item/clothing/mask/horsehead = 250, - /obj/item/clothing/mask/cowmask = 250, - /obj/item/clothing/mask/chicken = 250, - /obj/item/weapon/kitchenknife/plastic = 300) - contraband = list(/obj/item/weapon/nullrod = 1, - /obj/item/weapon/kitchenknife/ritual = 1) - premium = list(/obj/item/clothing/glasses/gglasses = 1, - /obj/item/toy/figure/wizard = 1, - /obj/item/weapon/storage/fancy/crayons = 1) - product_slogans = "Amicitiae nostrae memoriam spero sempiternam fore;Aequam memento rebus in arduis servare mentem;Vitanda est improba siren desidia;Serva me, servabo te;Faber est suae quisque fortunae" - vend_reply = "Have fun! No returns!" - product_ads = "Occult is magic;Knowledge is magic;All the magic!;None to spook us;The dice has been cast" - -/obj/machinery/vending/weirdomat/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/device/occult_scanner)) - var/obj/item/device/occult_scanner/OS = I - OS.scanned_type = src.type - to_chat(user, "[src] has been succesfully scanned by [OS]") - if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/ectoplasm)) - RedeemEctoplasm(I, user) - return - ..() - -/obj/machinery/vending/weirdomat/proc/RedeemEctoplasm(obj/plasm, redeemer) - if(plasm.in_use) - return - plasm.in_use = TRUE - var/selection = input(redeemer, "Pick your eternal reward", "Ectoplasm Redemption") in list("Misfortune Set", "Spiritual Bond Set", "Contract From Below", "Cryptorecorder", "Black Candle Box", "Cancel") - if(!selection || !Adjacent(redeemer)) - plasm.in_use = FALSE - return - switch(selection) - if("Misfortune Set") - new /obj/item/weapon/storage/pill_bottle/ghostdice(loc) - if("Spiritual Bond Set") - new /obj/item/weapon/game_kit/chaplain(loc) - if("Contract From Below") - new /obj/item/weapon/pen/ghost(loc) - if("Cryptorecorder") - new /obj/item/device/camera/spooky(loc) - if("Black Candle Box") - new /obj/item/weapon/storage/fancy/black_candle_box(loc) - if("Cancel") - plasm.in_use = FALSE - return - qdel(plasm) - -/obj/machinery/vending/barbervend - name = "Fab-O-Vend" - desc = "It would seem it vends dyes, and other stuff to make you pretty." - icon_state = "barbervend" - product_slogans = "Spread the colour, like butter, onto toast... Onto their hair.; Sometimes, I dream about dyes...; Paint 'em up and call me Mr. Painter.; Look brother, I'm a vendomat, I solve practical problems." - product_ads = "Cut 'em all!; To sheds!; Hair be gone!; Prettify!; Beautify!" - req_access_txt = "69" - refill_canister = /obj/item/weapon/vending_refill/barbervend - products = list(/obj/item/weapon/reagent_containers/glass/bottle/hair_dye/white = 10, - /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/red = 10, - /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/green = 10, - /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/blue = 10, - /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/black = 10, - /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/brown = 10, - /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/blond = 10, - /obj/item/weapon/reagent_containers/spray/hair_color_spray = 3) - contraband = list(/obj/item/weapon/razor = 1) - premium = list(/obj/item/weapon/scissors = 3, - /obj/item/weapon/reagent_containers/glass/bottle/hair_growth_accelerator = 3, - /obj/item/weapon/storage/box/lipstick = 3) - -/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/kitchenknife = 3, - /obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8, - /obj/item/clothing/suit/chef/classic = 2, - /obj/item/weapon/kitchen/mould/bear = 1, - /obj/item/weapon/kitchen/mould/worm = 1, - /obj/item/weapon/kitchen/mould/bean = 1, - /obj/item/weapon/kitchen/mould/ball = 1, - /obj/item/weapon/kitchen/mould/cane = 1, - /obj/item/weapon/kitchen/mould/cash = 1, - /obj/item/weapon/kitchen/mould/coin = 1, - /obj/item/weapon/kitchen/mould/loli = 1 - ) - contraband = list(/obj/item/weapon/kitchen/utensil/spoon = 2,/obj/item/weapon/kitchen/rollingpin = 2, /obj/item/weapon/butch = 2) - -/obj/machinery/vending/sovietsoda - name = "BODA" - desc = "An old sweet water vending machine,how did this end up here?" - icon_state = "sovietsoda" - 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) - -/obj/machinery/vending/tool - name = "YouTool" - desc = "Tools for tools." - icon_state = "tool" - light_color = "#ffcc33" - 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) - contraband = list(/obj/item/weapon/weldingtool/hugetank = 2,/obj/item/clothing/gloves/fyellow = 2) - premium = list(/obj/item/clothing/gloves/yellow = 1) - -/obj/machinery/vending/engivend - name = "Engi-Vend" - desc = "Spare tool vending. What? Did you expect some witty description?" - icon_state = "engivend" - light_color = "#ffcc33" - 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/airlock_electronics = 10,/obj/item/weapon/module/power_control = 10,/obj/item/weapon/airalarm_electronics = 10,/obj/item/weapon/stock_parts/cell/high = 10) - contraband = list(/obj/item/weapon/stock_parts/cell/potato = 3) - premium = list(/obj/item/weapon/storage/belt/utility = 3) - -//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/chief_engineer = 4,/obj/item/clothing/under/rank/engineer = 4,/obj/item/clothing/shoes/workboots = 4,/obj/item/clothing/head/hardhat/yellow = 4, - /obj/item/clothing/head/hardhat/yellow/visor = 1,/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/heavyduty = 8, /obj/item/weapon/stock_parts/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) - // 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 - -//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/stack/cable_coil/random = 2,/obj/item/device/flash = 4, - /obj/item/weapon/stock_parts/cell/high = 5, /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 = 2) - //everything after the power cell had no amounts, I improvised. -Sayu - -//This one's from NTstation -//don't forget to change the refill size if you change the machine's contents! -/obj/machinery/vending/clothing - name = "ClothesMate" //renamed to make the slogan rhyme - desc = "A vending machine for clothing." - icon_state = "clothes" - product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this free swag!;Why leave style up to fate? Use the ClothesMate!" - vend_delay = 15 - vend_reply = "Thank you for using the ClothesMate!" - products = list(/obj/item/clothing/head/that=4,/obj/item/clothing/head/fedora=2,/obj/item/clothing/glasses/monocle=2, - /obj/item/clothing/suit/jacket=4, /obj/item/clothing/suit/jacket/puffer/vest=4, /obj/item/clothing/suit/jacket/puffer=4, - /obj/item/clothing/under/suit_jacket/navy=2,/obj/item/clothing/under/suit_jacket/really_black=2,/obj/item/clothing/under/suit_jacket/burgundy=2, - /obj/item/clothing/under/suit_jacket/charcoal=2, /obj/item/clothing/under/suit_jacket/white=2,/obj/item/clothing/under/kilt=2,/obj/item/clothing/under/overalls=2, - /obj/item/clothing/under/suit_jacket/really_black=4,/obj/item/clothing/under/suit_jacket/rouge =4,/obj/item/clothing/under/pants/jeans=6,/obj/item/clothing/under/pants/classicjeans=4, - /obj/item/clothing/under/pants/camo = 2,/obj/item/clothing/under/pants/blackjeans=4,/obj/item/clothing/under/pants/khaki=4, - /obj/item/clothing/under/pants/white=4,/obj/item/clothing/under/pants/red=2,/obj/item/clothing/under/pants/black=4, - /obj/item/clothing/under/pants/tan=4,/obj/item/clothing/under/pants/blue=2,/obj/item/clothing/under/pants/track=2, - /obj/item/clothing/under/sundress=4,/obj/item/clothing/under/blacktango=2, - /obj/item/clothing/suit/jacket=6,/obj/item/clothing/glasses/regular=4,/obj/item/clothing/head/sombrero=2, - /obj/item/clothing/suit/poncho=2,/obj/item/clothing/suit/ianshirt=1,/obj/item/clothing/shoes/laceup=4, - /obj/item/clothing/shoes/sandal=2, - /obj/item/clothing/mask/bandana/black=2,/obj/item/clothing/mask/bandana/skull=2,/obj/item/clothing/mask/bandana/green=2,/obj/item/clothing/mask/bandana/gold=2, - /obj/item/clothing/mask/bandana/blue=2,/obj/item/clothing/mask/scarf/blue=2,/obj/item/clothing/mask/scarf/red=2,/obj/item/clothing/mask/scarf/green=2, - /obj/item/clothing/mask/scarf/yellow=2,/obj/item/clothing/mask/scarf/violet=2, - /obj/item/clothing/suit/wintercoat=3,/obj/item/clothing/shoes/winterboots=3,/obj/item/clothing/head/santa=3, - /obj/item/clothing/suit/storage/miljacket_army=3,/obj/item/clothing/suit/storage/miljacket_army/miljacket_ranger=2,/obj/item/clothing/suit/storage/miljacket_army/miljacket_navy=2, - /obj/item/clothing/suit/student_jacket=3,/obj/item/clothing/suit/shawl=2,/obj/item/clothing/suit/atlas_jacket=4,/obj/item/clothing/under/sukeban_pants=2, - /obj/item/clothing/under/sukeban_dress=2,/obj/item/clothing/suit/sukeban_coat=4,/obj/item/clothing/under/pinkpolo=3,/obj/item/clothing/under/pretty_dress=1, - /obj/item/clothing/under/dress/dress_summer=2,/obj/item/clothing/under/dress/dress_vintage=2,/obj/item/clothing/under/dress/dress_evening=2,/obj/item/clothing/under/dress/dress_party=2) - - contraband = list(/obj/item/clothing/under/syndicate/tacticool=2,/obj/item/clothing/mask/balaclava=2,/obj/item/clothing/head/ushanka=2,/obj/item/clothing/under/soviet=2,/obj/item/clothing/mask/gas/fawkes = 6) - - premium = list(/obj/item/clothing/under/suit_jacket/checkered=2,/obj/item/clothing/head/mailman=2,/obj/item/clothing/under/rank/mailman=2,/obj/item/clothing/suit/jacket/leather=2, - /obj/item/clothing/suit/jacket/leather/overcoat=2,/obj/item/clothing/under/pants/mustangjeans=2) - - prices = list(/obj/item/clothing/head/that=419,/obj/item/clothing/head/fedora=419,/obj/item/clothing/glasses/monocle=109, - /obj/item/clothing/suit/jacket=299, /obj/item/clothing/suit/jacket/puffer/vest=239, /obj/item/clothing/suit/jacket/puffer=219, - /obj/item/clothing/under/suit_jacket/navy=119,/obj/item/clothing/under/suit_jacket/really_black=119,/obj/item/clothing/under/suit_jacket/burgundy=119, - /obj/item/clothing/under/suit_jacket/charcoal=119, /obj/item/clothing/under/suit_jacket/white=119,/obj/item/clothing/under/kilt=85,/obj/item/clothing/under/overalls=85, - /obj/item/clothing/under/suit_jacket/really_black=142,/obj/item/clothing/under/suit_jacket/rouge =248,/obj/item/clothing/under/pants/jeans=142, - /obj/item/clothing/under/pants/classicjeans=142,/obj/item/clothing/under/pants/camo = 142,/obj/item/clothing/under/pants/blackjeans=142,/obj/item/clothing/under/pants/khaki=142, - /obj/item/clothing/under/pants/white=142,/obj/item/clothing/under/pants/red=142,/obj/item/clothing/under/pants/black=142, - /obj/item/clothing/under/pants/tan=142,/obj/item/clothing/under/pants/blue=142,/obj/item/clothing/under/pants/track=142, - /obj/item/clothing/under/sundress=85,/obj/item/clothing/under/blacktango=99, - /obj/item/clothing/suit/jacket=138,/obj/item/clothing/glasses/regular=55,/obj/item/clothing/head/sombrero=240, - /obj/item/clothing/suit/poncho=295,/obj/item/clothing/suit/ianshirt=4000,/obj/item/clothing/shoes/laceup=99, - /obj/item/clothing/shoes/sandal=35, - /obj/item/clothing/mask/bandana/black=384,/obj/item/clothing/mask/bandana/skull=399,/obj/item/clothing/mask/bandana/green=384,/obj/item/clothing/mask/bandana/gold=389, - /obj/item/clothing/mask/bandana/blue=384,/obj/item/clothing/mask/scarf/blue=250,/obj/item/clothing/mask/scarf/red=250,/obj/item/clothing/mask/scarf/green=250, - /obj/item/clothing/mask/scarf/yellow=250,/obj/item/clothing/mask/scarf/violet=250, - /obj/item/clothing/suit/wintercoat=130,/obj/item/clothing/shoes/winterboots=70,/obj/item/clothing/head/santa=50, - /obj/item/clothing/suit/storage/miljacket_army=655,/obj/item/clothing/suit/storage/miljacket_army/miljacket_ranger=655,/obj/item/clothing/suit/storage/miljacket_army/miljacket_navy=655, - /obj/item/clothing/suit/student_jacket=459,/obj/item/clothing/suit/shawl=344,/obj/item/clothing/suit/atlas_jacket=250,/obj/item/clothing/under/sukeban_pants=366, - /obj/item/clothing/under/sukeban_dress=366,/obj/item/clothing/suit/sukeban_coat=579,/obj/item/clothing/under/pinkpolo=638,/obj/item/clothing/under/pretty_dress=564, - /obj/item/clothing/under/dress/dress_summer=332,/obj/item/clothing/under/dress/dress_vintage=465,/obj/item/clothing/under/dress/dress_evening=386,/obj/item/clothing/under/dress/dress_party=349) - - refill_canister = /obj/item/weapon/vending_refill/clothing - -//from old nanotrasen -/obj/machinery/vending/blood - name = "Blood'O'Matic" - desc = "Human blood dispenser. With internal freezer. Brought to you by EmpireV corp." - icon_state = "blood2" - light_color = "#ffc0c0" - icon_deny = "blood2deny" - product_ads = "Go and grab some blood!;I'm hope you are not bloody vampire.;Only from nice virgins!;Natural liquids!;This stuff saves lives." - //req_access_txt = "5" - products = list(/obj/item/weapon/reagent_containers/blood/APlus = 7, /obj/item/weapon/reagent_containers/blood/AMinus = 4, - /obj/item/weapon/reagent_containers/blood/BPlus = 4, /obj/item/weapon/reagent_containers/blood/BMinus = 2, - /obj/item/weapon/reagent_containers/blood/OPlus = 7, /obj/item/weapon/reagent_containers/blood/OMinus = 4) - contraband = list(/obj/item/weapon/reagent_containers/pill/stox = 10, /obj/item/weapon/reagent_containers/blood/empty = 10) - -//from old nanotrasen -/obj/machinery/vending/holy - name = "HolyVend" - desc = "Special items to prayers, sacrifices, rites and other methods to tell your God: I remember you!" - icon_state = "holy" - product_slogans = "HolyVend: Select your Religion today" - product_ads = "Pray now!;Atheists are heretic;Everything 100% Holy;Thirsty? Wanna pray? Why without candles?" - products = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 10, /obj/item/weapon/storage/fancy/candle_box = 25, /obj/item/weapon/storage/fancy/candle_box/red = 25,) - contraband = list(/obj/item/weapon/nullrod = 2) - prices = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 30, /obj/item/weapon/storage/fancy/candle_box = 50, /obj/item/weapon/storage/fancy/candle_box/red = 50, /obj/item/weapon/nullrod = 100) - -/obj/machinery/vending/eva - name = "Hardsuit Kits" - desc = "Conversion kits for your alien hardsuit needs." - products = list(/obj/item/device/modkit/engineering/tajaran = 5, /obj/item/device/modkit/engineering/unathi = 5, /obj/item/device/modkit/engineering/skrell = 5, - /obj/item/device/modkit/atmos/tajaran = 5, /obj/item/device/modkit/atmos/unathi = 5, /obj/item/device/modkit/atmos/skrell = 5, - /obj/item/device/modkit/med/tajaran = 5, /obj/item/device/modkit/med/unathi = 5, /obj/item/device/modkit/med/skrell = 5, - /obj/item/device/modkit/sec/tajaran = 5, /obj/item/device/modkit/sec/unathi = 5, /obj/item/device/modkit/sec/skrell = 5, - /obj/item/device/modkit/mining/tajaran = 5, /obj/item/device/modkit/mining/unathi = 5, /obj/item/device/modkit/mining/skrell = 5, - /obj/item/device/modkit/engineering/chief/tajaran = 1, /obj/item/device/modkit/engineering/chief/unathi = 1, /obj/item/device/modkit/engineering/chief/skrell = 1, - /obj/item/device/modkit/med/cmo/tajaran = 1, /obj/item/device/modkit/med/cmo/unathi = 1, /obj/item/device/modkit/med/cmo/skrell = 1, - /obj/item/device/modkit/sec/hos/tajaran = 1, /obj/item/device/modkit/sec/hos/unathi = 1, /obj/item/device/modkit/sec/hos/skrell = 1, - /obj/item/device/modkit = 10) - -/obj/machinery/vending/eva/mining - name = "Mining Hardsuit Kits" - desc = "Conversion kits for your alien mining hardsuits." - icon_state = "evamine" - products = list(/obj/item/device/modkit/mining/tajaran = 3, /obj/item/device/modkit/mining/unathi = 3, /obj/item/device/modkit/mining/skrell = 3, /obj/item/device/modkit = 5) - -/obj/machinery/vending/eva/engineering - name = "Engineering Hardsuit Kits" - desc = "Conversion kits for your alien engineering and atmos hardsuits." - icon_state = "evaengi" - products = list(/obj/item/device/modkit/engineering/tajaran = 3, /obj/item/device/modkit/engineering/unathi = 3, /obj/item/device/modkit/engineering/skrell = 3, - /obj/item/device/modkit/atmos/tajaran = 3, /obj/item/device/modkit/atmos/unathi = 3, /obj/item/device/modkit/atmos/skrell = 3, - /obj/item/device/modkit/engineering/chief/tajaran = 1, /obj/item/device/modkit/engineering/chief/unathi = 1, /obj/item/device/modkit/engineering/chief/skrell = 1, - /obj/item/device/modkit = 6) - - -//from old nanotrasen -//i deleted all drugs here, now it's just a joke -/obj/machinery/vending/omskvend - name = "Omsk-o-mat" - desc = "Drug dispenser." - icon_state = "omskvend" - product_ads = "NORKOMAN SUKA SHTOLE?;STOP NARTCOTICS!; so i heard u liek mudkipz; METRO ZATOPEELO" - products = list(/obj/item/device/healthanalyzer = 5) - contraband = list(/obj/item/weapon/reagent_containers/glass/bottle/antitoxin = 4) - -/obj/item/weapon/reagent_containers/pill/LSD - name = "LSD" - desc = "Ahaha oh wow." - icon_state = "pill9" - -/obj/item/weapon/reagent_containers/pill/LSD/atom_init() - . = ..() - reagents.add_reagent("mindbreaker", 0) - -/obj/item/weapon/reagent_containers/glass/beaker/LSD - name = "LSD IV" - desc = "Ahaha oh wow." - -/obj/item/weapon/reagent_containers/glass/beaker/LSD/atom_init() - . = ..() - reagents.add_reagent("mindbreaker", 0) - update_icon() - -/obj/machinery/vending/sustenance - name = "\improper Sustenance Vendor" - desc = "A vending machine which vends food, as required by section 47-C of the NT's Prisoner Ethical Treatment Agreement." - product_slogans = "Enjoy your meal.;Enough calories to support strenuous labor." - product_ads = "Sufficiently healthy.;Efficiently produced tofu!;Mmm! So good!;Have a meal.;You need food to live!;Have some more candy corn!;Try our new ice cups!" - icon_state = "sustenance" - products = list(/obj/item/weapon/reagent_containers/food/snacks/tofu = 20, - /obj/item/weapon/reagent_containers/food/drinks/ice = 12, - /obj/item/weapon/reagent_containers/food/snacks/candy_corn = 6, - /obj/item/weapon/reagent_containers/food/snacks/cracker = 20, - /obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 12) - contraband = list(/obj/item/weapon/kitchenknife = 6) - -//from old nanotrasen -/obj/machinery/vending/theater - name = "Theater-o-mat" - desc = "Special costume pack to add randomness in boring life." - icon_state = "Theater" - products = list(/obj/item/clothing/head/xenos = 5, /obj/item/clothing/suit/xenos = 5, /obj/item/clothing/suit/monkeysuit = 5, /obj/item/clothing/suit/syndicatefake = 5, /obj/item/clothing/head/syndicatefake = 5, - /obj/item/clothing/head/collectable/slime = 5, /obj/item/clothing/head/collectable/xenom = 5, /obj/item/clothing/head/collectable/petehat = 5, /obj/item/clothing/head/kitty = 5, - /obj/item/clothing/head/pumpkinhead = 5, /obj/item/clothing/head/ushanka = 5, /obj/item/clothing/head/cardborg = 5, /obj/item/clothing/suit/cardborg = 5, /obj/item/clothing/head/bearpelt = 5, - /obj/item/clothing/suit/space/santa = 5, /obj/item/clothing/head/helmet/space/santahat = 5, /obj/item/weapon/storage/backpack/santabag = 5, /obj/item/clothing/mask/fakemoustache = 5, - /obj/item/clothing/mask/gas/sexyclown = 5, /obj/item/clothing/mask/gas/sexymime = 5, /obj/item/clothing/mask/horsehead = 5, /obj/item/clothing/suit/apron = 5, /obj/item/clothing/suit/apron/overalls = 5, - /obj/item/clothing/suit/chickensuit = 5, /obj/item/clothing/head/chicken = 5, /obj/item/clothing/under/fluff/tian_dress = 5, /obj/item/clothing/under/fluff/wyatt_1 = 5, - /obj/item/clothing/under/fluff/olddressuniform = 5, /obj/item/clothing/under/fluff/jumpsuitdown = 5, /obj/item/clothing/under/fluff/jane_sidsuit = 5, /obj/item/clothing/under/sundress = 5, - /obj/item/clothing/under/roman = 3, /obj/item/clothing/shoes/roman = 3, /obj/item/clothing/head/helmet/roman = 2, /obj/item/clothing/head/helmet/roman/legionaire = 1, /obj/item/clothing/under/smoking = 3, - /obj/item/clothing/suit/tuxedo = 3,/obj/item/clothing/under/popking = 1, /obj/item/clothing/under/popking/alternate = 1, /obj/item/clothing/suit/hooded/angel_suit = 1, - /obj/item/clothing/mask/fake_face = 2, /obj/item/clothing/suit/hooded/ian_costume = 1, /obj/item/clothing/suit/hooded/carp_costume = 1) - prices = list(/obj/item/clothing/head/xenos = 100, /obj/item/clothing/suit/xenos = 200, /obj/item/clothing/suit/monkeysuit = 200, /obj/item/clothing/suit/hooded/carp_costume = 200) - contraband = list(/obj/item/clothing/mask/gas/fawkes = 2) +/datum/data/vending_product + var/product_name = "generic" + var/product_path = null + var/amount = 0 + var/max_amount = 0 + var/price = 0 + var/display_color = "blue" + + + +/obj/machinery/vending + name = "Vendomat" + desc = "A generic vending machine." + icon = 'icons/obj/vending.dmi' + icon_state = "generic" + var/light_range_on = 3 + var/light_power_on = 1 + layer = 2.9 + anchored = 1 + density = 1 + allowed_checks = ALLOWED_CHECK_NONE + 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/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 = 1 //Stop spouting those godawful pitches! + var/extended_inventory = 0 //can we access the hidden inventory? + var/obj/item/weapon/coin/coin + var/obj/item/weapon/vending_refill/refill_canister = null //The type of refill canisters used by this machine. + + var/check_accounts = 1 // 1 = requires PIN and checks accounts. 0 = You slide an ID, it vends, SPACE COMMUNISM! + var/obj/item/weapon/spacecash/ewallet/ewallet + var/datum/wires/vending/wires = null + var/scan_id = TRUE + + +/obj/machinery/vending/atom_init() + . = ..() + wires = new(src) + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/vendor(null) + + slogan_list = splittext(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. + last_slogan = world.time + rand(0, slogan_delay) + + build_inventory(products) + //Add hidden inventory + build_inventory(contraband, 1) + build_inventory(premium, 0, 1) + power_change() + +/obj/machinery/vending/Destroy() + QDEL_NULL(wires) + QDEL_NULL(coin) + return ..() + +/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)) + spawn(0) + src.malfunction() + return + return + else + return + +/obj/machinery/vending/blob_act() + if (prob(50)) + spawn(0) + src.malfunction() + qdel(src) + return + + return + +/obj/machinery/vending/proc/build_inventory(list/productlist,hidden=0,req_coin=0) + 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 /datum/data/vending_product() + + R.product_path = typepath + R.amount = amount + R.max_amount = amount + R.price = price + R.display_color = pick("red","orange","green") + + if(hidden) + hidden_records += R + else if(req_coin) + coin_records += R + else + product_records += R + + var/atom/temp = typepath + R.product_name = initial(temp.name) +// world << "Added: [R.product_name]] - [R.amount] - [R.product_path]" + return + +/obj/machinery/vending/proc/refill_inventory(obj/item/weapon/vending_refill/refill, datum/data/vending_product/machine, mob/user) //Restocking from TG + var/total = 0 + + var/to_restock = 0 + for(var/datum/data/vending_product/machine_content in machine) + to_restock += machine_content.max_amount - machine_content.amount + + if(to_restock <= refill.charges) + for(var/datum/data/vending_product/machine_content in machine) + if(machine_content.amount != machine_content.max_amount) + to_chat(usr, "[machine_content.max_amount - machine_content.amount] of [machine_content.product_name]") + machine_content.amount = machine_content.max_amount + refill.charges -= to_restock + total = to_restock + else + var/tmp_charges = refill.charges + for(var/datum/data/vending_product/machine_content in machine) + var/restock = ceil(((machine_content.max_amount - machine_content.amount) / to_restock) * tmp_charges) + if(restock > refill.charges) + restock = refill.charges + machine_content.amount += restock + refill.charges -= restock + total += restock + if(restock) + to_chat(usr, "[restock] of [machine_content.product_name]") + if(refill.charges == 0) //due to rounding, we ran out of refill charges, exit. + break + return total + +/obj/machinery/vending/attackby(obj/item/weapon/W, mob/user) + if(panel_open) + if(default_unfasten_wrench(user, W, time = 60)) + return + + if(istype(W, /obj/item/weapon/crowbar)) + default_deconstruction_crowbar(W) + + if (istype(W, /obj/item/weapon/card/emag)) + src.emagged = 1 + to_chat(user, "You short out the product lock on [src]") + return + + else if(istype(W, /obj/item/weapon/screwdriver) && anchored) + src.panel_open = !src.panel_open + to_chat(user, "You [src.panel_open ? "open" : "close"] the maintenance panel.") + src.overlays.Cut() + if(src.panel_open) + src.overlays += image(src.icon, "[initial(icon_state)]-panel") + src.updateUsrDialog() + + return + else if(is_wire_tool(W) && panel_open && wires.interact(user)) + return + + else if(istype(W, /obj/item/weapon/coin) && premium.len > 0) + user.drop_item() + W.loc = src + coin = W + to_chat(user, "\blue You insert the [W] into the [src]") + return + + else if(istype(W, /obj/item/weapon/wrench)) //unwrenching vendomats + var/turf/T = user.loc + if(user.is_busy(src)) return + to_chat(user, "You begin [anchored ? "unwrenching" : "wrenching"] the [src].") + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, 40, target = src)) + if( !istype(src, /obj/machinery/vending) || !user || !W || !T ) return + if( user.loc == T && user.get_active_hand() == W ) + anchored = !anchored + to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].") + if (!(src.anchored & powered())) + src.icon_state = "[initial(icon_state)]-off" + stat |= NOPOWER + set_light(0) + else + icon_state = initial(icon_state) + stat &= ~NOPOWER + set_light(light_range_on, light_power_on) + + else if(currently_vending && istype(W, /obj/item/device/pda) && W.GetID()) + var/obj/item/weapon/card/I = W.GetID() + scan_card(I) + + else if(currently_vending && istype(W, /obj/item/weapon/card)) + var/obj/item/weapon/card/I = W + scan_card(I) + + else if(istype(W, refill_canister) && refill_canister != null) + if(stat & (BROKEN|NOPOWER)) + to_chat(user, "It does nothing.") + else if(panel_open) + //if the panel is open we attempt to refill the machine + var/obj/item/weapon/vending_refill/canister = W + if(canister.charges == 0) + to_chat(user, "This [canister.name] is empty!") + else + var/transfered = refill_inventory(canister,product_records,user) + if(transfered) + to_chat(user, "You loaded [transfered] items in \the [name].") + else + to_chat(user, "The [name] is fully stocked.") + return; + else + to_chat(user, "You should probably unscrew the service panel first.") + + else if (istype(W, /obj/item/weapon/spacecash/ewallet)) + user.drop_item() + W.loc = src + ewallet = W + to_chat(user, "\blue You insert the [W] into the [src]") + + else if(src.panel_open) + for(var/datum/data/vending_product/R in product_records) + if(istype(W, R.product_path)) + stock(R, user) + qdel(W) + else + ..() + +/obj/machinery/vending/default_deconstruction_crowbar(obj/item/O) + var/list/all_products = product_records + hidden_records + coin_records + for(var/datum/data/vending_product/machine_content in all_products) + while(machine_content.amount !=0) + var/safety = 0 //to avoid infinite loop + for(var/obj/item/weapon/vending_refill/VR in component_parts) + safety++ + if(VR.charges < initial(VR.charges)) + VR.charges++ + machine_content.amount-- + if(!machine_content.amount) + break + else + safety-- + if(safety <= 0) + break + ..() + +/obj/machinery/vending/proc/scan_card(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(check_accounts) + if(vendor_account) + var/datum/money_account/D = get_account(C.associated_account_number) + var/attempt_pin = 0 + if(D) + if(D.security_level > 0) + attempt_pin = input("Enter pin code", "Vendor transaction") as num + if(attempt_pin) + D = attempt_account_access(C.associated_account_number, attempt_pin, 2) + if(D) + var/transaction_amount = currently_vending.price + if(transaction_amount <= D.money) + + //transfer the money + D.money -= transaction_amount + vendor_account.money += transaction_amount + + //create entries in the two account transaction logs + var/datum/transaction/T = new() + T.target_name = "[vendor_account.owner_name] (via [src.name])" + T.purpose = "Purchase of [currently_vending.product_name]" + if(transaction_amount > 0) + T.amount = "([transaction_amount])" + else + T.amount = "[transaction_amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + D.transaction_log.Add(T) + // + T = new() + T.target_name = D.owner_name + T.purpose = "Purchase of [currently_vending.product_name]" + T.amount = "[transaction_amount]" + T.source_terminal = src.name + T.date = current_date_string + T.time = worldtime2text() + vendor_account.transaction_log.Add(T) + + // Vend the item + src.vend(src.currently_vending, usr) + currently_vending = null + else + to_chat(usr, "[bicon(src)]You don't have that much money!") + else + to_chat(usr, "[bicon(src)]You entered wrong account PIN!") + else + to_chat(usr, "[bicon(src)]Unable to find your money account!") + else + to_chat(usr, "[bicon(src)]Unable to access account. Check security settings and try again.") + else + //Just Vend it. + src.vend(src.currently_vending, usr) + currently_vending = null + else + to_chat(usr, "[bicon(src)]Unable to access vendor account. Please record the machine ID and call CentComm Support.") + +/obj/machinery/vending/ui_interact(mob/user) + if(seconds_electrified && !issilicon(user) && !isobserver(user)) + if(shock(user, 100)) + return + + var/vendorname = name //import the machine's name + + if(currently_vending) + var/dat + dat += "You have selected [currently_vending.product_name].
                    Please swipe your ID to pay for the article.

                    " + dat += "Cancel" + var/datum/browser/popup = new(user, "window=vending", "[vendorname]", 400, 550) + popup.set_content(dat) + popup.open() + return + + var/dat + dat += "

                    Select an item

                    " + dat += "
                    " + + if (product_records.len == 0) + dat += "No product loaded!" + + else + dat += "
                      " + + dat += print_recors(product_records) + if(extended_inventory) + dat += print_recors(hidden_records) + if(coin) + dat += print_recors(coin_records) + + dat += "
                    " + dat += "
                    " + + if (premium.len > 0) + dat += "Coin slot: [coin ? coin : "No coin inserted"] Remove
                    " + + if (ewallet) + dat += "Charge card's credits: [ewallet ? ewallet.worth : "No charge card inserted"] (Remove)

                    " + + var/datum/browser/popup = new(user, "window=vending", "[vendorname]", 450, 500) + popup.set_content(dat) + popup.open() + +/obj/machinery/vending/proc/print_recors(list/record) + var/dat + for (var/datum/data/vending_product/R in record) + dat += "
                  • " + if (R.amount > 0) + dat += " Vend" + else + dat += " SOLD OUT" + dat += "[R.product_name]:" + dat += " [R.amount] " + if(R.price) + dat += " (Price: [R.price])" + dat += "
                  • " + return dat + +/obj/machinery/vending/Topic(href, href_list) + . = ..() + if(!.) + return + + if(href_list["remove_coin"] && !issilicon(usr) && !isobserver(usr)) + if(!coin) + to_chat(usr, "There is no coin in this machine.") + return FALSE + + coin.loc = loc + if(!usr.get_active_hand()) + usr.put_in_hands(coin) + to_chat(usr, "\blue You remove the [coin] from the [src]") + coin = null + + else if(href_list["remove_ewallet"] && !issilicon(usr) && !isobserver(usr)) + if (!ewallet) + to_chat(usr, "There is no charge card in this machine.") + return + ewallet.loc = loc + if(!usr.get_active_hand()) + usr.put_in_hands(ewallet) + to_chat(usr, "\blue You remove the [ewallet] from the [src]") + ewallet = null + + else if (href_list["vend"] && vend_ready && !currently_vending) + + if(isrobot(usr)) + var/mob/living/silicon/robot/R = usr + if(!(R.module && istype(R.module,/obj/item/weapon/robot_module/butler) )) + to_chat(usr, "\red The vending machine refuses to interface with you, as you are not in its target demographic!") + return FALSE + else if(issilicon(usr)) + to_chat(usr, "\red The vending machine refuses to interface with you, as you are not in its target demographic!") + return FALSE + + 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 FALSE + + var/datum/data/vending_product/R = locate(href_list["vend"]) + if (!R || !istype(R) || !R.product_path || R.amount <= 0) + return FALSE + + if(R.price == null || isobserver(usr)) //Centcomm buys somethin at himself? Nope, because they can just take this + src.vend(R, usr) + else + if (ewallet) + if (R.price <= ewallet.worth) + ewallet.worth -= R.price + src.vend(R, usr) + else + to_chat(usr, "\red The ewallet doesn't have enough money to pay for that.") + src.currently_vending = R + src.updateUsrDialog() + else + src.currently_vending = R + src.updateUsrDialog() + return + + else if (href_list["cancel_buying"]) + src.currently_vending = null + src.updateUsrDialog() + return + + src.updateUsrDialog() + +/obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user) + if (!allowed(user) && !emagged && scan_id) //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 (R in coin_records) + if(!coin) + to_chat(user, "\blue You need to insert a coin to get this item.") + return + if(coin.string_attached) + if(prob(50)) + to_chat(user, "\blue You successfully pull the coin out before the [src] could swallow it.") + else + to_chat(user, "\blue You weren't able to pull the coin out fast enough, the machine ate it, string and all.") + QDEL_NULL(coin) + else + QDEL_NULL(coin) + + 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)) + playsound(src, 'sound/items/vending.ogg', 50, 1, 1) + src.vend_ready = 1 + return + + src.updateUsrDialog() + +/obj/machinery/vending/proc/stock(datum/data/vending_product/R, mob/user) + if(src.panel_open) + to_chat(user, "\blue You stock the [src] with \a [R.product_name]") + R.amount++ + + 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(2)) + src.throw_item() + + return + +/obj/machinery/vending/proc/speak(message) + if(stat & NOPOWER) + return + + if (!message) + return + + for(var/mob/O in hearers(src, null)) + O.show_message("[src] beeps, \"[message]\"",2) + return + +/obj/machinery/vending/power_change() + if(stat & BROKEN) + icon_state = "[initial(icon_state)]-broken" + set_light(0) + else + if( powered() & src.anchored ) + icon_state = initial(icon_state) + stat &= ~NOPOWER + set_light(light_range_on, light_power_on) + else + spawn(rand(0, 15)) + src.icon_state = "[initial(icon_state)]-off" + stat |= NOPOWER + set_light(0) + +//Oh no we're malfunctioning! Dump out some product and break. +/obj/machinery/vending/proc/malfunction() + for(var/datum/data/vending_product/R in src.product_records) + if (R.amount <= 0) //Try to use a record that actually has something to dump. + continue + var/dump_path = R.product_path + if (!dump_path) + continue + + while(R.amount>0) + new dump_path(src.loc) + R.amount-- + continue + + 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/obj/throw_item = null + var/mob/living/target = locate() in view(7,src) + if(!target) + return 0 + + for(var/datum/data/vending_product/R in src.product_records) + if (R.amount <= 0) //Try to use a record that actually has something to dump. + continue + var/dump_path = R.product_path + if (!dump_path) + continue + + R.amount-- + throw_item = new dump_path(src.loc) + break + if (!throw_item) + return 0 + throw_item.throw_at(target, 16, 3) + visible_message("[src] launches [throw_item.name] at [target.name]!") + return 1 + +/obj/machinery/vending/proc/shock(mob/user, prb) + 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 (electrocute_mob(user, get_area(src), src, 0.7)) + return 1 + else + 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/phoron;/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" + light_color = "#77beda" + 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/tequilla = 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/bottle/beer = 6, + /obj/item/weapon/reagent_containers/food/drinks/bottle/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/cans/tonic = 8, + /obj/item/weapon/reagent_containers/food/drinks/cans/cola = 8, /obj/item/weapon/reagent_containers/food/drinks/cans/sodawater = 15, + /obj/item/weapon/reagent_containers/food/drinks/flask/barflask = 2, /obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask = 2, + /obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 30,/obj/item/weapon/reagent_containers/food/drinks/ice = 9, + /obj/item/weapon/reagent_containers/food/drinks/bottle/melonliquor = 2,/obj/item/weapon/reagent_containers/food/drinks/bottle/bluecuracao = 2, + /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe = 2,/obj/item/weapon/reagent_containers/food/drinks/bottle/grenadine = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/champagne = 5) + contraband = list(/obj/item/weapon/reagent_containers/food/drinks/tea = 10) + vend_delay = 15 + 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" + refill_canister = /obj/item/weapon/vending_refill/boozeomat + +/obj/machinery/vending/assist + 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) + product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!" + +/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" + light_color = "#b88b2e" + 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) + refill_canister = /obj/item/weapon/vending_refill/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!;Twice the calories for half the price!" + 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" + light_color = "#d00023" + products = list(/obj/item/weapon/reagent_containers/food/snacks/candy/candybar = 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) + contraband = list(/obj/item/weapon/reagent_containers/food/snacks/syndicake = 6) + prices = list(/obj/item/weapon/reagent_containers/food/snacks/candy/candybar = 1,/obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 5,/obj/item/weapon/reagent_containers/food/snacks/chips = 1, + /obj/item/weapon/reagent_containers/food/snacks/sosjerky = 2,/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 1,/obj/item/weapon/reagent_containers/food/snacks/spacetwinkie = 1, + /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 1) + refill_canister = /obj/item/weapon/vending_refill/snack + +/obj/machinery/vending/chinese + name = "\improper Mr. Chang" + desc = "A self-serving Chinese food machine, for all your Chinese food needs." + product_slogans = "Taste 5000 years of culture!" + icon_state = "snack" + light_color = "#d00023" + products = list(/obj/item/weapon/reagent_containers/food/snacks/chinese/chowmein = 6, /obj/item/weapon/reagent_containers/food/snacks/chinese/tao = 6, /obj/item/weapon/reagent_containers/food/snacks/chinese/sweetsourchickenball = 6, /obj/item/weapon/reagent_containers/food/snacks/chinese/newdles = 6, + /obj/item/weapon/reagent_containers/food/snacks/chinese/rice = 6, /obj/item/weapon/kitchen/utensil/fork/sticks = 18) + prices = list(/obj/item/weapon/reagent_containers/food/snacks/chinese/chowmein = 50, /obj/item/weapon/reagent_containers/food/snacks/chinese/tao = 50, /obj/item/weapon/reagent_containers/food/snacks/chinese/sweetsourchickenball = 50, /obj/item/weapon/reagent_containers/food/snacks/chinese/newdles = 50, + /obj/item/weapon/reagent_containers/food/snacks/chinese/rice = 50, /obj/item/weapon/kitchen/utensil/fork/sticks = 1) + refill_canister = /obj/item/weapon/vending_refill/snack + +/obj/machinery/vending/cola + name = "Robust Softdrinks" + desc = "A softdrink vendor provided by Robust Industries, LLC." + icon_state = "Cola_Machine" + light_color = "#315ab4" + product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!" + 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/cans/cola = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 10, + /obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 10, + /obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 10,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 10, + /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10, /obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10) + contraband = list(/obj/item/weapon/reagent_containers/food/drinks/cans/thirteenloko = 5) + prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/space_mountain_wind = 1, + /obj/item/weapon/reagent_containers/food/drinks/cans/dr_gibb = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/starkist = 1, + /obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 2,/obj/item/weapon/reagent_containers/food/drinks/cans/space_up = 1, + /obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1) + +//This one's from bay12 +/obj/machinery/vending/cart + name = "PTech" + desc = "Cartridges for PDAs." + product_slogans = "Carts to go!" + icon_state = "cart" + light_color = "#dddddd" + 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/science = 10,/obj/item/device/pda/heads = 10, + /obj/item/weapon/cartridge/captain = 3,/obj/item/weapon/cartridge/quartermaster = 10) + + +/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." + vend_delay = 34 + icon_state = "cigs" + light_color = "#dddddd" + products = list(/obj/item/weapon/storage/fancy/cigarettes = 10, /obj/item/weapon/storage/fancy/cigarettes/menthol = 5, /obj/item/weapon/storage/box/matches = 10, /obj/item/weapon/lighter/random = 4, /obj/item/clothing/mask/ecig = 4) + contraband = list(/obj/item/weapon/lighter/zippo = 4) + premium = list(/obj/item/clothing/mask/cigarette/cigar/havana = 2) + prices = list(/obj/item/weapon/storage/fancy/cigarettes = 20, /obj/item/weapon/storage/fancy/cigarettes/menthol = 30, /obj/item/weapon/storage/box/matches = 10, /obj/item/weapon/lighter/random = 15, /obj/item/clothing/mask/ecig = 40) + refill_canister = /obj/item/weapon/vending_refill/cigarette + +/obj/machinery/vending/medical + name = "NanoMed Plus" + desc = "Medical drug dispenser." + icon_state = "med" + icon_deny = "med-deny" + light_color = "#e6fff2" + 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/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, + /obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 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/dylovene = 6) + + +//This one's from bay12 +/obj/machinery/vending/phoronresearch + name = "Toximate 3000" + desc = "All the fine parts you need in one vending machine!" + products = list(/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) + +/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" + light_power_on = 1 + light_color = "#e6fff2" + 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/hypospray/autoinjector = 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) + +/obj/machinery/vending/wallmed2 + name = "NanoMed" + desc = "Wall-mounted Medical Equipment dispenser." + icon_state = "wallmed" + light_power_on = 1 + light_color = "#e6fff2" + 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/hypospray/autoinjector = 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) + +/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" + light_color = "#f1f8ff" + 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) + contraband = list(/obj/item/clothing/glasses/sunglasses = 2,/obj/item/weapon/storage/fancy/donut_box = 2,/obj/item/device/flashlight/seclite = 4) + +/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" + light_color = "#34ff7b" + icon_deny = "nutri-deny" + products = list(/obj/item/nutrient/ez = 45,/obj/item/nutrient/l4z = 25,/obj/item/nutrient/rh = 15,/obj/item/weapon/pestspray = 20, + /obj/item/weapon/reagent_containers/syringe = 5,/obj/item/weapon/storage/bag/plants = 5) + premium = list(/obj/item/weapon/reagent_containers/glass/bottle/ammonia = 10,/obj/item/weapon/reagent_containers/glass/bottle/diethylamine = 5) + +/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" + light_color = "#34ff7b" + products = list(/obj/item/seeds/ambrosiavulgarisseed = 3,/obj/item/seeds/appleseed = 3,/obj/item/seeds/bananaseed = 3,/obj/item/seeds/berryseed = 3, + /obj/item/seeds/cabbageseed = 3,/obj/item/seeds/carrotseed = 3,/obj/item/seeds/cherryseed = 3,/obj/item/seeds/chantermycelium = 3, + /obj/item/seeds/chiliseed = 3,/obj/item/seeds/cocoapodseed = 3,/obj/item/seeds/cornseed = 3,/obj/item/seeds/replicapod = 3, + /obj/item/seeds/eggplantseed = 3,/obj/item/seeds/grapeseed = 3,/obj/item/seeds/grassseed = 3,/obj/item/seeds/lemonseed = 3, + /obj/item/seeds/limeseed = 3,/obj/item/seeds/orangeseed = 3,/obj/item/seeds/plastiseed = 3,/obj/item/seeds/potatoseed = 3, + /obj/item/seeds/poppyseed = 3,/obj/item/seeds/pumpkinseed = 3,/obj/item/seeds/riceseed= 3,/obj/item/seeds/soyaseed = 3, + /obj/item/seeds/sunflowerseed = 3,/obj/item/seeds/tomatoseed = 3,/obj/item/seeds/towermycelium = 3,/obj/item/seeds/watermelonseed = 3, + /obj/item/seeds/wheatseed = 3,/obj/item/seeds/whitebeetseed = 3) + contraband = list(/obj/item/seeds/amanitamycelium = 2,/obj/item/seeds/glowshroom = 2,/obj/item/seeds/libertymycelium = 2,/obj/item/seeds/mtearseed = 2, + /obj/item/seeds/nettleseed = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/shandseed = 2,) + premium = list(/obj/item/toy/waterflower = 1) + + +/obj/machinery/vending/magivend + name = "MagiVend" + desc = "A magic vending machine." + icon_state = "MagiVend" + light_color = "#97429a" + 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/shoes/sandal = 1,/obj/item/weapon/staff = 2, /obj/item/device/modkit/wizard/skrell = 1, + /obj/item/device/modkit/wizard/unathi = 1, /obj/item/device/modkit/wizard/tajaran = 1, /obj/item/clothing/head/wizard/redhood = 1, /obj/item/clothing/head/wizard/bluehood = 1, + /obj/item/clothing/suit/wizrobe/wiz_blue = 1, /obj/item/clothing/suit/wizrobe/wiz_red = 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 + +/obj/machinery/vending/weirdomat + name = "Weird-O-Mat" + desc = "A marvel, on the brink of technobabble and pixie fiction." + icon_state = "MagiVend" + light_color = "#97429a" + products = list(/obj/item/weapon/occult_pinpointer = 3, + /obj/item/device/occult_scanner = 3, + /obj/item/clothing/mask/gas/owl_mask = 3, + /obj/item/clothing/mask/pig = 3, + /obj/item/clothing/mask/horsehead = 3, + /obj/item/clothing/mask/cowmask = 3, + /obj/item/clothing/mask/chicken = 3, + /obj/item/weapon/kitchenknife/plastic = 3) + prices = list(/obj/item/weapon/occult_pinpointer = 400, + /obj/item/device/occult_scanner = 400, + /obj/item/clothing/mask/gas/owl_mask = 250, + /obj/item/clothing/mask/pig = 250, + /obj/item/clothing/mask/horsehead = 250, + /obj/item/clothing/mask/cowmask = 250, + /obj/item/clothing/mask/chicken = 250, + /obj/item/weapon/kitchenknife/plastic = 300) + contraband = list(/obj/item/weapon/nullrod = 1, + /obj/item/weapon/kitchenknife/ritual = 1) + premium = list(/obj/item/clothing/glasses/gglasses = 1, + /obj/item/toy/figure/wizard = 1, + /obj/item/weapon/storage/fancy/crayons = 1) + product_slogans = "Amicitiae nostrae memoriam spero sempiternam fore;Aequam memento rebus in arduis servare mentem;Vitanda est improba siren desidia;Serva me, servabo te;Faber est suae quisque fortunae" + vend_reply = "Have fun! No returns!" + product_ads = "Occult is magic;Knowledge is magic;All the magic!;None to spook us;The dice has been cast" + +/obj/machinery/vending/weirdomat/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/device/occult_scanner)) + var/obj/item/device/occult_scanner/OS = I + OS.scanned_type = src.type + to_chat(user, "[src] has been succesfully scanned by [OS]") + if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/ectoplasm)) + RedeemEctoplasm(I, user) + return + ..() + +/obj/machinery/vending/weirdomat/proc/RedeemEctoplasm(obj/plasm, redeemer) + if(plasm.in_use) + return + plasm.in_use = TRUE + var/selection = input(redeemer, "Pick your eternal reward", "Ectoplasm Redemption") in list("Misfortune Set", "Spiritual Bond Set", "Contract From Below", "Cryptorecorder", "Black Candle Box", "Cancel") + if(!selection || !Adjacent(redeemer)) + plasm.in_use = FALSE + return + switch(selection) + if("Misfortune Set") + new /obj/item/weapon/storage/pill_bottle/ghostdice(loc) + if("Spiritual Bond Set") + new /obj/item/weapon/game_kit/chaplain(loc) + if("Contract From Below") + new /obj/item/weapon/pen/ghost(loc) + if("Cryptorecorder") + new /obj/item/device/camera/spooky(loc) + if("Black Candle Box") + new /obj/item/weapon/storage/fancy/black_candle_box(loc) + if("Cancel") + plasm.in_use = FALSE + return + qdel(plasm) + +/obj/machinery/vending/barbervend + name = "Fab-O-Vend" + desc = "It would seem it vends dyes, and other stuff to make you pretty." + icon_state = "barbervend" + product_slogans = "Spread the colour, like butter, onto toast... Onto their hair.; Sometimes, I dream about dyes...; Paint 'em up and call me Mr. Painter.; Look brother, I'm a vendomat, I solve practical problems." + product_ads = "Cut 'em all!; To sheds!; Hair be gone!; Prettify!; Beautify!" + req_access_txt = "69" + refill_canister = /obj/item/weapon/vending_refill/barbervend + products = list(/obj/item/weapon/reagent_containers/glass/bottle/hair_dye/white = 10, + /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/red = 10, + /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/green = 10, + /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/blue = 10, + /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/black = 10, + /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/brown = 10, + /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/blond = 10, + /obj/item/weapon/reagent_containers/spray/hair_color_spray = 3) + contraband = list(/obj/item/weapon/razor = 1) + premium = list(/obj/item/weapon/scissors = 3, + /obj/item/weapon/reagent_containers/glass/bottle/hair_growth_accelerator = 3, + /obj/item/weapon/storage/box/lipstick = 3) + +/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/kitchenknife = 3, + /obj/item/weapon/reagent_containers/food/drinks/drinkingglass = 8, + /obj/item/clothing/suit/chef/classic = 2, + /obj/item/weapon/kitchen/mould/bear = 1, + /obj/item/weapon/kitchen/mould/worm = 1, + /obj/item/weapon/kitchen/mould/bean = 1, + /obj/item/weapon/kitchen/mould/ball = 1, + /obj/item/weapon/kitchen/mould/cane = 1, + /obj/item/weapon/kitchen/mould/cash = 1, + /obj/item/weapon/kitchen/mould/coin = 1, + /obj/item/weapon/kitchen/mould/loli = 1 + ) + contraband = list(/obj/item/weapon/kitchen/utensil/spoon = 2,/obj/item/weapon/kitchen/rollingpin = 2, /obj/item/weapon/butch = 2) + +/obj/machinery/vending/sovietsoda + name = "BODA" + desc = "An old sweet water vending machine,how did this end up here?" + icon_state = "sovietsoda" + 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) + +/obj/machinery/vending/tool + name = "YouTool" + desc = "Tools for tools." + icon_state = "tool" + light_color = "#ffcc33" + 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) + contraband = list(/obj/item/weapon/weldingtool/hugetank = 2,/obj/item/clothing/gloves/fyellow = 2) + premium = list(/obj/item/clothing/gloves/yellow = 1) + +/obj/machinery/vending/engivend + name = "Engi-Vend" + desc = "Spare tool vending. What? Did you expect some witty description?" + icon_state = "engivend" + light_color = "#ffcc33" + 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/airlock_electronics = 10,/obj/item/weapon/module/power_control = 10,/obj/item/weapon/airalarm_electronics = 10,/obj/item/weapon/stock_parts/cell/high = 10) + contraband = list(/obj/item/weapon/stock_parts/cell/potato = 3) + premium = list(/obj/item/weapon/storage/belt/utility = 3) + +//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/chief_engineer = 4,/obj/item/clothing/under/rank/engineer = 4,/obj/item/clothing/shoes/workboots = 4,/obj/item/clothing/head/hardhat/yellow = 4, + /obj/item/clothing/head/hardhat/yellow/visor = 1,/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/heavyduty = 8, /obj/item/weapon/stock_parts/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) + // 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 + +//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/stack/cable_coil/random = 2,/obj/item/device/flash = 4, + /obj/item/weapon/stock_parts/cell/high = 5, /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 = 2) + //everything after the power cell had no amounts, I improvised. -Sayu + +//This one's from NTstation +//don't forget to change the refill size if you change the machine's contents! +/obj/machinery/vending/clothing + name = "ClothesMate" //renamed to make the slogan rhyme + desc = "A vending machine for clothing." + icon_state = "clothes" + product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this free swag!;Why leave style up to fate? Use the ClothesMate!" + vend_delay = 15 + vend_reply = "Thank you for using the ClothesMate!" + products = list(/obj/item/clothing/head/that=4,/obj/item/clothing/head/fedora=2,/obj/item/clothing/glasses/monocle=2, + /obj/item/clothing/suit/jacket=4, /obj/item/clothing/suit/jacket/puffer/vest=4, /obj/item/clothing/suit/jacket/puffer=4, + /obj/item/clothing/under/suit_jacket/navy=2,/obj/item/clothing/under/suit_jacket/really_black=2,/obj/item/clothing/under/suit_jacket/burgundy=2, + /obj/item/clothing/under/suit_jacket/charcoal=2, /obj/item/clothing/under/suit_jacket/white=2,/obj/item/clothing/under/kilt=2,/obj/item/clothing/under/overalls=2, + /obj/item/clothing/under/suit_jacket/really_black=4,/obj/item/clothing/under/suit_jacket/rouge =4,/obj/item/clothing/under/pants/jeans=6,/obj/item/clothing/under/pants/classicjeans=4, + /obj/item/clothing/under/pants/camo = 2,/obj/item/clothing/under/pants/blackjeans=4,/obj/item/clothing/under/pants/khaki=4, + /obj/item/clothing/under/pants/white=4,/obj/item/clothing/under/pants/red=2,/obj/item/clothing/under/pants/black=4, + /obj/item/clothing/under/pants/tan=4,/obj/item/clothing/under/pants/blue=2,/obj/item/clothing/under/pants/track=2, + /obj/item/clothing/under/sundress=4,/obj/item/clothing/under/blacktango=2, + /obj/item/clothing/suit/jacket=6,/obj/item/clothing/glasses/regular=4,/obj/item/clothing/head/sombrero=2, + /obj/item/clothing/suit/poncho=2,/obj/item/clothing/suit/ianshirt=1,/obj/item/clothing/shoes/laceup=4, + /obj/item/clothing/shoes/sandal=2, + /obj/item/clothing/mask/bandana/black=2,/obj/item/clothing/mask/bandana/skull=2,/obj/item/clothing/mask/bandana/green=2,/obj/item/clothing/mask/bandana/gold=2, + /obj/item/clothing/mask/bandana/blue=2,/obj/item/clothing/mask/scarf/blue=2,/obj/item/clothing/mask/scarf/red=2,/obj/item/clothing/mask/scarf/green=2, + /obj/item/clothing/mask/scarf/yellow=2,/obj/item/clothing/mask/scarf/violet=2, + /obj/item/clothing/suit/wintercoat=3,/obj/item/clothing/shoes/winterboots=3,/obj/item/clothing/head/santa=3, + /obj/item/clothing/suit/storage/miljacket_army=3,/obj/item/clothing/suit/storage/miljacket_army/miljacket_ranger=2,/obj/item/clothing/suit/storage/miljacket_army/miljacket_navy=2, + /obj/item/clothing/suit/student_jacket=3,/obj/item/clothing/suit/shawl=2,/obj/item/clothing/suit/atlas_jacket=4,/obj/item/clothing/under/sukeban_pants=2, + /obj/item/clothing/under/sukeban_dress=2,/obj/item/clothing/suit/sukeban_coat=4,/obj/item/clothing/under/pinkpolo=3,/obj/item/clothing/under/pretty_dress=1, + /obj/item/clothing/under/dress/dress_summer=2,/obj/item/clothing/under/dress/dress_vintage=2,/obj/item/clothing/under/dress/dress_evening=2,/obj/item/clothing/under/dress/dress_party=2) + + contraband = list(/obj/item/clothing/under/syndicate/tacticool=2,/obj/item/clothing/mask/balaclava=2,/obj/item/clothing/head/ushanka=2,/obj/item/clothing/under/soviet=2,/obj/item/clothing/mask/gas/fawkes = 6) + + premium = list(/obj/item/clothing/under/suit_jacket/checkered=2,/obj/item/clothing/head/mailman=2,/obj/item/clothing/under/rank/mailman=2,/obj/item/clothing/suit/jacket/leather=2, + /obj/item/clothing/suit/jacket/leather/overcoat=2,/obj/item/clothing/under/pants/mustangjeans=2) + + prices = list(/obj/item/clothing/head/that=419,/obj/item/clothing/head/fedora=419,/obj/item/clothing/glasses/monocle=109, + /obj/item/clothing/suit/jacket=299, /obj/item/clothing/suit/jacket/puffer/vest=239, /obj/item/clothing/suit/jacket/puffer=219, + /obj/item/clothing/under/suit_jacket/navy=119,/obj/item/clothing/under/suit_jacket/really_black=119,/obj/item/clothing/under/suit_jacket/burgundy=119, + /obj/item/clothing/under/suit_jacket/charcoal=119, /obj/item/clothing/under/suit_jacket/white=119,/obj/item/clothing/under/kilt=85,/obj/item/clothing/under/overalls=85, + /obj/item/clothing/under/suit_jacket/really_black=142,/obj/item/clothing/under/suit_jacket/rouge =248,/obj/item/clothing/under/pants/jeans=142, + /obj/item/clothing/under/pants/classicjeans=142,/obj/item/clothing/under/pants/camo = 142,/obj/item/clothing/under/pants/blackjeans=142,/obj/item/clothing/under/pants/khaki=142, + /obj/item/clothing/under/pants/white=142,/obj/item/clothing/under/pants/red=142,/obj/item/clothing/under/pants/black=142, + /obj/item/clothing/under/pants/tan=142,/obj/item/clothing/under/pants/blue=142,/obj/item/clothing/under/pants/track=142, + /obj/item/clothing/under/sundress=85,/obj/item/clothing/under/blacktango=99, + /obj/item/clothing/suit/jacket=138,/obj/item/clothing/glasses/regular=55,/obj/item/clothing/head/sombrero=240, + /obj/item/clothing/suit/poncho=295,/obj/item/clothing/suit/ianshirt=4000,/obj/item/clothing/shoes/laceup=99, + /obj/item/clothing/shoes/sandal=35, + /obj/item/clothing/mask/bandana/black=384,/obj/item/clothing/mask/bandana/skull=399,/obj/item/clothing/mask/bandana/green=384,/obj/item/clothing/mask/bandana/gold=389, + /obj/item/clothing/mask/bandana/blue=384,/obj/item/clothing/mask/scarf/blue=250,/obj/item/clothing/mask/scarf/red=250,/obj/item/clothing/mask/scarf/green=250, + /obj/item/clothing/mask/scarf/yellow=250,/obj/item/clothing/mask/scarf/violet=250, + /obj/item/clothing/suit/wintercoat=130,/obj/item/clothing/shoes/winterboots=70,/obj/item/clothing/head/santa=50, + /obj/item/clothing/suit/storage/miljacket_army=655,/obj/item/clothing/suit/storage/miljacket_army/miljacket_ranger=655,/obj/item/clothing/suit/storage/miljacket_army/miljacket_navy=655, + /obj/item/clothing/suit/student_jacket=459,/obj/item/clothing/suit/shawl=344,/obj/item/clothing/suit/atlas_jacket=250,/obj/item/clothing/under/sukeban_pants=366, + /obj/item/clothing/under/sukeban_dress=366,/obj/item/clothing/suit/sukeban_coat=579,/obj/item/clothing/under/pinkpolo=638,/obj/item/clothing/under/pretty_dress=564, + /obj/item/clothing/under/dress/dress_summer=332,/obj/item/clothing/under/dress/dress_vintage=465,/obj/item/clothing/under/dress/dress_evening=386,/obj/item/clothing/under/dress/dress_party=349) + + refill_canister = /obj/item/weapon/vending_refill/clothing + +//from old nanotrasen +/obj/machinery/vending/blood + name = "Blood'O'Matic" + desc = "Human blood dispenser. With internal freezer. Brought to you by EmpireV corp." + icon_state = "blood2" + light_color = "#ffc0c0" + icon_deny = "blood2deny" + product_ads = "Go and grab some blood!;I'm hope you are not bloody vampire.;Only from nice virgins!;Natural liquids!;This stuff saves lives." + //req_access_txt = "5" + products = list(/obj/item/weapon/reagent_containers/blood/APlus = 7, /obj/item/weapon/reagent_containers/blood/AMinus = 4, + /obj/item/weapon/reagent_containers/blood/BPlus = 4, /obj/item/weapon/reagent_containers/blood/BMinus = 2, + /obj/item/weapon/reagent_containers/blood/OPlus = 7, /obj/item/weapon/reagent_containers/blood/OMinus = 4) + contraband = list(/obj/item/weapon/reagent_containers/pill/stox = 10, /obj/item/weapon/reagent_containers/blood/empty = 10) + +//from old nanotrasen +/obj/machinery/vending/holy + name = "HolyVend" + desc = "Special items to prayers, sacrifices, rites and other methods to tell your God: I remember you!" + icon_state = "holy" + product_slogans = "HolyVend: Select your Religion today" + product_ads = "Pray now!;Atheists are heretic;Everything 100% Holy;Thirsty? Wanna pray? Why without candles?" + products = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 10, /obj/item/weapon/storage/fancy/candle_box = 25, /obj/item/weapon/storage/fancy/candle_box/red = 25,) + contraband = list(/obj/item/weapon/nullrod = 2) + prices = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 30, /obj/item/weapon/storage/fancy/candle_box = 50, /obj/item/weapon/storage/fancy/candle_box/red = 50, /obj/item/weapon/nullrod = 100) + +/obj/machinery/vending/eva + name = "Hardsuit Kits" + desc = "Conversion kits for your alien hardsuit needs." + products = list(/obj/item/device/modkit/engineering/tajaran = 5, /obj/item/device/modkit/engineering/unathi = 5, /obj/item/device/modkit/engineering/skrell = 5, + /obj/item/device/modkit/atmos/tajaran = 5, /obj/item/device/modkit/atmos/unathi = 5, /obj/item/device/modkit/atmos/skrell = 5, + /obj/item/device/modkit/med/tajaran = 5, /obj/item/device/modkit/med/unathi = 5, /obj/item/device/modkit/med/skrell = 5, + /obj/item/device/modkit/sec/tajaran = 5, /obj/item/device/modkit/sec/unathi = 5, /obj/item/device/modkit/sec/skrell = 5, + /obj/item/device/modkit/mining/tajaran = 5, /obj/item/device/modkit/mining/unathi = 5, /obj/item/device/modkit/mining/skrell = 5, + /obj/item/device/modkit/engineering/chief/tajaran = 1, /obj/item/device/modkit/engineering/chief/unathi = 1, /obj/item/device/modkit/engineering/chief/skrell = 1, + /obj/item/device/modkit/med/cmo/tajaran = 1, /obj/item/device/modkit/med/cmo/unathi = 1, /obj/item/device/modkit/med/cmo/skrell = 1, + /obj/item/device/modkit/sec/hos/tajaran = 1, /obj/item/device/modkit/sec/hos/unathi = 1, /obj/item/device/modkit/sec/hos/skrell = 1, + /obj/item/device/modkit = 10) + +/obj/machinery/vending/eva/mining + name = "Mining Hardsuit Kits" + desc = "Conversion kits for your alien mining hardsuits." + icon_state = "evamine" + products = list(/obj/item/device/modkit/mining/tajaran = 3, /obj/item/device/modkit/mining/unathi = 3, /obj/item/device/modkit/mining/skrell = 3, /obj/item/device/modkit = 5) + +/obj/machinery/vending/eva/engineering + name = "Engineering Hardsuit Kits" + desc = "Conversion kits for your alien engineering and atmos hardsuits." + icon_state = "evaengi" + products = list(/obj/item/device/modkit/engineering/tajaran = 3, /obj/item/device/modkit/engineering/unathi = 3, /obj/item/device/modkit/engineering/skrell = 3, + /obj/item/device/modkit/atmos/tajaran = 3, /obj/item/device/modkit/atmos/unathi = 3, /obj/item/device/modkit/atmos/skrell = 3, + /obj/item/device/modkit/engineering/chief/tajaran = 1, /obj/item/device/modkit/engineering/chief/unathi = 1, /obj/item/device/modkit/engineering/chief/skrell = 1, + /obj/item/device/modkit = 6) + + +//from old nanotrasen +//i deleted all drugs here, now it's just a joke +/obj/machinery/vending/omskvend + name = "Omsk-o-mat" + desc = "Drug dispenser." + icon_state = "omskvend" + product_ads = "NORKOMAN SUKA SHTOLE?;STOP NARTCOTICS!; so i heard u liek mudkipz; METRO ZATOPEELO" + products = list(/obj/item/device/healthanalyzer = 5) + contraband = list(/obj/item/weapon/reagent_containers/glass/bottle/antitoxin = 4) + +/obj/item/weapon/reagent_containers/pill/LSD + name = "LSD" + desc = "Ahaha oh wow." + icon_state = "pill9" + +/obj/item/weapon/reagent_containers/pill/LSD/atom_init() + . = ..() + reagents.add_reagent("mindbreaker", 0) + +/obj/item/weapon/reagent_containers/glass/beaker/LSD + name = "LSD IV" + desc = "Ahaha oh wow." + +/obj/item/weapon/reagent_containers/glass/beaker/LSD/atom_init() + . = ..() + reagents.add_reagent("mindbreaker", 0) + update_icon() + +/obj/machinery/vending/sustenance + name = "\improper Sustenance Vendor" + desc = "A vending machine which vends food, as required by section 47-C of the NT's Prisoner Ethical Treatment Agreement." + product_slogans = "Enjoy your meal.;Enough calories to support strenuous labor." + product_ads = "Sufficiently healthy.;Efficiently produced tofu!;Mmm! So good!;Have a meal.;You need food to live!;Have some more candy corn!;Try our new ice cups!" + icon_state = "sustenance" + products = list(/obj/item/weapon/reagent_containers/food/snacks/tofu = 20, + /obj/item/weapon/reagent_containers/food/drinks/ice = 12, + /obj/item/weapon/reagent_containers/food/snacks/candy_corn = 6, + /obj/item/weapon/reagent_containers/food/snacks/cracker = 20, + /obj/item/weapon/reagent_containers/food/drinks/cans/waterbottle = 12) + contraband = list(/obj/item/weapon/kitchenknife = 6) + +//from old nanotrasen +/obj/machinery/vending/theater + name = "Theater-o-mat" + desc = "Special costume pack to add randomness in boring life." + icon_state = "Theater" + products = list(/obj/item/clothing/head/xenos = 5, /obj/item/clothing/suit/xenos = 5, /obj/item/clothing/suit/monkeysuit = 5, /obj/item/clothing/suit/syndicatefake = 5, /obj/item/clothing/head/syndicatefake = 5, + /obj/item/clothing/head/collectable/slime = 5, /obj/item/clothing/head/collectable/xenom = 5, /obj/item/clothing/head/collectable/petehat = 5, /obj/item/clothing/head/kitty = 5, + /obj/item/clothing/head/pumpkinhead = 5, /obj/item/clothing/head/ushanka = 5, /obj/item/clothing/head/cardborg = 5, /obj/item/clothing/suit/cardborg = 5, /obj/item/clothing/head/bearpelt = 5, + /obj/item/clothing/suit/space/santa = 5, /obj/item/clothing/head/helmet/space/santahat = 5, /obj/item/weapon/storage/backpack/santabag = 5, /obj/item/clothing/mask/fakemoustache = 5, + /obj/item/clothing/mask/gas/sexyclown = 5, /obj/item/clothing/mask/gas/sexymime = 5, /obj/item/clothing/mask/horsehead = 5, /obj/item/clothing/suit/apron = 5, /obj/item/clothing/suit/apron/overalls = 5, + /obj/item/clothing/suit/chickensuit = 5, /obj/item/clothing/head/chicken = 5, /obj/item/clothing/under/fluff/tian_dress = 5, /obj/item/clothing/under/fluff/wyatt_1 = 5, + /obj/item/clothing/under/fluff/olddressuniform = 5, /obj/item/clothing/under/fluff/jumpsuitdown = 5, /obj/item/clothing/under/fluff/jane_sidsuit = 5, /obj/item/clothing/under/sundress = 5, + /obj/item/clothing/under/roman = 3, /obj/item/clothing/shoes/roman = 3, /obj/item/clothing/head/helmet/roman = 2, /obj/item/clothing/head/helmet/roman/legionaire = 1, /obj/item/clothing/under/smoking = 3, + /obj/item/clothing/suit/tuxedo = 3,/obj/item/clothing/under/popking = 1, /obj/item/clothing/under/popking/alternate = 1, /obj/item/clothing/suit/hooded/angel_suit = 1, + /obj/item/clothing/mask/fake_face = 2, /obj/item/clothing/suit/hooded/ian_costume = 1, /obj/item/clothing/suit/hooded/carp_costume = 1) + prices = list(/obj/item/clothing/head/xenos = 100, /obj/item/clothing/suit/xenos = 200, /obj/item/clothing/suit/monkeysuit = 200, /obj/item/clothing/suit/hooded/carp_costume = 200) + contraband = list(/obj/item/clothing/mask/gas/fawkes = 2) diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index a29df906cb4a..529d65c65f7e 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -1,343 +1,343 @@ -/obj/machinery/washing_machine - name = "Washing Machine" - icon = 'icons/obj/machines/washing_machine.dmi' - icon_state = "wm_10" - density = 1 - anchored = 1.0 - use_power = 0 - var/state = 1 - //1 = empty, open door - //2 = empty, closed door - //3 = full, open door - //4 = full, closed door - //5 = running - //6 = blood, open door - //7 = blood, closed door - //8 = blood, running - var/panel = 0 - //0 = closed - //1 = open - var/hacked = 1 //Bleh, screw hacking, let's have it hacked by default. - //0 = not hacked - //1 = hacked - var/gibs_ready = 0 - var/obj/crayon - -/obj/machinery/washing_machine/verb/start() - set name = "Start Washing" - set category = "Object" - set src in oview(1) - - if(!istype(usr, /mob/living)) //ew ew ew usr, but it's the only way to check. - return - - if( state != 4 ) - to_chat(usr, "The washing machine cannot run in this state.") - return - - if( locate(/mob,contents) ) - state = 8 - else - state = 5 - update_icon() - playsound(src, 'sound/items/washingmachine.ogg', 100, 1, 1) - sleep(210) - for(var/atom/A in contents) - A.clean_blood() - - for(var/obj/item/I in contents) - I.decontaminate() - I.wet = 0 - - //Tanning! - for(var/obj/item/stack/sheet/hairlesshide/HH in contents) - new/obj/item/stack/sheet/wetleather(src, HH.get_amount()) - qdel(HH) - - - if(crayon) - var/wash_color - if(istype(crayon,/obj/item/toy/crayon)) - var/obj/item/toy/crayon/CR = crayon - wash_color = CR.colourName - else if(istype(crayon,/obj/item/weapon/stamp)) - var/obj/item/weapon/stamp/ST = crayon - wash_color = ST.item_color - - if(wash_color) - var/new_jumpsuit_icon_state = "" - var/new_jumpsuit_item_state = "" - var/new_jumpsuit_name = "" - var/new_glove_fingerless_item_state = "" - var/new_glove_fingerless_icon_state = "" - var/new_glove_fingerless_name = "" - var/new_glove_item_state = "" - var/new_glove_icon_state = "" - var/new_glove_name = "" - var/new_shoe_icon_state = "" - var/new_shoe_name = "" - var/new_sheet_icon_state = "" - var/new_sheet_name = "" - var/new_softcap_icon_state = "" - var/new_softcap_name = "" - var/new_desc = "The colors are a bit dodgy." - for(var/T in typesof(/obj/item/clothing/under)) - var/obj/item/clothing/under/J = new T - //world << "DEBUG: [color] == [J.color]" - if(wash_color == J.item_color) - new_jumpsuit_icon_state = J.icon_state - new_jumpsuit_item_state = J.item_state - new_jumpsuit_name = J.name - qdel(J) - //world << "DEBUG: YUP! [new_icon_state] and [new_item_state]" - break - qdel(J) - for(var/T in typesof(/obj/item/clothing/gloves/fingerless)) - var/obj/item/clothing/gloves/fingerless/G = new T - if(wash_color == G.item_color) - new_glove_fingerless_icon_state = G.icon_state - new_glove_fingerless_item_state = G.item_state - new_glove_fingerless_name = G.name - qdel(G) - break - qdel(G) - for(var/T in typesof(/obj/item/clothing/gloves)) - var/obj/item/clothing/gloves/G = new T - if(wash_color == G.item_color) - new_glove_icon_state = G.icon_state - new_glove_item_state = G.item_state - new_glove_name = G.name - qdel(G) - break - qdel(G) - for(var/T in typesof(/obj/item/clothing/shoes)) - var/obj/item/clothing/shoes/S = new T - //world << "DEBUG: [color] == [J.color]" - if(wash_color == S.item_color) - new_shoe_icon_state = S.icon_state - new_shoe_name = S.name - qdel(S) - //world << "DEBUG: YUP! [new_icon_state] and [new_item_state]" - break - qdel(S) - for(var/T in typesof(/obj/item/weapon/bedsheet)) - var/obj/item/weapon/bedsheet/B = new T - //world << "DEBUG: [color] == [J.color]" - if(wash_color == B.item_color) - new_sheet_icon_state = B.icon_state - new_sheet_name = B.name - qdel(B) - //world << "DEBUG: YUP! [new_icon_state] and [new_item_state]" - break - qdel(B) - for(var/T in typesof(/obj/item/clothing/head/soft)) - var/obj/item/clothing/head/soft/H = new T - //world << "DEBUG: [color] == [J.color]" - if(wash_color == H.item_color) - new_softcap_icon_state = H.icon_state - new_softcap_name = H.name - qdel(H) - //world << "DEBUG: YUP! [new_icon_state] and [new_item_state]" - break - qdel(H) - if(new_jumpsuit_icon_state && new_jumpsuit_item_state && new_jumpsuit_name) - for(var/obj/item/clothing/under/J in contents) - //world << "DEBUG: YUP! FOUND IT!" - J.item_state = new_jumpsuit_item_state - J.icon_state = new_jumpsuit_icon_state - J.item_color = wash_color - J.name = new_jumpsuit_name - J.desc = new_desc - if(new_glove_name && new_glove_item_state && new_glove_icon_state||new_glove_fingerless_name && new_glove_fingerless_item_state && new_glove_fingerless_icon_state) - for(var/obj/item/clothing/gloves/G in contents) - if(istype(G, /obj/item/clothing/gloves/fingerless)) - if(new_glove_fingerless_name && new_glove_fingerless_item_state && new_glove_fingerless_icon_state) - G.item_state = new_glove_fingerless_item_state - G.icon_state = new_glove_fingerless_icon_state - G.item_color = wash_color - G.name = new_glove_fingerless_name - G.desc = new_desc - else - if (new_glove_name && new_glove_item_state && new_glove_icon_state) - G.item_state = new_glove_item_state - G.icon_state = new_glove_icon_state - G.item_color = wash_color - G.name = new_glove_name - G.desc = new_desc - if(new_shoe_icon_state && new_shoe_name) - for(var/obj/item/clothing/shoes/S in contents) - //world << "DEBUG: YUP! FOUND IT!" - if (istype(S,/obj/item/clothing/shoes/orange)) - var/obj/item/clothing/shoes/orange/L = S - if (L.chained) - L.remove_cuffs() - S.icon_state = new_shoe_icon_state - S.item_color = wash_color - S.name = new_shoe_name - S.desc = new_desc - if(new_sheet_icon_state && new_sheet_name) - for(var/obj/item/weapon/bedsheet/B in contents) - //world << "DEBUG: YUP! FOUND IT!" - B.icon_state = new_sheet_icon_state - B.item_color = wash_color - B.name = new_sheet_name - B.desc = new_desc - if(new_softcap_icon_state && new_softcap_name) - for(var/obj/item/clothing/head/soft/H in contents) - //world << "DEBUG: YUP! FOUND IT!" - H.icon_state = new_softcap_icon_state - H.item_color = wash_color - H.name = new_softcap_name - H.desc = new_desc - qdel(crayon) - crayon = null - - - if( locate(/mob,contents) ) - state = 7 - gibs_ready = 1 - else - state = 4 - update_icon() - -/obj/machinery/washing_machine/verb/climb_out() - set name = "Climb out" - set category = "Object" - set src in usr.loc - - sleep(20) - if(state in list(1,3,6) ) - usr.loc = src.loc - - -/obj/machinery/washing_machine/update_icon() - icon_state = "wm_[state][panel]" - -/obj/machinery/washing_machine/attackby(obj/item/weapon/W, mob/user) - /*if(istype(W,/obj/item/weapon/screwdriver)) - panel = !panel - to_chat(user, "\blue you [panel ? "open" : "close"] the [src]'s maintenance panel")*/ - if(istype(W,/obj/item/toy/crayon) ||istype(W,/obj/item/weapon/stamp)) - if( state in list( 1, 3, 6 ) ) - if(!crayon) - user.drop_item() - crayon = W - crayon.loc = src - else - ..() - else - ..() - else if(istype(W,/obj/item/weapon/grab)) - if( (state == 1) && hacked) - var/obj/item/weapon/grab/G = W - if(ishuman(G.assailant) && iscorgi(G.affecting)) - G.affecting.loc = src - qdel(G) - state = 3 - else - ..() - else if(istype(W,/obj/item/stack/sheet/hairlesshide) || \ - istype(W,/obj/item/clothing/under) || \ - istype(W,/obj/item/clothing/mask) || \ - istype(W,/obj/item/clothing/head) || \ - istype(W,/obj/item/clothing/gloves) || \ - istype(W,/obj/item/clothing/shoes) || \ - istype(W,/obj/item/clothing/suit) || \ - istype(W,/obj/item/weapon/bedsheet)) - - //YES, it's hardcoded... saves a var/can_be_washed for every single clothing item. - if ( istype(W,/obj/item/clothing/suit/space ) ) - to_chat(user, "This item does not fit.") - return - if ( istype(W,/obj/item/clothing/suit/syndicatefake ) ) - to_chat(user, "This item does not fit.") - return -// if ( istype(W,/obj/item/clothing/suit/powered ) ) -// user << "This item does not fit." -// return - if ( istype(W,/obj/item/clothing/suit/cyborg_suit ) ) - to_chat(user, "This item does not fit.") - return - if ( istype(W,/obj/item/clothing/suit/bomb_suit ) ) - to_chat(user, "This item does not fit.") - return - if ( istype(W,/obj/item/clothing/suit/armor ) ) - to_chat(user, "This item does not fit.") - return - if ( istype(W,/obj/item/clothing/suit/armor ) ) - to_chat(user, "This item does not fit.") - return - if ( istype(W,/obj/item/clothing/mask/gas ) ) - to_chat(user, "This item does not fit.") - return - if ( istype(W,/obj/item/clothing/mask/cigarette ) ) - to_chat(user, "This item does not fit.") - return - if ( istype(W,/obj/item/clothing/head/syndicatefake ) ) - to_chat(user, "This item does not fit.") - return -// if ( istype(W,/obj/item/clothing/head/powered ) ) -// user << "This item does not fit." -// return - if ( istype(W,/obj/item/clothing/head/helmet ) ) - to_chat(user, "This item does not fit.") - return - if (istype(W, /obj/item/clothing/gloves/pipboy)) - to_chat(user, "This item does not fit.") - return - if(!W.canremove) //if "can't drop" item - to_chat(user, "\The [W] is stuck to your hand, you cannot put it in the washing machine!") - return - - if(contents.len < 5) - if ( state in list(1, 3) ) - user.drop_item() - W.loc = src - state = 3 - else - to_chat(user, "\blue You can't put the item in right now.") - else - to_chat(user, "\blue The washing machine is full.") - else - ..() - update_icon() - -/obj/machinery/washing_machine/attack_ai(mob/user) - if(IsAdminGhost(user)) - return ..() - -/obj/machinery/washing_machine/attack_hand(mob/user) - if(..()) - return 1 - user.SetNextMove(CLICK_CD_RAPID) - switch(state) - if(1) - state = 2 - if(2) - state = 1 - for(var/atom/movable/O in contents) - O.loc = src.loc - if(3) - state = 4 - if(4) - state = 3 - for(var/atom/movable/O in contents) - O.loc = src.loc - crayon = null - state = 1 - if(5) - to_chat(user, "\red The [src] is busy.") - if(6) - state = 7 - if(7) - if(gibs_ready) - gibs_ready = 0 - if(locate(/mob,contents)) - var/mob/M = locate(/mob,contents) - M.gib() - for(var/atom/movable/O in contents) - O.loc = src.loc - crayon = null - state = 1 - - update_icon() +/obj/machinery/washing_machine + name = "Washing Machine" + icon = 'icons/obj/machines/washing_machine.dmi' + icon_state = "wm_10" + density = 1 + anchored = 1.0 + use_power = 0 + var/state = 1 + //1 = empty, open door + //2 = empty, closed door + //3 = full, open door + //4 = full, closed door + //5 = running + //6 = blood, open door + //7 = blood, closed door + //8 = blood, running + var/panel = 0 + //0 = closed + //1 = open + var/hacked = 1 //Bleh, screw hacking, let's have it hacked by default. + //0 = not hacked + //1 = hacked + var/gibs_ready = 0 + var/obj/crayon + +/obj/machinery/washing_machine/verb/start() + set name = "Start Washing" + set category = "Object" + set src in oview(1) + + if(!istype(usr, /mob/living)) //ew ew ew usr, but it's the only way to check. + return + + if( state != 4 ) + to_chat(usr, "The washing machine cannot run in this state.") + return + + if( locate(/mob,contents) ) + state = 8 + else + state = 5 + update_icon() + playsound(src, 'sound/items/washingmachine.ogg', 100, 1, 1) + sleep(210) + for(var/atom/A in contents) + A.clean_blood() + + for(var/obj/item/I in contents) + I.decontaminate() + I.wet = 0 + + //Tanning! + for(var/obj/item/stack/sheet/hairlesshide/HH in contents) + new/obj/item/stack/sheet/wetleather(src, HH.get_amount()) + qdel(HH) + + + if(crayon) + var/wash_color + if(istype(crayon,/obj/item/toy/crayon)) + var/obj/item/toy/crayon/CR = crayon + wash_color = CR.colourName + else if(istype(crayon,/obj/item/weapon/stamp)) + var/obj/item/weapon/stamp/ST = crayon + wash_color = ST.item_color + + if(wash_color) + var/new_jumpsuit_icon_state = "" + var/new_jumpsuit_item_state = "" + var/new_jumpsuit_name = "" + var/new_glove_fingerless_item_state = "" + var/new_glove_fingerless_icon_state = "" + var/new_glove_fingerless_name = "" + var/new_glove_item_state = "" + var/new_glove_icon_state = "" + var/new_glove_name = "" + var/new_shoe_icon_state = "" + var/new_shoe_name = "" + var/new_sheet_icon_state = "" + var/new_sheet_name = "" + var/new_softcap_icon_state = "" + var/new_softcap_name = "" + var/new_desc = "The colors are a bit dodgy." + for(var/T in typesof(/obj/item/clothing/under)) + var/obj/item/clothing/under/J = new T + //world << "DEBUG: [color] == [J.color]" + if(wash_color == J.item_color) + new_jumpsuit_icon_state = J.icon_state + new_jumpsuit_item_state = J.item_state + new_jumpsuit_name = J.name + qdel(J) + //world << "DEBUG: YUP! [new_icon_state] and [new_item_state]" + break + qdel(J) + for(var/T in typesof(/obj/item/clothing/gloves/fingerless)) + var/obj/item/clothing/gloves/fingerless/G = new T + if(wash_color == G.item_color) + new_glove_fingerless_icon_state = G.icon_state + new_glove_fingerless_item_state = G.item_state + new_glove_fingerless_name = G.name + qdel(G) + break + qdel(G) + for(var/T in typesof(/obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = new T + if(wash_color == G.item_color) + new_glove_icon_state = G.icon_state + new_glove_item_state = G.item_state + new_glove_name = G.name + qdel(G) + break + qdel(G) + for(var/T in typesof(/obj/item/clothing/shoes)) + var/obj/item/clothing/shoes/S = new T + //world << "DEBUG: [color] == [J.color]" + if(wash_color == S.item_color) + new_shoe_icon_state = S.icon_state + new_shoe_name = S.name + qdel(S) + //world << "DEBUG: YUP! [new_icon_state] and [new_item_state]" + break + qdel(S) + for(var/T in typesof(/obj/item/weapon/bedsheet)) + var/obj/item/weapon/bedsheet/B = new T + //world << "DEBUG: [color] == [J.color]" + if(wash_color == B.item_color) + new_sheet_icon_state = B.icon_state + new_sheet_name = B.name + qdel(B) + //world << "DEBUG: YUP! [new_icon_state] and [new_item_state]" + break + qdel(B) + for(var/T in typesof(/obj/item/clothing/head/soft)) + var/obj/item/clothing/head/soft/H = new T + //world << "DEBUG: [color] == [J.color]" + if(wash_color == H.item_color) + new_softcap_icon_state = H.icon_state + new_softcap_name = H.name + qdel(H) + //world << "DEBUG: YUP! [new_icon_state] and [new_item_state]" + break + qdel(H) + if(new_jumpsuit_icon_state && new_jumpsuit_item_state && new_jumpsuit_name) + for(var/obj/item/clothing/under/J in contents) + //world << "DEBUG: YUP! FOUND IT!" + J.item_state = new_jumpsuit_item_state + J.icon_state = new_jumpsuit_icon_state + J.item_color = wash_color + J.name = new_jumpsuit_name + J.desc = new_desc + if(new_glove_name && new_glove_item_state && new_glove_icon_state||new_glove_fingerless_name && new_glove_fingerless_item_state && new_glove_fingerless_icon_state) + for(var/obj/item/clothing/gloves/G in contents) + if(istype(G, /obj/item/clothing/gloves/fingerless)) + if(new_glove_fingerless_name && new_glove_fingerless_item_state && new_glove_fingerless_icon_state) + G.item_state = new_glove_fingerless_item_state + G.icon_state = new_glove_fingerless_icon_state + G.item_color = wash_color + G.name = new_glove_fingerless_name + G.desc = new_desc + else + if (new_glove_name && new_glove_item_state && new_glove_icon_state) + G.item_state = new_glove_item_state + G.icon_state = new_glove_icon_state + G.item_color = wash_color + G.name = new_glove_name + G.desc = new_desc + if(new_shoe_icon_state && new_shoe_name) + for(var/obj/item/clothing/shoes/S in contents) + //world << "DEBUG: YUP! FOUND IT!" + if (istype(S,/obj/item/clothing/shoes/orange)) + var/obj/item/clothing/shoes/orange/L = S + if (L.chained) + L.remove_cuffs() + S.icon_state = new_shoe_icon_state + S.item_color = wash_color + S.name = new_shoe_name + S.desc = new_desc + if(new_sheet_icon_state && new_sheet_name) + for(var/obj/item/weapon/bedsheet/B in contents) + //world << "DEBUG: YUP! FOUND IT!" + B.icon_state = new_sheet_icon_state + B.item_color = wash_color + B.name = new_sheet_name + B.desc = new_desc + if(new_softcap_icon_state && new_softcap_name) + for(var/obj/item/clothing/head/soft/H in contents) + //world << "DEBUG: YUP! FOUND IT!" + H.icon_state = new_softcap_icon_state + H.item_color = wash_color + H.name = new_softcap_name + H.desc = new_desc + qdel(crayon) + crayon = null + + + if( locate(/mob,contents) ) + state = 7 + gibs_ready = 1 + else + state = 4 + update_icon() + +/obj/machinery/washing_machine/verb/climb_out() + set name = "Climb out" + set category = "Object" + set src in usr.loc + + sleep(20) + if(state in list(1,3,6) ) + usr.loc = src.loc + + +/obj/machinery/washing_machine/update_icon() + icon_state = "wm_[state][panel]" + +/obj/machinery/washing_machine/attackby(obj/item/weapon/W, mob/user) + /*if(istype(W,/obj/item/weapon/screwdriver)) + panel = !panel + to_chat(user, "\blue you [panel ? "open" : "close"] the [src]'s maintenance panel")*/ + if(istype(W,/obj/item/toy/crayon) ||istype(W,/obj/item/weapon/stamp)) + if( state in list( 1, 3, 6 ) ) + if(!crayon) + user.drop_item() + crayon = W + crayon.loc = src + else + ..() + else + ..() + else if(istype(W,/obj/item/weapon/grab)) + if( (state == 1) && hacked) + var/obj/item/weapon/grab/G = W + if(ishuman(G.assailant) && iscorgi(G.affecting)) + G.affecting.loc = src + qdel(G) + state = 3 + else + ..() + else if(istype(W,/obj/item/stack/sheet/hairlesshide) || \ + istype(W,/obj/item/clothing/under) || \ + istype(W,/obj/item/clothing/mask) || \ + istype(W,/obj/item/clothing/head) || \ + istype(W,/obj/item/clothing/gloves) || \ + istype(W,/obj/item/clothing/shoes) || \ + istype(W,/obj/item/clothing/suit) || \ + istype(W,/obj/item/weapon/bedsheet)) + + //YES, it's hardcoded... saves a var/can_be_washed for every single clothing item. + if ( istype(W,/obj/item/clothing/suit/space ) ) + to_chat(user, "This item does not fit.") + return + if ( istype(W,/obj/item/clothing/suit/syndicatefake ) ) + to_chat(user, "This item does not fit.") + return +// if ( istype(W,/obj/item/clothing/suit/powered ) ) +// user << "This item does not fit." +// return + if ( istype(W,/obj/item/clothing/suit/cyborg_suit ) ) + to_chat(user, "This item does not fit.") + return + if ( istype(W,/obj/item/clothing/suit/bomb_suit ) ) + to_chat(user, "This item does not fit.") + return + if ( istype(W,/obj/item/clothing/suit/armor ) ) + to_chat(user, "This item does not fit.") + return + if ( istype(W,/obj/item/clothing/suit/armor ) ) + to_chat(user, "This item does not fit.") + return + if ( istype(W,/obj/item/clothing/mask/gas ) ) + to_chat(user, "This item does not fit.") + return + if ( istype(W,/obj/item/clothing/mask/cigarette ) ) + to_chat(user, "This item does not fit.") + return + if ( istype(W,/obj/item/clothing/head/syndicatefake ) ) + to_chat(user, "This item does not fit.") + return +// if ( istype(W,/obj/item/clothing/head/powered ) ) +// user << "This item does not fit." +// return + if ( istype(W,/obj/item/clothing/head/helmet ) ) + to_chat(user, "This item does not fit.") + return + if (istype(W, /obj/item/clothing/gloves/pipboy)) + to_chat(user, "This item does not fit.") + return + if(!W.canremove) //if "can't drop" item + to_chat(user, "\The [W] is stuck to your hand, you cannot put it in the washing machine!") + return + + if(contents.len < 5) + if ( state in list(1, 3) ) + user.drop_item() + W.loc = src + state = 3 + else + to_chat(user, "\blue You can't put the item in right now.") + else + to_chat(user, "\blue The washing machine is full.") + else + ..() + update_icon() + +/obj/machinery/washing_machine/attack_ai(mob/user) + if(IsAdminGhost(user)) + return ..() + +/obj/machinery/washing_machine/attack_hand(mob/user) + if(..()) + return 1 + user.SetNextMove(CLICK_CD_RAPID) + switch(state) + if(1) + state = 2 + if(2) + state = 1 + for(var/atom/movable/O in contents) + O.loc = src.loc + if(3) + state = 4 + if(4) + state = 3 + for(var/atom/movable/O in contents) + O.loc = src.loc + crayon = null + state = 1 + if(5) + to_chat(user, "\red The [src] is busy.") + if(6) + state = 7 + if(7) + if(gibs_ready) + gibs_ready = 0 + if(locate(/mob,contents)) + var/mob/M = locate(/mob,contents) + M.gib() + for(var/atom/movable/O in contents) + O.loc = src.loc + crayon = null + state = 1 + + update_icon() diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm index e95e0fa1f61a..4f07bf449dc5 100644 --- a/code/game/mecha/combat/combat.dm +++ b/code/game/mecha/combat/combat.dm @@ -1,273 +1,273 @@ -/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" - var/animated = 0 - -/* -/obj/mecha/combat/range_action(target) - 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) - 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 == "hurt") - playsound(src, 'sound/weapons/punch4.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/obj/item/organ/external/BP = H.bodyparts_by_name[pick(BP_CHEST , BP_CHEST , BP_CHEST , BP_HEAD)] - if(BP) - switch(damtype) - if("brute") - H.Paralyse(1) - BP.take_damage(rand(force / 2, force), 0) - if("fire") - BP.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 - 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("\blue 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.make_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, 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(mob/living/carbon/human/H) - if(..()) - if(H.client) - H.client.mouse_pointer_icon = file("icons/mecha/mecha_mouse.dmi") - return 1 - else - return 0 - -/obj/mecha/combat/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc,mob/user) - if(..()) - if(occupant.client) - occupant.client.mouse_pointer_icon = file("icons/mecha/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/F = new (href,href_list) - if(F.get("close")) - am = null - return - /* - if(F.get("saminput")) - if(md5(F.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" + var/animated = 0 + +/* +/obj/mecha/combat/range_action(target) + 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) + 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 == "hurt") + playsound(src, 'sound/weapons/punch4.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/obj/item/organ/external/BP = H.bodyparts_by_name[pick(BP_CHEST , BP_CHEST , BP_CHEST , BP_HEAD)] + if(BP) + switch(damtype) + if("brute") + H.Paralyse(1) + BP.take_damage(rand(force / 2, force), 0) + if("fire") + BP.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 + 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("\blue 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.make_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, 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(mob/living/carbon/human/H) + if(..()) + if(H.client) + H.client.mouse_pointer_icon = file("icons/mecha/mecha_mouse.dmi") + return 1 + else + return 0 + +/obj/mecha/combat/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc,mob/user) + if(..()) + if(occupant.client) + occupant.client.mouse_pointer_icon = file("icons/mecha/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/F = new (href,href_list) + if(F.get("close")) + am = null + return + /* + if(F.get("saminput")) + if(md5(F.get("saminput")) == am) + occupant_message("From the lies of the Antipath, Circuit preserve us.") + am = null + return + */ diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm index 68af124dd070..0df15f4ff7c6 100644 --- a/code/game/mecha/combat/durand.dm +++ b/code/game/mecha/combat/durand.dm @@ -1,96 +1,96 @@ -/obj/mecha/combat/durand - desc = "An aging combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms." - name = "Durand" - 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/atom_init() - . = ..() - weapons += new /datum/mecha_weapon/ballistic/lmg(src) - weapons += new /datum/mecha_weapon/ballistic/scattershot(src) - selected_weapon = weapons[1] -*/ - -/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) - if(animated) - flick("vindicator-lockdown-a",src) - icon_state = "vindicator-lockdown" - deflect_chance = defence_deflect - src.occupant_message("You enable [src] defence mode.") - else - deflect_chance = initial(deflect_chance) - if(animated) - 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/vindicator - desc = "A highly improved version of old Durand exosuit, with improved shock absorption and refined internal electronics." - name = "Vindicator" - icon_state = "vindicator" - initial_icon = "vindicator" - step_in = 4 - dir_in = 1 //Facing North. - health = 440 - deflect_chance = 25 - damage_absorption = list("brute"=0.5,"fire"=1.0,"bullet"=0.55,"laser"=0.75,"energy"=0.8,"bomb"=0.7) - max_temperature = 30000 - infra_luminosity = 8 - internal_damage_threshold = 40 - force = 40 - wreckage = /obj/effect/decal/mecha_wreckage/durand/vindicator - animated = 1 +/obj/mecha/combat/durand + desc = "An aging combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms." + name = "Durand" + 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/atom_init() + . = ..() + weapons += new /datum/mecha_weapon/ballistic/lmg(src) + weapons += new /datum/mecha_weapon/ballistic/scattershot(src) + selected_weapon = weapons[1] +*/ + +/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) + if(animated) + flick("vindicator-lockdown-a",src) + icon_state = "vindicator-lockdown" + deflect_chance = defence_deflect + src.occupant_message("You enable [src] defence mode.") + else + deflect_chance = initial(deflect_chance) + if(animated) + 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/vindicator + desc = "A highly improved version of old Durand exosuit, with improved shock absorption and refined internal electronics." + name = "Vindicator" + icon_state = "vindicator" + initial_icon = "vindicator" + step_in = 4 + dir_in = 1 //Facing North. + health = 440 + deflect_chance = 25 + damage_absorption = list("brute"=0.5,"fire"=1.0,"bullet"=0.55,"laser"=0.75,"energy"=0.8,"bomb"=0.7) + max_temperature = 30000 + infra_luminosity = 8 + internal_damage_threshold = 40 + force = 40 + wreckage = /obj/effect/decal/mecha_wreckage/durand/vindicator + animated = 1 diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm index 969e9e217093..af8bd57e9ae5 100644 --- a/code/game/mecha/combat/gygax.dm +++ b/code/game/mecha/combat/gygax.dm @@ -1,127 +1,127 @@ -/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/ultra - desc = "A highly improved version of Gygax exosuit." - name = "Gygax Ultra" - icon_state = "ultra" - initial_icon = "ultra" - health = 350 - deflect_chance = 20 - damage_absorption = list("brute"=0.65,"fire"=0.9,"bullet"=0.7,"laser"=0.6,"energy"=0.75,"bomb"=0.9) - max_temperature = 30000 - wreckage = /obj/effect/decal/mecha_wreckage/gygax/ultra - animated = 1 - -/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/atom_init() - . = ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine(src) - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang(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) - -/obj/mecha/combat/gygax/dark/add_cell(obj/item/weapon/stock_parts/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(animated) - flick("ultra-gofasta-off",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(animated) - flick("ultra-gofasta-on",src) - icon_state = "ultra-gofasta" - 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.") - if(animated) - flick("ultra-gofasta-off",src) - reset_icon() - 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 +/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/ultra + desc = "A highly improved version of Gygax exosuit." + name = "Gygax Ultra" + icon_state = "ultra" + initial_icon = "ultra" + health = 350 + deflect_chance = 20 + damage_absorption = list("brute"=0.65,"fire"=0.9,"bullet"=0.7,"laser"=0.6,"energy"=0.75,"bomb"=0.9) + max_temperature = 30000 + wreckage = /obj/effect/decal/mecha_wreckage/gygax/ultra + animated = 1 + +/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/atom_init() + . = ..() + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine(src) + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang(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) + +/obj/mecha/combat/gygax/dark/add_cell(obj/item/weapon/stock_parts/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(animated) + flick("ultra-gofasta-off",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(animated) + flick("ultra-gofasta-on",src) + icon_state = "ultra-gofasta" + 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.") + if(animated) + flick("ultra-gofasta-off",src) + reset_icon() + 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 diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm index 6beecfc77a63..ee6ea8c9dea4 100644 --- a/code/game/mecha/combat/honker.dm +++ b/code/game/mecha/combat/honker.dm @@ -1,162 +1,162 @@ -/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/atom_init() - . = ..() - weapons += new /datum/mecha_weapon/honker(src) - weapons += new /datum/mecha_weapon/missile_rack/banana_mortar(src) - weapons += new /datum/mecha_weapon/missile_rack/banana_mortar/mousetrap_mortar(src) - selected_weapon = weapons[1] -*/ - - -/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/atom_init() + . = ..() + weapons += new /datum/mecha_weapon/honker(src) + weapons += new /datum/mecha_weapon/missile_rack/banana_mortar(src) + weapons += new /datum/mecha_weapon/missile_rack/banana_mortar/mousetrap_mortar(src) + selected_weapon = weapons[1] +*/ + + +/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 7ff2f2d64798..344b2da6457d 100644 --- a/code/game/mecha/combat/marauder.dm +++ b/code/game/mecha/combat/marauder.dm @@ -1,198 +1,198 @@ -/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/mauler/atom_init() - . = ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg(src) - ME.attach(src) - 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/explosive(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) - smoke_system.set_up(3, 0, src) - smoke_system.attach(src) - -/obj/mecha/combat/marauder/loaded/atom_init() - . = ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse(src) - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive(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) - smoke_system.set_up(3, 0, src) - smoke_system.attach(src) - -/obj/mecha/combat/marauder/seraph/atom_init() - ..()//Let it equip whatever is needed. - return INITIALIZE_HINT_LATELOAD - -/obj/mecha/combat/marauder/seraph/atom_init_late() // because of qdel() ... - // actually, mech equipment should be made as closets with their PopulateContents proc ... - // or any other idea. so we dont need to clean parent's equipment - 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 = 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/explosive(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) - -/obj/mecha/combat/marauder/relaymove(mob/user,direction) - if(zoom) - if(world.time - last_message > 20) - src.occupant_message("Unable to move while in zoom mode.") - last_message = world.time - return 0 - return ..() - -/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/Process_Spacemove(movement_dir = 0) - if(..()) - return 1 - if(thrusters && movement_dir && use_power(step_energy_drain)) - return 1 - return 0 - -/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 - 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 +/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/mauler/atom_init() + . = ..() + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg(src) + ME.attach(src) + 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/explosive(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) + smoke_system.set_up(3, 0, src) + smoke_system.attach(src) + +/obj/mecha/combat/marauder/loaded/atom_init() + . = ..() + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse(src) + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive(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) + smoke_system.set_up(3, 0, src) + smoke_system.attach(src) + +/obj/mecha/combat/marauder/seraph/atom_init() + ..()//Let it equip whatever is needed. + return INITIALIZE_HINT_LATELOAD + +/obj/mecha/combat/marauder/seraph/atom_init_late() // because of qdel() ... + // actually, mech equipment should be made as closets with their PopulateContents proc ... + // or any other idea. so we dont need to clean parent's equipment + 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 = 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/explosive(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) + +/obj/mecha/combat/marauder/relaymove(mob/user,direction) + if(zoom) + if(world.time - last_message > 20) + src.occupant_message("Unable to move while in zoom mode.") + last_message = world.time + return 0 + return ..() + +/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/Process_Spacemove(movement_dir = 0) + if(..()) + return 1 + if(thrusters && movement_dir && use_power(step_energy_drain)) + return 1 + return 0 + +/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 + 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 diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm index 84af9448f672..22e3c9442fc5 100644 --- a/code/game/mecha/combat/phazon.dm +++ b/code/game/mecha/combat/phazon.dm @@ -1,89 +1,89 @@ -/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/atom_init() - . = ..() - 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) - -/obj/mecha/combat/phazon/Bump(atom/obstacle) - if(phasing && get_charge()>=phasing_energy_drain) - 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/verb/switch_damtype() - set category = "Exosuit Interface" - set name = "Change melee damage type" - set src = usr.loc - set popup_menu = 0 - if(usr!=src.occupant) - return - var/new_damtype = alert(src.occupant,"Melee Damage Type",null,"Brute","Fire","Toxic") - switch(new_damtype) - if("Brute") - damtype = "brute" - if("Fire") - damtype = "fire" - if("Toxic") - damtype = "tox" - src.occupant_message("Melee damage type switched to [new_damtype ]") - return - -/obj/mecha/combat/phazon/get_commands() - var/output = {" - "} - output += ..() - return output - -/obj/mecha/combat/phazon/Topic(href, href_list) - ..() - if (href_list["switch_damtype"]) - src.switch_damtype() - 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 +/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/atom_init() + . = ..() + 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) + +/obj/mecha/combat/phazon/Bump(atom/obstacle) + if(phasing && get_charge()>=phasing_energy_drain) + 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/verb/switch_damtype() + set category = "Exosuit Interface" + set name = "Change melee damage type" + set src = usr.loc + set popup_menu = 0 + if(usr!=src.occupant) + return + var/new_damtype = alert(src.occupant,"Melee Damage Type",null,"Brute","Fire","Toxic") + switch(new_damtype) + if("Brute") + damtype = "brute" + if("Fire") + damtype = "fire" + if("Toxic") + damtype = "tox" + src.occupant_message("Melee damage type switched to [new_damtype ]") + return + +/obj/mecha/combat/phazon/get_commands() + var/output = {" + "} + output += ..() + return output + +/obj/mecha/combat/phazon/Topic(href, href_list) + ..() + if (href_list["switch_damtype"]) + src.switch_damtype() + 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 diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 24bb24a1b96c..180383e2c553 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -1,140 +1,140 @@ -//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) - sleep(equip_cooldown) - set_ready_state(1) - if(target && chassis) - return 1 - return 0 - - -/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/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)) - chassis.occupant << sound('sound/mecha/weapdestr.ogg',volume=50) - else - chassis.occupant << sound('sound/mecha/critdestr.ogg',volume=50) - 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) - if(istype(M)) - if(istype(src, /obj/item/mecha_parts/mecha_equipment/Drop_system)) - return 1 - if(M.equipment.len[src]: [message]") - return +//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) + sleep(equip_cooldown) + set_ready_state(1) + if(target && chassis) + return 1 + return 0 + + +/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/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)) + chassis.occupant << sound('sound/mecha/weapdestr.ogg',volume=50) + else + chassis.occupant << sound('sound/mecha/critdestr.ogg',volume=50) + 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) + if(istype(M)) + if(istype(src, /obj/item/mecha_parts/mecha_equipment/Drop_system)) + return 1 + 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 d1df3a136cd7..97629af2472a 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -1,676 +1,676 @@ -/obj/item/mecha_parts/mecha_equipment/tool/sleeper - name = "Mounted Sleeper" - desc = "Mounted Sleeper. (Can be attached to: Medical Exosuits)" - icon = 'icons/obj/Cryogenic3.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 = 5 - 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/atom_init() - . = ..() - pr_mech_sleeper = new /datum/global_iterator/mech_sleeper(list(src),0) - pr_mech_sleeper.set_delay(equip_cooldown) - -/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(mob/living/carbon/target) - if(!action_checks(target)) - return - if(!istype(target)) - return - if(target.buckled) - occupant_message("[target] will not fit into the sleeper because they are buckled to [target.buckled].") - return - if(occupant) - occupant_message("The sleeper is already occupied") - return - if(istype(target, /mob/living/carbon/alien)) - occupant_message("Warning! Unauthorized life form detected!") - 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)) - 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 - for(var/atom/movable/AM in src) - AM.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) - 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/F = new /datum/topic_input(href,href_list) - if(F.get("eject")) - go_out() - if(F.get("view_stats")) - chassis.occupant << browse(entity_ja(get_occupant_stats()),"window=msleeper") - onclose(chassis.occupant, "msleeper") - return - if(F.get("inject")) - inject_reagent(F.getType("inject",/datum/reagent),F.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(datum/reagent/R,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*4) - 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 - -/obj/item/mecha_parts/mecha_equipment/tool/sleeper/container_resist() - go_out() - -/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("[S] 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 - 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/atom_init() - 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(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) - new/obj/item/stack/cable_coil(get_turf(chassis), 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(obj/item/stack/cable_coil/CC) - if(istype(CC) && CC.get_amount()) - var/cur_amount = cable? cable.amount : 0 - var/to_load = max(max_cable - cur_amount,0) - if(to_load) - to_load = min(CC.get_amount(), to_load) - if(!cable) - cable = new(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(turf/new_turf) - if(istype(new_turf, /turf/simulated/floor)) - var/turf/simulated/floor/T = new_turf - if(!T.is_plating() && !T.is_catwalk()) - if(!T.broken && !T.burnt) - new T.floor_type(T) - T.make_plating() - return !new_turf.intact - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/layCable(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 = new(new_turf) - NC.color = COLOR_RED - NC.d1 = 0 - NC.d2 = fdirn - NC.updateicon() - - 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.updateicon() - PN = last_piece.powernet - - if(!PN) - PN = new() - powernets += PN - 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 = "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/accessible_reagents - 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/atom_init() - . = ..() - flags |= NOREACT - syringes = new - accessible_reagents = list("inaprovaline","anti_toxin", "alkysine", "arithrazine", "bicaridine", "citalopram", "dermaline", - "dexalin", "dexalinp", "ethylredoxrazine", "hyperzine", "hyronalin", "imidazoline", "kelotane", "leporazine", "methylphenidate", - "oxycodone", "paracetamol", "paroxetine", "peridaxon", "rezadone", "ryetalyn", "spaceacillin", "sterilizine", "synaptizine", - "tramadol", "tricordrazine", "doctorsdelight") - 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_bodypart_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/F = new (href,href_list) - if(F.get("toggle_mode")) - mode = !mode - update_equip_info() - return - if(F.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 = F.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(F.get("show_reagents")) - chassis.occupant << browse(entity_ja(get_reagents_page()),"window=msyringegun") - if(F.get("purge_reagent")) - var/reagent = F.get("purge_reagent") - if(reagent) - reagents.del_reagent(reagent) - return - if(F.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) - inputs += "" - inputs += "" - inputs += "" - 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(accessible_reagents.Find(R.id) != 0 && 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/Cryogenic3.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 = 5 + 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/atom_init() + . = ..() + pr_mech_sleeper = new /datum/global_iterator/mech_sleeper(list(src),0) + pr_mech_sleeper.set_delay(equip_cooldown) + +/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(mob/living/carbon/target) + if(!action_checks(target)) + return + if(!istype(target)) + return + if(target.buckled) + occupant_message("[target] will not fit into the sleeper because they are buckled to [target.buckled].") + return + if(occupant) + occupant_message("The sleeper is already occupied") + return + if(istype(target, /mob/living/carbon/alien)) + occupant_message("Warning! Unauthorized life form detected!") + 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)) + 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 + for(var/atom/movable/AM in src) + AM.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) + 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/F = new /datum/topic_input(href,href_list) + if(F.get("eject")) + go_out() + if(F.get("view_stats")) + chassis.occupant << browse(entity_ja(get_occupant_stats()),"window=msleeper") + onclose(chassis.occupant, "msleeper") + return + if(F.get("inject")) + inject_reagent(F.getType("inject",/datum/reagent),F.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(datum/reagent/R,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*4) + 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 + +/obj/item/mecha_parts/mecha_equipment/tool/sleeper/container_resist() + go_out() + +/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("[S] 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 + 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/atom_init() + 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(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) + new/obj/item/stack/cable_coil(get_turf(chassis), 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(obj/item/stack/cable_coil/CC) + if(istype(CC) && CC.get_amount()) + var/cur_amount = cable? cable.amount : 0 + var/to_load = max(max_cable - cur_amount,0) + if(to_load) + to_load = min(CC.get_amount(), to_load) + if(!cable) + cable = new(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(turf/new_turf) + if(istype(new_turf, /turf/simulated/floor)) + var/turf/simulated/floor/T = new_turf + if(!T.is_plating() && !T.is_catwalk()) + if(!T.broken && !T.burnt) + new T.floor_type(T) + T.make_plating() + return !new_turf.intact + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/layCable(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 = new(new_turf) + NC.color = COLOR_RED + NC.d1 = 0 + NC.d2 = fdirn + NC.updateicon() + + 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.updateicon() + PN = last_piece.powernet + + if(!PN) + PN = new() + powernets += PN + 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 = "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/accessible_reagents + 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/atom_init() + . = ..() + flags |= NOREACT + syringes = new + accessible_reagents = list("inaprovaline","anti_toxin", "alkysine", "arithrazine", "bicaridine", "citalopram", "dermaline", + "dexalin", "dexalinp", "ethylredoxrazine", "hyperzine", "hyronalin", "imidazoline", "kelotane", "leporazine", "methylphenidate", + "oxycodone", "paracetamol", "paroxetine", "peridaxon", "rezadone", "ryetalyn", "spaceacillin", "sterilizine", "synaptizine", + "tramadol", "tricordrazine", "doctorsdelight") + 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_bodypart_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/F = new (href,href_list) + if(F.get("toggle_mode")) + mode = !mode + update_equip_info() + return + if(F.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 = F.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(F.get("show_reagents")) + chassis.occupant << browse(entity_ja(get_reagents_page()),"window=msyringegun") + if(F.get("purge_reagent")) + var/reagent = F.get("purge_reagent") + if(reagent) + reagents.del_reagent(reagent) + return + if(F.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) + inputs += "" + inputs += "" + inputs += "" + 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(accessible_reagents.Find(R.id) != 0 && 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 b5a8813a1845..ff56716cf52d 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -1,1203 +1,1203 @@ -/********Hydralic clamp********/ -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp - name = "hydraulic clamp" - icon_state = "mecha_clamp" - equip_cooldown = 15 - energy_drain = 10 - var/dam_force = 20 - var/obj/mecha/working/ripley/cargo_holder - -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/attach(obj/mecha/M) - ..() - cargo_holder = M - return - -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/action(atom/target) - if(!action_checks(target)) return - if(!cargo_holder) return - if(istype(target, /obj/structure/stool)) return - for(var/M in target.contents) - if(istype(M, /mob/living)) - return - - if(istype(target,/obj)) - var/obj/O = target - if(!O.anchored) - if(cargo_holder.cargo.len < cargo_holder.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 - var/T = chassis.loc - if(do_after_cooldown(target)) - if(T == chassis.loc && src == chassis.selected) - cargo_holder.cargo += O - O.loc = chassis - O.anchored = 0 - occupant_message("[target] succesfully loaded.") - log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") - else - occupant_message("You must hold still while handling objects.") - O.anchored = initial(O.anchored) - else - occupant_message("Not enough room in cargo compartment.") - else if(istype(target, /obj/structure/scrap)) - var/obj/structure/scrap/pile = target - playsound(target, 'sound/effects/metal_creaking.ogg', 50, 1) - if(do_after_cooldown(pile)) - occupant_message("You squeeze the [pile.name] into compact shape.") - pile.make_cube() - else - occupant_message("[target] is firmly secured.") - else if(istype(target, /obj/structure/droppod)) - var/obj/structure/droppod/Drop = target - if(Drop.flags & STATE_DROPING || Drop.intruder || Drop.second_intruder) - return - var/T = chassis.loc - if(do_after_cooldown(Drop) && T == chassis.loc && src == chassis.selected\ - && !Drop.intruder && !Drop.second_intruder && !(Drop.flags & STATE_DROPING) && !(Drop.flags & STATE_AIMING)) - cargo_holder.cargo += Drop - Drop.loc = chassis - occupant_message("[target] succesfully loaded.") - log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") - return 1 - - else if(istype(target,/mob/living)) - var/mob/living/M = target - if(M.stat>1) return - if(chassis.occupant.a_intent == "hurt") - M.take_overall_damage(dam_force) - M.adjustOxyLoss(round(dam_force/2)) - M.updatehealth() - occupant_message("\red You squeeze [target] with [src.name]. Something cracks.") - chassis.visible_message("\red [chassis] squeezes [target].") - - chassis.occupant.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name]" - M.attack_log += "\[[time_stamp()]\] Attacked by [chassis.occupant.name] ([chassis.occupant.ckey]) with [name]" - msg_admin_attack("[key_name(chassis.occupant)] attacked [key_name(M)] with [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 - - -/********Drill********/ -/obj/item/mecha_parts/mecha_equipment/tool/drill - name = "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 = 30 - energy_drain = 10 - force = 15 - var/penetration = 5 - -/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.use_power(energy_drain) - chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.") - occupant_message("You start to drill [target]") - var/T = chassis.loc - var/C = target.loc //why are these backwards? we may never know -Pete - if(do_after_cooldown(target)) - if(T == chassis.loc && src == chassis.selected) - if(istype(target, /turf/simulated/wall/r_wall)) - occupant_message("[target] is too durable to drill through.") - else if(istype(target, /turf/simulated/mineral)) - for(var/turf/simulated/mineral/M in range(chassis,1)) - if(get_dir(chassis,M)&chassis.dir) - M.GetDrilled() - log_message("Drilled through [target]") - if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) - var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo - if(ore_box) - for(var/obj/item/weapon/ore/ore in range(chassis,1)) - if(get_dir(chassis,ore)&chassis.dir) - ore.Move(ore_box) - else if(istype(target, /turf/simulated/floor/plating/airless/asteroid)) - for(var/turf/simulated/floor/plating/airless/asteroid/M in range(chassis,1)) - if(get_dir(chassis,M)&chassis.dir) - M.gets_dug() - log_message("Drilled through [target]") - if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) - var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo - if(ore_box) - for(var/obj/item/weapon/ore/ore in range(chassis,1)) - if(get_dir(chassis,ore)&chassis.dir) - ore.Move(ore_box) - else if(target.loc == C) - if(istype(target,/mob/living)) - var/mob/living/M = target - chassis.occupant.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name]" - M.attack_log += "\[[time_stamp()]\] Attacked by [chassis.occupant.name] ([chassis.occupant.ckey]) with [name]" - msg_admin_attack("[key_name(chassis.occupant)] attacked [key_name(M)] with [name]") - - log_message("Drilled through [target]") - target.ex_act(2) - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/drill/can_attach(obj/mecha/M) - if(..()) - if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) - return 1 - return 0 - - -/********Diamond drill********/ -/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill - name = "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 = 20 - force = 15 - penetration = 6 - -/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/action(atom/target) - if(!action_checks(target)) return - if(isobj(target)) - var/obj/target_obj = target - if(target_obj.unacidable) return - set_ready_state(0) - chassis.use_power(energy_drain) - chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.") - occupant_message("You start to drill [target]") - var/T = chassis.loc - var/C = target.loc //why are these backwards? we may never know -Pete - if(do_after_cooldown(target)) - if(T == chassis.loc && src == chassis.selected) - if(istype(target, /turf/simulated/wall/r_wall)) - if(do_after_cooldown(target))//To slow down how fast mechs can drill through the station - log_message("Drilled through [target]") - target.ex_act(3) - else if(istype(target, /turf/simulated/mineral)) - for(var/turf/simulated/mineral/M in range(chassis,1)) - if(get_dir(chassis,M)&chassis.dir) - M.GetDrilled() - log_message("Drilled through [target]") - if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) - var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo - if(ore_box) - for(var/obj/item/weapon/ore/ore in range(chassis,1)) - if(get_dir(chassis,ore)&chassis.dir) - ore.Move(ore_box) - else if(istype(target,/turf/simulated/floor/plating/airless/asteroid)) - for(var/turf/simulated/floor/plating/airless/asteroid/M in range(target,1)) - M.gets_dug() - log_message("Drilled through [target]") - if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) - var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo - if(ore_box) - for(var/obj/item/weapon/ore/ore in range(target,1)) - ore.Move(ore_box) - else if(target.loc == C) - if(istype(target,/mob/living)) - var/mob/living/M = target - chassis.occupant.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name]" - M.attack_log += "\[[time_stamp()]\] Attacked by [chassis.occupant.name] ([chassis.occupant.ckey]) with [name]" - msg_admin_attack("[key_name(chassis.occupant)] attacked [key_name(M)] with [name]") - - log_message("Drilled through [target]") - target.ex_act(2) - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/can_attach(obj/mecha/M) - if(..()) - if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) - return 1 - return 0 - - -/********Extinguisher********/ -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher - name = "extinguisher" - desc = "Exosuit-mounted extinguisher (Can be attached to: Engineering exosuits)" - icon_state = "mecha_exting" - equip_cooldown = 5 - energy_drain = 0 - range = MELEE|RANGED - -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/atom_init() - reagents = new/datum/reagents(200) - reagents.my_atom = src - reagents.add_reagent("water", 200) - . = ..() - -/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)>3) return - if(get_dist(chassis, target)>2) 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("\blue 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) - spawn(0) - for(var/a in 1 to 5) - var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(chassis)) - if(!W) return - var/turf/my_target = pick(the_targets) - var/datum/reagents/R = new/datum/reagents(5) - W.reagents = R - R.my_atom = W - src.reagents.trans_to(W,1) - for(var/b in 1 to 4) - if(!W) return - if(!W.reagents) break - step_towards(W,my_target) - W.reagents.reaction(get_turf(W)) - for(var/atom/atm in get_turf(W)) - W.reagents.reaction(atm) - if(isliving(atm)) //For extinguishing mobs on fire - var/mob/living/M = atm - M.ExtinguishMob() - if(W.loc == my_target) break - sleep(2) - qdel(W) - 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) - if(..()) - if(istype(M)) - return 1 - return 0 - - -/********RCD********/ -/obj/item/mecha_parts/mecha_equipment/tool/rcd - name = "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/atom_init() - . = ..() - mecha_rcd_list += src - -/obj/item/mecha_parts/mecha_equipment/tool/rcd/Destroy() - mecha_rcd_list -= src - return ..() - -/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:BreakToBase() - 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) - 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) - 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\]" - - -/********Teleporter********/ -/obj/item/mecha_parts/mecha_equipment/teleporter - name = "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 == ZLEVEL_CENTCOMM) 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 - - -/********Teleporter********/ -/obj/item/mecha_parts/mecha_equipment/wormhole_generator - name = "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 == ZLEVEL_CENTCOMM) 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.creator = null - P.icon = 'icons/obj/objects.dmi' - P.failchance = 0 - P.icon_state = "anom" - P.name = "wormhole" - do_after_cooldown() - src = null - QDEL_IN(P, rand(150,300)) - return - - -/********Gravcatapult********/ -/obj/item/mecha_parts/mecha_equipment/gravcatapult - name = "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, chassis) - 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 - - -/********Armor booster module (Close Combat Weaponry)********/ -/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster //what is that noise? A BAWWW from TK mutants. - name = "closed armor booster module" - 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) - 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) - ..() - 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, mob/user) - 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, "\red 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 - - -/********Armor booster module (Ranged Weaponry)********/ -/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster - name = "ranged armor booster module" - 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) - 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) - ..() - 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(obj/item/projectile/Proj) - if(!action_checks(src)) - return chassis.dynbulletdamage(Proj) - if(prob(chassis.deflect_chance*deflect_coeff)) - chassis.occupant_message("\blue 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("\blue 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_bodypart_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 - - -/********Repair droid********/ -/obj/item/mecha_parts/mecha_equipment/repair_droid - name = "repair droid" - 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/atom_init() - . = ..() - pr_repair_droid = new /datum/global_iterator/mecha_repair_droid(list(src),0) - pr_repair_droid.set_delay(equip_cooldown) - -/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M) - ..() - droid_overlay = new(src.icon, icon_state = "repair_droid") - M.overlays += droid_overlay - return - -/obj/item/mecha_parts/mecha_equipment/repair_droid/Destroy() - if(chassis) - 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 - - -/********Energy relay********/ -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay - name = "energy relay" - desc = "Wirelessly drains energy from any available power channel in area. The performance index is quite low." - icon_state = "tesla" - origin_tech = "magnets=4" - 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/atom_init() - . = ..() - pr_energy_relay = new /datum/global_iterator/mecha_energy_relay(list(src),0) - pr_energy_relay.set_delay(equip_cooldown) - -/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(area/A) - var/pow_chan - if(A) - for(var/c in use_channels) - if(A.master && A.master.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(obj/item/stack/sheet/P) - if(P.type == fuel.type && P.get_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.get_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.gas["phoron"] += 100 - GM.temperature = 1500+T0C //should be enough to start a fire - T.visible_message("The [src] suddenly disgorges a cloud of heated phoron.") - qdel(src) - else - GM.gas["phoron"] += 5 - GM.temperature = istype(T) ? T.air.temperature : T20C - T.visible_message("The [src] suddenly disgorges a cloud of phoron.") - 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 == "hurt") - chassis.occupant_message("\red You obliterate [target] with [src.name], leaving blood and guts everywhere.") - chassis.visible_message("\red [chassis] destroys [target] in an unholy fury.") - if(chassis.occupant.a_intent == "disarm") - chassis.occupant_message("\red You tear [target]'s limbs off with [src.name].") - chassis.visible_message("\red [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 - - -/********Mecha customisation kit********/ -/obj/item/weapon/paintkit //Please don't use this for anything, it's a base type for custom mech paintjobs. - name = "mecha customisation kit" - desc = "A generic kit containing all the needed tools and parts to turn a mech into another mech." - icon = 'icons/obj/custom_items.dmi' - icon_state = "royce_kit" - - var/new_name = "mech" //What is the variant called? - var/new_desc = "A mech." //How is the new mech described? - var/new_icon = "ripley" //What base icon will the new mech use? - var/removable = null //Can the kit be removed? - var/list/allowed_types = list() //Types of mech that the kit will work on. - - -/********Mecha Drop System********/ -/obj/item/mecha_parts/mecha_equipment/Drop_system - name = "Drop System" - desc = "Allow to drop mech from skies." - icon_state = "tesla" - origin_tech = "magnets=4" - equip_cooldown = 10 - energy_drain = 2500 - range = 0 - var/uses = 1 - var/aiming = FALSE - var/static/datum/droppod_allowed/allowed_areas - -/obj/item/mecha_parts/mecha_equipment/Drop_system/atom_init() - . = ..() - if(!allowed_areas) - allowed_areas = new - -/obj/item/mecha_parts/mecha_equipment/Drop_system/Topic(href, href_list) - ..() - if(href_list["start_drop"]) - if(!aiming && uses) - Select() - log_message("Select Drop Point.") - else - chassis.occupant_message("You cannot drop for now!") - return - -/obj/item/mecha_parts/mecha_equipment/Drop_system/get_equip_info() - if(!chassis) - return - return "* [name] - Start Drop" - -/obj/item/mecha_parts/mecha_equipment/Drop_system/proc/Select() // little copypaste from droppod code - if(aiming) - return - aiming = TRUE - var/A - A = input("Select Area for Droping Pod", "Select", A) in allowed_areas.areas - var/area/thearea = allowed_areas.areas[A] - var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - if(!T.density && !istype(T, /turf/space) && !T.obscured) - L+=T - if(isemptylist(L)) - chassis.occupant_message("Automatic Aim System cannot find an appropriate target!") - aiming = FALSE - return - if(!Challenge) - if(world.time < SYNDICATE_CHALLENGE_TIMER) - chassis.occupant_message("You've issued a combat challenge to the station! \ - You've got to give them at least [round(((SYNDICATE_CHALLENGE_TIMER - world.time) / 10) / 60)] \ - time more minutes to allow them to prepare.") - aiming = FALSE - return - else - Challenge.Dropod_used = TRUE - chassis.occupant_message("You succesfully selected target!") - chassis.loc = pick(L) - uses-- - chassis.freeze_movement = TRUE // to prevent moving in drop phase. - chassis.density = FALSE - chassis.opacity = FALSE - var/initial_x = chassis.pixel_x - var/initial_y = chassis.pixel_y - playsound(src, 'sound/effects/drop_start.ogg', 100, 2) - chassis.pixel_x = rand(-150, 150) - chassis.pixel_y = 500 - animate(chassis, pixel_y = initial_y, pixel_x = initial_x, time = 20) - addtimer(CALLBACK(src, .proc/perform_drop), 20) - - -/obj/item/mecha_parts/mecha_equipment/Drop_system/proc/perform_drop() - for(var/atom/movable/T in loc) - if(T != src && T != chassis.occupant && !(istype(T, /obj/structure/window) || istype(T, /obj/machinery/door/airlock) || istype(T, /obj/machinery/door/poddoor))) - if(!(T in chassis.contents)) T.ex_act(1) - for(var/mob/living/M in oviewers(6, src)) - shake_camera(M, 2, 2) - for(var/turf/simulated/floor/T in RANGE_TURFS(1, chassis)) - T.break_tile_to_plating() - playsound(loc, 'sound/effects/drop_land.ogg', 100, 2) - chassis.freeze_movement = FALSE - chassis.density = TRUE - chassis.opacity = TRUE - aiming = FALSE +/********Hydralic clamp********/ +/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp + name = "hydraulic clamp" + icon_state = "mecha_clamp" + equip_cooldown = 15 + energy_drain = 10 + var/dam_force = 20 + var/obj/mecha/working/ripley/cargo_holder + +/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/attach(obj/mecha/M) + ..() + cargo_holder = M + return + +/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/action(atom/target) + if(!action_checks(target)) return + if(!cargo_holder) return + if(istype(target, /obj/structure/stool)) return + for(var/M in target.contents) + if(istype(M, /mob/living)) + return + + if(istype(target,/obj)) + var/obj/O = target + if(!O.anchored) + if(cargo_holder.cargo.len < cargo_holder.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 + var/T = chassis.loc + if(do_after_cooldown(target)) + if(T == chassis.loc && src == chassis.selected) + cargo_holder.cargo += O + O.loc = chassis + O.anchored = 0 + occupant_message("[target] succesfully loaded.") + log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") + else + occupant_message("You must hold still while handling objects.") + O.anchored = initial(O.anchored) + else + occupant_message("Not enough room in cargo compartment.") + else if(istype(target, /obj/structure/scrap)) + var/obj/structure/scrap/pile = target + playsound(target, 'sound/effects/metal_creaking.ogg', 50, 1) + if(do_after_cooldown(pile)) + occupant_message("You squeeze the [pile.name] into compact shape.") + pile.make_cube() + else + occupant_message("[target] is firmly secured.") + else if(istype(target, /obj/structure/droppod)) + var/obj/structure/droppod/Drop = target + if(Drop.flags & STATE_DROPING || Drop.intruder || Drop.second_intruder) + return + var/T = chassis.loc + if(do_after_cooldown(Drop) && T == chassis.loc && src == chassis.selected\ + && !Drop.intruder && !Drop.second_intruder && !(Drop.flags & STATE_DROPING) && !(Drop.flags & STATE_AIMING)) + cargo_holder.cargo += Drop + Drop.loc = chassis + occupant_message("[target] succesfully loaded.") + log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") + return 1 + + else if(istype(target,/mob/living)) + var/mob/living/M = target + if(M.stat>1) return + if(chassis.occupant.a_intent == "hurt") + M.take_overall_damage(dam_force) + M.adjustOxyLoss(round(dam_force/2)) + M.updatehealth() + occupant_message("\red You squeeze [target] with [src.name]. Something cracks.") + chassis.visible_message("\red [chassis] squeezes [target].") + + chassis.occupant.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name]" + M.attack_log += "\[[time_stamp()]\] Attacked by [chassis.occupant.name] ([chassis.occupant.ckey]) with [name]" + msg_admin_attack("[key_name(chassis.occupant)] attacked [key_name(M)] with [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 + + +/********Drill********/ +/obj/item/mecha_parts/mecha_equipment/tool/drill + name = "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 = 30 + energy_drain = 10 + force = 15 + var/penetration = 5 + +/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.use_power(energy_drain) + chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.") + occupant_message("You start to drill [target]") + var/T = chassis.loc + var/C = target.loc //why are these backwards? we may never know -Pete + if(do_after_cooldown(target)) + if(T == chassis.loc && src == chassis.selected) + if(istype(target, /turf/simulated/wall/r_wall)) + occupant_message("[target] is too durable to drill through.") + else if(istype(target, /turf/simulated/mineral)) + for(var/turf/simulated/mineral/M in range(chassis,1)) + if(get_dir(chassis,M)&chassis.dir) + M.GetDrilled() + log_message("Drilled through [target]") + if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) + var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo + if(ore_box) + for(var/obj/item/weapon/ore/ore in range(chassis,1)) + if(get_dir(chassis,ore)&chassis.dir) + ore.Move(ore_box) + else if(istype(target, /turf/simulated/floor/plating/airless/asteroid)) + for(var/turf/simulated/floor/plating/airless/asteroid/M in range(chassis,1)) + if(get_dir(chassis,M)&chassis.dir) + M.gets_dug() + log_message("Drilled through [target]") + if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) + var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo + if(ore_box) + for(var/obj/item/weapon/ore/ore in range(chassis,1)) + if(get_dir(chassis,ore)&chassis.dir) + ore.Move(ore_box) + else if(target.loc == C) + if(istype(target,/mob/living)) + var/mob/living/M = target + chassis.occupant.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name]" + M.attack_log += "\[[time_stamp()]\] Attacked by [chassis.occupant.name] ([chassis.occupant.ckey]) with [name]" + msg_admin_attack("[key_name(chassis.occupant)] attacked [key_name(M)] with [name]") + + log_message("Drilled through [target]") + target.ex_act(2) + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/drill/can_attach(obj/mecha/M) + if(..()) + if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) + return 1 + return 0 + + +/********Diamond drill********/ +/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill + name = "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 = 20 + force = 15 + penetration = 6 + +/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/action(atom/target) + if(!action_checks(target)) return + if(isobj(target)) + var/obj/target_obj = target + if(target_obj.unacidable) return + set_ready_state(0) + chassis.use_power(energy_drain) + chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.") + occupant_message("You start to drill [target]") + var/T = chassis.loc + var/C = target.loc //why are these backwards? we may never know -Pete + if(do_after_cooldown(target)) + if(T == chassis.loc && src == chassis.selected) + if(istype(target, /turf/simulated/wall/r_wall)) + if(do_after_cooldown(target))//To slow down how fast mechs can drill through the station + log_message("Drilled through [target]") + target.ex_act(3) + else if(istype(target, /turf/simulated/mineral)) + for(var/turf/simulated/mineral/M in range(chassis,1)) + if(get_dir(chassis,M)&chassis.dir) + M.GetDrilled() + log_message("Drilled through [target]") + if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) + var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo + if(ore_box) + for(var/obj/item/weapon/ore/ore in range(chassis,1)) + if(get_dir(chassis,ore)&chassis.dir) + ore.Move(ore_box) + else if(istype(target,/turf/simulated/floor/plating/airless/asteroid)) + for(var/turf/simulated/floor/plating/airless/asteroid/M in range(target,1)) + M.gets_dug() + log_message("Drilled through [target]") + if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) + var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo + if(ore_box) + for(var/obj/item/weapon/ore/ore in range(target,1)) + ore.Move(ore_box) + else if(target.loc == C) + if(istype(target,/mob/living)) + var/mob/living/M = target + chassis.occupant.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name]" + M.attack_log += "\[[time_stamp()]\] Attacked by [chassis.occupant.name] ([chassis.occupant.ckey]) with [name]" + msg_admin_attack("[key_name(chassis.occupant)] attacked [key_name(M)] with [name]") + + log_message("Drilled through [target]") + target.ex_act(2) + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/can_attach(obj/mecha/M) + if(..()) + if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) + return 1 + return 0 + + +/********Extinguisher********/ +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher + name = "extinguisher" + desc = "Exosuit-mounted extinguisher (Can be attached to: Engineering exosuits)" + icon_state = "mecha_exting" + equip_cooldown = 5 + energy_drain = 0 + range = MELEE|RANGED + +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher/atom_init() + reagents = new/datum/reagents(200) + reagents.my_atom = src + reagents.add_reagent("water", 200) + . = ..() + +/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)>3) return + if(get_dist(chassis, target)>2) 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("\blue 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) + spawn(0) + for(var/a in 1 to 5) + var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(chassis)) + if(!W) return + var/turf/my_target = pick(the_targets) + var/datum/reagents/R = new/datum/reagents(5) + W.reagents = R + R.my_atom = W + src.reagents.trans_to(W,1) + for(var/b in 1 to 4) + if(!W) return + if(!W.reagents) break + step_towards(W,my_target) + W.reagents.reaction(get_turf(W)) + for(var/atom/atm in get_turf(W)) + W.reagents.reaction(atm) + if(isliving(atm)) //For extinguishing mobs on fire + var/mob/living/M = atm + M.ExtinguishMob() + if(W.loc == my_target) break + sleep(2) + qdel(W) + 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) + if(..()) + if(istype(M)) + return 1 + return 0 + + +/********RCD********/ +/obj/item/mecha_parts/mecha_equipment/tool/rcd + name = "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/atom_init() + . = ..() + mecha_rcd_list += src + +/obj/item/mecha_parts/mecha_equipment/tool/rcd/Destroy() + mecha_rcd_list -= src + return ..() + +/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:BreakToBase() + 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) + 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) + 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\]" + + +/********Teleporter********/ +/obj/item/mecha_parts/mecha_equipment/teleporter + name = "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 == ZLEVEL_CENTCOMM) 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 + + +/********Teleporter********/ +/obj/item/mecha_parts/mecha_equipment/wormhole_generator + name = "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 == ZLEVEL_CENTCOMM) 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.creator = null + P.icon = 'icons/obj/objects.dmi' + P.failchance = 0 + P.icon_state = "anom" + P.name = "wormhole" + do_after_cooldown() + src = null + QDEL_IN(P, rand(150,300)) + return + + +/********Gravcatapult********/ +/obj/item/mecha_parts/mecha_equipment/gravcatapult + name = "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, chassis) + 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 + + +/********Armor booster module (Close Combat Weaponry)********/ +/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster //what is that noise? A BAWWW from TK mutants. + name = "closed armor booster module" + 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) + 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) + ..() + 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, mob/user) + 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, "\red 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 + + +/********Armor booster module (Ranged Weaponry)********/ +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster + name = "ranged armor booster module" + 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) + 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) + ..() + 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(obj/item/projectile/Proj) + if(!action_checks(src)) + return chassis.dynbulletdamage(Proj) + if(prob(chassis.deflect_chance*deflect_coeff)) + chassis.occupant_message("\blue 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("\blue 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_bodypart_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 + + +/********Repair droid********/ +/obj/item/mecha_parts/mecha_equipment/repair_droid + name = "repair droid" + 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/atom_init() + . = ..() + pr_repair_droid = new /datum/global_iterator/mecha_repair_droid(list(src),0) + pr_repair_droid.set_delay(equip_cooldown) + +/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M) + ..() + droid_overlay = new(src.icon, icon_state = "repair_droid") + M.overlays += droid_overlay + return + +/obj/item/mecha_parts/mecha_equipment/repair_droid/Destroy() + if(chassis) + 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 + + +/********Energy relay********/ +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay + name = "energy relay" + desc = "Wirelessly drains energy from any available power channel in area. The performance index is quite low." + icon_state = "tesla" + origin_tech = "magnets=4" + 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/atom_init() + . = ..() + pr_energy_relay = new /datum/global_iterator/mecha_energy_relay(list(src),0) + pr_energy_relay.set_delay(equip_cooldown) + +/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(area/A) + var/pow_chan + if(A) + for(var/c in use_channels) + if(A.master && A.master.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(obj/item/stack/sheet/P) + if(P.type == fuel.type && P.get_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.get_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.gas["phoron"] += 100 + GM.temperature = 1500+T0C //should be enough to start a fire + T.visible_message("The [src] suddenly disgorges a cloud of heated phoron.") + qdel(src) + else + GM.gas["phoron"] += 5 + GM.temperature = istype(T) ? T.air.temperature : T20C + T.visible_message("The [src] suddenly disgorges a cloud of phoron.") + 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 == "hurt") + chassis.occupant_message("\red You obliterate [target] with [src.name], leaving blood and guts everywhere.") + chassis.visible_message("\red [chassis] destroys [target] in an unholy fury.") + if(chassis.occupant.a_intent == "disarm") + chassis.occupant_message("\red You tear [target]'s limbs off with [src.name].") + chassis.visible_message("\red [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 + + +/********Mecha customisation kit********/ +/obj/item/weapon/paintkit //Please don't use this for anything, it's a base type for custom mech paintjobs. + name = "mecha customisation kit" + desc = "A generic kit containing all the needed tools and parts to turn a mech into another mech." + icon = 'icons/obj/custom_items.dmi' + icon_state = "royce_kit" + + var/new_name = "mech" //What is the variant called? + var/new_desc = "A mech." //How is the new mech described? + var/new_icon = "ripley" //What base icon will the new mech use? + var/removable = null //Can the kit be removed? + var/list/allowed_types = list() //Types of mech that the kit will work on. + + +/********Mecha Drop System********/ +/obj/item/mecha_parts/mecha_equipment/Drop_system + name = "Drop System" + desc = "Allow to drop mech from skies." + icon_state = "tesla" + origin_tech = "magnets=4" + equip_cooldown = 10 + energy_drain = 2500 + range = 0 + var/uses = 1 + var/aiming = FALSE + var/static/datum/droppod_allowed/allowed_areas + +/obj/item/mecha_parts/mecha_equipment/Drop_system/atom_init() + . = ..() + if(!allowed_areas) + allowed_areas = new + +/obj/item/mecha_parts/mecha_equipment/Drop_system/Topic(href, href_list) + ..() + if(href_list["start_drop"]) + if(!aiming && uses) + Select() + log_message("Select Drop Point.") + else + chassis.occupant_message("You cannot drop for now!") + return + +/obj/item/mecha_parts/mecha_equipment/Drop_system/get_equip_info() + if(!chassis) + return + return "* [name] - Start Drop" + +/obj/item/mecha_parts/mecha_equipment/Drop_system/proc/Select() // little copypaste from droppod code + if(aiming) + return + aiming = TRUE + var/A + A = input("Select Area for Droping Pod", "Select", A) in allowed_areas.areas + var/area/thearea = allowed_areas.areas[A] + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + if(!T.density && !istype(T, /turf/space) && !T.obscured) + L+=T + if(isemptylist(L)) + chassis.occupant_message("Automatic Aim System cannot find an appropriate target!") + aiming = FALSE + return + if(!Challenge) + if(world.time < SYNDICATE_CHALLENGE_TIMER) + chassis.occupant_message("You've issued a combat challenge to the station! \ + You've got to give them at least [round(((SYNDICATE_CHALLENGE_TIMER - world.time) / 10) / 60)] \ + time more minutes to allow them to prepare.") + aiming = FALSE + return + else + Challenge.Dropod_used = TRUE + chassis.occupant_message("You succesfully selected target!") + chassis.loc = pick(L) + uses-- + chassis.freeze_movement = TRUE // to prevent moving in drop phase. + chassis.density = FALSE + chassis.opacity = FALSE + var/initial_x = chassis.pixel_x + var/initial_y = chassis.pixel_y + playsound(src, 'sound/effects/drop_start.ogg', 100, 2) + chassis.pixel_x = rand(-150, 150) + chassis.pixel_y = 500 + animate(chassis, pixel_y = initial_y, pixel_x = initial_x, time = 20) + addtimer(CALLBACK(src, .proc/perform_drop), 20) + + +/obj/item/mecha_parts/mecha_equipment/Drop_system/proc/perform_drop() + for(var/atom/movable/T in loc) + if(T != src && T != chassis.occupant && !(istype(T, /obj/structure/window) || istype(T, /obj/machinery/door/airlock) || istype(T, /obj/machinery/door/poddoor))) + if(!(T in chassis.contents)) T.ex_act(1) + for(var/mob/living/M in oviewers(6, src)) + shake_camera(M, 2, 2) + for(var/turf/simulated/floor/T in RANGE_TURFS(1, chassis)) + T.break_tile_to_plating() + playsound(loc, 'sound/effects/drop_land.ogg', 100, 2) + chassis.freeze_movement = FALSE + chassis.density = TRUE + chassis.opacity = TRUE + aiming = FALSE diff --git a/code/game/mecha/equipment/tools/unused_tools.dm b/code/game/mecha/equipment/tools/unused_tools.dm index 2d471a1668a2..324ed5b146d4 100644 --- a/code/game/mecha/equipment/tools/unused_tools.dm +++ b/code/game/mecha/equipment/tools/unused_tools.dm @@ -1,157 +1,157 @@ - - - -/****** Do not tick this file in without looking over this code first ******/ - - - - - -//NEEDS SPRITE! (When this gets ticked in search for 'TODO MECHA JETPACK SPRITE MISSING' through code to uncomment the place where it's missing.) -/obj/item/mecha_parts/mecha_equipment/jetpack - name = "Jetpack" - desc = "Using directed ion bursts and cunning solar wind reflection technique, this device enables controlled space flight." - icon_state = "mecha_equip" - equip_cooldown = 5 - energy_drain = 50 - var/wait = 0 - var/datum/effect/effect/system/ion_trail_follow/ion_trail - - - can_attach(obj/mecha/M) - if(!(locate(src.type) in M.equipment) && !M.proc_res["dyndomove"]) - return ..() - - detach() - ..() - chassis.proc_res["dyndomove"] = null - return - - attach(obj/mecha/M) - ..() - if(!ion_trail) - ion_trail = new - ion_trail.set_up(chassis) - return - - proc/toggle() - if(!chassis) - return - !equip_ready? turn_off() : turn_on() - return equip_ready - - proc/turn_on() - set_ready_state(0) - chassis.proc_res["dyndomove"] = src - ion_trail.start() - occupant_message("Activated") - log_message("Activated") - - proc/turn_off() - set_ready_state(1) - chassis.proc_res["dyndomove"] = null - ion_trail.stop() - occupant_message("Deactivated") - log_message("Deactivated") - - 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 - - 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 - - get_equip_info() - if(!chassis) return - return "* [src.name] \[Toggle\]" - - - Topic(href,href_list) - ..() - if(href_list["toggle"]) - toggle() - - do_after_cooldown() - sleep(equip_cooldown) - wait = 0 - return 1 - - -/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) - 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) - ..() - chassis.proc_res["dynattackby"] = src - return - - proc/dynattackby(obj/item/weapon/W, mob/user) - 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(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 ******/ + + + + + +//NEEDS SPRITE! (When this gets ticked in search for 'TODO MECHA JETPACK SPRITE MISSING' through code to uncomment the place where it's missing.) +/obj/item/mecha_parts/mecha_equipment/jetpack + name = "Jetpack" + desc = "Using directed ion bursts and cunning solar wind reflection technique, this device enables controlled space flight." + icon_state = "mecha_equip" + equip_cooldown = 5 + energy_drain = 50 + var/wait = 0 + var/datum/effect/effect/system/ion_trail_follow/ion_trail + + + can_attach(obj/mecha/M) + if(!(locate(src.type) in M.equipment) && !M.proc_res["dyndomove"]) + return ..() + + detach() + ..() + chassis.proc_res["dyndomove"] = null + return + + attach(obj/mecha/M) + ..() + if(!ion_trail) + ion_trail = new + ion_trail.set_up(chassis) + return + + proc/toggle() + if(!chassis) + return + !equip_ready? turn_off() : turn_on() + return equip_ready + + proc/turn_on() + set_ready_state(0) + chassis.proc_res["dyndomove"] = src + ion_trail.start() + occupant_message("Activated") + log_message("Activated") + + proc/turn_off() + set_ready_state(1) + chassis.proc_res["dyndomove"] = null + ion_trail.stop() + occupant_message("Deactivated") + log_message("Deactivated") + + 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 + + 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 + + get_equip_info() + if(!chassis) return + return "* [src.name] \[Toggle\]" + + + Topic(href,href_list) + ..() + if(href_list["toggle"]) + toggle() + + do_after_cooldown() + sleep(equip_cooldown) + wait = 0 + return 1 + + +/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) + 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) + ..() + chassis.proc_res["dynattackby"] = src + return + + proc/dynattackby(obj/item/weapon/W, mob/user) + 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(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 86c9a76d02da..c3d2850e8753 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -1,323 +1,323 @@ -/obj/item/mecha_parts/mecha_equipment/weapon - name = "mecha weapon" - range = RANGED - origin_tech = "materials=3;combat=3" - var/projectile //Type of projectile fired. - var/projectiles = 1 //Amount of projectiles loaded. - var/projectiles_per_shot = 1 //Amount of projectiles fired per single shot. - var/deviation = 0 //Inaccuracy of shots. - var/fire_cooldown = 0 //Duration of sleep between firing projectiles in single shot. - var/fire_sound //Sound played while firing. - var/fire_volume = 50 //How loud it is played. - var/auto_rearm = 0 //Does the weapon reload itself after each shot? - -/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/combat/M) - if(!istype(M)) - return 0 - return ..() - -/obj/item/mecha_parts/mecha_equipment/weapon/action_checks(atom/target) - if(projectiles <= 0) - return 0 - return ..() - -/obj/item/mecha_parts/mecha_equipment/weapon/action(atom/target) - if(!action_checks(target)) - return - var/turf/curloc = chassis.loc - var/turf/targloc = get_turf(target) - if(!curloc || !targloc) - return - chassis.use_power(energy_drain) - chassis.visible_message("[chassis] fires [src]!") - occupant_message("You fire [src]!") - log_message("Fired from [src], targeting [target].") - for(var/i = 1 to min(projectiles, projectiles_per_shot)) - var/turf/aimloc = targloc - if(deviation) - aimloc = locate(targloc.x+GaussRandRound(deviation,1),targloc.y+GaussRandRound(deviation,1),targloc.z) - if(!aimloc || aimloc == curloc) - break - playsound(chassis, fire_sound, fire_volume, 1) - projectiles-- - var/P = new projectile(curloc) - Fire(P, target, aimloc) - if(fire_cooldown) - sleep(fire_cooldown) - if(auto_rearm) - projectiles = projectiles_per_shot - set_ready_state(0) - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/proc/Fire(atom/A, atom/target, turf/aimloc) - var/obj/item/projectile/P = A - P.shot_from = src - P.original = target - P.starting = P.loc - P.current = P.loc - P.firer = chassis.occupant - if(isbrain(chassis.occupant)) - P.def_zone = ran_zone() - else - P.def_zone = check_zone(chassis.occupant.zone_sel.selecting) - P.yo = aimloc.y - P.loc.y - P.xo = aimloc.x - P.loc.x - P.process() - -/obj/item/mecha_parts/mecha_equipment/weapon/energy - name = "General Energy Weapon" - auto_rearm = 1 - -/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/Laser.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 = "pulse1_bl" - var/life = 20 - - Bump(atom/A) - A.bullet_act(src, def_zone) - src.life -= 10 - if(life <= 0) - qdel(src) - return - -/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser - name = "PBT \"Pacifier\" Mounted Taser" - icon_state = "mecha_taser" - energy_drain = 20 - equip_cooldown = 8 - projectile = /obj/item/projectile/beam/stun - fire_sound = 'sound/weapons/Taser.ogg' - - -/obj/item/mecha_parts/mecha_equipment/weapon/honker - name = "HoNkER BlAsT 5000" - icon_state = "mecha_honker" - energy_drain = 200 - equip_cooldown = 150 - range = MELEE|RANGED - - can_attach(obj/mecha/combat/honker/M) - if(!istype(M)) - return 0 - return ..() - - 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(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs)) - 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.make_jittery(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!") - do_after_cooldown() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic - name = "General Ballisic Weapon" - var/projectile_energy_cost - - get_equip_info() - return "[..()]\[[src.projectiles]\][(src.projectiles < initial(src.projectiles))?" - Rearm":null]" - - 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 - - Topic(href, href_list) - ..() - if (href_list["rearm"]) - src.rearm() - return - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine - name = "\improper FNX-66 Carbine" - icon_state = "mecha_carbine" - equip_cooldown = 5 - projectile = /obj/item/projectile/bullet/incendiary - fire_sound = 'sound/weapons/Gunshot.ogg' - projectiles = 24 - projectile_energy_cost = 15 - -/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/Gunshot.ogg' - fire_volume = 80 - projectiles = 40 - projectiles_per_shot = 4 - deviation = 0.7 - projectile_energy_cost = 25 - -/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/midbullet - fire_sound = 'sound/weapons/Gunshot.ogg' - projectiles = 300 - projectiles_per_shot = 3 - deviation = 0.3 - projectile_energy_cost = 20 - fire_cooldown = 2 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack - var/missile_speed = 2 - var/missile_range = 30 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc) - AM.throw_at(target, missile_range, missile_speed, spin = FALSE) - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive - name = "SRM-8 Missile Rack" - icon_state = "mecha_missilerack" - projectile = /obj/item/missile - fire_sound = 'sound/effects/bang.ogg' - projectiles = 8 - projectile_energy_cost = 1000 - equip_cooldown = 60 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/Fire(atom/movable/AM, atom/target, turf/aimloc) - var/obj/item/missile/M = AM - M.primed = 1 - ..() - -/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, 0, 2, 4) - 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/effects/bang.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/Fire(atom/movable/AM, atom/target, turf/aimloc) - ..() - var/obj/item/weapon/grenade/flashbang/F = AM - addtimer(CALLBACK(F, /obj/item/weapon/grenade/flashbang.proc/prime), det_time) - -/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/clusterbuster - -/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 - - can_attach(obj/mecha/combat/honker/M) - if(!istype(M)) - return 0 - return ..() - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/mousetrap_mortar - name = "Mousetrap Mortar" - icon_state = "mecha_mousetrapmrtr" - projectile = /obj/item/device/assembly/mousetrap - equip_cooldown = 10 - -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/mousetrap_mortar/Fire(atom/movable/AM, atom/target, turf/aimloc) - var/obj/item/device/assembly/mousetrap/M = AM - M.secured = 1 - ..() +/obj/item/mecha_parts/mecha_equipment/weapon + name = "mecha weapon" + range = RANGED + origin_tech = "materials=3;combat=3" + var/projectile //Type of projectile fired. + var/projectiles = 1 //Amount of projectiles loaded. + var/projectiles_per_shot = 1 //Amount of projectiles fired per single shot. + var/deviation = 0 //Inaccuracy of shots. + var/fire_cooldown = 0 //Duration of sleep between firing projectiles in single shot. + var/fire_sound //Sound played while firing. + var/fire_volume = 50 //How loud it is played. + var/auto_rearm = 0 //Does the weapon reload itself after each shot? + +/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/combat/M) + if(!istype(M)) + return 0 + return ..() + +/obj/item/mecha_parts/mecha_equipment/weapon/action_checks(atom/target) + if(projectiles <= 0) + return 0 + return ..() + +/obj/item/mecha_parts/mecha_equipment/weapon/action(atom/target) + if(!action_checks(target)) + return + var/turf/curloc = chassis.loc + var/turf/targloc = get_turf(target) + if(!curloc || !targloc) + return + chassis.use_power(energy_drain) + chassis.visible_message("[chassis] fires [src]!") + occupant_message("You fire [src]!") + log_message("Fired from [src], targeting [target].") + for(var/i = 1 to min(projectiles, projectiles_per_shot)) + var/turf/aimloc = targloc + if(deviation) + aimloc = locate(targloc.x+GaussRandRound(deviation,1),targloc.y+GaussRandRound(deviation,1),targloc.z) + if(!aimloc || aimloc == curloc) + break + playsound(chassis, fire_sound, fire_volume, 1) + projectiles-- + var/P = new projectile(curloc) + Fire(P, target, aimloc) + if(fire_cooldown) + sleep(fire_cooldown) + if(auto_rearm) + projectiles = projectiles_per_shot + set_ready_state(0) + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/proc/Fire(atom/A, atom/target, turf/aimloc) + var/obj/item/projectile/P = A + P.shot_from = src + P.original = target + P.starting = P.loc + P.current = P.loc + P.firer = chassis.occupant + if(isbrain(chassis.occupant)) + P.def_zone = ran_zone() + else + P.def_zone = check_zone(chassis.occupant.zone_sel.selecting) + P.yo = aimloc.y - P.loc.y + P.xo = aimloc.x - P.loc.x + P.process() + +/obj/item/mecha_parts/mecha_equipment/weapon/energy + name = "General Energy Weapon" + auto_rearm = 1 + +/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/Laser.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 = "pulse1_bl" + var/life = 20 + + Bump(atom/A) + A.bullet_act(src, def_zone) + src.life -= 10 + if(life <= 0) + qdel(src) + return + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/taser + name = "PBT \"Pacifier\" Mounted Taser" + icon_state = "mecha_taser" + energy_drain = 20 + equip_cooldown = 8 + projectile = /obj/item/projectile/beam/stun + fire_sound = 'sound/weapons/Taser.ogg' + + +/obj/item/mecha_parts/mecha_equipment/weapon/honker + name = "HoNkER BlAsT 5000" + icon_state = "mecha_honker" + energy_drain = 200 + equip_cooldown = 150 + range = MELEE|RANGED + + can_attach(obj/mecha/combat/honker/M) + if(!istype(M)) + return 0 + return ..() + + 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(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs)) + 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.make_jittery(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!") + do_after_cooldown() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic + name = "General Ballisic Weapon" + var/projectile_energy_cost + + get_equip_info() + return "[..()]\[[src.projectiles]\][(src.projectiles < initial(src.projectiles))?" - Rearm":null]" + + 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 + + Topic(href, href_list) + ..() + if (href_list["rearm"]) + src.rearm() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine + name = "\improper FNX-66 Carbine" + icon_state = "mecha_carbine" + equip_cooldown = 5 + projectile = /obj/item/projectile/bullet/incendiary + fire_sound = 'sound/weapons/Gunshot.ogg' + projectiles = 24 + projectile_energy_cost = 15 + +/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/Gunshot.ogg' + fire_volume = 80 + projectiles = 40 + projectiles_per_shot = 4 + deviation = 0.7 + projectile_energy_cost = 25 + +/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/midbullet + fire_sound = 'sound/weapons/Gunshot.ogg' + projectiles = 300 + projectiles_per_shot = 3 + deviation = 0.3 + projectile_energy_cost = 20 + fire_cooldown = 2 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack + var/missile_speed = 2 + var/missile_range = 30 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc) + AM.throw_at(target, missile_range, missile_speed, spin = FALSE) + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive + name = "SRM-8 Missile Rack" + icon_state = "mecha_missilerack" + projectile = /obj/item/missile + fire_sound = 'sound/effects/bang.ogg' + projectiles = 8 + projectile_energy_cost = 1000 + equip_cooldown = 60 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/Fire(atom/movable/AM, atom/target, turf/aimloc) + var/obj/item/missile/M = AM + M.primed = 1 + ..() + +/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, 0, 2, 4) + 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/effects/bang.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/Fire(atom/movable/AM, atom/target, turf/aimloc) + ..() + var/obj/item/weapon/grenade/flashbang/F = AM + addtimer(CALLBACK(F, /obj/item/weapon/grenade/flashbang.proc/prime), det_time) + +/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/clusterbuster + +/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 + + can_attach(obj/mecha/combat/honker/M) + if(!istype(M)) + return 0 + return ..() + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/mousetrap_mortar + name = "Mousetrap Mortar" + icon_state = "mecha_mousetrapmrtr" + projectile = /obj/item/device/assembly/mousetrap + equip_cooldown = 10 + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar/mousetrap_mortar/Fire(atom/movable/AM, atom/target, turf/aimloc) + var/obj/item/device/assembly/mousetrap/M = AM + M.secured = 1 + ..() diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index bd0f3cb273fa..cd69498fda92 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -1,162 +1,162 @@ -/turf/simulated/floor/mech_bay_recharge_floor // Whos idea it was - name = "mech bay recharge station" // Recharging turfs - icon = 'icons/turf/floors.dmi' // That are set in stone to check the west turf for recharge port - icon_state = "recharge_floor" // Some people just want to watch the world burn i guess - -/turf/simulated/floor/mech_bay_recharge_floor/airless - icon_state = "recharge_floor_asteroid" - oxygen = 0.01 - nitrogen = 0.01 - temperature = TCMB - -/obj/machinery/mech_bay_recharge_port - name = "mech bay power port" - density = 1 - anchored = 1 - dir = 4 - icon = 'icons/mecha/mech_bay.dmi' - icon_state = "recharge_port" - var/obj/mecha/recharging_mech - var/obj/machinery/computer/mech_bay_power_console/recharge_console - var/max_charge = 50 - var/on = 0 - var/repairability = 0 - var/turf/recharging_turf = null - -/obj/machinery/mech_bay_recharge_port/atom_init() - . = ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/mech_recharger(null) - component_parts += new /obj/item/weapon/stock_parts/capacitor(null) - component_parts += new /obj/item/weapon/stock_parts/capacitor(null) - component_parts += new /obj/item/weapon/stock_parts/capacitor(null) - component_parts += new /obj/item/weapon/stock_parts/capacitor(null) - component_parts += new /obj/item/weapon/stock_parts/capacitor(null) - component_parts += new /obj/item/stack/cable_coil/random(null, 1) - RefreshParts() - recharging_turf = get_step(loc, dir) - -/obj/machinery/mech_bay_recharge_port/RefreshParts() - var/MC - for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) - MC += C.rating - max_charge = MC * 25 - -/obj/machinery/mech_bay_recharge_port/process() - if(stat & NOPOWER || !recharge_console) - return - if(!recharging_mech) - recharging_mech = locate(/obj/mecha) in recharging_turf - if(recharging_mech) - recharge_console.update_icon() - if(recharging_mech && recharging_mech.cell) - if(recharging_mech.cell.charge < recharging_mech.cell.maxcharge) - var/delta = min(max_charge, recharging_mech.cell.maxcharge - recharging_mech.cell.charge) - recharging_mech.give_power(delta) - use_power(delta*150) - else - recharge_console.update_icon() - if(recharging_mech.loc != recharging_turf) - recharging_mech = null - recharge_console.update_icon() - - -/obj/machinery/mech_bay_recharge_port/attackby(obj/item/I, mob/user) - if(default_deconstruction_screwdriver(user, "recharge_port-o", "recharge_port", I)) - return - - if(default_change_direction_wrench(user, I)) - recharging_turf = get_step(loc, dir) - return - - if(exchange_parts(user, I)) - return - - default_deconstruction_crowbar(I) - - if(panel_open) - if(istype(I, /obj/item/device/multitool)) - var/obj/item/device/multitool/MT = I - if(istype(MT.buffer, /obj/machinery/computer/mech_bay_power_console)) - recharge_console = MT.buffer - MT.buffer = 0 - recharge_console.recharge_port = src - to_chat(user, "You upload the data from the buffer to [src.name].") - -/obj/machinery/computer/mech_bay_power_console - name = "mech bay power control console" - desc = "Used to control mechbay power ports." - density = 1 - anchored = 1 - icon = 'icons/obj/computer.dmi' - icon_state = "recharge_comp" - light_color = "#a97faa" - circuit = /obj/item/weapon/circuitboard/mech_bay_power_console - var/obj/machinery/mech_bay_recharge_port/recharge_port - -/obj/machinery/computer/mech_bay_power_console/attackby(obj/item/I, mob/user) - ..() - if(istype(I, /obj/item/device/multitool)) - var/obj/item/device/multitool/MT = I - MT.buffer = src - to_chat(user, "You download data to the buffer.") - -/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user) - var/data - if(!recharge_port) - data += "
                    No recharging port detected.

                    " - data += "Reconnect" - else - data += "

                    Mech status

                    " - if(!recharge_port.recharging_mech) - data += "
                    No mech detected.
                    " - else - data += "
                    Integrity: [recharge_port.recharging_mech.health]
                    " - if(recharge_port.recharging_mech.cell.crit_fail) - data += "WARNING : the mech cell seems faulty!
                    " - else - data += "Power: [recharge_port.recharging_mech.cell.charge]/[recharge_port.recharging_mech.cell.maxcharge]" - - var/datum/browser/popup = new(user, "mech recharger", name, 300, 300) - popup.set_content(data) - popup.open() - -/obj/machinery/computer/mech_bay_power_console/Topic(href, href_list) - . = ..() - if(!.) - return - if(href_list["reconnect"]) - reconnect() - updateUsrDialog() - -/obj/machinery/computer/mech_bay_power_console/proc/reconnect() - if(recharge_port) - return - recharge_port = locate(/obj/machinery/mech_bay_recharge_port) in range(1) - if(!recharge_port ) - for(var/D in cardinal) - var/turf/A = get_step(src, D) - A = get_step(A, D) - recharge_port = locate(/obj/machinery/mech_bay_recharge_port) in A - if(recharge_port) - break - if(recharge_port) - if(!recharge_port.recharge_console) - recharge_port.recharge_console = src - else - recharge_port = null - -/obj/machinery/computer/mech_bay_power_console/process() - if(recharge_port && recharge_port.recharging_mech && recharge_port.recharging_mech.cell) - updateUsrDialog() - update_icon() - -/obj/machinery/computer/mech_bay_power_console/update_icon() - if(!recharge_port || !recharge_port.recharging_mech || !recharge_port.recharging_mech.cell || !(recharge_port.recharging_mech.cell.charge < recharge_port.recharging_mech.cell.maxcharge)) - icon_state = "recharge_comp" - else - icon_state = "recharge_comp_on" - -/obj/machinery/computer/mech_bay_power_console/atom_init() - . = ..() - reconnect() +/turf/simulated/floor/mech_bay_recharge_floor // Whos idea it was + name = "mech bay recharge station" // Recharging turfs + icon = 'icons/turf/floors.dmi' // That are set in stone to check the west turf for recharge port + icon_state = "recharge_floor" // Some people just want to watch the world burn i guess + +/turf/simulated/floor/mech_bay_recharge_floor/airless + icon_state = "recharge_floor_asteroid" + oxygen = 0.01 + nitrogen = 0.01 + temperature = TCMB + +/obj/machinery/mech_bay_recharge_port + name = "mech bay power port" + density = 1 + anchored = 1 + dir = 4 + icon = 'icons/mecha/mech_bay.dmi' + icon_state = "recharge_port" + var/obj/mecha/recharging_mech + var/obj/machinery/computer/mech_bay_power_console/recharge_console + var/max_charge = 50 + var/on = 0 + var/repairability = 0 + var/turf/recharging_turf = null + +/obj/machinery/mech_bay_recharge_port/atom_init() + . = ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/mech_recharger(null) + component_parts += new /obj/item/weapon/stock_parts/capacitor(null) + component_parts += new /obj/item/weapon/stock_parts/capacitor(null) + component_parts += new /obj/item/weapon/stock_parts/capacitor(null) + component_parts += new /obj/item/weapon/stock_parts/capacitor(null) + component_parts += new /obj/item/weapon/stock_parts/capacitor(null) + component_parts += new /obj/item/stack/cable_coil/random(null, 1) + RefreshParts() + recharging_turf = get_step(loc, dir) + +/obj/machinery/mech_bay_recharge_port/RefreshParts() + var/MC + for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) + MC += C.rating + max_charge = MC * 25 + +/obj/machinery/mech_bay_recharge_port/process() + if(stat & NOPOWER || !recharge_console) + return + if(!recharging_mech) + recharging_mech = locate(/obj/mecha) in recharging_turf + if(recharging_mech) + recharge_console.update_icon() + if(recharging_mech && recharging_mech.cell) + if(recharging_mech.cell.charge < recharging_mech.cell.maxcharge) + var/delta = min(max_charge, recharging_mech.cell.maxcharge - recharging_mech.cell.charge) + recharging_mech.give_power(delta) + use_power(delta*150) + else + recharge_console.update_icon() + if(recharging_mech.loc != recharging_turf) + recharging_mech = null + recharge_console.update_icon() + + +/obj/machinery/mech_bay_recharge_port/attackby(obj/item/I, mob/user) + if(default_deconstruction_screwdriver(user, "recharge_port-o", "recharge_port", I)) + return + + if(default_change_direction_wrench(user, I)) + recharging_turf = get_step(loc, dir) + return + + if(exchange_parts(user, I)) + return + + default_deconstruction_crowbar(I) + + if(panel_open) + if(istype(I, /obj/item/device/multitool)) + var/obj/item/device/multitool/MT = I + if(istype(MT.buffer, /obj/machinery/computer/mech_bay_power_console)) + recharge_console = MT.buffer + MT.buffer = 0 + recharge_console.recharge_port = src + to_chat(user, "You upload the data from the buffer to [src.name].") + +/obj/machinery/computer/mech_bay_power_console + name = "mech bay power control console" + desc = "Used to control mechbay power ports." + density = 1 + anchored = 1 + icon = 'icons/obj/computer.dmi' + icon_state = "recharge_comp" + light_color = "#a97faa" + circuit = /obj/item/weapon/circuitboard/mech_bay_power_console + var/obj/machinery/mech_bay_recharge_port/recharge_port + +/obj/machinery/computer/mech_bay_power_console/attackby(obj/item/I, mob/user) + ..() + if(istype(I, /obj/item/device/multitool)) + var/obj/item/device/multitool/MT = I + MT.buffer = src + to_chat(user, "You download data to the buffer.") + +/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user) + var/data + if(!recharge_port) + data += "
                    No recharging port detected.

                    " + data += "Reconnect" + else + data += "

                    Mech status

                    " + if(!recharge_port.recharging_mech) + data += "
                    No mech detected.
                    " + else + data += "
                    Integrity: [recharge_port.recharging_mech.health]
                    " + if(recharge_port.recharging_mech.cell.crit_fail) + data += "WARNING : the mech cell seems faulty!
                    " + else + data += "Power: [recharge_port.recharging_mech.cell.charge]/[recharge_port.recharging_mech.cell.maxcharge]" + + var/datum/browser/popup = new(user, "mech recharger", name, 300, 300) + popup.set_content(data) + popup.open() + +/obj/machinery/computer/mech_bay_power_console/Topic(href, href_list) + . = ..() + if(!.) + return + if(href_list["reconnect"]) + reconnect() + updateUsrDialog() + +/obj/machinery/computer/mech_bay_power_console/proc/reconnect() + if(recharge_port) + return + recharge_port = locate(/obj/machinery/mech_bay_recharge_port) in range(1) + if(!recharge_port ) + for(var/D in cardinal) + var/turf/A = get_step(src, D) + A = get_step(A, D) + recharge_port = locate(/obj/machinery/mech_bay_recharge_port) in A + if(recharge_port) + break + if(recharge_port) + if(!recharge_port.recharge_console) + recharge_port.recharge_console = src + else + recharge_port = null + +/obj/machinery/computer/mech_bay_power_console/process() + if(recharge_port && recharge_port.recharging_mech && recharge_port.recharging_mech.cell) + updateUsrDialog() + update_icon() + +/obj/machinery/computer/mech_bay_power_console/update_icon() + if(!recharge_port || !recharge_port.recharging_mech || !recharge_port.recharging_mech.cell || !(recharge_port.recharging_mech.cell.charge < recharge_port.recharging_mech.cell.maxcharge)) + icon_state = "recharge_comp" + else + icon_state = "recharge_comp_on" + +/obj/machinery/computer/mech_bay_power_console/atom_init() + . = ..() + reconnect() diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 0c3b9e783f19..e3c35eb4f2f4 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -1,567 +1,567 @@ -/obj/machinery/mecha_part_fabricator - icon = 'icons/obj/robotics.dmi' - icon_state = "fab-idle" - name = "Exosuit Fabricator" - desc = "Nothing is being built." - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 20 - active_power_usage = 5000 - req_access = list(access_robotics) - allowed_checks = ALLOWED_CHECK_TOPIC - var/time_coeff = 1 - var/time_coeff_tech = 1 - var/resource_coeff = 1 - var/resource_coeff_tech = 1 - var/list/resources = list( - MAT_METAL=0, - MAT_GLASS=0, - MAT_DIAMOND=0, - MAT_GOLD=0, - MAT_PHORON=0, - MAT_SILVER=0, - MAT_URANIUM=0 - ) - var/build_type = MECHFAB - var/res_max_amount = 200000 - var/datum/research/files - var/id - var/sync = 0 - var/part_set - var/datum/design/being_built - var/list/queue = list() - var/processing_queue = 0 - var/screen = "main" - var/temp - var/list/part_sets = list( - "Cyborg", - "Ripley", - "Odysseus", - "Gygax", - "Gygax Ultra", - "Durand", - "Vindicator", - "Exosuit Equipment", - "Cyborg Upgrade Modules", - "Cyborg Components", - "Misc" - ) - -/obj/machinery/mecha_part_fabricator/atom_init() - . = ..() - New_parts() - files = new /datum/research(src) //Setup the research data holder. - -/obj/machinery/mecha_part_fabricator/proc/New_parts() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/mechfab(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) - component_parts += new /obj/item/weapon/stock_parts/manipulator(null) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(null) - component_parts += new /obj/item/weapon/stock_parts/console_screen(null) - RefreshParts() - -/obj/machinery/mecha_part_fabricator/RefreshParts() - var/T = 0 - - //maximum stocking amount (max 412000) - for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) - T += M.rating - res_max_amount = (187000+(T * 37500)) - - //ressources adjustment coefficient (1 -> 0.88 -> 0.75) - T = -1 - for(var/obj/item/weapon/stock_parts/micro_laser/Ma in component_parts) - T += Ma.rating - resource_coeff = round(initial(resource_coeff) - (initial(resource_coeff)*(T))/8,0.01) - - //building time adjustment coefficient (1 -> 0.8 -> 0.6) - T = -1 - for(var/obj/item/weapon/stock_parts/manipulator/Ml in component_parts) - T += Ml.rating - time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01) - -/obj/machinery/mecha_part_fabricator/check_access(obj/item/weapon/card/id/I) - 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 - for(var/req in req_access) - if(!(req in I.access)) //doesn't have this access - return 0 - return 1 - -/obj/machinery/mecha_part_fabricator/proc/emag() - switch(emagged) - if(0) - emagged = 0.5 - visible_message("[bicon(src)] \The [src] beeps: \"DB error \[Code 0x00F1\]\"") - sleep(10) - visible_message("[bicon(src)] \The [src] beeps: \"Attempting auto-repair\"") - sleep(15) - visible_message("[bicon(src)] \The [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"") - sleep(30) - visible_message("[bicon(src)] \The [src] beeps: \"User DB truncated. Please contact your Nanotrasen system operator for future assistance.\"") - req_access = null - emagged = 1 - if(0.5) - visible_message("[bicon(src)] \The [src] beeps: \"DB not responding \[Code 0x0003\]...\"") - if(1) - visible_message("[bicon(src)] \The [src] beeps: \"No records in User DB\"") - return - -/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name) - var/output = "" - for(var/datum/design/D in files.known_designs) - if(D.build_type & build_type) - if(!(set_name in D.category)) - continue - var/resources_available = check_resources(D) - output += "
                    [output_part_info(D)]
                    \[[resources_available?"Build | ":null]Add to queue\]\[?\]
                    " - return output - -/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D) - var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [get_construction_time_w_coeff(D)/10]sec" - return output - -/obj/machinery/mecha_part_fabricator/proc/output_part_cost(datum/design/D) - var/i = 0 - var/output - for(var/c in D.materials) - if(c in resources) - output += "[i?" | ":null][get_resource_cost_w_coeff(D,c)] [material2name(c)]" - i++ - return output - -/obj/machinery/mecha_part_fabricator/proc/output_available_resources() - var/output - for(var/resource in resources) - var/amount = min(res_max_amount, resources[resource]) - output += "[material2name(resource)]: [amount] cm³" - if(amount>0) - output += "- Remove \[1\] | \[10\] | \[All\]" - output += "
                    " - return output - -/obj/machinery/mecha_part_fabricator/proc/remove_resources(datum/design/D) - for(var/resource in D.materials) - if(resource in resources) - resources[resource] -= get_resource_cost_w_coeff(D,resource) - -/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) - for(var/R in D.materials) - if(R in resources) - if(resources[R] < get_resource_cost_w_coeff(D, R)) - return 0 - else - return 0 - return 1 - -/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D) - being_built = D - desc = "It's building \a [initial(D.name)]." - remove_resources(D) - overlays += "fab-active" - use_power = 2 - updateUsrDialog() - sleep(get_construction_time_w_coeff(D)) - use_power = 1 - overlays -= "fab-active" - desc = initial(desc) - - var/location = get_step(src,(dir)) - var/I = new D.build_path(location) - if(istype(I, /obj/item)) - var/obj/item/Item = I - Item.materials[MAT_METAL] = get_resource_cost_w_coeff(D,MAT_METAL) - Item.materials[MAT_GLASS] = get_resource_cost_w_coeff(D,MAT_GLASS) - visible_message("[bicon(src)] \The [src] beeps, \"\The [I] is complete.\"") - being_built = null - - updateUsrDialog() - return 1 - -/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page() - send_byjax(usr,"mecha_fabricator.browser","queue",list_queue()) - return - -/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name) - if(set_name in part_sets) - for(var/datum/design/D in files.known_designs) - if(D.build_type & build_type) - if(set_name in D.category) - add_to_queue(D) - -/obj/machinery/mecha_part_fabricator/proc/add_to_queue(D) - if(!istype(queue)) - queue = list() - if(D) - queue[++queue.len] = D - return queue.len - -/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index) - if(!isnum(index) || !IsInteger(index) || !istype(queue) || (index<1 || index>queue.len)) - return 0 - queue.Cut(index,++index) - return 1 - -/obj/machinery/mecha_part_fabricator/proc/process_queue() - var/datum/design/D = queue[1] - if(!D) - remove_from_queue(1) - if(queue.len) - return process_queue() - else - return - temp = null - while(D) - if(stat&(NOPOWER|BROKEN)) - return 0 - if(!check_resources(D)) - visible_message("[bicon(src)] \The [src] beeps, \"Not enough resources. Queue processing stopped.\"") - temp = {"Not enough resources to build next part.
                    - Try again | Return"} - return 0 - remove_from_queue(1) - build_part(D) - D = listgetindex(queue, 1) - visible_message("[bicon(src)] \The [src] beeps, \"Queue processing finished successfully.\"") - -/obj/machinery/mecha_part_fabricator/proc/list_queue() - var/output = "Queue contains:" - if(!istype(queue) || !queue.len) - output += "
                    Nothing" - else - output += "
                      " - var/i = 0 - for(var/datum/design/D in queue) - i++ - var/obj/part = D.build_path - output += "[initial(part.name)] - [i>1?"":null] [i↓":null] Remove" - - output += "
                    " - output += "\[Process queue | Clear queue\]" - return output - -/obj/machinery/mecha_part_fabricator/proc/update_tech() - if(!files) - return - var/output - for(var/datum/tech/T in files.known_tech) - if(T && T.level > 1) - var/diff - switch(T.id) - if("materials") - //one materials level is 1/32, so that max level is 0.75 coefficient - diff = round(initial(resource_coeff_tech) - (initial(resource_coeff_tech)*(T.level-1))/32,0.01) - if(resource_coeff_tech>diff) - resource_coeff_tech = diff - output+="Production efficiency increased.
                    " - if("programming") - //one materials level is 1/40, so that max level is 0.8 coefficient - diff = round(initial(time_coeff_tech) - (initial(time_coeff_tech)*(T.level-1))/40,0.1) - if(time_coeff_tech>diff) - time_coeff_tech = diff - output+="Production routines updated.
                    " - return output - - -/obj/machinery/mecha_part_fabricator/proc/sync() - temp = "Updating local R&D database..." - updateUsrDialog() - sleep(30) //only sleep if called by user - - for(var/obj/machinery/computer/rdconsole/RDC in oview(7,src)) - if(!RDC.sync) - continue - for(var/datum/tech/T in RDC.files.known_tech) - files.AddTech2Known(T) - for(var/datum/design/D in RDC.files.known_designs) - files.AddDesign2Known(D) - files.RefreshResearch() - temp = "Processed equipment designs.
                    " - //check if the tech coefficients have changed - temp += update_tech() - temp += "Return" - - updateUsrDialog() - visible_message("[bicon(src)] \The [src] beeps, \"Successfully synchronized with R&D server.\"") - return - - temp = "Unable to connect to local R&D Database.
                    Please check your connections and try again.
                    Return" - updateUsrDialog() - return - -/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, resource, roundto = 1) - return round(D.materials[resource]*resource_coeff*resource_coeff_tech, roundto) - -/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(datum/design/D, roundto = 1) //aran - return round(initial(D.construction_time)*time_coeff*time_coeff_tech, roundto) - -/obj/machinery/mecha_part_fabricator/ui_interact(mob/user) - var/dat - var/left_part - - var/turf/exit = get_step(src,(dir)) - if(exit.density) - visible_message("[bicon(src)] \The [src] beeps, \"Error! Part outlet is obstructed.\"") - return - if(temp) - left_part = temp - else if(being_built) - var/obj/I = being_built.build_path - left_part = {"Building [initial(I.name)].
                    - Please wait until completion...
                    "} - else - switch(screen) - if("main") - left_part = output_available_resources()+"
                    " - left_part += "Sync with R&D servers
                    " - for(var/part_set in part_sets) - left_part += "[part_set] - \[Add all parts to queue\]
                    " - if("parts") - left_part += output_parts_list(part_set) - left_part += "
                    Return" - dat = {" - - [name] - - - - - - - - - -
                    - [left_part] - - [list_queue()] -
                    - - "} - user << browse(entity_ja(dat), "window=mecha_fabricator;size=1000x430") - onclose(user, "mecha_fabricator") - -/obj/machinery/mecha_part_fabricator/Topic(href, href_list) - . = ..() - if(!.) - return - - var/datum/topic_input/F = new /datum/topic_input(href,href_list) - if(href_list["part_set"]) - var/tpart_set = F.getStr("part_set") - if(tpart_set) - if(tpart_set=="clear") - part_set = null - else - part_set = tpart_set - screen = "parts" - - if(href_list["part"]) - var/T = F.getStr("part") - for(var/datum/design/D in files.known_designs) - if(D.build_type & build_type) - if(D.id == T) - if(!processing_queue) - build_part(D) - else - add_to_queue(D) - break - - if(href_list["add_to_queue"]) - var/T = F.getStr("add_to_queue") - for(var/datum/design/D in files.known_designs) - if(D.build_type & build_type) - if(D.id == T) - add_to_queue(D) - break - return update_queue_on_page() - - if(href_list["remove_from_queue"]) - remove_from_queue(F.getNum("remove_from_queue")) - return update_queue_on_page() - - if(href_list["partset_to_queue"]) - add_part_set_to_queue(F.get("partset_to_queue")) - return update_queue_on_page() - - if(href_list["process_queue"]) - if(processing_queue || being_built) - return FALSE - processing_queue() - - if(href_list["clear_temp"]) - temp = null - - if(href_list["screen"]) - screen = href_list["screen"] - - if(href_list["queue_move"] && href_list["index"]) - var/index = F.getNum("index") - var/new_index = index + F.getNum("queue_move") - if(isnum(index) && isnum(new_index) && IsInteger(index) && IsInteger(new_index)) - if(IsInRange(new_index,1,queue.len)) - queue.Swap(index,new_index) - return update_queue_on_page() - - if(href_list["clear_queue"]) - queue = list() - return update_queue_on_page() - - if(href_list["sync"]) - sync() - - if(href_list["part_desc"]) - var/T = F.getStr("part_desc") - for(var/datum/design/D in files.known_designs) - if(D.build_type & build_type) - if(D.id == T) - var/obj/part = D.build_path - temp = {"

                    [initial(part.name)] description:

                    - [initial(part.desc)]
                    - Return - "} - break - - if(href_list["remove_mat"] && href_list["material"]) - var/amount = text2num(href_list["remove_mat"]) - var/material = href_list["material"] - if(amount < 0 || amount > resources[material]) //href protection - return FALSE - - var/removed = remove_material(material,amount) - if(removed == -1) - temp = "Not enough [material2name(material)] to produce a sheet." - else - temp = "Ejected [removed] of [material2name(material)]" - temp += "
                    Return" - - updateUsrDialog() - -/obj/machinery/mecha_part_fabricator/proc/processing_queue() - set waitfor = FALSE - - processing_queue = TRUE - process_queue() - processing_queue = FALSE - -/obj/machinery/mecha_part_fabricator/proc/remove_material(mat_string, amount) - if(resources[mat_string] < MINERAL_MATERIAL_AMOUNT) //not enough mineral for a sheet - return -1 - var/type - switch(mat_string) - if(MAT_METAL) - type = /obj/item/stack/sheet/metal - if(MAT_GLASS) - type = /obj/item/stack/sheet/glass - if(MAT_GOLD) - type = /obj/item/stack/sheet/mineral/gold - if(MAT_SILVER) - type = /obj/item/stack/sheet/mineral/silver - if(MAT_DIAMOND) - type = /obj/item/stack/sheet/mineral/diamond - if(MAT_PHORON) - type = /obj/item/stack/sheet/mineral/phoron - if(MAT_URANIUM) - type = /obj/item/stack/sheet/mineral/uranium - else - return 0 - var/result = 0 - - while(amount > 50) - new type(get_turf(src),50) - amount -= 50 - result += 50 - resources[mat_string] -= 50 * MINERAL_MATERIAL_AMOUNT - - var/total_amount = round(resources[mat_string]/MINERAL_MATERIAL_AMOUNT) - if(total_amount)//if there's still enough material for sheets - var/obj/item/stack/sheet/res = new type(get_turf(src),min(amount,total_amount)) - resources[mat_string] -= res.get_amount()*MINERAL_MATERIAL_AMOUNT - result += res.get_amount() - - return result - - -/obj/machinery/mecha_part_fabricator/attackby(obj/W, mob/user, params) - - if(istype(W, /obj/item/weapon/card/emag)) - emag() - return - - if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W)) - return - - if(exchange_parts(user, W)) - return - - if(panel_open) - if(istype(W, /obj/item/weapon/crowbar)) - for(var/material in resources) - remove_material(material, resources[material]/MINERAL_MATERIAL_AMOUNT) - default_deconstruction_crowbar(W) - return 1 - else - to_chat(user, "You can't load \the [name] while it's opened!") - return 1 - - if(istype(W, /obj/item/stack)) - var/material - switch(W.type) - if(/obj/item/stack/sheet/mineral/gold) - material = MAT_GOLD - if(/obj/item/stack/sheet/mineral/silver) - material = MAT_SILVER - if(/obj/item/stack/sheet/mineral/diamond) - material = MAT_DIAMOND - if(/obj/item/stack/sheet/mineral/phoron) - material = MAT_PHORON - if(/obj/item/stack/sheet/metal) - material = MAT_METAL - if(/obj/item/stack/sheet/glass) - material = MAT_GLASS - if(/obj/item/stack/sheet/mineral/uranium) - material = MAT_URANIUM - else - return ..() - - if(being_built) - to_chat(user, "\The [src] is currently processing! Please wait until completion.") - return - if(res_max_amount - resources[material] < MINERAL_MATERIAL_AMOUNT) //overstuffing the fabricator - to_chat(user, "\The [src] [material2name(material)] storage is full!") - return - var/obj/item/stack/sheet/stack = W - var/sname = "[stack.name]" - if(resources[material] < res_max_amount) - overlays += "fab-load-[material2name(material)]"//loading animation is now an overlay based on material type. No more spontaneous conversion of all ores to metal. -vey - - var/transfer_amount = min(stack.get_amount(), round((res_max_amount - resources[material])/MINERAL_MATERIAL_AMOUNT,1)) - resources[material] += transfer_amount * MINERAL_MATERIAL_AMOUNT - stack.use(transfer_amount) - to_chat(user, "You insert [transfer_amount] [sname] sheet\s into \the [src].") - sleep(10) - updateUsrDialog() - overlays -= "fab-load-[material2name(material)]" //No matter what the overlay shall still be deleted - else - to_chat(user, "\The [src] cannot hold any more [sname] sheet\s!") - return - -/obj/machinery/mecha_part_fabricator/proc/material2name(ID) - return copytext(ID,2) +/obj/machinery/mecha_part_fabricator + icon = 'icons/obj/robotics.dmi' + icon_state = "fab-idle" + name = "Exosuit Fabricator" + desc = "Nothing is being built." + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 20 + active_power_usage = 5000 + req_access = list(access_robotics) + allowed_checks = ALLOWED_CHECK_TOPIC + var/time_coeff = 1 + var/time_coeff_tech = 1 + var/resource_coeff = 1 + var/resource_coeff_tech = 1 + var/list/resources = list( + MAT_METAL=0, + MAT_GLASS=0, + MAT_DIAMOND=0, + MAT_GOLD=0, + MAT_PHORON=0, + MAT_SILVER=0, + MAT_URANIUM=0 + ) + var/build_type = MECHFAB + var/res_max_amount = 200000 + var/datum/research/files + var/id + var/sync = 0 + var/part_set + var/datum/design/being_built + var/list/queue = list() + var/processing_queue = 0 + var/screen = "main" + var/temp + var/list/part_sets = list( + "Cyborg", + "Ripley", + "Odysseus", + "Gygax", + "Gygax Ultra", + "Durand", + "Vindicator", + "Exosuit Equipment", + "Cyborg Upgrade Modules", + "Cyborg Components", + "Misc" + ) + +/obj/machinery/mecha_part_fabricator/atom_init() + . = ..() + New_parts() + files = new /datum/research(src) //Setup the research data holder. + +/obj/machinery/mecha_part_fabricator/proc/New_parts() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/mechfab(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/micro_laser(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + RefreshParts() + +/obj/machinery/mecha_part_fabricator/RefreshParts() + var/T = 0 + + //maximum stocking amount (max 412000) + for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) + T += M.rating + res_max_amount = (187000+(T * 37500)) + + //ressources adjustment coefficient (1 -> 0.88 -> 0.75) + T = -1 + for(var/obj/item/weapon/stock_parts/micro_laser/Ma in component_parts) + T += Ma.rating + resource_coeff = round(initial(resource_coeff) - (initial(resource_coeff)*(T))/8,0.01) + + //building time adjustment coefficient (1 -> 0.8 -> 0.6) + T = -1 + for(var/obj/item/weapon/stock_parts/manipulator/Ml in component_parts) + T += Ml.rating + time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01) + +/obj/machinery/mecha_part_fabricator/check_access(obj/item/weapon/card/id/I) + 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 + for(var/req in req_access) + if(!(req in I.access)) //doesn't have this access + return 0 + return 1 + +/obj/machinery/mecha_part_fabricator/proc/emag() + switch(emagged) + if(0) + emagged = 0.5 + visible_message("[bicon(src)] \The [src] beeps: \"DB error \[Code 0x00F1\]\"") + sleep(10) + visible_message("[bicon(src)] \The [src] beeps: \"Attempting auto-repair\"") + sleep(15) + visible_message("[bicon(src)] \The [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"") + sleep(30) + visible_message("[bicon(src)] \The [src] beeps: \"User DB truncated. Please contact your Nanotrasen system operator for future assistance.\"") + req_access = null + emagged = 1 + if(0.5) + visible_message("[bicon(src)] \The [src] beeps: \"DB not responding \[Code 0x0003\]...\"") + if(1) + visible_message("[bicon(src)] \The [src] beeps: \"No records in User DB\"") + return + +/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name) + var/output = "" + for(var/datum/design/D in files.known_designs) + if(D.build_type & build_type) + if(!(set_name in D.category)) + continue + var/resources_available = check_resources(D) + output += "
                    [output_part_info(D)]
                    \[[resources_available?"Build | ":null]Add to queue\]\[?\]
                    " + return output + +/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D) + var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [get_construction_time_w_coeff(D)/10]sec" + return output + +/obj/machinery/mecha_part_fabricator/proc/output_part_cost(datum/design/D) + var/i = 0 + var/output + for(var/c in D.materials) + if(c in resources) + output += "[i?" | ":null][get_resource_cost_w_coeff(D,c)] [material2name(c)]" + i++ + return output + +/obj/machinery/mecha_part_fabricator/proc/output_available_resources() + var/output + for(var/resource in resources) + var/amount = min(res_max_amount, resources[resource]) + output += "[material2name(resource)]: [amount] cm³" + if(amount>0) + output += "- Remove \[1\] | \[10\] | \[All\]" + output += "
                    " + return output + +/obj/machinery/mecha_part_fabricator/proc/remove_resources(datum/design/D) + for(var/resource in D.materials) + if(resource in resources) + resources[resource] -= get_resource_cost_w_coeff(D,resource) + +/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) + for(var/R in D.materials) + if(R in resources) + if(resources[R] < get_resource_cost_w_coeff(D, R)) + return 0 + else + return 0 + return 1 + +/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D) + being_built = D + desc = "It's building \a [initial(D.name)]." + remove_resources(D) + overlays += "fab-active" + use_power = 2 + updateUsrDialog() + sleep(get_construction_time_w_coeff(D)) + use_power = 1 + overlays -= "fab-active" + desc = initial(desc) + + var/location = get_step(src,(dir)) + var/I = new D.build_path(location) + if(istype(I, /obj/item)) + var/obj/item/Item = I + Item.materials[MAT_METAL] = get_resource_cost_w_coeff(D,MAT_METAL) + Item.materials[MAT_GLASS] = get_resource_cost_w_coeff(D,MAT_GLASS) + visible_message("[bicon(src)] \The [src] beeps, \"\The [I] is complete.\"") + being_built = null + + updateUsrDialog() + return 1 + +/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page() + send_byjax(usr,"mecha_fabricator.browser","queue",list_queue()) + return + +/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name) + if(set_name in part_sets) + for(var/datum/design/D in files.known_designs) + if(D.build_type & build_type) + if(set_name in D.category) + add_to_queue(D) + +/obj/machinery/mecha_part_fabricator/proc/add_to_queue(D) + if(!istype(queue)) + queue = list() + if(D) + queue[++queue.len] = D + return queue.len + +/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index) + if(!isnum(index) || !IsInteger(index) || !istype(queue) || (index<1 || index>queue.len)) + return 0 + queue.Cut(index,++index) + return 1 + +/obj/machinery/mecha_part_fabricator/proc/process_queue() + var/datum/design/D = queue[1] + if(!D) + remove_from_queue(1) + if(queue.len) + return process_queue() + else + return + temp = null + while(D) + if(stat&(NOPOWER|BROKEN)) + return 0 + if(!check_resources(D)) + visible_message("[bicon(src)] \The [src] beeps, \"Not enough resources. Queue processing stopped.\"") + temp = {"Not enough resources to build next part.
                    + Try again | Return"} + return 0 + remove_from_queue(1) + build_part(D) + D = listgetindex(queue, 1) + visible_message("[bicon(src)] \The [src] beeps, \"Queue processing finished successfully.\"") + +/obj/machinery/mecha_part_fabricator/proc/list_queue() + var/output = "Queue contains:" + if(!istype(queue) || !queue.len) + output += "
                    Nothing" + else + output += "
                      " + var/i = 0 + for(var/datum/design/D in queue) + i++ + var/obj/part = D.build_path + output += "[initial(part.name)] - [i>1?"":null] [i↓":null] Remove" + + output += "
                    " + output += "\[Process queue | Clear queue\]" + return output + +/obj/machinery/mecha_part_fabricator/proc/update_tech() + if(!files) + return + var/output + for(var/datum/tech/T in files.known_tech) + if(T && T.level > 1) + var/diff + switch(T.id) + if("materials") + //one materials level is 1/32, so that max level is 0.75 coefficient + diff = round(initial(resource_coeff_tech) - (initial(resource_coeff_tech)*(T.level-1))/32,0.01) + if(resource_coeff_tech>diff) + resource_coeff_tech = diff + output+="Production efficiency increased.
                    " + if("programming") + //one materials level is 1/40, so that max level is 0.8 coefficient + diff = round(initial(time_coeff_tech) - (initial(time_coeff_tech)*(T.level-1))/40,0.1) + if(time_coeff_tech>diff) + time_coeff_tech = diff + output+="Production routines updated.
                    " + return output + + +/obj/machinery/mecha_part_fabricator/proc/sync() + temp = "Updating local R&D database..." + updateUsrDialog() + sleep(30) //only sleep if called by user + + for(var/obj/machinery/computer/rdconsole/RDC in oview(7,src)) + if(!RDC.sync) + continue + for(var/datum/tech/T in RDC.files.known_tech) + files.AddTech2Known(T) + for(var/datum/design/D in RDC.files.known_designs) + files.AddDesign2Known(D) + files.RefreshResearch() + temp = "Processed equipment designs.
                    " + //check if the tech coefficients have changed + temp += update_tech() + temp += "Return" + + updateUsrDialog() + visible_message("[bicon(src)] \The [src] beeps, \"Successfully synchronized with R&D server.\"") + return + + temp = "Unable to connect to local R&D Database.
                    Please check your connections and try again.
                    Return" + updateUsrDialog() + return + +/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, resource, roundto = 1) + return round(D.materials[resource]*resource_coeff*resource_coeff_tech, roundto) + +/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(datum/design/D, roundto = 1) //aran + return round(initial(D.construction_time)*time_coeff*time_coeff_tech, roundto) + +/obj/machinery/mecha_part_fabricator/ui_interact(mob/user) + var/dat + var/left_part + + var/turf/exit = get_step(src,(dir)) + if(exit.density) + visible_message("[bicon(src)] \The [src] beeps, \"Error! Part outlet is obstructed.\"") + return + if(temp) + left_part = temp + else if(being_built) + var/obj/I = being_built.build_path + left_part = {"Building [initial(I.name)].
                    + Please wait until completion...
                    "} + else + switch(screen) + if("main") + left_part = output_available_resources()+"
                    " + left_part += "Sync with R&D servers
                    " + for(var/part_set in part_sets) + left_part += "[part_set] - \[Add all parts to queue\]
                    " + if("parts") + left_part += output_parts_list(part_set) + left_part += "
                    Return" + dat = {" + + [name] + + + + + + + + + +
                    + [left_part] + + [list_queue()] +
                    + + "} + user << browse(entity_ja(dat), "window=mecha_fabricator;size=1000x430") + onclose(user, "mecha_fabricator") + +/obj/machinery/mecha_part_fabricator/Topic(href, href_list) + . = ..() + if(!.) + return + + var/datum/topic_input/F = new /datum/topic_input(href,href_list) + if(href_list["part_set"]) + var/tpart_set = F.getStr("part_set") + if(tpart_set) + if(tpart_set=="clear") + part_set = null + else + part_set = tpart_set + screen = "parts" + + if(href_list["part"]) + var/T = F.getStr("part") + for(var/datum/design/D in files.known_designs) + if(D.build_type & build_type) + if(D.id == T) + if(!processing_queue) + build_part(D) + else + add_to_queue(D) + break + + if(href_list["add_to_queue"]) + var/T = F.getStr("add_to_queue") + for(var/datum/design/D in files.known_designs) + if(D.build_type & build_type) + if(D.id == T) + add_to_queue(D) + break + return update_queue_on_page() + + if(href_list["remove_from_queue"]) + remove_from_queue(F.getNum("remove_from_queue")) + return update_queue_on_page() + + if(href_list["partset_to_queue"]) + add_part_set_to_queue(F.get("partset_to_queue")) + return update_queue_on_page() + + if(href_list["process_queue"]) + if(processing_queue || being_built) + return FALSE + processing_queue() + + if(href_list["clear_temp"]) + temp = null + + if(href_list["screen"]) + screen = href_list["screen"] + + if(href_list["queue_move"] && href_list["index"]) + var/index = F.getNum("index") + var/new_index = index + F.getNum("queue_move") + if(isnum(index) && isnum(new_index) && IsInteger(index) && IsInteger(new_index)) + if(IsInRange(new_index,1,queue.len)) + queue.Swap(index,new_index) + return update_queue_on_page() + + if(href_list["clear_queue"]) + queue = list() + return update_queue_on_page() + + if(href_list["sync"]) + sync() + + if(href_list["part_desc"]) + var/T = F.getStr("part_desc") + for(var/datum/design/D in files.known_designs) + if(D.build_type & build_type) + if(D.id == T) + var/obj/part = D.build_path + temp = {"

                    [initial(part.name)] description:

                    + [initial(part.desc)]
                    + Return + "} + break + + if(href_list["remove_mat"] && href_list["material"]) + var/amount = text2num(href_list["remove_mat"]) + var/material = href_list["material"] + if(amount < 0 || amount > resources[material]) //href protection + return FALSE + + var/removed = remove_material(material,amount) + if(removed == -1) + temp = "Not enough [material2name(material)] to produce a sheet." + else + temp = "Ejected [removed] of [material2name(material)]" + temp += "
                    Return" + + updateUsrDialog() + +/obj/machinery/mecha_part_fabricator/proc/processing_queue() + set waitfor = FALSE + + processing_queue = TRUE + process_queue() + processing_queue = FALSE + +/obj/machinery/mecha_part_fabricator/proc/remove_material(mat_string, amount) + if(resources[mat_string] < MINERAL_MATERIAL_AMOUNT) //not enough mineral for a sheet + return -1 + var/type + switch(mat_string) + if(MAT_METAL) + type = /obj/item/stack/sheet/metal + if(MAT_GLASS) + type = /obj/item/stack/sheet/glass + if(MAT_GOLD) + type = /obj/item/stack/sheet/mineral/gold + if(MAT_SILVER) + type = /obj/item/stack/sheet/mineral/silver + if(MAT_DIAMOND) + type = /obj/item/stack/sheet/mineral/diamond + if(MAT_PHORON) + type = /obj/item/stack/sheet/mineral/phoron + if(MAT_URANIUM) + type = /obj/item/stack/sheet/mineral/uranium + else + return 0 + var/result = 0 + + while(amount > 50) + new type(get_turf(src),50) + amount -= 50 + result += 50 + resources[mat_string] -= 50 * MINERAL_MATERIAL_AMOUNT + + var/total_amount = round(resources[mat_string]/MINERAL_MATERIAL_AMOUNT) + if(total_amount)//if there's still enough material for sheets + var/obj/item/stack/sheet/res = new type(get_turf(src),min(amount,total_amount)) + resources[mat_string] -= res.get_amount()*MINERAL_MATERIAL_AMOUNT + result += res.get_amount() + + return result + + +/obj/machinery/mecha_part_fabricator/attackby(obj/W, mob/user, params) + + if(istype(W, /obj/item/weapon/card/emag)) + emag() + return + + if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W)) + return + + if(exchange_parts(user, W)) + return + + if(panel_open) + if(istype(W, /obj/item/weapon/crowbar)) + for(var/material in resources) + remove_material(material, resources[material]/MINERAL_MATERIAL_AMOUNT) + default_deconstruction_crowbar(W) + return 1 + else + to_chat(user, "You can't load \the [name] while it's opened!") + return 1 + + if(istype(W, /obj/item/stack)) + var/material + switch(W.type) + if(/obj/item/stack/sheet/mineral/gold) + material = MAT_GOLD + if(/obj/item/stack/sheet/mineral/silver) + material = MAT_SILVER + if(/obj/item/stack/sheet/mineral/diamond) + material = MAT_DIAMOND + if(/obj/item/stack/sheet/mineral/phoron) + material = MAT_PHORON + if(/obj/item/stack/sheet/metal) + material = MAT_METAL + if(/obj/item/stack/sheet/glass) + material = MAT_GLASS + if(/obj/item/stack/sheet/mineral/uranium) + material = MAT_URANIUM + else + return ..() + + if(being_built) + to_chat(user, "\The [src] is currently processing! Please wait until completion.") + return + if(res_max_amount - resources[material] < MINERAL_MATERIAL_AMOUNT) //overstuffing the fabricator + to_chat(user, "\The [src] [material2name(material)] storage is full!") + return + var/obj/item/stack/sheet/stack = W + var/sname = "[stack.name]" + if(resources[material] < res_max_amount) + overlays += "fab-load-[material2name(material)]"//loading animation is now an overlay based on material type. No more spontaneous conversion of all ores to metal. -vey + + var/transfer_amount = min(stack.get_amount(), round((res_max_amount - resources[material])/MINERAL_MATERIAL_AMOUNT,1)) + resources[material] += transfer_amount * MINERAL_MATERIAL_AMOUNT + stack.use(transfer_amount) + to_chat(user, "You insert [transfer_amount] [sname] sheet\s into \the [src].") + sleep(10) + updateUsrDialog() + overlays -= "fab-load-[material2name(material)]" //No matter what the overlay shall still be deleted + else + to_chat(user, "\The [src] cannot hold any more [sname] sheet\s!") + return + +/obj/machinery/mecha_part_fabricator/proc/material2name(ID) + return copytext(ID,2) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index b7eef82f4b57..4f3b0f7fdad3 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -1,1847 +1,1847 @@ -#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 - - -/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/stock_parts/cell/cell - var/state = 0 - 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 - var/last_user_hud = 1 // used to show/hide the mecha hud while preserving previous preference - - //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/components/unary/portables_connector/connected_port = null - - var/obj/item/device/radio/radio = 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_give_air //moves air from tank to cabin - var/datum/global_iterator/pr_internal_damage //processes internal damage - var/datum/global_iterator/pr_mecha_light // processing mecha lights - - - var/wreckage - - var/list/equipment = new - var/obj/item/mecha_parts/mecha_equipment/selected - var/max_equip = 3 - var/datum/events/events - -/obj/mecha/atom_init() - . = ..() - 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() - poi_list += src - add_iterators() - removeVerb(/obj/mecha/verb/disconnect_from_port) - log_message("[src.name] created.") - loc.Entered(src) - mechas_list += src //global mech list - -/obj/mecha/Destroy() - poi_list -= src - go_out() - poi_list.Remove(src) - for(var/mob/M in src) - M.loc = get_turf(src) - M.loc.Entered(M) - step_rand(M) - 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(obj/item/weapon/stock_parts/cell/C=null) - if(C) - C.forceMove(src) - cell = C - return - cell = new(src) - cell.name = "high-capacity power cell" - cell.charge = 15000 - cell.maxcharge = 15000 - -/obj/mecha/proc/add_cabin() - cabin_air = new - cabin_air.temperature = T20C - cabin_air.volume = 200 - cabin_air.adjust_multi("oxygen", O2STANDARD * cabin_air.volume / (R_IDEAL_GAS_EQUATION * cabin_air.temperature), "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 - -/obj/mecha/proc/add_iterators() - pr_int_temp_processor = new /datum/global_iterator/mecha_preserve_temp(list(src)) - 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) - pr_mecha_light = new /datum/global_iterator/mecha_light(list(src)) - -/obj/mecha/proc/do_after(delay) - sleep(delay) - if(src) - return 1 - return 0 - -/obj/mecha/proc/enter_after(delay, mob/user, numticks = 5) - var/delayfraction = delay/numticks - - var/turf/T = user.loc - - for(var/i = 0, iMaintenance 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(!target.Adjacent(src)) - 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(atom/newLoc, direct) - . = ..() - if(.) - events.fireEvent("onMove",get_turf(src)) - -/obj/mecha/Process_Spacemove(movement_dir = 0) - if(occupant) - return occupant.Process_Spacemove(movement_dir) //We'll just say you used the clamp to grab the wall - 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(!Process_Spacemove(direction)) - 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 - if(do_after(step_in)) - can_move = 1 - return 1 - return 0 - -/obj/mecha/proc/mechturn(direction) - dir = direction - use_power(step_energy_drain) - playsound(src,'sound/mecha/Mech_Rotation.ogg',40,1) - return 1 - -/obj/mecha/proc/mechstep(direction) - var/result = step(src,direction) - if(result) - playsound(src,'sound/mecha/Mech_Step.ogg',40,1) - use_power(step_energy_drain) - return result - - -/obj/mecha/proc/mechsteprand() - var/result = step_rand(src) - if(result) - playsound(src,'sound/mecha/Mech_Step.ogg',40,1) - use_power(step_energy_drain) - return result - -/obj/mecha/Bump(var/atom/obstacle, non_native_bump) - if(non_native_bump) - if(throwing) - ..() - return - if(istype(obstacle, /obj/machinery/disposal/deliveryChute/)) - return - obstacle.Bumped(src) - if(istype(obstacle, /obj)) - var/obj/O = obstacle - if(!O.anchored) - step(obstacle, dir) - else if(istype(obstacle, /mob)) - step(obstacle, dir) - -/////////////////////////////////// -//////// Internal damage //////// -/////////////////////////////////// - -/obj/mecha/proc/check_for_internal_damage(list/possible_int_damage,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) - src.log_message("Attack by hand/paw. Attacker - [user].",1) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - - if ((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) - return src.attack_hand(user) - - -/obj/mecha/attack_alien(mob/user) - src.log_message("Attack by alien. Attacker - [user].",1) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - 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(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) - to_chat(user, "\red You slash at the armored suit!") - visible_message("\red The [user] slashes at [src.name]'s armor!") - else - src.log_append_to_last("Armor saved.") - playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) - to_chat(user, "\green Your claws had no effect!") - src.occupant_message("\blue The [user]'s claws are stopped by the armor.") - visible_message("\blue The [user] rebounds off [src.name]'s armor!") - return - - -/obj/mecha/attack_animal(mob/living/simple_animal/user) - 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("\red [user] [user.attacktext] [src]!") - user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") - else - src.log_append_to_last("Armor saved.") - playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) - src.occupant_message("\blue The [user]'s attack is stopped by the armor.") - visible_message("\blue The [user] rebounds off [src.name]'s armor!") - user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") - return - -/obj/mecha/hitby(atom/movable/A) //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)) - A.forceMove(src) - src.visible_message("The [A] fastens firmly to [src].") - return - if(prob(src.deflect_chance) || istype(A, /mob)) - src.occupant_message("\blue 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_bodypart_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(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(obj/item/projectile/Proj) - if(prob(src.deflect_chance)) - src.occupant_message("\blue 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(is_type_in_list(Proj, taser_projectiles)) //taser_projectiles defined in projectile.dm - 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() - go_out() - var/turf/T = get_turf(src) - if(wreckage) - var/obj/effect/decal/mecha_wreckage/WR = new wreckage(T) - WR.reliability = rand(33) + 15 - for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) - WR.salvage["crowbar"] += E.type - if(cell) - WR.salvage["crowbar"] += cell.type - qdel(cell) - if(internal_tank) - WR.salvage["crowbar"] += internal_tank.type - qdel(internal_tank) - for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) - qdel(E) - if(prob(60)) - explosion(T, 0, 0, 1, 3) - qdel(src) - - -/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) - destroy() - if(2.0) - if (prob(30)) - 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)) - 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(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1) - to_chat(user, "\red You smash at the armored suit!") - for (var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("\red The [user] smashes against [src.name]'s armor!", 1) - else - src.log_append_to_last("Armor saved.") - playsound(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1) - to_chat(user, "\green Your attack had no effect!") - src.occupant_message("\blue The [user]'s attack is stopped by the armor.") - for (var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("\blue The [user] rebounds off the [src.name] armor!", 1) - return -*/ - - -/obj/mecha/blob_act() - take_damage(10, "brute") - return - -//TODO -/obj/mecha/meteorhit() - return ex_act(rand(1,3))//should do for now - -/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, mob/user) - user.do_attack_animation(src) - src.log_message("Attacked by [W]. Attacker - [user]") - if(prob(src.deflect_chance)) - to_chat(user, "\red \The [W] bounces off [src.name].") - 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, mob/user) - - 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)) - user.drop_item() - E.attach(src) - user.visible_message("[user] attaches [W] to [src]", "You attach [W] to [src]") - 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, "\red Invalid ID: Access denied.") - else - to_chat(user, "\red Maintenance protocols disabled by operator.") - else if(istype(W, /obj/item/weapon/wrench)) - if(state==1) - state = 2 - to_chat(user, "You undo the securing bolts.") - else if(state==2) - state = 1 - to_chat(user, "You tighten the securing bolts.") - return - else if(istype(W, /obj/item/weapon/crowbar)) - if(state==2) - state = 3 - to_chat(user, "You open the hatch to the power unit") - else if(state==3) - state=2 - to_chat(user, "You close the hatch to the power unit") - return - else if(istype(W, /obj/item/stack/cable_coil)) - if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) - var/obj/item/stack/cable_coil/CC = W - if(!CC.use(2)) - to_chat(user, "There's not enough wire to finish the task.") - return - clearInternalDamage(MECHA_INT_SHORT_CIRCUIT) - to_chat(user, "You replace the fused wires.") - 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.") - else if(state==3 && src.cell) - src.cell.forceMove(src.loc) - src.cell = null - state = 4 - to_chat(user, "You unscrew and pry out the powercell.") - src.log_message("Powercell removed") - else if(state==4 && src.cell) - state=3 - to_chat(user, "You screw the cell in place") - return - - else if(istype(W, /obj/item/weapon/stock_parts/cell)) - if(state==4) - if(!src.cell) - to_chat(user, "You install the powercell") - user.drop_item() - W.forceMove(src) - 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/weapon/weldingtool) && user.a_intent != "hurt") - var/obj/item/weapon/weldingtool/WT = W - user.SetNextMove(CLICK_CD_MELEE) - if (WT.remove_fuel(0,user)) - if (hasInternalDamage(MECHA_INT_TANK_BREACH)) - clearInternalDamage(MECHA_INT_TANK_BREACH) - to_chat(user, "\blue You repair the damaged gas tank.") - else - return - if(src.health[user] has punched \the [src]!") - playsound(loc, 'sound/effects/grillehit.ogg', 50, 1) - if(prob(50) && Ham.use_charge(user,6)) - take_damage(Ham.force * 3) - else - user.SetNextMove(CLICK_CD_MELEE) - call((proc_res["dynattackby"]||src), "dynattackby")(W,user) -/* - src.log_message("Attacked by [W]. Attacker - [user]") - if(prob(src.deflect_chance)) - to_chat(user, "\red 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(mob/living/silicon/ai/user) - 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.temperature - else - var/datum/gas_mixture/t_air = get_turf_air() - if(t_air) - . = t_air.temperature - return - -/obj/mecha/proc/connect(obj/machinery/atmospherics/components/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/pipeline/P = connected_port.returnPipenet(src) - if(P && !(internal_tank.return_air() in P.other_airs)) - P.other_airs += internal_tank.return_air() - P.update = 1 - log_message("Connected to gas port.") - return 1 - -/obj/mecha/proc/disconnect() - if(!connected_port) - return 0 - - var/datum/pipeline/P = connected_port.returnPipenet(src) - if(P) - P.other_airs -= 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/components/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/components/unary/portables_connector/) in loc - if(possible_port) - if(connect(possible_port)) - src.occupant_message("\blue [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("\red [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("\blue [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("\red [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 - if(!has_charge(lights_power)) - return - lights = !lights - if(lights) set_light(light_range + lights_power) - else set_light(light_range - 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/verb/move_inside() - set category = "Object" - set name = "Enter Exosuit" - set src in oview(1) - - if (usr.stat || !ishuman(usr)) - return - if (usr.buckled) - to_chat(usr,"You can't climb into the exosuit while buckled!") - return - src.log_message("[usr] tries to move in.") - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - if(C.handcuffed) - to_chat(usr, "\red Kinda hard to climb in while handcuffed don't you think?") - return - if (src.occupant) - to_chat(usr, "\blue The [src.name] is already occupied!") - src.log_append_to_last("Permission denied.") - return -/* - if (usr.abiotic()) - to_chat(usr, "\blue 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, "\red 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 -// usr << "You start climbing into [src.name]" - - visible_message("\blue [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(mob/living/carbon/human/H) - if(H && H.client && H in range(1)) - H.reset_view(src) - H.forceMove(src) - if(H.hud_used) - last_user_hud = H.hud_used.hud_shown - H.hud_used.show_hud(HUD_STYLE_REDUCED) - - src.occupant = H - src.add_fingerprint(H) - src.forceMove(src.loc) - src.log_append_to_last("[H] moved in as pilot.") - log_admin("[key_name(H)] has moved in [src.type] with name [src.name]") - src.icon_state = src.reset_icon() - dir = dir_in - playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) - if(!hasInternalDamage()) - src.occupant << sound('sound/mecha/nominal.ogg',volume = 50) - return 1 - else - return 0 - -/obj/mecha/proc/mmi_move_inside(obj/item/device/mmi/mmi_as_oc,mob/user) - 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 -// user << "Installing MMI, please stand by." - - visible_message("\blue [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(obj/item/device/mmi/mmi_as_oc,mob/user) - if(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.") - log_admin("[key_name(mmi_as_oc)] has moved in [src.type] with name [src.name] as MMI brain by [key_name(user)]") - if(!hasInternalDamage()) - src.occupant << sound('sound/mecha/nominal.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(entity_ja(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/container_resist() - go_out() - -/obj/mecha/proc/go_out() - 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(src.loc))//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.") - log_admin("[key_name(mob_container)] has moved out of [src.type] with name [src.name]") - occupant.reset_view() - /* - if(src.occupant.client) - src.occupant.client.eye = src.occupant.client.mob - src.occupant.client.perspective = MOB_PERSPECTIVE - */ - src.occupant << browse(null, "window=exosuit") - if(src.occupant.hud_used && src.last_user_hud) - src.occupant.hud_used.show_hud(HUD_STYLE_STANDARD) - - 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 - src.occupant = null - src.icon_state = src.reset_icon()+"-open" - src.dir = dir_in - return - -///////////////////////// -////// 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, /obj/item/weapon/storage/wallet)) - var/obj/item/weapon/storage/wallet/wallet = I - I = wallet.GetID() - 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
                    -
                    " - 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
                    " - output += "
                    Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.)" - output += "" - user << browse(entity_ja(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?"Initiate maintenance protocol":null] - [(state>0) ?"Set Cabin Air Pressure":null] - - "} - user << browse(entity_ja(output), "window=exosuit_maint_console") - onclose(user, "exosuit_maint_console") - return - - -//////////////////////////////// -/////// Messages and Log /////// -//////////////////////////////// - -/obj/mecha/proc/occupant_message(message) - if(message) - if(src.occupant && src.occupant.client) - to_chat(src.occupant, "[bicon(src)] [message]") - return - -/obj/mecha/proc/log_message(message,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,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"]) - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) - return - if(usr.stat > 0) - return - var/datum/topic_input/F = new /datum/topic_input(href,href_list) - if(href_list["select_equip"]) - if(usr != src.occupant) return - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) - var/obj/item/mecha_parts/mecha_equipment/equip = F.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 - playsound(src,'sound/mecha/ROBOTIC_Servo_Large_Dual_Servos_Open_mono.ogg',100,1) - src.eject() - return - if(href_list["toggle_lights"]) - if(usr != src.occupant) return - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel= 4, volume = 100) - src.toggle_lights() - return - if(href_list["toggle_airtank"]) - if(usr != src.occupant) return - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) - src.toggle_internal_tank() - return - if(href_list["rmictoggle"]) - if(usr != src.occupant) return - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) - 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 - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) - 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 - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) - var/new_frequency = (radio.frequency + F.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 - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) - src.disconnect_from_port() - return - if (href_list["port_connect"]) - if(usr != src.occupant) return - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) - src.connect_to_port() - return - if (href_list["view_log"]) - if(usr != src.occupant) return - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) - src.occupant << browse(entity_ja(src.get_log_html()), "window=exosuit_log") - onclose(occupant, "exosuit_log") - return - if (href_list["change_name"]) - if(usr != src.occupant) return - var/newname = sanitize_safe(input(occupant,"Choose new exosuit name","Rename exosuit",initial(name)) as text, MAX_NAME_LEN) - if(newname) - usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_22_stereo_complite.ogg',channel = 4, volume=100) - name = newname - else - usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_15_stereo_error.ogg',channel = 4, volume = 100) - 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(F.getObj("id_card"),F.getMob("user")) - return - if(href_list["maint_access"] && maint_access) - if(!in_range(src, usr)) return - var/mob/user = F.getMob("user") - if(user) - if(state==0) - state = 1 - to_chat(user, "The securing bolts are now exposed.") - else if(state==1) - state = 0 - to_chat(user, "The securing bolts are now hidden.") - output_maintenance_dialog(F.getObj("id_card"),user) - return - if(href_list["set_internal_tank_valve"] && state >=1) - if(!in_range(src, usr)) return - var/mob/user = F.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 && F.getObj("id_card")) - if(!in_range(src, usr)) return - operation_req_access += F.getNum("add_req_access") - output_access_dialog(F.getObj("id_card"),F.getMob("user")) - return - if(href_list["del_req_access"] && add_req_access && F.getObj("id_card")) - if(!in_range(src, usr)) return - operation_req_access -= F.getNum("del_req_access") - output_access_dialog(F.getObj("id_card"),F.getMob("user")) - return - if(href_list["finish_req_access"]) - if(!in_range(src, usr)) return - add_req_access = 0 - var/mob/user = F.getMob("user") - user << browse(null,"window=exosuit_add_access") - user << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_22_stereo_complite.ogg',channel = 4, volume = 100) - return - if(href_list["dna_lock"]) - if(usr != src.occupant) return - if(istype(occupant, /mob/living/carbon/brain)) - occupant_message("You are a brain. No.") - usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_15_stereo_error.ogg',channel = 4, volume= 100) - return - if(src.occupant) - src.dna = src.occupant.dna.unique_enzymes - src.occupant_message("You feel a prick as the needle takes your DNA sample.") - usr << sound('sound/mecha/UI_SCI-FI_Compute_01_Wet_stereo.ogg',channel = 4, volume = 100) - return - if(href_list["reset_dna"]) - if(usr != src.occupant) return - usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume=100) - 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.") - usr << sound('sound/mecha/UI_SCI-FI_Compute_01_Wet_stereo.ogg',channel = 4, volume = 100) - var/T = src.loc - if(do_after(100)) - if(T == src.loc) - src.clearInternalDamage(MECHA_INT_CONTROL_LOST) - usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_22_stereo_complite.ogg',channel = 4, volume = 100) - src.occupant_message("Recalibration successful.") - src.log_message("Recalibration of coordination system finished with 0 errors.") - else - usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_15_stereo_error.ogg',channel = 4, volume = 100) - 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(F.getNum("set_i_dam")) - if(href_list["clear_i_dam"]) - clearInternalDamage(F.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() - qdel(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.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.temperature > 0) - transfer_moles = pressure_delta * cabin_air.volume / (cabin_air.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.volume/(cabin_air.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) - else - return 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.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.volume>0) - mecha.cabin_air.temperature = min(6000 + T0C, mecha.cabin_air.temperature+rand(10, 15)) - if(mecha.cabin_air.temperature > mecha.max_temperature / 2) - mecha.take_damage(4 / round(mecha.max_temperature / mecha.cabin_air.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) - 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 - -/datum/global_iterator/mecha_light - - process(var/obj/mecha/mecha) - if(!mecha.lights) - return - if(mecha.has_charge(mecha.lights_power)) - mecha.use_power(mecha.lights_power) - else - mecha.lights = 0 - mecha.set_light(mecha.light_range - mecha.lights_power) - 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 -*/ +#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 + + +/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/stock_parts/cell/cell + var/state = 0 + 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 + var/last_user_hud = 1 // used to show/hide the mecha hud while preserving previous preference + + //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/components/unary/portables_connector/connected_port = null + + var/obj/item/device/radio/radio = 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_give_air //moves air from tank to cabin + var/datum/global_iterator/pr_internal_damage //processes internal damage + var/datum/global_iterator/pr_mecha_light // processing mecha lights + + + var/wreckage + + var/list/equipment = new + var/obj/item/mecha_parts/mecha_equipment/selected + var/max_equip = 3 + var/datum/events/events + +/obj/mecha/atom_init() + . = ..() + 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() + poi_list += src + add_iterators() + removeVerb(/obj/mecha/verb/disconnect_from_port) + log_message("[src.name] created.") + loc.Entered(src) + mechas_list += src //global mech list + +/obj/mecha/Destroy() + poi_list -= src + go_out() + poi_list.Remove(src) + for(var/mob/M in src) + M.loc = get_turf(src) + M.loc.Entered(M) + step_rand(M) + 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(obj/item/weapon/stock_parts/cell/C=null) + if(C) + C.forceMove(src) + cell = C + return + cell = new(src) + cell.name = "high-capacity power cell" + cell.charge = 15000 + cell.maxcharge = 15000 + +/obj/mecha/proc/add_cabin() + cabin_air = new + cabin_air.temperature = T20C + cabin_air.volume = 200 + cabin_air.adjust_multi("oxygen", O2STANDARD * cabin_air.volume / (R_IDEAL_GAS_EQUATION * cabin_air.temperature), "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 + +/obj/mecha/proc/add_iterators() + pr_int_temp_processor = new /datum/global_iterator/mecha_preserve_temp(list(src)) + 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) + pr_mecha_light = new /datum/global_iterator/mecha_light(list(src)) + +/obj/mecha/proc/do_after(delay) + sleep(delay) + if(src) + return 1 + return 0 + +/obj/mecha/proc/enter_after(delay, mob/user, numticks = 5) + var/delayfraction = delay/numticks + + var/turf/T = user.loc + + for(var/i = 0, iMaintenance 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(!target.Adjacent(src)) + 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(atom/newLoc, direct) + . = ..() + if(.) + events.fireEvent("onMove",get_turf(src)) + +/obj/mecha/Process_Spacemove(movement_dir = 0) + if(occupant) + return occupant.Process_Spacemove(movement_dir) //We'll just say you used the clamp to grab the wall + 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(!Process_Spacemove(direction)) + 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 + if(do_after(step_in)) + can_move = 1 + return 1 + return 0 + +/obj/mecha/proc/mechturn(direction) + dir = direction + use_power(step_energy_drain) + playsound(src,'sound/mecha/Mech_Rotation.ogg',40,1) + return 1 + +/obj/mecha/proc/mechstep(direction) + var/result = step(src,direction) + if(result) + playsound(src,'sound/mecha/Mech_Step.ogg',40,1) + use_power(step_energy_drain) + return result + + +/obj/mecha/proc/mechsteprand() + var/result = step_rand(src) + if(result) + playsound(src,'sound/mecha/Mech_Step.ogg',40,1) + use_power(step_energy_drain) + return result + +/obj/mecha/Bump(var/atom/obstacle, non_native_bump) + if(non_native_bump) + if(throwing) + ..() + return + if(istype(obstacle, /obj/machinery/disposal/deliveryChute/)) + return + obstacle.Bumped(src) + if(istype(obstacle, /obj)) + var/obj/O = obstacle + if(!O.anchored) + step(obstacle, dir) + else if(istype(obstacle, /mob)) + step(obstacle, dir) + +/////////////////////////////////// +//////// Internal damage //////// +/////////////////////////////////// + +/obj/mecha/proc/check_for_internal_damage(list/possible_int_damage,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) + src.log_message("Attack by hand/paw. Attacker - [user].",1) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + + if ((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) + return src.attack_hand(user) + + +/obj/mecha/attack_alien(mob/user) + src.log_message("Attack by alien. Attacker - [user].",1) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + 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(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) + to_chat(user, "\red You slash at the armored suit!") + visible_message("\red The [user] slashes at [src.name]'s armor!") + else + src.log_append_to_last("Armor saved.") + playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) + to_chat(user, "\green Your claws had no effect!") + src.occupant_message("\blue The [user]'s claws are stopped by the armor.") + visible_message("\blue The [user] rebounds off [src.name]'s armor!") + return + + +/obj/mecha/attack_animal(mob/living/simple_animal/user) + 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("\red [user] [user.attacktext] [src]!") + user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + else + src.log_append_to_last("Armor saved.") + playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) + src.occupant_message("\blue The [user]'s attack is stopped by the armor.") + visible_message("\blue The [user] rebounds off [src.name]'s armor!") + user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + return + +/obj/mecha/hitby(atom/movable/A) //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)) + A.forceMove(src) + src.visible_message("The [A] fastens firmly to [src].") + return + if(prob(src.deflect_chance) || istype(A, /mob)) + src.occupant_message("\blue 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_bodypart_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(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(obj/item/projectile/Proj) + if(prob(src.deflect_chance)) + src.occupant_message("\blue 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(is_type_in_list(Proj, taser_projectiles)) //taser_projectiles defined in projectile.dm + 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() + go_out() + var/turf/T = get_turf(src) + if(wreckage) + var/obj/effect/decal/mecha_wreckage/WR = new wreckage(T) + WR.reliability = rand(33) + 15 + for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) + WR.salvage["crowbar"] += E.type + if(cell) + WR.salvage["crowbar"] += cell.type + qdel(cell) + if(internal_tank) + WR.salvage["crowbar"] += internal_tank.type + qdel(internal_tank) + for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) + qdel(E) + if(prob(60)) + explosion(T, 0, 0, 1, 3) + qdel(src) + + +/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) + destroy() + if(2.0) + if (prob(30)) + 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)) + 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(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1) + to_chat(user, "\red You smash at the armored suit!") + for (var/mob/V in viewers(src)) + if(V.client && !(V.blinded)) + V.show_message("\red The [user] smashes against [src.name]'s armor!", 1) + else + src.log_append_to_last("Armor saved.") + playsound(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1) + to_chat(user, "\green Your attack had no effect!") + src.occupant_message("\blue The [user]'s attack is stopped by the armor.") + for (var/mob/V in viewers(src)) + if(V.client && !(V.blinded)) + V.show_message("\blue The [user] rebounds off the [src.name] armor!", 1) + return +*/ + + +/obj/mecha/blob_act() + take_damage(10, "brute") + return + +//TODO +/obj/mecha/meteorhit() + return ex_act(rand(1,3))//should do for now + +/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, mob/user) + user.do_attack_animation(src) + src.log_message("Attacked by [W]. Attacker - [user]") + if(prob(src.deflect_chance)) + to_chat(user, "\red \The [W] bounces off [src.name].") + 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, mob/user) + + 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)) + user.drop_item() + E.attach(src) + user.visible_message("[user] attaches [W] to [src]", "You attach [W] to [src]") + 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, "\red Invalid ID: Access denied.") + else + to_chat(user, "\red Maintenance protocols disabled by operator.") + else if(istype(W, /obj/item/weapon/wrench)) + if(state==1) + state = 2 + to_chat(user, "You undo the securing bolts.") + else if(state==2) + state = 1 + to_chat(user, "You tighten the securing bolts.") + return + else if(istype(W, /obj/item/weapon/crowbar)) + if(state==2) + state = 3 + to_chat(user, "You open the hatch to the power unit") + else if(state==3) + state=2 + to_chat(user, "You close the hatch to the power unit") + return + else if(istype(W, /obj/item/stack/cable_coil)) + if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) + var/obj/item/stack/cable_coil/CC = W + if(!CC.use(2)) + to_chat(user, "There's not enough wire to finish the task.") + return + clearInternalDamage(MECHA_INT_SHORT_CIRCUIT) + to_chat(user, "You replace the fused wires.") + 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.") + else if(state==3 && src.cell) + src.cell.forceMove(src.loc) + src.cell = null + state = 4 + to_chat(user, "You unscrew and pry out the powercell.") + src.log_message("Powercell removed") + else if(state==4 && src.cell) + state=3 + to_chat(user, "You screw the cell in place") + return + + else if(istype(W, /obj/item/weapon/stock_parts/cell)) + if(state==4) + if(!src.cell) + to_chat(user, "You install the powercell") + user.drop_item() + W.forceMove(src) + 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/weapon/weldingtool) && user.a_intent != "hurt") + var/obj/item/weapon/weldingtool/WT = W + user.SetNextMove(CLICK_CD_MELEE) + if (WT.remove_fuel(0,user)) + if (hasInternalDamage(MECHA_INT_TANK_BREACH)) + clearInternalDamage(MECHA_INT_TANK_BREACH) + to_chat(user, "\blue You repair the damaged gas tank.") + else + return + if(src.health[user] has punched \the [src]!") + playsound(loc, 'sound/effects/grillehit.ogg', 50, 1) + if(prob(50) && Ham.use_charge(user,6)) + take_damage(Ham.force * 3) + else + user.SetNextMove(CLICK_CD_MELEE) + call((proc_res["dynattackby"]||src), "dynattackby")(W,user) +/* + src.log_message("Attacked by [W]. Attacker - [user]") + if(prob(src.deflect_chance)) + to_chat(user, "\red 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(mob/living/silicon/ai/user) + 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.temperature + else + var/datum/gas_mixture/t_air = get_turf_air() + if(t_air) + . = t_air.temperature + return + +/obj/mecha/proc/connect(obj/machinery/atmospherics/components/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/pipeline/P = connected_port.returnPipenet(src) + if(P && !(internal_tank.return_air() in P.other_airs)) + P.other_airs += internal_tank.return_air() + P.update = 1 + log_message("Connected to gas port.") + return 1 + +/obj/mecha/proc/disconnect() + if(!connected_port) + return 0 + + var/datum/pipeline/P = connected_port.returnPipenet(src) + if(P) + P.other_airs -= 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/components/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/components/unary/portables_connector/) in loc + if(possible_port) + if(connect(possible_port)) + src.occupant_message("\blue [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("\red [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("\blue [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("\red [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 + if(!has_charge(lights_power)) + return + lights = !lights + if(lights) set_light(light_range + lights_power) + else set_light(light_range - 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/verb/move_inside() + set category = "Object" + set name = "Enter Exosuit" + set src in oview(1) + + if (usr.stat || !ishuman(usr)) + return + if (usr.buckled) + to_chat(usr,"You can't climb into the exosuit while buckled!") + return + src.log_message("[usr] tries to move in.") + if(iscarbon(usr)) + var/mob/living/carbon/C = usr + if(C.handcuffed) + to_chat(usr, "\red Kinda hard to climb in while handcuffed don't you think?") + return + if (src.occupant) + to_chat(usr, "\blue The [src.name] is already occupied!") + src.log_append_to_last("Permission denied.") + return +/* + if (usr.abiotic()) + to_chat(usr, "\blue 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, "\red 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 +// usr << "You start climbing into [src.name]" + + visible_message("\blue [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(mob/living/carbon/human/H) + if(H && H.client && H in range(1)) + H.reset_view(src) + H.forceMove(src) + if(H.hud_used) + last_user_hud = H.hud_used.hud_shown + H.hud_used.show_hud(HUD_STYLE_REDUCED) + + src.occupant = H + src.add_fingerprint(H) + src.forceMove(src.loc) + src.log_append_to_last("[H] moved in as pilot.") + log_admin("[key_name(H)] has moved in [src.type] with name [src.name]") + src.icon_state = src.reset_icon() + dir = dir_in + playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) + if(!hasInternalDamage()) + src.occupant << sound('sound/mecha/nominal.ogg',volume = 50) + return 1 + else + return 0 + +/obj/mecha/proc/mmi_move_inside(obj/item/device/mmi/mmi_as_oc,mob/user) + 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 +// user << "Installing MMI, please stand by." + + visible_message("\blue [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(obj/item/device/mmi/mmi_as_oc,mob/user) + if(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.") + log_admin("[key_name(mmi_as_oc)] has moved in [src.type] with name [src.name] as MMI brain by [key_name(user)]") + if(!hasInternalDamage()) + src.occupant << sound('sound/mecha/nominal.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(entity_ja(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/container_resist() + go_out() + +/obj/mecha/proc/go_out() + 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(src.loc))//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.") + log_admin("[key_name(mob_container)] has moved out of [src.type] with name [src.name]") + occupant.reset_view() + /* + if(src.occupant.client) + src.occupant.client.eye = src.occupant.client.mob + src.occupant.client.perspective = MOB_PERSPECTIVE + */ + src.occupant << browse(null, "window=exosuit") + if(src.occupant.hud_used && src.last_user_hud) + src.occupant.hud_used.show_hud(HUD_STYLE_STANDARD) + + 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 + src.occupant = null + src.icon_state = src.reset_icon()+"-open" + src.dir = dir_in + return + +///////////////////////// +////// 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, /obj/item/weapon/storage/wallet)) + var/obj/item/weapon/storage/wallet/wallet = I + I = wallet.GetID() + 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
                    +
                    " + 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
                    " + output += "
                    Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.)" + output += "" + user << browse(entity_ja(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?"Initiate maintenance protocol":null] + [(state>0) ?"Set Cabin Air Pressure":null] + + "} + user << browse(entity_ja(output), "window=exosuit_maint_console") + onclose(user, "exosuit_maint_console") + return + + +//////////////////////////////// +/////// Messages and Log /////// +//////////////////////////////// + +/obj/mecha/proc/occupant_message(message) + if(message) + if(src.occupant && src.occupant.client) + to_chat(src.occupant, "[bicon(src)] [message]") + return + +/obj/mecha/proc/log_message(message,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,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"]) + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) + return + if(usr.stat > 0) + return + var/datum/topic_input/F = new /datum/topic_input(href,href_list) + if(href_list["select_equip"]) + if(usr != src.occupant) return + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) + var/obj/item/mecha_parts/mecha_equipment/equip = F.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 + playsound(src,'sound/mecha/ROBOTIC_Servo_Large_Dual_Servos_Open_mono.ogg',100,1) + src.eject() + return + if(href_list["toggle_lights"]) + if(usr != src.occupant) return + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel= 4, volume = 100) + src.toggle_lights() + return + if(href_list["toggle_airtank"]) + if(usr != src.occupant) return + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) + src.toggle_internal_tank() + return + if(href_list["rmictoggle"]) + if(usr != src.occupant) return + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) + 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 + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) + 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 + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) + var/new_frequency = (radio.frequency + F.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 + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) + src.disconnect_from_port() + return + if (href_list["port_connect"]) + if(usr != src.occupant) return + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) + src.connect_to_port() + return + if (href_list["view_log"]) + if(usr != src.occupant) return + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume = 100) + src.occupant << browse(entity_ja(src.get_log_html()), "window=exosuit_log") + onclose(occupant, "exosuit_log") + return + if (href_list["change_name"]) + if(usr != src.occupant) return + var/newname = sanitize_safe(input(occupant,"Choose new exosuit name","Rename exosuit",initial(name)) as text, MAX_NAME_LEN) + if(newname) + usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_22_stereo_complite.ogg',channel = 4, volume=100) + name = newname + else + usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_15_stereo_error.ogg',channel = 4, volume = 100) + 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(F.getObj("id_card"),F.getMob("user")) + return + if(href_list["maint_access"] && maint_access) + if(!in_range(src, usr)) return + var/mob/user = F.getMob("user") + if(user) + if(state==0) + state = 1 + to_chat(user, "The securing bolts are now exposed.") + else if(state==1) + state = 0 + to_chat(user, "The securing bolts are now hidden.") + output_maintenance_dialog(F.getObj("id_card"),user) + return + if(href_list["set_internal_tank_valve"] && state >=1) + if(!in_range(src, usr)) return + var/mob/user = F.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 && F.getObj("id_card")) + if(!in_range(src, usr)) return + operation_req_access += F.getNum("add_req_access") + output_access_dialog(F.getObj("id_card"),F.getMob("user")) + return + if(href_list["del_req_access"] && add_req_access && F.getObj("id_card")) + if(!in_range(src, usr)) return + operation_req_access -= F.getNum("del_req_access") + output_access_dialog(F.getObj("id_card"),F.getMob("user")) + return + if(href_list["finish_req_access"]) + if(!in_range(src, usr)) return + add_req_access = 0 + var/mob/user = F.getMob("user") + user << browse(null,"window=exosuit_add_access") + user << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_22_stereo_complite.ogg',channel = 4, volume = 100) + return + if(href_list["dna_lock"]) + if(usr != src.occupant) return + if(istype(occupant, /mob/living/carbon/brain)) + occupant_message("You are a brain. No.") + usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_15_stereo_error.ogg',channel = 4, volume= 100) + return + if(src.occupant) + src.dna = src.occupant.dna.unique_enzymes + src.occupant_message("You feel a prick as the needle takes your DNA sample.") + usr << sound('sound/mecha/UI_SCI-FI_Compute_01_Wet_stereo.ogg',channel = 4, volume = 100) + return + if(href_list["reset_dna"]) + if(usr != src.occupant) return + usr << sound('sound/mecha/UI_SCI-FI_Tone_10_stereo.ogg',channel = 4, volume=100) + 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.") + usr << sound('sound/mecha/UI_SCI-FI_Compute_01_Wet_stereo.ogg',channel = 4, volume = 100) + var/T = src.loc + if(do_after(100)) + if(T == src.loc) + src.clearInternalDamage(MECHA_INT_CONTROL_LOST) + usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_22_stereo_complite.ogg',channel = 4, volume = 100) + src.occupant_message("Recalibration successful.") + src.log_message("Recalibration of coordination system finished with 0 errors.") + else + usr << sound('sound/mecha/UI_SCI-FI_Tone_Deep_Wet_15_stereo_error.ogg',channel = 4, volume = 100) + 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(F.getNum("set_i_dam")) + if(href_list["clear_i_dam"]) + clearInternalDamage(F.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() + qdel(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.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.temperature > 0) + transfer_moles = pressure_delta * cabin_air.volume / (cabin_air.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.volume/(cabin_air.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) + else + return 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.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.volume>0) + mecha.cabin_air.temperature = min(6000 + T0C, mecha.cabin_air.temperature+rand(10, 15)) + if(mecha.cabin_air.temperature > mecha.max_temperature / 2) + mecha.take_damage(4 / round(mecha.max_temperature / mecha.cabin_air.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) + 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 + +/datum/global_iterator/mecha_light + + process(var/obj/mecha/mecha) + if(!mecha.lights) + return + if(mecha.has_charge(mecha.lights_power)) + mecha.use_power(mecha.lights_power) + else + mecha.lights = 0 + mecha.set_light(mecha.light_range - mecha.lights_power) + 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 +*/ diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index 3725fbdff419..2ac2f68b2851 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -1,1809 +1,1809 @@ -//////////////////////////////// -///// Construction datums ////// -//////////////////////////////// - -/datum/construction/reversible/mecha/custom_action(index, diff, atom/used_atom, mob/user) - if(istype(used_atom, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/W = used_atom - if (W.remove_fuel(3, user)) - playsound(holder, 'sound/items/Welder2.ogg', 50, 1) - return 1 - else - to_chat(user, ("There's not enough fuel.")) - return 0 - else if(istype(used_atom, /obj/item/weapon/wrench)) - playsound(holder, 'sound/items/Ratchet.ogg', 50, 1) - return 1 - else if(istype(used_atom, /obj/item/weapon/screwdriver)) - playsound(holder, 'sound/items/Screwdriver.ogg', 50, 1) - return 1 - else if(istype(used_atom, /obj/item/weapon/wirecutters)) - playsound(holder, 'sound/items/Wirecutter.ogg', 50, 1) - return 1 - else if(istype(used_atom, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = used_atom - if(!C.use(4)) - to_chat(user, ("There's not enough cable to finish the task.")) - return 0 - playsound(holder, 'sound/items/Deconstruct.ogg', 50, 1) - - else if(istype(used_atom, /obj/item/stack)) - var/obj/item/stack/S = used_atom - if(!S.use(5)) - to_chat(user, ("There's not enough material in this stack.")) - return 0 - if(istype(used_atom, /obj)) - var/obj/part = used_atom - if(part.crit_fail || part.reliability < 50) - user.visible_message("[user] was unable to connect [used_atom] to [holder].", "You failed to connect [used_atom] to [holder]") - return 0 - return 1 - - -/datum/construction/mecha/ripley_chassis - steps = list(list("key"=/obj/item/mecha_parts/part/ripley_torso),//1 - list("key"=/obj/item/mecha_parts/part/ripley_left_arm),//2 - list("key"=/obj/item/mecha_parts/part/ripley_right_arm),//3 - list("key"=/obj/item/mecha_parts/part/ripley_left_leg),//4 - list("key"=/obj/item/mecha_parts/part/ripley_right_leg)//5 - ) - - spawn_result() - var/obj/item/mecha_parts/chassis/const_holder = holder - const_holder.construct = new /datum/construction/reversible/mecha/ripley(const_holder) - const_holder.icon = 'icons/mecha/mech_construction.dmi' - const_holder.icon_state = "ripley0" - const_holder.density = 1 - const_holder.overlays.len = 0 - spawn() - qdel(src) - return - - -/datum/construction/reversible/mecha/ripley - result = "/obj/mecha/working/ripley" - steps = list( - //1 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="External armor is wrenched."), - //2 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="External armor is installed."), - //3 - list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/weapon/weldingtool, - "desc"="Internal armor is welded."), - //4 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="Internal armor is wrenched"), - //5 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Internal armor is installed"), - //6 - list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Peripherals control module is secured"), - //7 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Peripherals control module is installed"), - //8 - list("key"=/obj/item/weapon/circuitboard/mecha/ripley/peripherals, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Central control module is secured"), - //9 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Central control module is installed"), - //10 - list("key"=/obj/item/weapon/circuitboard/mecha/ripley/main, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is adjusted"), - //11 - list("key"=/obj/item/weapon/wirecutters, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is added"), - //12 - list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The hydraulic systems are active."), - //13 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are connected."), - //14 - list("key"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are disconnected.") - ) - - action(atom/used_atom,mob/user) - return check_step(used_atom,user) - - custom_action(index, diff, atom/used_atom, mob/user) - if(!..()) - return 0 - - //TODO: better messages. - switch(index) - if(14) - user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") - holder.icon_state = "ripley1" - if(13) - if(diff==FORWARD) - user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") - holder.icon_state = "ripley2" - else - user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") - holder.icon_state = "ripley0" - if(12) - if(diff==FORWARD) - user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") - holder.icon_state = "ripley3" - else - user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") - holder.icon_state = "ripley1" - if(11) - if(diff==FORWARD) - user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") - holder.icon_state = "ripley4" - else - user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") - new /obj/item/stack/cable_coil/random(get_turf(holder), 4) - holder.icon_state = "ripley2" - if(10) - if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") - qdel(used_atom) - holder.icon_state = "ripley5" - else - user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") - holder.icon_state = "ripley3" - if(9) - if(diff==FORWARD) - user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") - holder.icon_state = "ripley6" - else - user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") - new /obj/item/weapon/circuitboard/mecha/ripley/main(get_turf(holder)) - holder.icon_state = "ripley4" - if(8) - if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") - qdel(used_atom) - holder.icon_state = "ripley7" - else - user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") - holder.icon_state = "ripley5" - if(7) - if(diff==FORWARD) - user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") - holder.icon_state = "ripley8" - else - user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/ripley/peripherals(get_turf(holder)) - holder.icon_state = "ripley6" - if(6) - if(diff==FORWARD) - user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") - holder.icon_state = "ripley9" - else - user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") - holder.icon_state = "ripley7" - if(5) - if(diff==FORWARD) - user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") - holder.icon_state = "ripley10" - else - user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") - new /obj/item/stack/sheet/metal(get_turf(holder), 5) - holder.icon_state = "ripley8" - if(4) - if(diff==FORWARD) - user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") - holder.icon_state = "ripley11" - else - user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - holder.icon_state = "ripley9" - if(3) - if(diff==FORWARD) - user.visible_message("[user] installs external reinforced armor layer to [holder].", "You install external reinforced armor layer to [holder].") - holder.icon_state = "ripley12" - else - user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") - holder.icon_state = "ripley10" - if(2) - if(diff==FORWARD) - user.visible_message("[user] secures external armor layer.", "You secure external reinforced armor layer.") - holder.icon_state = "ripley13" - else - user.visible_message("[user] pries external armor layer from [holder].", "You prie external armor layer from [holder].") - new /obj/item/stack/sheet/plasteel(get_turf(holder), 5) - holder.icon_state = "ripley11" - if(1) - if(diff==FORWARD) - user.visible_message("[user] welds external armor layer to [holder].", "You weld external armor layer to [holder].") - else - user.visible_message("[user] unfastens the external armor layer.", "You unfasten the external armor layer.") - holder.icon_state = "ripley12" - return 1 - - spawn_result() - ..() - feedback_inc("mecha_ripley_created",1) - return - - - -/datum/construction/mecha/gygax_chassis - steps = list(list("key"=/obj/item/mecha_parts/part/gygax_torso),//1 - list("key"=/obj/item/mecha_parts/part/gygax_left_arm),//2 - list("key"=/obj/item/mecha_parts/part/gygax_right_arm),//3 - list("key"=/obj/item/mecha_parts/part/gygax_left_leg),//4 - list("key"=/obj/item/mecha_parts/part/gygax_right_leg),//5 - list("key"=/obj/item/mecha_parts/part/gygax_head) - ) - - spawn_result() - var/obj/item/mecha_parts/chassis/const_holder = holder - const_holder.construct = new /datum/construction/reversible/mecha/gygax(const_holder) - const_holder.icon = 'icons/mecha/mech_construction.dmi' - const_holder.icon_state = "gygax0" - const_holder.density = 1 - spawn() - qdel(src) - return - - -/datum/construction/reversible/mecha/gygax - result = "/obj/mecha/combat/gygax" - steps = list( - //1 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="External armor is wrenched."), - //2 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="External armor is installed."), - //3 - list("key"=/obj/item/mecha_parts/part/gygax_armour, - "backkey"=/obj/item/weapon/weldingtool, - "desc"="Internal armor is welded."), - //4 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="Internal armor is wrenched"), - //5 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Internal armor is installed"), - //6 - list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Advanced capacitor is secured"), - //7 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Advanced capacitor is installed"), - //8 - list("key"=/obj/item/weapon/stock_parts/capacitor/adv, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Advanced scanner module is secured"), - //9 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Advanced scanner module is installed"), - //10 - list("key"=/obj/item/weapon/stock_parts/scanning_module/adv, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Targeting module is secured"), - //11 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Targeting module is installed"), - //12 - list("key"=/obj/item/weapon/circuitboard/mecha/gygax/targeting, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Peripherals control module is secured"), - //13 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Peripherals control module is installed"), - //14 - list("key"=/obj/item/weapon/circuitboard/mecha/gygax/peripherals, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Central control module is secured"), - //15 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Central control module is installed"), - //16 - list("key"=/obj/item/weapon/circuitboard/mecha/gygax/main, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is adjusted"), - //17 - list("key"=/obj/item/weapon/wirecutters, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is added"), - //18 - list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The hydraulic systems are active."), - //19 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are connected."), - //20 - list("key"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are disconnected.") - ) - - action(atom/used_atom,mob/user) - return check_step(used_atom,user) - - custom_action(index, diff, atom/used_atom, mob/user) - if(!..()) - return 0 - - //TODO: better messages. - switch(index) - if(20) - user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") - holder.icon_state = "gygax1" - if(19) - if(diff==FORWARD) - user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") - holder.icon_state = "gygax2" - else - user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") - holder.icon_state = "gygax0" - if(18) - if(diff==FORWARD) - user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") - holder.icon_state = "gygax3" - else - user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") - holder.icon_state = "gygax1" - if(17) - if(diff==FORWARD) - user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") - holder.icon_state = "gygax4" - else - user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") - new /obj/item/stack/cable_coil/random(get_turf(holder), 4) - holder.icon_state = "gygax2" - if(16) - if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") - qdel(used_atom) - holder.icon_state = "gygax5" - else - user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") - holder.icon_state = "gygax3" - if(15) - if(diff==FORWARD) - user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") - holder.icon_state = "gygax6" - else - user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") - new /obj/item/weapon/circuitboard/mecha/gygax/main(get_turf(holder)) - holder.icon_state = "gygax4" - if(14) - if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") - qdel(used_atom) - holder.icon_state = "gygax7" - else - user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") - holder.icon_state = "gygax5" - if(13) - if(diff==FORWARD) - user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") - holder.icon_state = "gygax8" - else - user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/gygax/peripherals(get_turf(holder)) - holder.icon_state = "gygax6" - if(12) - if(diff==FORWARD) - user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") - qdel(used_atom) - holder.icon_state = "gygax9" - else - user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") - holder.icon_state = "gygax7" - if(11) - if(diff==FORWARD) - user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.") - holder.icon_state = "gygax10" - else - user.visible_message("[user] removes the weapon control module from [holder].", "You remove the weapon control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/gygax/targeting(get_turf(holder)) - holder.icon_state = "gygax8" - if(10) - if(diff==FORWARD) - user.visible_message("[user] installs advanced scanner module to [holder].", "You install advanced scanner module to [holder].") - qdel(used_atom) - holder.icon_state = "gygax11" - else - user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") - holder.icon_state = "gygax9" - if(9) - if(diff==FORWARD) - user.visible_message("[user] secures the advanced scanner module.", "You secure the advanced scanner module.") - holder.icon_state = "gygax12" - else - user.visible_message("[user] removes the advanced scanner module from [holder].", "You remove the advanced scanner module from [holder].") - new /obj/item/weapon/stock_parts/scanning_module/adv(get_turf(holder)) - holder.icon_state = "gygax10" - if(8) - if(diff==FORWARD) - user.visible_message("[user] installs advanced capacitor to [holder].", "You install advanced capacitor to [holder].") - qdel(used_atom) - holder.icon_state = "gygax13" - else - user.visible_message("[user] unfastens the advanced scanner module.", "You unfasten the advanced scanner module.") - holder.icon_state = "gygax11" - if(7) - if(diff==FORWARD) - user.visible_message("[user] secures the advanced capacitor.", "You secure the advanced capacitor.") - holder.icon_state = "gygax14" - else - user.visible_message("[user] removes the advanced capacitor from [holder].", "You remove the advanced capacitor from [holder].") - new /obj/item/weapon/stock_parts/capacitor/adv(get_turf(holder)) - holder.icon_state = "gygax12" - if(6) - if(diff==FORWARD) - user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") - holder.icon_state = "gygax15" - else - user.visible_message("[user] unfastens the advanced capacitor.", "You unfasten the advanced capacitor.") - holder.icon_state = "gygax13" - if(5) - if(diff==FORWARD) - user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") - holder.icon_state = "gygax16" - else - user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") - new /obj/item/stack/sheet/metal(get_turf(holder), 5) - holder.icon_state = "gygax14" - if(4) - if(diff==FORWARD) - user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") - holder.icon_state = "gygax17" - else - user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - holder.icon_state = "gygax15" - if(3) - if(diff==FORWARD) - user.visible_message("[user] installs Gygax Armour Plates to [holder].", "You install Gygax Armour Plates to [holder].") - qdel(used_atom) - holder.icon_state = "gygax18" - else - user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") - holder.icon_state = "gygax16" - if(2) - if(diff==FORWARD) - user.visible_message("[user] secures Gygax Armour Plates.", "You secure Gygax Armour Plates.") - holder.icon_state = "gygax19" - else - user.visible_message("[user] pries Gygax Armour Plates from [holder].", "You prie Gygax Armour Plates from [holder].") - new /obj/item/mecha_parts/part/gygax_armour(get_turf(holder)) - holder.icon_state = "gygax17" - if(1) - if(diff==FORWARD) - user.visible_message("[user] welds Gygax Armour Plates to [holder].", "You weld Gygax Armour Plates to [holder].") - else - user.visible_message("[user] unfastens Gygax Armour Plates.", "You unfasten Gygax Armour Plates.") - holder.icon_state = "gygax18" - return 1 - - spawn_result() - ..() - feedback_inc("mecha_gygax_created",1) - return - -/datum/construction/mecha/firefighter_chassis - steps = list(list("key"=/obj/item/mecha_parts/part/ripley_torso),//1 - list("key"=/obj/item/mecha_parts/part/ripley_left_arm),//2 - list("key"=/obj/item/mecha_parts/part/ripley_right_arm),//3 - list("key"=/obj/item/mecha_parts/part/ripley_left_leg),//4 - list("key"=/obj/item/mecha_parts/part/ripley_right_leg),//5 - list("key"=/obj/item/clothing/suit/fire)//6 - ) - - - spawn_result() - var/obj/item/mecha_parts/chassis/const_holder = holder - const_holder.construct = new /datum/construction/reversible/mecha/firefighter(const_holder) - const_holder.icon = 'icons/mecha/mech_construction.dmi' - const_holder.icon_state = "fireripley0" - const_holder.density = 1 - spawn() - qdel(src) - return - - -/datum/construction/reversible/mecha/firefighter - result = "/obj/mecha/working/ripley/firefighter" - steps = list( - //1 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="External armor is wrenched."), - //2 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="External armor is installed."), - //3 - list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/weapon/crowbar, - "desc"="External armor is being installed."), - //4 - list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/weapon/weldingtool, - "desc"="Internal armor is welded."), - //5 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="Internal armor is wrenched"), - //6 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Internal armor is installed"), - - //7 - list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Peripherals control module is secured"), - //8 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Peripherals control module is installed"), - //9 - list("key"=/obj/item/weapon/circuitboard/mecha/ripley/peripherals, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Central control module is secured"), - //10 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Central control module is installed"), - //11 - list("key"=/obj/item/weapon/circuitboard/mecha/ripley/main, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is adjusted"), - //12 - list("key"=/obj/item/weapon/wirecutters, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is added"), - //13 - list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The hydraulic systems are active."), - //14 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are connected."), - //15 - list("key"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are disconnected.") - ) - - action(atom/used_atom,mob/user) - return check_step(used_atom,user) - - custom_action(index, diff, atom/used_atom, mob/user) - if(!..()) - return 0 - - //TODO: better messages. - switch(index) - if(15) - user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") - holder.icon_state = "fireripley1" - if(14) - if(diff==FORWARD) - user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") - holder.icon_state = "fireripley2" - else - user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") - holder.icon_state = "fireripley0" - if(13) - if(diff==FORWARD) - user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") - holder.icon_state = "fireripley3" - else - user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") - holder.icon_state = "fireripley1" - if(12) - if(diff==FORWARD) - user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") - holder.icon_state = "fireripley4" - else - user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") - new /obj/item/stack/cable_coil/random(get_turf(holder), 4) - holder.icon_state = "fireripley2" - if(11) - if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") - qdel(used_atom) - holder.icon_state = "fireripley5" - else - user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") - holder.icon_state = "fireripley3" - if(10) - if(diff==FORWARD) - user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") - holder.icon_state = "fireripley6" - else - user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") - new /obj/item/weapon/circuitboard/mecha/ripley/main(get_turf(holder)) - holder.icon_state = "fireripley4" - if(9) - if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") - qdel(used_atom) - holder.icon_state = "fireripley7" - else - user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") - holder.icon_state = "fireripley5" - if(8) - if(diff==FORWARD) - user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") - holder.icon_state = "fireripley8" - else - user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/ripley/peripherals(get_turf(holder)) - holder.icon_state = "fireripley6" - if(7) - if(diff==FORWARD) - user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") - holder.icon_state = "fireripley9" - else - user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") - holder.icon_state = "fireripley7" - - if(6) - if(diff==FORWARD) - user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") - holder.icon_state = "fireripley10" - else - user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") - new /obj/item/stack/sheet/plasteel(get_turf(holder), 5) - holder.icon_state = "fireripley8" - if(5) - if(diff==FORWARD) - user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") - holder.icon_state = "fireripley11" - else - user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - holder.icon_state = "fireripley9" - if(4) - if(diff==FORWARD) - user.visible_message("[user] starts to install the external armor layer to [holder].", "You start to install the external armor layer to [holder].") - holder.icon_state = "fireripley12" - else - user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") - holder.icon_state = "fireripley10" - if(3) - if(diff==FORWARD) - user.visible_message("[user] installs external reinforced armor layer to [holder].", "You install external reinforced armor layer to [holder].") - holder.icon_state = "fireripley13" - else - user.visible_message("[user] removes the external armor from [holder].", "You remove the external armor from [holder].") - new /obj/item/stack/sheet/plasteel(get_turf(holder), 5) - holder.icon_state = "fireripley11" - if(2) - if(diff==FORWARD) - user.visible_message("[user] secures external armor layer.", "You secure external reinforced armor layer.") - holder.icon_state = "fireripley14" - else - user.visible_message("[user] pries external armor layer from [holder].", "You prie external armor layer from [holder].") - new /obj/item/stack/sheet/plasteel(get_turf(holder), 5) - holder.icon_state = "fireripley12" - if(1) - if(diff==FORWARD) - user.visible_message("[user] welds external armor layer to [holder].", "You weld external armor layer to [holder].") - else - user.visible_message("[user] unfastens the external armor layer.", "You unfasten the external armor layer.") - holder.icon_state = "fireripley13" - return 1 - - spawn_result() - ..() - feedback_inc("mecha_firefighter_created",1) - return - - - -/datum/construction/mecha/honker_chassis - steps = list(list("key"=/obj/item/mecha_parts/part/honker_torso),//1 - list("key"=/obj/item/mecha_parts/part/honker_left_arm),//2 - list("key"=/obj/item/mecha_parts/part/honker_right_arm),//3 - list("key"=/obj/item/mecha_parts/part/honker_left_leg),//4 - list("key"=/obj/item/mecha_parts/part/honker_right_leg),//5 - list("key"=/obj/item/mecha_parts/part/honker_head) - ) - - spawn_result() - var/obj/item/mecha_parts/chassis/const_holder = holder - const_holder.construct = new /datum/construction/mecha/honker(const_holder) - const_holder.density = 1 - spawn() - qdel(src) - return - - -/datum/construction/mecha/honker - result = "/obj/mecha/combat/honker" - steps = list(list("key"=/obj/item/weapon/bikehorn),//1 - list("key"=/obj/item/clothing/shoes/clown_shoes),//2 - list("key"=/obj/item/weapon/bikehorn),//3 - list("key"=/obj/item/clothing/mask/gas/clown_hat),//4 - list("key"=/obj/item/weapon/bikehorn),//5 - list("key"=/obj/item/weapon/circuitboard/mecha/honker/targeting),//6 - list("key"=/obj/item/weapon/bikehorn),//7 - list("key"=/obj/item/weapon/circuitboard/mecha/honker/peripherals),//8 - list("key"=/obj/item/weapon/bikehorn),//9 - list("key"=/obj/item/weapon/circuitboard/mecha/honker/main),//10 - list("key"=/obj/item/weapon/bikehorn),//11 - ) - - action(atom/used_atom,mob/user) - return check_step(used_atom,user) - - custom_action(step, 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!") - - //TODO: better messages. - switch(step) - if(10) - user.visible_message("[user] installs the central control module into [holder].", "You install the central control module into [holder].") - qdel(used_atom) - if(8) - user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") - qdel(used_atom) - if(6) - user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") - qdel(used_atom) - if(4) - user.visible_message("[user] puts clown wig and mask on [holder].", "You put clown wig and mask on [holder].") - qdel(used_atom) - if(2) - user.visible_message("[user] puts clown boots on [holder].", "You put clown boots on [holder].") - qdel(used_atom) - return 1 - - spawn_result() - ..() - feedback_inc("mecha_honker_created",1) - return - -/datum/construction/mecha/durand_chassis - steps = list(list("key"=/obj/item/mecha_parts/part/durand_torso),//1 - list("key"=/obj/item/mecha_parts/part/durand_left_arm),//2 - list("key"=/obj/item/mecha_parts/part/durand_right_arm),//3 - list("key"=/obj/item/mecha_parts/part/durand_left_leg),//4 - list("key"=/obj/item/mecha_parts/part/durand_right_leg),//5 - list("key"=/obj/item/mecha_parts/part/durand_head) - ) - - - spawn_result() - var/obj/item/mecha_parts/chassis/const_holder = holder - const_holder.construct = new /datum/construction/reversible/mecha/durand(const_holder) - const_holder.icon = 'icons/mecha/mech_construction.dmi' - const_holder.icon_state = "durand0" - const_holder.density = 1 - spawn() - qdel(src) - return - -/datum/construction/reversible/mecha/durand - result = "/obj/mecha/combat/durand" - steps = list( - //1 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="External armor is wrenched."), - //2 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="External armor is installed."), - //3 - list("key"=/obj/item/mecha_parts/part/durand_armour, - "backkey"=/obj/item/weapon/weldingtool, - "desc"="Internal armor is welded."), - //4 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="Internal armor is wrenched"), - //5 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Internal armor is installed"), - //6 - list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Advanced capacitor is secured"), - //7 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Advanced capacitor is installed"), - //8 - list("key"=/obj/item/weapon/stock_parts/capacitor/adv, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Advanced scanner module is secured"), - //9 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Advanced scanner module is installed"), - //10 - list("key"=/obj/item/weapon/stock_parts/scanning_module/adv, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Targeting module is secured"), - //11 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Targeting module is installed"), - //12 - list("key"=/obj/item/weapon/circuitboard/mecha/durand/targeting, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Peripherals control module is secured"), - //13 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Peripherals control module is installed"), - //14 - list("key"=/obj/item/weapon/circuitboard/mecha/durand/peripherals, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Central control module is secured"), - //15 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Central control module is installed"), - //16 - list("key"=/obj/item/weapon/circuitboard/mecha/durand/main, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is adjusted"), - //17 - list("key"=/obj/item/weapon/wirecutters, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is added"), - //18 - list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The hydraulic systems are active."), - //19 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are connected."), - //20 - list("key"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are disconnected.") - ) - - - action(atom/used_atom,mob/user) - return check_step(used_atom,user) - - custom_action(index, diff, atom/used_atom, mob/user) - if(!..()) - return 0 - - //TODO: better messages. - switch(index) - if(20) - user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") - holder.icon_state = "durand1" - if(19) - if(diff==FORWARD) - user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") - holder.icon_state = "durand2" - else - user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") - holder.icon_state = "durand0" - if(18) - if(diff==FORWARD) - user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") - holder.icon_state = "durand3" - else - user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") - holder.icon_state = "durand1" - if(17) - if(diff==FORWARD) - user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") - holder.icon_state = "durand4" - else - user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") - new /obj/item/stack/cable_coil/random(get_turf(holder), 4) - holder.icon_state = "durand2" - if(16) - if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") - qdel(used_atom) - holder.icon_state = "durand5" - else - user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") - holder.icon_state = "durand3" - if(15) - if(diff==FORWARD) - user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") - holder.icon_state = "durand6" - else - user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") - new /obj/item/weapon/circuitboard/mecha/durand/main(get_turf(holder)) - holder.icon_state = "durand4" - if(14) - if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") - qdel(used_atom) - holder.icon_state = "durand7" - else - user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") - holder.icon_state = "durand5" - if(13) - if(diff==FORWARD) - user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") - holder.icon_state = "durand8" - else - user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/durand/peripherals(get_turf(holder)) - holder.icon_state = "durand6" - if(12) - if(diff==FORWARD) - user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") - qdel(used_atom) - holder.icon_state = "durand9" - else - user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") - holder.icon_state = "durand7" - if(11) - if(diff==FORWARD) - user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.") - holder.icon_state = "durand10" - else - user.visible_message("[user] removes the weapon control module from [holder].", "You remove the weapon control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/durand/targeting(get_turf(holder)) - holder.icon_state = "durand8" - if(10) - if(diff==FORWARD) - user.visible_message("[user] installs advanced scanner module to [holder].", "You install advanced scanner module to [holder].") - qdel(used_atom) - holder.icon_state = "durand11" - else - user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") - holder.icon_state = "durand9" - if(9) - if(diff==FORWARD) - user.visible_message("[user] secures the advanced scanner module.", "You secure the advanced scanner module.") - holder.icon_state = "durand12" - else - user.visible_message("[user] removes the advanced scanner module from [holder].", "You remove the advanced scanner module from [holder].") - new /obj/item/weapon/stock_parts/scanning_module/adv(get_turf(holder)) - holder.icon_state = "durand10" - if(8) - if(diff==FORWARD) - user.visible_message("[user] installs advanced capacitor to [holder].", "You install advanced capacitor to [holder].") - qdel(used_atom) - holder.icon_state = "durand13" - else - user.visible_message("[user] unfastens the advanced scanner module.", "You unfasten the advanced scanner module.") - holder.icon_state = "durand11" - if(7) - if(diff==FORWARD) - user.visible_message("[user] secures the advanced capacitor.", "You secure the advanced capacitor.") - holder.icon_state = "durand14" - else - user.visible_message("[user] removes the advanced capacitor from [holder].", "You remove the advanced capacitor from [holder].") - new /obj/item/weapon/stock_parts/capacitor/adv(get_turf(holder)) - holder.icon_state = "durand12" - if(6) - if(diff==FORWARD) - user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") - holder.icon_state = "durand15" - else - user.visible_message("[user] unfastens the advanced capacitor.", "You unfasten the advanced capacitor.") - holder.icon_state = "durand13" - if(5) - if(diff==FORWARD) - user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") - holder.icon_state = "durand16" - else - user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") - new /obj/item/stack/sheet/metal(get_turf(holder), 5) - holder.icon_state = "durand14" - if(4) - if(diff==FORWARD) - user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") - holder.icon_state = "durand17" - else - user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - holder.icon_state = "durand15" - if(3) - if(diff==FORWARD) - user.visible_message("[user] installs Durand Armour Plates to [holder].", "You install Durand Armour Plates to [holder].") - qdel(used_atom) - holder.icon_state = "durand18" - else - user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") - holder.icon_state = "durand16" - if(2) - if(diff==FORWARD) - user.visible_message("[user] secures Durand Armour Plates.", "You secure Durand Armour Plates.") - holder.icon_state = "durand19" - else - user.visible_message("[user] pries Durand Armour Plates from [holder].", "You prie Durand Armour Plates from [holder].") - new /obj/item/mecha_parts/part/durand_armour(get_turf(holder)) - holder.icon_state = "durand17" - if(1) - if(diff==FORWARD) - user.visible_message("[user] welds Durand Armour Plates to [holder].", "You weld Durand Armour Plates to [holder].") - else - user.visible_message("[user] unfastens Durand Armour Plates.", "You unfasten Durand Armour Plates.") - holder.icon_state = "durand18" - return 1 - - spawn_result() - ..() - feedback_inc("mecha_durand_created",1) - return - - -/datum/construction/mecha/phazon_chassis - result = "/obj/mecha/combat/phazon" - steps = list(list("key"=/obj/item/mecha_parts/part/phazon_torso),//1 - list("key"=/obj/item/mecha_parts/part/phazon_left_arm),//2 - list("key"=/obj/item/mecha_parts/part/phazon_right_arm),//3 - list("key"=/obj/item/mecha_parts/part/phazon_left_leg),//4 - list("key"=/obj/item/mecha_parts/part/phazon_right_leg),//5 - list("key"=/obj/item/mecha_parts/part/phazon_head) - ) - - - -/datum/construction/mecha/odysseus_chassis - steps = list(list("key"=/obj/item/mecha_parts/part/odysseus_torso),//1 - list("key"=/obj/item/mecha_parts/part/odysseus_head),//2 - list("key"=/obj/item/mecha_parts/part/odysseus_left_arm),//3 - list("key"=/obj/item/mecha_parts/part/odysseus_right_arm),//4 - list("key"=/obj/item/mecha_parts/part/odysseus_left_leg),//5 - list("key"=/obj/item/mecha_parts/part/odysseus_right_leg)//6 - ) - - - spawn_result() - var/obj/item/mecha_parts/chassis/const_holder = holder - const_holder.construct = new /datum/construction/reversible/mecha/odysseus(const_holder) - const_holder.icon = 'icons/mecha/mech_construction.dmi' - const_holder.icon_state = "odysseus0" - const_holder.density = 1 - spawn() - qdel(src) - return - - -/datum/construction/reversible/mecha/odysseus - result = "/obj/mecha/medical/odysseus" - steps = list( - //1 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="External armor is wrenched."), - //2 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="External armor is installed."), - //3 - list("key"=/obj/item/stack/sheet/plasteel, - "backkey"=/obj/item/weapon/weldingtool, - "desc"="Internal armor is welded."), - //4 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="Internal armor is wrenched"), - //5 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Internal armor is installed"), - //6 - list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Peripherals control module is secured"), - //7 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Peripherals control module is installed"), - //8 - list("key"=/obj/item/weapon/circuitboard/mecha/odysseus/peripherals, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Central control module is secured"), - //9 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Central control module is installed"), - //10 - list("key"=/obj/item/weapon/circuitboard/mecha/odysseus/main, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is adjusted"), - //11 - list("key"=/obj/item/weapon/wirecutters, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is added"), - //12 - list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The hydraulic systems are active."), - //13 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are connected."), - //14 - list("key"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are disconnected.") - ) - - action(atom/used_atom,mob/user) - return check_step(used_atom,user) - - custom_action(index, diff, atom/used_atom, mob/user) - if(!..()) - return 0 - - //TODO: better messages. - switch(index) - if(14) - user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") - holder.icon_state = "odysseus1" - if(13) - if(diff==FORWARD) - user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") - holder.icon_state = "odysseus2" - else - user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") - holder.icon_state = "odysseus0" - if(12) - if(diff==FORWARD) - user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") - holder.icon_state = "odysseus3" - else - user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") - holder.icon_state = "odysseus1" - if(11) - if(diff==FORWARD) - user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") - holder.icon_state = "odysseus4" - else - user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") - new /obj/item/stack/cable_coil/random(get_turf(holder), 4) - holder.icon_state = "odysseus2" - if(10) - if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") - qdel(used_atom) - holder.icon_state = "odysseus5" - else - user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") - holder.icon_state = "odysseus3" - if(9) - if(diff==FORWARD) - user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") - holder.icon_state = "odysseus6" - else - user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") - new /obj/item/weapon/circuitboard/mecha/odysseus/main(get_turf(holder)) - holder.icon_state = "odysseus4" - if(8) - if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") - qdel(used_atom) - holder.icon_state = "odysseus7" - else - user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") - holder.icon_state = "odysseus5" - if(7) - if(diff==FORWARD) - user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") - holder.icon_state = "odysseus8" - else - user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/odysseus/peripherals(get_turf(holder)) - holder.icon_state = "odysseus6" - if(6) - if(diff==FORWARD) - user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") - holder.icon_state = "odysseus9" - else - user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") - holder.icon_state = "odysseus7" - if(5) - if(diff==FORWARD) - user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") - holder.icon_state = "odysseus10" - else - user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") - new /obj/item/stack/sheet/metal(get_turf(holder), 5) - holder.icon_state = "odysseus8" - if(4) - if(diff==FORWARD) - user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") - holder.icon_state = "odysseus11" - else - user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - holder.icon_state = "odysseus9" - if(3) - if(diff==FORWARD) - user.visible_message("[user] installs [used_atom] layer to [holder].", "You install external reinforced armor layer to [holder].") - - holder.icon_state = "odysseus12" - else - user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") - holder.icon_state = "odysseus10" - if(2) - if(diff==FORWARD) - user.visible_message("[user] secures external armor layer.", "You secure external reinforced armor layer.") - holder.icon_state = "odysseus13" - else - var/obj/item/stack/sheet/plasteel/MS = new (get_turf(holder), 5) - user.visible_message("[user] pries [MS] from [holder].", "You prie [MS] from [holder].") - holder.icon_state = "odysseus11" - if(1) - if(diff==FORWARD) - user.visible_message("[user] welds external armor layer to [holder].", "You weld external armor layer to [holder].") - holder.icon_state = "odysseus14" - else - user.visible_message("[user] unfastens the external armor layer.", "You unfasten the external armor layer.") - holder.icon_state = "odysseus12" - return 1 - - spawn_result() - ..() - feedback_inc("mecha_odysseus_created",1) - return - -/datum/construction/mecha/vindicator_chassis - steps = list(list("key"=/obj/item/mecha_parts/part/vindicator_torso),//1 - list("key"=/obj/item/mecha_parts/part/vindicator_left_arm),//2 - list("key"=/obj/item/mecha_parts/part/vindicator_right_arm),//3 - list("key"=/obj/item/mecha_parts/part/vindicator_left_leg),//4 - list("key"=/obj/item/mecha_parts/part/vindicator_right_leg),//5 - list("key"=/obj/item/mecha_parts/part/vindicator_head) - ) - - spawn_result() - var/obj/item/mecha_parts/chassis/const_holder = holder - const_holder.construct = new /datum/construction/reversible/mecha/vindicator(const_holder) - const_holder.icon = 'icons/mecha/mech_construction.dmi' - const_holder.icon_state = "vindicator0" - const_holder.density = 1 - spawn() - qdel(src) - return - -/datum/construction/reversible/mecha/vindicator - result = "/obj/mecha/combat/durand/vindicator" - steps = list( - //1 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="External armor is wrenched."), - //2 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="External armor is installed."), - //3 - list("key"=/obj/item/mecha_parts/part/vindicator_armour, - "backkey"=/obj/item/weapon/weldingtool, - "desc"="Internal armor is welded."), - //4 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="Internal armor is wrenched"), - //5 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Internal armor is installed"), - //6 - list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Advanced capacitor is secured"), - //7 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Advanced capacitor is installed"), - //8 - list("key"=/obj/item/weapon/stock_parts/capacitor/super, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Advanced scanner module is secured"), - //9 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Advanced scanner module is installed"), - //10 - list("key"=/obj/item/weapon/stock_parts/scanning_module/phasic, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Targeting module is secured"), - //11 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Targeting module is installed"), - //12 - list("key"=/obj/item/weapon/circuitboard/mecha/vindicator/targeting, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Peripherals control module is secured"), - //13 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Peripherals control module is installed"), - //14 - list("key"=/obj/item/weapon/circuitboard/mecha/vindicator/peripherals, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Central control module is secured"), - //15 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Central control module is installed"), - //16 - list("key"=/obj/item/weapon/circuitboard/mecha/vindicator/main, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is adjusted"), - //17 - list("key"=/obj/item/weapon/wirecutters, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is added"), - //18 - list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The hydraulic systems are active."), - //19 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are connected."), - //20 - list("key"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are disconnected.") - ) - - - action(atom/used_atom,mob/user) - return check_step(used_atom,user) - - custom_action(index, diff, atom/used_atom, mob/user) - if(!..()) - return 0 - - //TODO: better messages. - switch(index) - if(20) - user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") - holder.icon_state = "vindicator1" - if(19) - if(diff==FORWARD) - user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") - holder.icon_state = "vindicator2" - else - user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") - holder.icon_state = "vindicator0" - if(18) - if(diff==FORWARD) - user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") - holder.icon_state = "vindicator3" - else - user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") - holder.icon_state = "vindicator1" - if(17) - if(diff==FORWARD) - user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") - holder.icon_state = "vindicator4" - else - user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") - new /obj/item/stack/cable_coil/random(get_turf(holder), 30) - holder.icon_state = "vindicator2" - if(16) - if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") - qdel(used_atom) - holder.icon_state = "vindicator5" - else - user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") - holder.icon_state = "vindicator3" - if(15) - if(diff==FORWARD) - user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") - holder.icon_state = "vindicator6" - else - user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") - new /obj/item/weapon/circuitboard/mecha/vindicator/main(get_turf(holder)) - holder.icon_state = "vindicator4" - if(14) - if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") - qdel(used_atom) - holder.icon_state = "vindicator7" - else - user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") - holder.icon_state = "vindicator5" - if(13) - if(diff==FORWARD) - user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") - holder.icon_state = "vindicator8" - else - user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/vindicator/peripherals(get_turf(holder)) - holder.icon_state = "vindicator6" - if(12) - if(diff==FORWARD) - user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") - qdel(used_atom) - holder.icon_state = "vindicator9" - else - user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") - holder.icon_state = "vindicator7" - if(11) - if(diff==FORWARD) - user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.") - holder.icon_state = "vindicator10" - else - user.visible_message("[user] removes the weapon control module from [holder].", "You remove the weapon control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/vindicator/targeting(get_turf(holder)) - holder.icon_state = "vindicator8" - if(10) - if(diff==FORWARD) - user.visible_message("[user] installs phasic scanner module to [holder].", "You install phasic scanner module to [holder].") - qdel(used_atom) - holder.icon_state = "vindicator11" - else - user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") - holder.icon_state = "vindicator9" - if(9) - if(diff==FORWARD) - user.visible_message("[user] secures the phasic scanner module.", "You secure the phasic scanner module.") - holder.icon_state = "vindicator12" - else - user.visible_message("[user] removes the phasic scanner module from [holder].", "You remove the phasic scanner module from [holder].") - new /obj/item/weapon/stock_parts/scanning_module/phasic(get_turf(holder)) - holder.icon_state = "vindicator10" - if(8) - if(diff==FORWARD) - user.visible_message("[user] installs super capacitor to [holder].", "You install super capacitor to [holder].") - qdel(used_atom) - holder.icon_state = "vindicator13" - else - user.visible_message("[user] unfastens the phasic scanner module.", "You unfasten the phasic scanner module.") - holder.icon_state = "vindicator11" - if(7) - if(diff==FORWARD) - user.visible_message("[user] secures the super capacitor.", "You secure the super capacitor.") - holder.icon_state = "vindicator14" - else - user.visible_message("[user] removes the super capacitor from [holder].", "You remove the super capacitor from [holder].") - new /obj/item/weapon/stock_parts/capacitor/super(get_turf(holder)) - holder.icon_state = "vindicator12" - if(6) - if(diff==FORWARD) - user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") - holder.icon_state = "vindicator15" - else - user.visible_message("[user] unfastens the super capacitor.", "You unfasten the super capacitor.") - holder.icon_state = "vindicator13" - if(5) - if(diff==FORWARD) - user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") - holder.icon_state = "vindicator16" - else - user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") - new /obj/item/stack/sheet/metal(get_turf(holder), 30) - holder.icon_state = "vindicator14" - if(4) - if(diff==FORWARD) - user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") - holder.icon_state = "vindicator17" - else - user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - holder.icon_state = "vindicator15" - if(3) - if(diff==FORWARD) - user.visible_message("[user] installs Vindicator Armour Plates to [holder].", "You install Vindicator Armour Plates to [holder].") - qdel(used_atom) - holder.icon_state = "vindicator18" - else - user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") - holder.icon_state = "vindicator16" - if(2) - if(diff==FORWARD) - user.visible_message("[user] secures Vindicator Armour Plates.", "You secure Vindicator Armour Plates.") - holder.icon_state = "vindicator19" - else - user.visible_message("[user] pries Vindicator Armour Plates from [holder].", "You prie Vindicator Armour Plates from [holder].") - new /obj/item/mecha_parts/part/vindicator_armour(get_turf(holder)) - holder.icon_state = "vindicator17" - if(1) - if(diff==FORWARD) - user.visible_message("[user] welds Vindicator Armour Plates to [holder].", "You weld Vindicator Armour Plates to [holder].") - else - user.visible_message("[user] unfastens Vindicator Armour Plates.", "You unfasten Vindicator Armour Plates.") - holder.icon_state = "vindicator18" - return 1 - - spawn_result() - ..() - feedback_inc("mecha_vindicator_created",1) - return - -/datum/construction/mecha/ultra_chassis - steps = list(list("key"=/obj/item/mecha_parts/part/ultra_torso),//1 - list("key"=/obj/item/mecha_parts/part/ultra_left_arm),//2 - list("key"=/obj/item/mecha_parts/part/ultra_right_arm),//3 - list("key"=/obj/item/mecha_parts/part/ultra_left_leg),//4 - list("key"=/obj/item/mecha_parts/part/ultra_right_leg),//5 - list("key"=/obj/item/mecha_parts/part/ultra_head) - ) - - spawn_result() - var/obj/item/mecha_parts/chassis/const_holder = holder - const_holder.construct = new /datum/construction/reversible/mecha/ultra(const_holder) - const_holder.icon = 'icons/mecha/mech_construction.dmi' - const_holder.icon_state = "ultra0" - const_holder.density = 1 - spawn() - qdel(src) - return - - -/datum/construction/reversible/mecha/ultra - result = "/obj/mecha/combat/gygax/ultra" - steps = list( - //1 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="External armor is wrenched."), - //2 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="External armor is installed."), - //3 - list("key"=/obj/item/mecha_parts/part/ultra_armour, - "backkey"=/obj/item/weapon/weldingtool, - "desc"="Internal armor is welded."), - //4 - list("key"=/obj/item/weapon/weldingtool, - "backkey"=/obj/item/weapon/wrench, - "desc"="Internal armor is wrenched"), - //5 - list("key"=/obj/item/weapon/wrench, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Internal armor is installed"), - //6 - list("key"=/obj/item/stack/sheet/metal, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Super capacitor is secured"), - //7 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Super capacitor is installed"), - //8 - list("key"=/obj/item/weapon/stock_parts/capacitor/super, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Phasic scanner module is secured"), - //9 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Phasic scanner module is installed"), - //10 - list("key"=/obj/item/weapon/stock_parts/scanning_module/phasic, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Targeting module is secured"), - //11 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Targeting module is installed"), - //12 - list("key"=/obj/item/weapon/circuitboard/mecha/ultra/targeting, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Peripherals control module is secured"), - //13 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Peripherals control module is installed"), - //14 - list("key"=/obj/item/weapon/circuitboard/mecha/ultra/peripherals, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="Central control module is secured"), - //15 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/crowbar, - "desc"="Central control module is installed"), - //16 - list("key"=/obj/item/weapon/circuitboard/mecha/ultra/main, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is adjusted"), - //17 - list("key"=/obj/item/weapon/wirecutters, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The wiring is added"), - //18 - list("key"=/obj/item/stack/cable_coil, - "backkey"=/obj/item/weapon/screwdriver, - "desc"="The hydraulic systems are active."), - //19 - list("key"=/obj/item/weapon/screwdriver, - "backkey"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are connected."), - //20 - list("key"=/obj/item/weapon/wrench, - "desc"="The hydraulic systems are disconnected.") - ) - - action(atom/used_atom,mob/user) - return check_step(used_atom,user) - - custom_action(index, diff, atom/used_atom, mob/user) - if(!..()) - return 0 - - //TODO: better messages. - switch(index) - if(20) - user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") - holder.icon_state = "ultra1" - if(19) - if(diff==FORWARD) - user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") - holder.icon_state = "ultra2" - else - user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") - holder.icon_state = "ultra0" - if(18) - if(diff==FORWARD) - user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") - holder.icon_state = "ultra3" - else - user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") - holder.icon_state = "ultra1" - if(17) - if(diff==FORWARD) - user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") - holder.icon_state = "ultra4" - else - user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") - new /obj/item/stack/cable_coil/random(get_turf(holder), 4) - holder.icon_state = "ultra2" - if(16) - if(diff==FORWARD) - user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") - qdel(used_atom) - holder.icon_state = "ultra5" - else - user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") - holder.icon_state = "ultra3" - if(15) - if(diff==FORWARD) - user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") - holder.icon_state = "ultra6" - else - user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") - new /obj/item/weapon/circuitboard/mecha/ultra/main(get_turf(holder)) - holder.icon_state = "ultra4" - if(14) - if(diff==FORWARD) - user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") - qdel(used_atom) - holder.icon_state = "ultra7" - else - user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") - holder.icon_state = "ultra5" - if(13) - if(diff==FORWARD) - user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") - holder.icon_state = "ultra8" - else - user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/ultra/peripherals(get_turf(holder)) - holder.icon_state = "ultra6" - if(12) - if(diff==FORWARD) - user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") - qdel(used_atom) - holder.icon_state = "ultra9" - else - user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") - holder.icon_state = "ultra7" - if(11) - if(diff==FORWARD) - user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.") - holder.icon_state = "ultra10" - else - user.visible_message("[user] removes the weapon control module from [holder].", "You remove the weapon control module from [holder].") - new /obj/item/weapon/circuitboard/mecha/ultra/targeting(get_turf(holder)) - holder.icon_state = "ultra8" - if(10) - if(diff==FORWARD) - user.visible_message("[user] installs advanced scanner module to [holder].", "You install phasic scanner module to [holder].") - qdel(used_atom) - holder.icon_state = "ultra11" - else - user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") - holder.icon_state = "ultra9" - if(9) - if(diff==FORWARD) - user.visible_message("[user] secures the phasic scanner module.", "You secure the phasic scanner module.") - holder.icon_state = "ultra12" - else - user.visible_message("[user] removes the phasic scanner module from [holder].", "You remove the phasic scanner module from [holder].") - new /obj/item/weapon/stock_parts/scanning_module/phasic(get_turf(holder)) - holder.icon_state = "ultra10" - if(8) - if(diff==FORWARD) - user.visible_message("[user] installs super capacitor to [holder].", "You install super capacitor to [holder].") - qdel(used_atom) - holder.icon_state = "ultra13" - else - user.visible_message("[user] unfastens the phasic scanner module.", "You unfasten the phasic scanner module.") - holder.icon_state = "ultra11" - if(7) - if(diff==FORWARD) - user.visible_message("[user] secures the super capacitor.", "You secure the super capacitor.") - holder.icon_state = "ultra14" - else - user.visible_message("[user] removes the super capacitor from [holder].", "You remove the super capacitor from [holder].") - new /obj/item/weapon/stock_parts/capacitor/super(get_turf(holder)) - holder.icon_state = "ultra12" - if(6) - if(diff==FORWARD) - user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") - holder.icon_state = "ultra15" - else - user.visible_message("[user] unfastens the super capacitor.", "You unfasten the super capacitor.") - holder.icon_state = "ultra13" - if(5) - if(diff==FORWARD) - user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") - holder.icon_state = "ultra16" - else - user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") - new /obj/item/stack/sheet/metal(get_turf(holder), 5) - holder.icon_state = "ultra14" - if(4) - if(diff==FORWARD) - user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") - holder.icon_state = "ultra17" - else - user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") - holder.icon_state = "ultra15" - if(3) - if(diff==FORWARD) - user.visible_message("[user] installs Gygax Ultra Armour Plates to [holder].", "You install Gygax Ultra Armour Plates to [holder].") - qdel(used_atom) - holder.icon_state = "ultra18" - else - user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") - holder.icon_state = "ultra16" - if(2) - if(diff==FORWARD) - user.visible_message("[user] secures Gygax Ultra Armour Plates.", "You secure Gygax Ultra Armour Plates.") - holder.icon_state = "ultra19" - else - user.visible_message("[user] pries Gygax Ultra Armour Plates from [holder].", "You prie Gygax Ultra Armour Plates from [holder].") - new /obj/item/mecha_parts/part/ultra_armour(get_turf(holder)) - holder.icon_state = "ultra17" - if(1) - if(diff==FORWARD) - user.visible_message("[user] welds Gygax Ultra Armour Plates to [holder].", "You weld Gygax Ultra Armour Plates to [holder].") - else - user.visible_message("[user] unfastens Gygax Ultra Armour Plates.", "You unfasten Gygax Ultra Armour Plates.") - holder.icon_state = "ultra18" - return 1 - - spawn_result() - ..() - feedback_inc("mecha_ultra_created",1) - return +//////////////////////////////// +///// Construction datums ////// +//////////////////////////////// + +/datum/construction/reversible/mecha/custom_action(index, diff, atom/used_atom, mob/user) + if(istype(used_atom, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/W = used_atom + if (W.remove_fuel(3, user)) + playsound(holder, 'sound/items/Welder2.ogg', 50, 1) + return 1 + else + to_chat(user, ("There's not enough fuel.")) + return 0 + else if(istype(used_atom, /obj/item/weapon/wrench)) + playsound(holder, 'sound/items/Ratchet.ogg', 50, 1) + return 1 + else if(istype(used_atom, /obj/item/weapon/screwdriver)) + playsound(holder, 'sound/items/Screwdriver.ogg', 50, 1) + return 1 + else if(istype(used_atom, /obj/item/weapon/wirecutters)) + playsound(holder, 'sound/items/Wirecutter.ogg', 50, 1) + return 1 + else if(istype(used_atom, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = used_atom + if(!C.use(4)) + to_chat(user, ("There's not enough cable to finish the task.")) + return 0 + playsound(holder, 'sound/items/Deconstruct.ogg', 50, 1) + + else if(istype(used_atom, /obj/item/stack)) + var/obj/item/stack/S = used_atom + if(!S.use(5)) + to_chat(user, ("There's not enough material in this stack.")) + return 0 + if(istype(used_atom, /obj)) + var/obj/part = used_atom + if(part.crit_fail || part.reliability < 50) + user.visible_message("[user] was unable to connect [used_atom] to [holder].", "You failed to connect [used_atom] to [holder]") + return 0 + return 1 + + +/datum/construction/mecha/ripley_chassis + steps = list(list("key"=/obj/item/mecha_parts/part/ripley_torso),//1 + list("key"=/obj/item/mecha_parts/part/ripley_left_arm),//2 + list("key"=/obj/item/mecha_parts/part/ripley_right_arm),//3 + list("key"=/obj/item/mecha_parts/part/ripley_left_leg),//4 + list("key"=/obj/item/mecha_parts/part/ripley_right_leg)//5 + ) + + spawn_result() + var/obj/item/mecha_parts/chassis/const_holder = holder + const_holder.construct = new /datum/construction/reversible/mecha/ripley(const_holder) + const_holder.icon = 'icons/mecha/mech_construction.dmi' + const_holder.icon_state = "ripley0" + const_holder.density = 1 + const_holder.overlays.len = 0 + spawn() + qdel(src) + return + + +/datum/construction/reversible/mecha/ripley + result = "/obj/mecha/working/ripley" + steps = list( + //1 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="External armor is wrenched."), + //2 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="External armor is installed."), + //3 + list("key"=/obj/item/stack/sheet/plasteel, + "backkey"=/obj/item/weapon/weldingtool, + "desc"="Internal armor is welded."), + //4 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="Internal armor is wrenched"), + //5 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Internal armor is installed"), + //6 + list("key"=/obj/item/stack/sheet/metal, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Peripherals control module is secured"), + //7 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Peripherals control module is installed"), + //8 + list("key"=/obj/item/weapon/circuitboard/mecha/ripley/peripherals, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Central control module is secured"), + //9 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Central control module is installed"), + //10 + list("key"=/obj/item/weapon/circuitboard/mecha/ripley/main, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is adjusted"), + //11 + list("key"=/obj/item/weapon/wirecutters, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is added"), + //12 + list("key"=/obj/item/stack/cable_coil, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The hydraulic systems are active."), + //13 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are connected."), + //14 + list("key"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are disconnected.") + ) + + action(atom/used_atom,mob/user) + return check_step(used_atom,user) + + custom_action(index, diff, atom/used_atom, mob/user) + if(!..()) + return 0 + + //TODO: better messages. + switch(index) + if(14) + user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") + holder.icon_state = "ripley1" + if(13) + if(diff==FORWARD) + user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") + holder.icon_state = "ripley2" + else + user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") + holder.icon_state = "ripley0" + if(12) + if(diff==FORWARD) + user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") + holder.icon_state = "ripley3" + else + user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") + holder.icon_state = "ripley1" + if(11) + if(diff==FORWARD) + user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") + holder.icon_state = "ripley4" + else + user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") + new /obj/item/stack/cable_coil/random(get_turf(holder), 4) + holder.icon_state = "ripley2" + if(10) + if(diff==FORWARD) + user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") + qdel(used_atom) + holder.icon_state = "ripley5" + else + user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") + holder.icon_state = "ripley3" + if(9) + if(diff==FORWARD) + user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") + holder.icon_state = "ripley6" + else + user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") + new /obj/item/weapon/circuitboard/mecha/ripley/main(get_turf(holder)) + holder.icon_state = "ripley4" + if(8) + if(diff==FORWARD) + user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") + qdel(used_atom) + holder.icon_state = "ripley7" + else + user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") + holder.icon_state = "ripley5" + if(7) + if(diff==FORWARD) + user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") + holder.icon_state = "ripley8" + else + user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/ripley/peripherals(get_turf(holder)) + holder.icon_state = "ripley6" + if(6) + if(diff==FORWARD) + user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") + holder.icon_state = "ripley9" + else + user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") + holder.icon_state = "ripley7" + if(5) + if(diff==FORWARD) + user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") + holder.icon_state = "ripley10" + else + user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") + new /obj/item/stack/sheet/metal(get_turf(holder), 5) + holder.icon_state = "ripley8" + if(4) + if(diff==FORWARD) + user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") + holder.icon_state = "ripley11" + else + user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") + holder.icon_state = "ripley9" + if(3) + if(diff==FORWARD) + user.visible_message("[user] installs external reinforced armor layer to [holder].", "You install external reinforced armor layer to [holder].") + holder.icon_state = "ripley12" + else + user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") + holder.icon_state = "ripley10" + if(2) + if(diff==FORWARD) + user.visible_message("[user] secures external armor layer.", "You secure external reinforced armor layer.") + holder.icon_state = "ripley13" + else + user.visible_message("[user] pries external armor layer from [holder].", "You prie external armor layer from [holder].") + new /obj/item/stack/sheet/plasteel(get_turf(holder), 5) + holder.icon_state = "ripley11" + if(1) + if(diff==FORWARD) + user.visible_message("[user] welds external armor layer to [holder].", "You weld external armor layer to [holder].") + else + user.visible_message("[user] unfastens the external armor layer.", "You unfasten the external armor layer.") + holder.icon_state = "ripley12" + return 1 + + spawn_result() + ..() + feedback_inc("mecha_ripley_created",1) + return + + + +/datum/construction/mecha/gygax_chassis + steps = list(list("key"=/obj/item/mecha_parts/part/gygax_torso),//1 + list("key"=/obj/item/mecha_parts/part/gygax_left_arm),//2 + list("key"=/obj/item/mecha_parts/part/gygax_right_arm),//3 + list("key"=/obj/item/mecha_parts/part/gygax_left_leg),//4 + list("key"=/obj/item/mecha_parts/part/gygax_right_leg),//5 + list("key"=/obj/item/mecha_parts/part/gygax_head) + ) + + spawn_result() + var/obj/item/mecha_parts/chassis/const_holder = holder + const_holder.construct = new /datum/construction/reversible/mecha/gygax(const_holder) + const_holder.icon = 'icons/mecha/mech_construction.dmi' + const_holder.icon_state = "gygax0" + const_holder.density = 1 + spawn() + qdel(src) + return + + +/datum/construction/reversible/mecha/gygax + result = "/obj/mecha/combat/gygax" + steps = list( + //1 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="External armor is wrenched."), + //2 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="External armor is installed."), + //3 + list("key"=/obj/item/mecha_parts/part/gygax_armour, + "backkey"=/obj/item/weapon/weldingtool, + "desc"="Internal armor is welded."), + //4 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="Internal armor is wrenched"), + //5 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Internal armor is installed"), + //6 + list("key"=/obj/item/stack/sheet/metal, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Advanced capacitor is secured"), + //7 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Advanced capacitor is installed"), + //8 + list("key"=/obj/item/weapon/stock_parts/capacitor/adv, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Advanced scanner module is secured"), + //9 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Advanced scanner module is installed"), + //10 + list("key"=/obj/item/weapon/stock_parts/scanning_module/adv, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Targeting module is secured"), + //11 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Targeting module is installed"), + //12 + list("key"=/obj/item/weapon/circuitboard/mecha/gygax/targeting, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Peripherals control module is secured"), + //13 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Peripherals control module is installed"), + //14 + list("key"=/obj/item/weapon/circuitboard/mecha/gygax/peripherals, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Central control module is secured"), + //15 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Central control module is installed"), + //16 + list("key"=/obj/item/weapon/circuitboard/mecha/gygax/main, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is adjusted"), + //17 + list("key"=/obj/item/weapon/wirecutters, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is added"), + //18 + list("key"=/obj/item/stack/cable_coil, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The hydraulic systems are active."), + //19 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are connected."), + //20 + list("key"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are disconnected.") + ) + + action(atom/used_atom,mob/user) + return check_step(used_atom,user) + + custom_action(index, diff, atom/used_atom, mob/user) + if(!..()) + return 0 + + //TODO: better messages. + switch(index) + if(20) + user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") + holder.icon_state = "gygax1" + if(19) + if(diff==FORWARD) + user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") + holder.icon_state = "gygax2" + else + user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") + holder.icon_state = "gygax0" + if(18) + if(diff==FORWARD) + user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") + holder.icon_state = "gygax3" + else + user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") + holder.icon_state = "gygax1" + if(17) + if(diff==FORWARD) + user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") + holder.icon_state = "gygax4" + else + user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") + new /obj/item/stack/cable_coil/random(get_turf(holder), 4) + holder.icon_state = "gygax2" + if(16) + if(diff==FORWARD) + user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") + qdel(used_atom) + holder.icon_state = "gygax5" + else + user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") + holder.icon_state = "gygax3" + if(15) + if(diff==FORWARD) + user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") + holder.icon_state = "gygax6" + else + user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") + new /obj/item/weapon/circuitboard/mecha/gygax/main(get_turf(holder)) + holder.icon_state = "gygax4" + if(14) + if(diff==FORWARD) + user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") + qdel(used_atom) + holder.icon_state = "gygax7" + else + user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") + holder.icon_state = "gygax5" + if(13) + if(diff==FORWARD) + user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") + holder.icon_state = "gygax8" + else + user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/gygax/peripherals(get_turf(holder)) + holder.icon_state = "gygax6" + if(12) + if(diff==FORWARD) + user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") + qdel(used_atom) + holder.icon_state = "gygax9" + else + user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") + holder.icon_state = "gygax7" + if(11) + if(diff==FORWARD) + user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.") + holder.icon_state = "gygax10" + else + user.visible_message("[user] removes the weapon control module from [holder].", "You remove the weapon control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/gygax/targeting(get_turf(holder)) + holder.icon_state = "gygax8" + if(10) + if(diff==FORWARD) + user.visible_message("[user] installs advanced scanner module to [holder].", "You install advanced scanner module to [holder].") + qdel(used_atom) + holder.icon_state = "gygax11" + else + user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") + holder.icon_state = "gygax9" + if(9) + if(diff==FORWARD) + user.visible_message("[user] secures the advanced scanner module.", "You secure the advanced scanner module.") + holder.icon_state = "gygax12" + else + user.visible_message("[user] removes the advanced scanner module from [holder].", "You remove the advanced scanner module from [holder].") + new /obj/item/weapon/stock_parts/scanning_module/adv(get_turf(holder)) + holder.icon_state = "gygax10" + if(8) + if(diff==FORWARD) + user.visible_message("[user] installs advanced capacitor to [holder].", "You install advanced capacitor to [holder].") + qdel(used_atom) + holder.icon_state = "gygax13" + else + user.visible_message("[user] unfastens the advanced scanner module.", "You unfasten the advanced scanner module.") + holder.icon_state = "gygax11" + if(7) + if(diff==FORWARD) + user.visible_message("[user] secures the advanced capacitor.", "You secure the advanced capacitor.") + holder.icon_state = "gygax14" + else + user.visible_message("[user] removes the advanced capacitor from [holder].", "You remove the advanced capacitor from [holder].") + new /obj/item/weapon/stock_parts/capacitor/adv(get_turf(holder)) + holder.icon_state = "gygax12" + if(6) + if(diff==FORWARD) + user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") + holder.icon_state = "gygax15" + else + user.visible_message("[user] unfastens the advanced capacitor.", "You unfasten the advanced capacitor.") + holder.icon_state = "gygax13" + if(5) + if(diff==FORWARD) + user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") + holder.icon_state = "gygax16" + else + user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") + new /obj/item/stack/sheet/metal(get_turf(holder), 5) + holder.icon_state = "gygax14" + if(4) + if(diff==FORWARD) + user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") + holder.icon_state = "gygax17" + else + user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") + holder.icon_state = "gygax15" + if(3) + if(diff==FORWARD) + user.visible_message("[user] installs Gygax Armour Plates to [holder].", "You install Gygax Armour Plates to [holder].") + qdel(used_atom) + holder.icon_state = "gygax18" + else + user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") + holder.icon_state = "gygax16" + if(2) + if(diff==FORWARD) + user.visible_message("[user] secures Gygax Armour Plates.", "You secure Gygax Armour Plates.") + holder.icon_state = "gygax19" + else + user.visible_message("[user] pries Gygax Armour Plates from [holder].", "You prie Gygax Armour Plates from [holder].") + new /obj/item/mecha_parts/part/gygax_armour(get_turf(holder)) + holder.icon_state = "gygax17" + if(1) + if(diff==FORWARD) + user.visible_message("[user] welds Gygax Armour Plates to [holder].", "You weld Gygax Armour Plates to [holder].") + else + user.visible_message("[user] unfastens Gygax Armour Plates.", "You unfasten Gygax Armour Plates.") + holder.icon_state = "gygax18" + return 1 + + spawn_result() + ..() + feedback_inc("mecha_gygax_created",1) + return + +/datum/construction/mecha/firefighter_chassis + steps = list(list("key"=/obj/item/mecha_parts/part/ripley_torso),//1 + list("key"=/obj/item/mecha_parts/part/ripley_left_arm),//2 + list("key"=/obj/item/mecha_parts/part/ripley_right_arm),//3 + list("key"=/obj/item/mecha_parts/part/ripley_left_leg),//4 + list("key"=/obj/item/mecha_parts/part/ripley_right_leg),//5 + list("key"=/obj/item/clothing/suit/fire)//6 + ) + + + spawn_result() + var/obj/item/mecha_parts/chassis/const_holder = holder + const_holder.construct = new /datum/construction/reversible/mecha/firefighter(const_holder) + const_holder.icon = 'icons/mecha/mech_construction.dmi' + const_holder.icon_state = "fireripley0" + const_holder.density = 1 + spawn() + qdel(src) + return + + +/datum/construction/reversible/mecha/firefighter + result = "/obj/mecha/working/ripley/firefighter" + steps = list( + //1 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="External armor is wrenched."), + //2 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="External armor is installed."), + //3 + list("key"=/obj/item/stack/sheet/plasteel, + "backkey"=/obj/item/weapon/crowbar, + "desc"="External armor is being installed."), + //4 + list("key"=/obj/item/stack/sheet/plasteel, + "backkey"=/obj/item/weapon/weldingtool, + "desc"="Internal armor is welded."), + //5 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="Internal armor is wrenched"), + //6 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Internal armor is installed"), + + //7 + list("key"=/obj/item/stack/sheet/plasteel, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Peripherals control module is secured"), + //8 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Peripherals control module is installed"), + //9 + list("key"=/obj/item/weapon/circuitboard/mecha/ripley/peripherals, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Central control module is secured"), + //10 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Central control module is installed"), + //11 + list("key"=/obj/item/weapon/circuitboard/mecha/ripley/main, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is adjusted"), + //12 + list("key"=/obj/item/weapon/wirecutters, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is added"), + //13 + list("key"=/obj/item/stack/cable_coil, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The hydraulic systems are active."), + //14 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are connected."), + //15 + list("key"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are disconnected.") + ) + + action(atom/used_atom,mob/user) + return check_step(used_atom,user) + + custom_action(index, diff, atom/used_atom, mob/user) + if(!..()) + return 0 + + //TODO: better messages. + switch(index) + if(15) + user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") + holder.icon_state = "fireripley1" + if(14) + if(diff==FORWARD) + user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") + holder.icon_state = "fireripley2" + else + user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") + holder.icon_state = "fireripley0" + if(13) + if(diff==FORWARD) + user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") + holder.icon_state = "fireripley3" + else + user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") + holder.icon_state = "fireripley1" + if(12) + if(diff==FORWARD) + user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") + holder.icon_state = "fireripley4" + else + user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") + new /obj/item/stack/cable_coil/random(get_turf(holder), 4) + holder.icon_state = "fireripley2" + if(11) + if(diff==FORWARD) + user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") + qdel(used_atom) + holder.icon_state = "fireripley5" + else + user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") + holder.icon_state = "fireripley3" + if(10) + if(diff==FORWARD) + user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") + holder.icon_state = "fireripley6" + else + user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") + new /obj/item/weapon/circuitboard/mecha/ripley/main(get_turf(holder)) + holder.icon_state = "fireripley4" + if(9) + if(diff==FORWARD) + user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") + qdel(used_atom) + holder.icon_state = "fireripley7" + else + user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") + holder.icon_state = "fireripley5" + if(8) + if(diff==FORWARD) + user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") + holder.icon_state = "fireripley8" + else + user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/ripley/peripherals(get_turf(holder)) + holder.icon_state = "fireripley6" + if(7) + if(diff==FORWARD) + user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") + holder.icon_state = "fireripley9" + else + user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") + holder.icon_state = "fireripley7" + + if(6) + if(diff==FORWARD) + user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") + holder.icon_state = "fireripley10" + else + user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") + new /obj/item/stack/sheet/plasteel(get_turf(holder), 5) + holder.icon_state = "fireripley8" + if(5) + if(diff==FORWARD) + user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") + holder.icon_state = "fireripley11" + else + user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") + holder.icon_state = "fireripley9" + if(4) + if(diff==FORWARD) + user.visible_message("[user] starts to install the external armor layer to [holder].", "You start to install the external armor layer to [holder].") + holder.icon_state = "fireripley12" + else + user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") + holder.icon_state = "fireripley10" + if(3) + if(diff==FORWARD) + user.visible_message("[user] installs external reinforced armor layer to [holder].", "You install external reinforced armor layer to [holder].") + holder.icon_state = "fireripley13" + else + user.visible_message("[user] removes the external armor from [holder].", "You remove the external armor from [holder].") + new /obj/item/stack/sheet/plasteel(get_turf(holder), 5) + holder.icon_state = "fireripley11" + if(2) + if(diff==FORWARD) + user.visible_message("[user] secures external armor layer.", "You secure external reinforced armor layer.") + holder.icon_state = "fireripley14" + else + user.visible_message("[user] pries external armor layer from [holder].", "You prie external armor layer from [holder].") + new /obj/item/stack/sheet/plasteel(get_turf(holder), 5) + holder.icon_state = "fireripley12" + if(1) + if(diff==FORWARD) + user.visible_message("[user] welds external armor layer to [holder].", "You weld external armor layer to [holder].") + else + user.visible_message("[user] unfastens the external armor layer.", "You unfasten the external armor layer.") + holder.icon_state = "fireripley13" + return 1 + + spawn_result() + ..() + feedback_inc("mecha_firefighter_created",1) + return + + + +/datum/construction/mecha/honker_chassis + steps = list(list("key"=/obj/item/mecha_parts/part/honker_torso),//1 + list("key"=/obj/item/mecha_parts/part/honker_left_arm),//2 + list("key"=/obj/item/mecha_parts/part/honker_right_arm),//3 + list("key"=/obj/item/mecha_parts/part/honker_left_leg),//4 + list("key"=/obj/item/mecha_parts/part/honker_right_leg),//5 + list("key"=/obj/item/mecha_parts/part/honker_head) + ) + + spawn_result() + var/obj/item/mecha_parts/chassis/const_holder = holder + const_holder.construct = new /datum/construction/mecha/honker(const_holder) + const_holder.density = 1 + spawn() + qdel(src) + return + + +/datum/construction/mecha/honker + result = "/obj/mecha/combat/honker" + steps = list(list("key"=/obj/item/weapon/bikehorn),//1 + list("key"=/obj/item/clothing/shoes/clown_shoes),//2 + list("key"=/obj/item/weapon/bikehorn),//3 + list("key"=/obj/item/clothing/mask/gas/clown_hat),//4 + list("key"=/obj/item/weapon/bikehorn),//5 + list("key"=/obj/item/weapon/circuitboard/mecha/honker/targeting),//6 + list("key"=/obj/item/weapon/bikehorn),//7 + list("key"=/obj/item/weapon/circuitboard/mecha/honker/peripherals),//8 + list("key"=/obj/item/weapon/bikehorn),//9 + list("key"=/obj/item/weapon/circuitboard/mecha/honker/main),//10 + list("key"=/obj/item/weapon/bikehorn),//11 + ) + + action(atom/used_atom,mob/user) + return check_step(used_atom,user) + + custom_action(step, 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!") + + //TODO: better messages. + switch(step) + if(10) + user.visible_message("[user] installs the central control module into [holder].", "You install the central control module into [holder].") + qdel(used_atom) + if(8) + user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") + qdel(used_atom) + if(6) + user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") + qdel(used_atom) + if(4) + user.visible_message("[user] puts clown wig and mask on [holder].", "You put clown wig and mask on [holder].") + qdel(used_atom) + if(2) + user.visible_message("[user] puts clown boots on [holder].", "You put clown boots on [holder].") + qdel(used_atom) + return 1 + + spawn_result() + ..() + feedback_inc("mecha_honker_created",1) + return + +/datum/construction/mecha/durand_chassis + steps = list(list("key"=/obj/item/mecha_parts/part/durand_torso),//1 + list("key"=/obj/item/mecha_parts/part/durand_left_arm),//2 + list("key"=/obj/item/mecha_parts/part/durand_right_arm),//3 + list("key"=/obj/item/mecha_parts/part/durand_left_leg),//4 + list("key"=/obj/item/mecha_parts/part/durand_right_leg),//5 + list("key"=/obj/item/mecha_parts/part/durand_head) + ) + + + spawn_result() + var/obj/item/mecha_parts/chassis/const_holder = holder + const_holder.construct = new /datum/construction/reversible/mecha/durand(const_holder) + const_holder.icon = 'icons/mecha/mech_construction.dmi' + const_holder.icon_state = "durand0" + const_holder.density = 1 + spawn() + qdel(src) + return + +/datum/construction/reversible/mecha/durand + result = "/obj/mecha/combat/durand" + steps = list( + //1 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="External armor is wrenched."), + //2 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="External armor is installed."), + //3 + list("key"=/obj/item/mecha_parts/part/durand_armour, + "backkey"=/obj/item/weapon/weldingtool, + "desc"="Internal armor is welded."), + //4 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="Internal armor is wrenched"), + //5 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Internal armor is installed"), + //6 + list("key"=/obj/item/stack/sheet/metal, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Advanced capacitor is secured"), + //7 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Advanced capacitor is installed"), + //8 + list("key"=/obj/item/weapon/stock_parts/capacitor/adv, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Advanced scanner module is secured"), + //9 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Advanced scanner module is installed"), + //10 + list("key"=/obj/item/weapon/stock_parts/scanning_module/adv, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Targeting module is secured"), + //11 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Targeting module is installed"), + //12 + list("key"=/obj/item/weapon/circuitboard/mecha/durand/targeting, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Peripherals control module is secured"), + //13 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Peripherals control module is installed"), + //14 + list("key"=/obj/item/weapon/circuitboard/mecha/durand/peripherals, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Central control module is secured"), + //15 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Central control module is installed"), + //16 + list("key"=/obj/item/weapon/circuitboard/mecha/durand/main, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is adjusted"), + //17 + list("key"=/obj/item/weapon/wirecutters, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is added"), + //18 + list("key"=/obj/item/stack/cable_coil, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The hydraulic systems are active."), + //19 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are connected."), + //20 + list("key"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are disconnected.") + ) + + + action(atom/used_atom,mob/user) + return check_step(used_atom,user) + + custom_action(index, diff, atom/used_atom, mob/user) + if(!..()) + return 0 + + //TODO: better messages. + switch(index) + if(20) + user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") + holder.icon_state = "durand1" + if(19) + if(diff==FORWARD) + user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") + holder.icon_state = "durand2" + else + user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") + holder.icon_state = "durand0" + if(18) + if(diff==FORWARD) + user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") + holder.icon_state = "durand3" + else + user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") + holder.icon_state = "durand1" + if(17) + if(diff==FORWARD) + user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") + holder.icon_state = "durand4" + else + user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") + new /obj/item/stack/cable_coil/random(get_turf(holder), 4) + holder.icon_state = "durand2" + if(16) + if(diff==FORWARD) + user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") + qdel(used_atom) + holder.icon_state = "durand5" + else + user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") + holder.icon_state = "durand3" + if(15) + if(diff==FORWARD) + user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") + holder.icon_state = "durand6" + else + user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") + new /obj/item/weapon/circuitboard/mecha/durand/main(get_turf(holder)) + holder.icon_state = "durand4" + if(14) + if(diff==FORWARD) + user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") + qdel(used_atom) + holder.icon_state = "durand7" + else + user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") + holder.icon_state = "durand5" + if(13) + if(diff==FORWARD) + user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") + holder.icon_state = "durand8" + else + user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/durand/peripherals(get_turf(holder)) + holder.icon_state = "durand6" + if(12) + if(diff==FORWARD) + user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") + qdel(used_atom) + holder.icon_state = "durand9" + else + user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") + holder.icon_state = "durand7" + if(11) + if(diff==FORWARD) + user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.") + holder.icon_state = "durand10" + else + user.visible_message("[user] removes the weapon control module from [holder].", "You remove the weapon control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/durand/targeting(get_turf(holder)) + holder.icon_state = "durand8" + if(10) + if(diff==FORWARD) + user.visible_message("[user] installs advanced scanner module to [holder].", "You install advanced scanner module to [holder].") + qdel(used_atom) + holder.icon_state = "durand11" + else + user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") + holder.icon_state = "durand9" + if(9) + if(diff==FORWARD) + user.visible_message("[user] secures the advanced scanner module.", "You secure the advanced scanner module.") + holder.icon_state = "durand12" + else + user.visible_message("[user] removes the advanced scanner module from [holder].", "You remove the advanced scanner module from [holder].") + new /obj/item/weapon/stock_parts/scanning_module/adv(get_turf(holder)) + holder.icon_state = "durand10" + if(8) + if(diff==FORWARD) + user.visible_message("[user] installs advanced capacitor to [holder].", "You install advanced capacitor to [holder].") + qdel(used_atom) + holder.icon_state = "durand13" + else + user.visible_message("[user] unfastens the advanced scanner module.", "You unfasten the advanced scanner module.") + holder.icon_state = "durand11" + if(7) + if(diff==FORWARD) + user.visible_message("[user] secures the advanced capacitor.", "You secure the advanced capacitor.") + holder.icon_state = "durand14" + else + user.visible_message("[user] removes the advanced capacitor from [holder].", "You remove the advanced capacitor from [holder].") + new /obj/item/weapon/stock_parts/capacitor/adv(get_turf(holder)) + holder.icon_state = "durand12" + if(6) + if(diff==FORWARD) + user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") + holder.icon_state = "durand15" + else + user.visible_message("[user] unfastens the advanced capacitor.", "You unfasten the advanced capacitor.") + holder.icon_state = "durand13" + if(5) + if(diff==FORWARD) + user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") + holder.icon_state = "durand16" + else + user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") + new /obj/item/stack/sheet/metal(get_turf(holder), 5) + holder.icon_state = "durand14" + if(4) + if(diff==FORWARD) + user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") + holder.icon_state = "durand17" + else + user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") + holder.icon_state = "durand15" + if(3) + if(diff==FORWARD) + user.visible_message("[user] installs Durand Armour Plates to [holder].", "You install Durand Armour Plates to [holder].") + qdel(used_atom) + holder.icon_state = "durand18" + else + user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") + holder.icon_state = "durand16" + if(2) + if(diff==FORWARD) + user.visible_message("[user] secures Durand Armour Plates.", "You secure Durand Armour Plates.") + holder.icon_state = "durand19" + else + user.visible_message("[user] pries Durand Armour Plates from [holder].", "You prie Durand Armour Plates from [holder].") + new /obj/item/mecha_parts/part/durand_armour(get_turf(holder)) + holder.icon_state = "durand17" + if(1) + if(diff==FORWARD) + user.visible_message("[user] welds Durand Armour Plates to [holder].", "You weld Durand Armour Plates to [holder].") + else + user.visible_message("[user] unfastens Durand Armour Plates.", "You unfasten Durand Armour Plates.") + holder.icon_state = "durand18" + return 1 + + spawn_result() + ..() + feedback_inc("mecha_durand_created",1) + return + + +/datum/construction/mecha/phazon_chassis + result = "/obj/mecha/combat/phazon" + steps = list(list("key"=/obj/item/mecha_parts/part/phazon_torso),//1 + list("key"=/obj/item/mecha_parts/part/phazon_left_arm),//2 + list("key"=/obj/item/mecha_parts/part/phazon_right_arm),//3 + list("key"=/obj/item/mecha_parts/part/phazon_left_leg),//4 + list("key"=/obj/item/mecha_parts/part/phazon_right_leg),//5 + list("key"=/obj/item/mecha_parts/part/phazon_head) + ) + + + +/datum/construction/mecha/odysseus_chassis + steps = list(list("key"=/obj/item/mecha_parts/part/odysseus_torso),//1 + list("key"=/obj/item/mecha_parts/part/odysseus_head),//2 + list("key"=/obj/item/mecha_parts/part/odysseus_left_arm),//3 + list("key"=/obj/item/mecha_parts/part/odysseus_right_arm),//4 + list("key"=/obj/item/mecha_parts/part/odysseus_left_leg),//5 + list("key"=/obj/item/mecha_parts/part/odysseus_right_leg)//6 + ) + + + spawn_result() + var/obj/item/mecha_parts/chassis/const_holder = holder + const_holder.construct = new /datum/construction/reversible/mecha/odysseus(const_holder) + const_holder.icon = 'icons/mecha/mech_construction.dmi' + const_holder.icon_state = "odysseus0" + const_holder.density = 1 + spawn() + qdel(src) + return + + +/datum/construction/reversible/mecha/odysseus + result = "/obj/mecha/medical/odysseus" + steps = list( + //1 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="External armor is wrenched."), + //2 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="External armor is installed."), + //3 + list("key"=/obj/item/stack/sheet/plasteel, + "backkey"=/obj/item/weapon/weldingtool, + "desc"="Internal armor is welded."), + //4 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="Internal armor is wrenched"), + //5 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Internal armor is installed"), + //6 + list("key"=/obj/item/stack/sheet/metal, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Peripherals control module is secured"), + //7 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Peripherals control module is installed"), + //8 + list("key"=/obj/item/weapon/circuitboard/mecha/odysseus/peripherals, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Central control module is secured"), + //9 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Central control module is installed"), + //10 + list("key"=/obj/item/weapon/circuitboard/mecha/odysseus/main, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is adjusted"), + //11 + list("key"=/obj/item/weapon/wirecutters, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is added"), + //12 + list("key"=/obj/item/stack/cable_coil, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The hydraulic systems are active."), + //13 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are connected."), + //14 + list("key"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are disconnected.") + ) + + action(atom/used_atom,mob/user) + return check_step(used_atom,user) + + custom_action(index, diff, atom/used_atom, mob/user) + if(!..()) + return 0 + + //TODO: better messages. + switch(index) + if(14) + user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") + holder.icon_state = "odysseus1" + if(13) + if(diff==FORWARD) + user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") + holder.icon_state = "odysseus2" + else + user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") + holder.icon_state = "odysseus0" + if(12) + if(diff==FORWARD) + user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") + holder.icon_state = "odysseus3" + else + user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") + holder.icon_state = "odysseus1" + if(11) + if(diff==FORWARD) + user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") + holder.icon_state = "odysseus4" + else + user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") + new /obj/item/stack/cable_coil/random(get_turf(holder), 4) + holder.icon_state = "odysseus2" + if(10) + if(diff==FORWARD) + user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") + qdel(used_atom) + holder.icon_state = "odysseus5" + else + user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") + holder.icon_state = "odysseus3" + if(9) + if(diff==FORWARD) + user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") + holder.icon_state = "odysseus6" + else + user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") + new /obj/item/weapon/circuitboard/mecha/odysseus/main(get_turf(holder)) + holder.icon_state = "odysseus4" + if(8) + if(diff==FORWARD) + user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") + qdel(used_atom) + holder.icon_state = "odysseus7" + else + user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") + holder.icon_state = "odysseus5" + if(7) + if(diff==FORWARD) + user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") + holder.icon_state = "odysseus8" + else + user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/odysseus/peripherals(get_turf(holder)) + holder.icon_state = "odysseus6" + if(6) + if(diff==FORWARD) + user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") + holder.icon_state = "odysseus9" + else + user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") + holder.icon_state = "odysseus7" + if(5) + if(diff==FORWARD) + user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") + holder.icon_state = "odysseus10" + else + user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") + new /obj/item/stack/sheet/metal(get_turf(holder), 5) + holder.icon_state = "odysseus8" + if(4) + if(diff==FORWARD) + user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") + holder.icon_state = "odysseus11" + else + user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") + holder.icon_state = "odysseus9" + if(3) + if(diff==FORWARD) + user.visible_message("[user] installs [used_atom] layer to [holder].", "You install external reinforced armor layer to [holder].") + + holder.icon_state = "odysseus12" + else + user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") + holder.icon_state = "odysseus10" + if(2) + if(diff==FORWARD) + user.visible_message("[user] secures external armor layer.", "You secure external reinforced armor layer.") + holder.icon_state = "odysseus13" + else + var/obj/item/stack/sheet/plasteel/MS = new (get_turf(holder), 5) + user.visible_message("[user] pries [MS] from [holder].", "You prie [MS] from [holder].") + holder.icon_state = "odysseus11" + if(1) + if(diff==FORWARD) + user.visible_message("[user] welds external armor layer to [holder].", "You weld external armor layer to [holder].") + holder.icon_state = "odysseus14" + else + user.visible_message("[user] unfastens the external armor layer.", "You unfasten the external armor layer.") + holder.icon_state = "odysseus12" + return 1 + + spawn_result() + ..() + feedback_inc("mecha_odysseus_created",1) + return + +/datum/construction/mecha/vindicator_chassis + steps = list(list("key"=/obj/item/mecha_parts/part/vindicator_torso),//1 + list("key"=/obj/item/mecha_parts/part/vindicator_left_arm),//2 + list("key"=/obj/item/mecha_parts/part/vindicator_right_arm),//3 + list("key"=/obj/item/mecha_parts/part/vindicator_left_leg),//4 + list("key"=/obj/item/mecha_parts/part/vindicator_right_leg),//5 + list("key"=/obj/item/mecha_parts/part/vindicator_head) + ) + + spawn_result() + var/obj/item/mecha_parts/chassis/const_holder = holder + const_holder.construct = new /datum/construction/reversible/mecha/vindicator(const_holder) + const_holder.icon = 'icons/mecha/mech_construction.dmi' + const_holder.icon_state = "vindicator0" + const_holder.density = 1 + spawn() + qdel(src) + return + +/datum/construction/reversible/mecha/vindicator + result = "/obj/mecha/combat/durand/vindicator" + steps = list( + //1 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="External armor is wrenched."), + //2 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="External armor is installed."), + //3 + list("key"=/obj/item/mecha_parts/part/vindicator_armour, + "backkey"=/obj/item/weapon/weldingtool, + "desc"="Internal armor is welded."), + //4 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="Internal armor is wrenched"), + //5 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Internal armor is installed"), + //6 + list("key"=/obj/item/stack/sheet/metal, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Advanced capacitor is secured"), + //7 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Advanced capacitor is installed"), + //8 + list("key"=/obj/item/weapon/stock_parts/capacitor/super, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Advanced scanner module is secured"), + //9 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Advanced scanner module is installed"), + //10 + list("key"=/obj/item/weapon/stock_parts/scanning_module/phasic, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Targeting module is secured"), + //11 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Targeting module is installed"), + //12 + list("key"=/obj/item/weapon/circuitboard/mecha/vindicator/targeting, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Peripherals control module is secured"), + //13 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Peripherals control module is installed"), + //14 + list("key"=/obj/item/weapon/circuitboard/mecha/vindicator/peripherals, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Central control module is secured"), + //15 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Central control module is installed"), + //16 + list("key"=/obj/item/weapon/circuitboard/mecha/vindicator/main, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is adjusted"), + //17 + list("key"=/obj/item/weapon/wirecutters, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is added"), + //18 + list("key"=/obj/item/stack/cable_coil, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The hydraulic systems are active."), + //19 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are connected."), + //20 + list("key"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are disconnected.") + ) + + + action(atom/used_atom,mob/user) + return check_step(used_atom,user) + + custom_action(index, diff, atom/used_atom, mob/user) + if(!..()) + return 0 + + //TODO: better messages. + switch(index) + if(20) + user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") + holder.icon_state = "vindicator1" + if(19) + if(diff==FORWARD) + user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") + holder.icon_state = "vindicator2" + else + user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") + holder.icon_state = "vindicator0" + if(18) + if(diff==FORWARD) + user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") + holder.icon_state = "vindicator3" + else + user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") + holder.icon_state = "vindicator1" + if(17) + if(diff==FORWARD) + user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") + holder.icon_state = "vindicator4" + else + user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") + new /obj/item/stack/cable_coil/random(get_turf(holder), 30) + holder.icon_state = "vindicator2" + if(16) + if(diff==FORWARD) + user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") + qdel(used_atom) + holder.icon_state = "vindicator5" + else + user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") + holder.icon_state = "vindicator3" + if(15) + if(diff==FORWARD) + user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") + holder.icon_state = "vindicator6" + else + user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") + new /obj/item/weapon/circuitboard/mecha/vindicator/main(get_turf(holder)) + holder.icon_state = "vindicator4" + if(14) + if(diff==FORWARD) + user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") + qdel(used_atom) + holder.icon_state = "vindicator7" + else + user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") + holder.icon_state = "vindicator5" + if(13) + if(diff==FORWARD) + user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") + holder.icon_state = "vindicator8" + else + user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/vindicator/peripherals(get_turf(holder)) + holder.icon_state = "vindicator6" + if(12) + if(diff==FORWARD) + user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") + qdel(used_atom) + holder.icon_state = "vindicator9" + else + user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") + holder.icon_state = "vindicator7" + if(11) + if(diff==FORWARD) + user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.") + holder.icon_state = "vindicator10" + else + user.visible_message("[user] removes the weapon control module from [holder].", "You remove the weapon control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/vindicator/targeting(get_turf(holder)) + holder.icon_state = "vindicator8" + if(10) + if(diff==FORWARD) + user.visible_message("[user] installs phasic scanner module to [holder].", "You install phasic scanner module to [holder].") + qdel(used_atom) + holder.icon_state = "vindicator11" + else + user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") + holder.icon_state = "vindicator9" + if(9) + if(diff==FORWARD) + user.visible_message("[user] secures the phasic scanner module.", "You secure the phasic scanner module.") + holder.icon_state = "vindicator12" + else + user.visible_message("[user] removes the phasic scanner module from [holder].", "You remove the phasic scanner module from [holder].") + new /obj/item/weapon/stock_parts/scanning_module/phasic(get_turf(holder)) + holder.icon_state = "vindicator10" + if(8) + if(diff==FORWARD) + user.visible_message("[user] installs super capacitor to [holder].", "You install super capacitor to [holder].") + qdel(used_atom) + holder.icon_state = "vindicator13" + else + user.visible_message("[user] unfastens the phasic scanner module.", "You unfasten the phasic scanner module.") + holder.icon_state = "vindicator11" + if(7) + if(diff==FORWARD) + user.visible_message("[user] secures the super capacitor.", "You secure the super capacitor.") + holder.icon_state = "vindicator14" + else + user.visible_message("[user] removes the super capacitor from [holder].", "You remove the super capacitor from [holder].") + new /obj/item/weapon/stock_parts/capacitor/super(get_turf(holder)) + holder.icon_state = "vindicator12" + if(6) + if(diff==FORWARD) + user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") + holder.icon_state = "vindicator15" + else + user.visible_message("[user] unfastens the super capacitor.", "You unfasten the super capacitor.") + holder.icon_state = "vindicator13" + if(5) + if(diff==FORWARD) + user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") + holder.icon_state = "vindicator16" + else + user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") + new /obj/item/stack/sheet/metal(get_turf(holder), 30) + holder.icon_state = "vindicator14" + if(4) + if(diff==FORWARD) + user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") + holder.icon_state = "vindicator17" + else + user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") + holder.icon_state = "vindicator15" + if(3) + if(diff==FORWARD) + user.visible_message("[user] installs Vindicator Armour Plates to [holder].", "You install Vindicator Armour Plates to [holder].") + qdel(used_atom) + holder.icon_state = "vindicator18" + else + user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") + holder.icon_state = "vindicator16" + if(2) + if(diff==FORWARD) + user.visible_message("[user] secures Vindicator Armour Plates.", "You secure Vindicator Armour Plates.") + holder.icon_state = "vindicator19" + else + user.visible_message("[user] pries Vindicator Armour Plates from [holder].", "You prie Vindicator Armour Plates from [holder].") + new /obj/item/mecha_parts/part/vindicator_armour(get_turf(holder)) + holder.icon_state = "vindicator17" + if(1) + if(diff==FORWARD) + user.visible_message("[user] welds Vindicator Armour Plates to [holder].", "You weld Vindicator Armour Plates to [holder].") + else + user.visible_message("[user] unfastens Vindicator Armour Plates.", "You unfasten Vindicator Armour Plates.") + holder.icon_state = "vindicator18" + return 1 + + spawn_result() + ..() + feedback_inc("mecha_vindicator_created",1) + return + +/datum/construction/mecha/ultra_chassis + steps = list(list("key"=/obj/item/mecha_parts/part/ultra_torso),//1 + list("key"=/obj/item/mecha_parts/part/ultra_left_arm),//2 + list("key"=/obj/item/mecha_parts/part/ultra_right_arm),//3 + list("key"=/obj/item/mecha_parts/part/ultra_left_leg),//4 + list("key"=/obj/item/mecha_parts/part/ultra_right_leg),//5 + list("key"=/obj/item/mecha_parts/part/ultra_head) + ) + + spawn_result() + var/obj/item/mecha_parts/chassis/const_holder = holder + const_holder.construct = new /datum/construction/reversible/mecha/ultra(const_holder) + const_holder.icon = 'icons/mecha/mech_construction.dmi' + const_holder.icon_state = "ultra0" + const_holder.density = 1 + spawn() + qdel(src) + return + + +/datum/construction/reversible/mecha/ultra + result = "/obj/mecha/combat/gygax/ultra" + steps = list( + //1 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="External armor is wrenched."), + //2 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="External armor is installed."), + //3 + list("key"=/obj/item/mecha_parts/part/ultra_armour, + "backkey"=/obj/item/weapon/weldingtool, + "desc"="Internal armor is welded."), + //4 + list("key"=/obj/item/weapon/weldingtool, + "backkey"=/obj/item/weapon/wrench, + "desc"="Internal armor is wrenched"), + //5 + list("key"=/obj/item/weapon/wrench, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Internal armor is installed"), + //6 + list("key"=/obj/item/stack/sheet/metal, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Super capacitor is secured"), + //7 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Super capacitor is installed"), + //8 + list("key"=/obj/item/weapon/stock_parts/capacitor/super, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Phasic scanner module is secured"), + //9 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Phasic scanner module is installed"), + //10 + list("key"=/obj/item/weapon/stock_parts/scanning_module/phasic, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Targeting module is secured"), + //11 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Targeting module is installed"), + //12 + list("key"=/obj/item/weapon/circuitboard/mecha/ultra/targeting, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Peripherals control module is secured"), + //13 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Peripherals control module is installed"), + //14 + list("key"=/obj/item/weapon/circuitboard/mecha/ultra/peripherals, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="Central control module is secured"), + //15 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/crowbar, + "desc"="Central control module is installed"), + //16 + list("key"=/obj/item/weapon/circuitboard/mecha/ultra/main, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is adjusted"), + //17 + list("key"=/obj/item/weapon/wirecutters, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The wiring is added"), + //18 + list("key"=/obj/item/stack/cable_coil, + "backkey"=/obj/item/weapon/screwdriver, + "desc"="The hydraulic systems are active."), + //19 + list("key"=/obj/item/weapon/screwdriver, + "backkey"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are connected."), + //20 + list("key"=/obj/item/weapon/wrench, + "desc"="The hydraulic systems are disconnected.") + ) + + action(atom/used_atom,mob/user) + return check_step(used_atom,user) + + custom_action(index, diff, atom/used_atom, mob/user) + if(!..()) + return 0 + + //TODO: better messages. + switch(index) + if(20) + user.visible_message("[user] connects [holder] hydraulic systems", "You connect [holder] hydraulic systems.") + holder.icon_state = "ultra1" + if(19) + if(diff==FORWARD) + user.visible_message("[user] activates [holder] hydraulic systems.", "You activate [holder] hydraulic systems.") + holder.icon_state = "ultra2" + else + user.visible_message("[user] disconnects [holder] hydraulic systems", "You disconnect [holder] hydraulic systems.") + holder.icon_state = "ultra0" + if(18) + if(diff==FORWARD) + user.visible_message("[user] adds the wiring to [holder].", "You add the wiring to [holder].") + holder.icon_state = "ultra3" + else + user.visible_message("[user] deactivates [holder] hydraulic systems.", "You deactivate [holder] hydraulic systems.") + holder.icon_state = "ultra1" + if(17) + if(diff==FORWARD) + user.visible_message("[user] adjusts the wiring of [holder].", "You adjust the wiring of [holder].") + holder.icon_state = "ultra4" + else + user.visible_message("[user] removes the wiring from [holder].", "You remove the wiring from [holder].") + new /obj/item/stack/cable_coil/random(get_turf(holder), 4) + holder.icon_state = "ultra2" + if(16) + if(diff==FORWARD) + user.visible_message("[user] installs the central control module into [holder].", "You install the central computer mainboard into [holder].") + qdel(used_atom) + holder.icon_state = "ultra5" + else + user.visible_message("[user] disconnects the wiring of [holder].", "You disconnect the wiring of [holder].") + holder.icon_state = "ultra3" + if(15) + if(diff==FORWARD) + user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") + holder.icon_state = "ultra6" + else + user.visible_message("[user] removes the central control module from [holder].", "You remove the central computer mainboard from [holder].") + new /obj/item/weapon/circuitboard/mecha/ultra/main(get_turf(holder)) + holder.icon_state = "ultra4" + if(14) + if(diff==FORWARD) + user.visible_message("[user] installs the peripherals control module into [holder].", "You install the peripherals control module into [holder].") + qdel(used_atom) + holder.icon_state = "ultra7" + else + user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") + holder.icon_state = "ultra5" + if(13) + if(diff==FORWARD) + user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") + holder.icon_state = "ultra8" + else + user.visible_message("[user] removes the peripherals control module from [holder].", "You remove the peripherals control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/ultra/peripherals(get_turf(holder)) + holder.icon_state = "ultra6" + if(12) + if(diff==FORWARD) + user.visible_message("[user] installs the weapon control module into [holder].", "You install the weapon control module into [holder].") + qdel(used_atom) + holder.icon_state = "ultra9" + else + user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") + holder.icon_state = "ultra7" + if(11) + if(diff==FORWARD) + user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.") + holder.icon_state = "ultra10" + else + user.visible_message("[user] removes the weapon control module from [holder].", "You remove the weapon control module from [holder].") + new /obj/item/weapon/circuitboard/mecha/ultra/targeting(get_turf(holder)) + holder.icon_state = "ultra8" + if(10) + if(diff==FORWARD) + user.visible_message("[user] installs advanced scanner module to [holder].", "You install phasic scanner module to [holder].") + qdel(used_atom) + holder.icon_state = "ultra11" + else + user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") + holder.icon_state = "ultra9" + if(9) + if(diff==FORWARD) + user.visible_message("[user] secures the phasic scanner module.", "You secure the phasic scanner module.") + holder.icon_state = "ultra12" + else + user.visible_message("[user] removes the phasic scanner module from [holder].", "You remove the phasic scanner module from [holder].") + new /obj/item/weapon/stock_parts/scanning_module/phasic(get_turf(holder)) + holder.icon_state = "ultra10" + if(8) + if(diff==FORWARD) + user.visible_message("[user] installs super capacitor to [holder].", "You install super capacitor to [holder].") + qdel(used_atom) + holder.icon_state = "ultra13" + else + user.visible_message("[user] unfastens the phasic scanner module.", "You unfasten the phasic scanner module.") + holder.icon_state = "ultra11" + if(7) + if(diff==FORWARD) + user.visible_message("[user] secures the super capacitor.", "You secure the super capacitor.") + holder.icon_state = "ultra14" + else + user.visible_message("[user] removes the super capacitor from [holder].", "You remove the super capacitor from [holder].") + new /obj/item/weapon/stock_parts/capacitor/super(get_turf(holder)) + holder.icon_state = "ultra12" + if(6) + if(diff==FORWARD) + user.visible_message("[user] installs internal armor layer to [holder].", "You install internal armor layer to [holder].") + holder.icon_state = "ultra15" + else + user.visible_message("[user] unfastens the super capacitor.", "You unfasten the super capacitor.") + holder.icon_state = "ultra13" + if(5) + if(diff==FORWARD) + user.visible_message("[user] secures internal armor layer.", "You secure internal armor layer.") + holder.icon_state = "ultra16" + else + user.visible_message("[user] pries internal armor layer from [holder].", "You prie internal armor layer from [holder].") + new /obj/item/stack/sheet/metal(get_turf(holder), 5) + holder.icon_state = "ultra14" + if(4) + if(diff==FORWARD) + user.visible_message("[user] welds internal armor layer to [holder].", "You weld the internal armor layer to [holder].") + holder.icon_state = "ultra17" + else + user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") + holder.icon_state = "ultra15" + if(3) + if(diff==FORWARD) + user.visible_message("[user] installs Gygax Ultra Armour Plates to [holder].", "You install Gygax Ultra Armour Plates to [holder].") + qdel(used_atom) + holder.icon_state = "ultra18" + else + user.visible_message("[user] cuts internal armor layer from [holder].", "You cut the internal armor layer from [holder].") + holder.icon_state = "ultra16" + if(2) + if(diff==FORWARD) + user.visible_message("[user] secures Gygax Ultra Armour Plates.", "You secure Gygax Ultra Armour Plates.") + holder.icon_state = "ultra19" + else + user.visible_message("[user] pries Gygax Ultra Armour Plates from [holder].", "You prie Gygax Ultra Armour Plates from [holder].") + new /obj/item/mecha_parts/part/ultra_armour(get_turf(holder)) + holder.icon_state = "ultra17" + if(1) + if(diff==FORWARD) + user.visible_message("[user] welds Gygax Ultra Armour Plates to [holder].", "You weld Gygax Ultra Armour Plates to [holder].") + else + user.visible_message("[user] unfastens Gygax Ultra Armour Plates.", "You unfasten Gygax Ultra Armour Plates.") + holder.icon_state = "ultra18" + return 1 + + spawn_result() + ..() + feedback_inc("mecha_ultra_created",1) + return diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index 95d08460a451..4d1ce99c9aa9 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -1,126 +1,126 @@ -/obj/machinery/computer/mecha - name = "Exosuit Control" - icon = 'icons/obj/computer.dmi' - icon_state = "mecha" - light_color = "#a97faa" - req_access = list(access_robotics) - circuit = "/obj/item/weapon/circuitboard/mecha_control" - var/list/located = list() - var/screen = 0 - var/stored_data - -/obj/machinery/computer/mecha/ui_interact(mob/user) - var/dat = "[name]" - if(screen == 0) - dat += "

                    Tracking beacons data

                    " - for(var/obj/item/mecha_parts/mecha_tracking/TR in mecha_tracking_list) - var/answer = TR.get_mecha_info() - if(answer) - dat += {"
                    [answer]
                    - Send message
                    - Show exosuit log | (EMP pulse)
                    "} - - if(screen == 1) - dat += "

                    Log contents

                    " - dat += "Return
                    " - dat += "[stored_data]" - - dat += "(Refresh)
                    " - dat += "" - - user << browse(entity_ja(dat), "window=computer;size=400x500") - onclose(user, "computer") - -/obj/machinery/computer/mecha/Topic(href, href_list) - . = ..() - if(!.) - return - - var/datum/topic_input/F = new /datum/topic_input(href,href_list) - if(href_list["send_message"]) - var/obj/item/mecha_parts/mecha_tracking/MT = F.getObj("send_message") - var/message = sanitize(input(usr,"Input message","Transmit message") as text) - var/obj/mecha/M = MT.in_mecha() - if(message && M) - M.occupant_message(message) - else if(href_list["shock"]) - var/obj/item/mecha_parts/mecha_tracking/MT = F.getObj("shock") - MT.shock() - else if(href_list["get_log"]) - var/obj/item/mecha_parts/mecha_tracking/MT = F.getObj("get_log") - stored_data = MT.get_mecha_log() - screen = 1 - else if(href_list["return"]) - screen = 0 - - src.updateUsrDialog() - - - -/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" - -/obj/item/mecha_parts/mecha_tracking/atom_init() - . = ..() - mecha_tracking_list += src - -/obj/item/mecha_parts/mecha_tracking/Destroy() - mecha_tracking_list -= src - return ..() - -/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.emp_act(2) - qdel(src) - -/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/atom_init() - . = ..() - for (var/i in 1 to 7) - new /obj/item/mecha_parts/mecha_tracking(src) - make_exact_fit() +/obj/machinery/computer/mecha + name = "Exosuit Control" + icon = 'icons/obj/computer.dmi' + icon_state = "mecha" + light_color = "#a97faa" + req_access = list(access_robotics) + circuit = "/obj/item/weapon/circuitboard/mecha_control" + var/list/located = list() + var/screen = 0 + var/stored_data + +/obj/machinery/computer/mecha/ui_interact(mob/user) + var/dat = "[name]" + if(screen == 0) + dat += "

                    Tracking beacons data

                    " + for(var/obj/item/mecha_parts/mecha_tracking/TR in mecha_tracking_list) + var/answer = TR.get_mecha_info() + if(answer) + dat += {"
                    [answer]
                    + Send message
                    + Show exosuit log | (EMP pulse)
                    "} + + if(screen == 1) + dat += "

                    Log contents

                    " + dat += "Return
                    " + dat += "[stored_data]" + + dat += "(Refresh)
                    " + dat += "" + + user << browse(entity_ja(dat), "window=computer;size=400x500") + onclose(user, "computer") + +/obj/machinery/computer/mecha/Topic(href, href_list) + . = ..() + if(!.) + return + + var/datum/topic_input/F = new /datum/topic_input(href,href_list) + if(href_list["send_message"]) + var/obj/item/mecha_parts/mecha_tracking/MT = F.getObj("send_message") + var/message = sanitize(input(usr,"Input message","Transmit message") as text) + var/obj/mecha/M = MT.in_mecha() + if(message && M) + M.occupant_message(message) + else if(href_list["shock"]) + var/obj/item/mecha_parts/mecha_tracking/MT = F.getObj("shock") + MT.shock() + else if(href_list["get_log"]) + var/obj/item/mecha_parts/mecha_tracking/MT = F.getObj("get_log") + stored_data = MT.get_mecha_log() + screen = 1 + else if(href_list["return"]) + screen = 0 + + src.updateUsrDialog() + + + +/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" + +/obj/item/mecha_parts/mecha_tracking/atom_init() + . = ..() + mecha_tracking_list += src + +/obj/item/mecha_parts/mecha_tracking/Destroy() + mecha_tracking_list -= src + return ..() + +/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.emp_act(2) + qdel(src) + +/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/atom_init() + . = ..() + for (var/i in 1 to 7) + new /obj/item/mecha_parts/mecha_tracking(src) + make_exact_fit() diff --git a/code/game/mecha/mecha_parts.dm b/code/game/mecha/mecha_parts.dm index 0a0714ef79f6..b427237485f1 100644 --- a/code/game/mecha/mecha_parts.dm +++ b/code/game/mecha/mecha_parts.dm @@ -1,521 +1,521 @@ -///////////////////////// -////// Mecha Parts ////// -///////////////////////// - -/obj/item/mecha_parts - name = "mecha part" - icon = 'icons/mecha/mech_construct.dmi' - icon_state = "blank" - w_class = 5 - flags = CONDUCT - origin_tech = "programming=2;materials=2" - - -/obj/item/mecha_parts/chassis - name="Mecha Chassis" - icon_state = "backbone" - var/datum/construction/construct - flags = CONDUCT - -/obj/item/mecha_parts/chassis/attackby(obj/item/W, mob/user) - if(!construct || !construct.action(W, user)) - ..() - return - -/obj/item/mecha_parts/chassis/attack_hand() - return - -/////////// Ripley - -/obj/item/mecha_parts/chassis/ripley - name = "Ripley Chassis" - -/obj/item/mecha_parts/chassis/ripley/atom_init() - . = ..() - construct = new /datum/construction/mecha/ripley_chassis(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" - -/obj/item/mecha_parts/chassis/gygax/atom_init() - . = ..() - construct = new /datum/construction/mecha/gygax_chassis(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" - -/obj/item/mecha_parts/chassis/durand/atom_init() - . = ..() - construct = new /datum/construction/mecha/durand_chassis(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" - -/obj/item/mecha_parts/chassis/firefighter/atom_init() - . = ..() - construct = new /datum/construction/mecha/firefighter_chassis(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" - -/obj/item/mecha_parts/chassis/honker/atom_init() - . = ..() - construct = new /datum/construction/mecha/honker_chassis(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" - -/obj/item/mecha_parts/chassis/phazon/atom_init() - . = ..() - construct = new /datum/construction/mecha/phazon_chassis(src) - -/obj/item/mecha_parts/part/phazon_torso - name="Phazon Torso" - icon_state = "phazon_harness" - origin_tech = "programming=5;materials=7;bluespace=6;powerstorage=6" - -/obj/item/mecha_parts/part/phazon_head - name="Phazon Head" - icon_state = "phazon_head" - origin_tech = "programming=4;materials=5;magnets=6" - -/obj/item/mecha_parts/part/phazon_left_arm - name="Phazon Left Arm" - icon_state = "phazon_l_arm" - origin_tech = "materials=5;bluespace=2;magnets=2" - -/obj/item/mecha_parts/part/phazon_right_arm - name="Phazon Right Arm" - icon_state = "phazon_r_arm" - origin_tech = "materials=5;bluespace=2;magnets=2" - -/obj/item/mecha_parts/part/phazon_left_leg - name="Phazon Left Leg" - icon_state = "phazon_l_leg" - origin_tech = "materials=5;bluespace=3;magnets=3" - -/obj/item/mecha_parts/part/phazon_right_leg - name="Phazon Right Leg" - icon_state = "phazon_r_leg" - origin_tech = "materials=5;bluespace=3;magnets=3" - -///////// Odysseus - - -/obj/item/mecha_parts/chassis/odysseus - name = "Odysseus Chassis" - -/obj/item/mecha_parts/chassis/odysseus/atom_init() - . = ..() - construct = new /datum/construction/mecha/odysseus_chassis(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"*/ - - -///////// Circuitboards - -/obj/item/weapon/circuitboard/mecha - name = "Exosuit Circuit board" - icon = 'icons/obj/module.dmi' - icon_state = "std_mod" - item_state = "electronic" - board_type = "other" - flags = CONDUCT - 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" - - ultra - origin_tech = "programming=4;combat=4" - - ultra/peripherals - name = "Circuit board (Gygax Ultra Peripherals Control module)" - icon_state = "mcontroller" - - ultra/targeting - name = "Circuit board (Gygax Ultra Weapon Control and Targeting module)" - icon_state = "mcontroller" - - ultra/main - name = "Circuit board (Gygax Ultra 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" - - vindicator - origin_tech = "programming=4;combat=4" - - vindicator/peripherals - name = "Circuit board (Vindicator Peripherals Control module)" - icon_state = "mcontroller" - - vindicator/targeting - name = "Circuit board (Vindicator Weapon Control and Targeting module)" - icon_state = "mcontroller" - - vindicator/main - name = "Circuit board (Vindicator 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" - -////////////Vindicator - -/obj/item/mecha_parts/chassis/vindicator - name = "Vindicator Chassis" - -/obj/item/mecha_parts/chassis/vindicator/atom_init() - . = ..() - construct = new /datum/construction/mecha/vindicator_chassis(src) - -/obj/item/mecha_parts/part/vindicator_torso - name="Vindicator Torso" - icon_state = "vindicator_harness" - origin_tech = "programming=2;materials=4;biotech=3;engineering=4;powerstorage=4" - -/obj/item/mecha_parts/part/vindicator_head - name="Vindicator Head" - icon_state = "vindicator_head" - origin_tech = "programming=2;materials=4;magnets=3;engineering=4" - -/obj/item/mecha_parts/part/vindicator_left_arm - name="Vindicator Left Arm" - icon_state = "vindicator_l_arm" - origin_tech = "programming=2;materials=4;engineering=4" - -/obj/item/mecha_parts/part/vindicator_right_arm - name="Vindicator Right Arm" - icon_state = "vindicator_r_arm" - origin_tech = "programming=2;materials=4;engineering=4" - -/obj/item/mecha_parts/part/vindicator_left_leg - name="Vindicator Left Leg" - icon_state = "vindicator_l_leg" - origin_tech = "programming=2;materials=4;engineering=4" - -/obj/item/mecha_parts/part/vindicator_right_leg - name="Vindicator Right Leg" - icon_state = "vindicator_r_leg" - origin_tech = "programming=2;materials=4;engineering=4" - -/obj/item/mecha_parts/part/vindicator_armour - name="Vindicator Armour Plates" - icon_state = "vindicator_armour" - origin_tech = "materials=5;combat=4;engineering=5" - -///////// Gygax Ultra - -/obj/item/mecha_parts/chassis/ultra - name = "Gygax Ultra Chassis" - -/obj/item/mecha_parts/chassis/ultra/atom_init() - . = ..() - construct = new /datum/construction/mecha/ultra_chassis(src) - -/obj/item/mecha_parts/part/ultra_torso - name="Gygax Ultra Torso" - desc="A torso part of Gygax Ultra. Contains power unit, processing core and life support systems. Has an additional equipment slot." - icon_state = "ultra_harness" - origin_tech = "programming=3;materials=3;biotech=3;engineering=4" - -/obj/item/mecha_parts/part/ultra_head - name="Gygax Ultra Head" - desc="A Gygax Ultra head. Houses advanced surveilance and targeting sensors." - icon_state = "ultra_head" - origin_tech = "programming=2;materials=4;magnets=3;engineering=4" - -/obj/item/mecha_parts/part/ultra_left_arm - name="Gygax Ultra Left Arm" - desc="A Gygax Ultra left arm. Data and power sockets are compatible with most exosuit tools and weapons." - icon_state = "ultra_l_arm" - origin_tech = "programming=2;materials=3;engineering=4" - -/obj/item/mecha_parts/part/ultra_right_arm - name="Gygax Ultra Right Arm" - desc="A Gygax Ultra right arm. Data and power sockets are compatible with most exosuit tools and weapons." - icon_state = "ultra_r_arm" - origin_tech = "programming=2;materials=3;engineering=4" - -/obj/item/mecha_parts/part/ultra_left_leg - name="Gygax Ultra Left Leg" - icon_state = "ultra_l_leg" - origin_tech = "programming=2;materials=3;engineering=4" - -/obj/item/mecha_parts/part/ultra_right_leg - name="Gygax Ultra Right Leg" - icon_state = "ultra_r_leg" - origin_tech = "programming=2;materials=3;engineering=4" - -/obj/item/mecha_parts/part/ultra_armour - name="Gygax Ultra Armour Plates" - icon_state = "ultra_armour" - origin_tech = "materials=6;combat=5;engineering=5" +///////////////////////// +////// Mecha Parts ////// +///////////////////////// + +/obj/item/mecha_parts + name = "mecha part" + icon = 'icons/mecha/mech_construct.dmi' + icon_state = "blank" + w_class = 5 + flags = CONDUCT + origin_tech = "programming=2;materials=2" + + +/obj/item/mecha_parts/chassis + name="Mecha Chassis" + icon_state = "backbone" + var/datum/construction/construct + flags = CONDUCT + +/obj/item/mecha_parts/chassis/attackby(obj/item/W, mob/user) + if(!construct || !construct.action(W, user)) + ..() + return + +/obj/item/mecha_parts/chassis/attack_hand() + return + +/////////// Ripley + +/obj/item/mecha_parts/chassis/ripley + name = "Ripley Chassis" + +/obj/item/mecha_parts/chassis/ripley/atom_init() + . = ..() + construct = new /datum/construction/mecha/ripley_chassis(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" + +/obj/item/mecha_parts/chassis/gygax/atom_init() + . = ..() + construct = new /datum/construction/mecha/gygax_chassis(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" + +/obj/item/mecha_parts/chassis/durand/atom_init() + . = ..() + construct = new /datum/construction/mecha/durand_chassis(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" + +/obj/item/mecha_parts/chassis/firefighter/atom_init() + . = ..() + construct = new /datum/construction/mecha/firefighter_chassis(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" + +/obj/item/mecha_parts/chassis/honker/atom_init() + . = ..() + construct = new /datum/construction/mecha/honker_chassis(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" + +/obj/item/mecha_parts/chassis/phazon/atom_init() + . = ..() + construct = new /datum/construction/mecha/phazon_chassis(src) + +/obj/item/mecha_parts/part/phazon_torso + name="Phazon Torso" + icon_state = "phazon_harness" + origin_tech = "programming=5;materials=7;bluespace=6;powerstorage=6" + +/obj/item/mecha_parts/part/phazon_head + name="Phazon Head" + icon_state = "phazon_head" + origin_tech = "programming=4;materials=5;magnets=6" + +/obj/item/mecha_parts/part/phazon_left_arm + name="Phazon Left Arm" + icon_state = "phazon_l_arm" + origin_tech = "materials=5;bluespace=2;magnets=2" + +/obj/item/mecha_parts/part/phazon_right_arm + name="Phazon Right Arm" + icon_state = "phazon_r_arm" + origin_tech = "materials=5;bluespace=2;magnets=2" + +/obj/item/mecha_parts/part/phazon_left_leg + name="Phazon Left Leg" + icon_state = "phazon_l_leg" + origin_tech = "materials=5;bluespace=3;magnets=3" + +/obj/item/mecha_parts/part/phazon_right_leg + name="Phazon Right Leg" + icon_state = "phazon_r_leg" + origin_tech = "materials=5;bluespace=3;magnets=3" + +///////// Odysseus + + +/obj/item/mecha_parts/chassis/odysseus + name = "Odysseus Chassis" + +/obj/item/mecha_parts/chassis/odysseus/atom_init() + . = ..() + construct = new /datum/construction/mecha/odysseus_chassis(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"*/ + + +///////// Circuitboards + +/obj/item/weapon/circuitboard/mecha + name = "Exosuit Circuit board" + icon = 'icons/obj/module.dmi' + icon_state = "std_mod" + item_state = "electronic" + board_type = "other" + flags = CONDUCT + 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" + + ultra + origin_tech = "programming=4;combat=4" + + ultra/peripherals + name = "Circuit board (Gygax Ultra Peripherals Control module)" + icon_state = "mcontroller" + + ultra/targeting + name = "Circuit board (Gygax Ultra Weapon Control and Targeting module)" + icon_state = "mcontroller" + + ultra/main + name = "Circuit board (Gygax Ultra 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" + + vindicator + origin_tech = "programming=4;combat=4" + + vindicator/peripherals + name = "Circuit board (Vindicator Peripherals Control module)" + icon_state = "mcontroller" + + vindicator/targeting + name = "Circuit board (Vindicator Weapon Control and Targeting module)" + icon_state = "mcontroller" + + vindicator/main + name = "Circuit board (Vindicator 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" + +////////////Vindicator + +/obj/item/mecha_parts/chassis/vindicator + name = "Vindicator Chassis" + +/obj/item/mecha_parts/chassis/vindicator/atom_init() + . = ..() + construct = new /datum/construction/mecha/vindicator_chassis(src) + +/obj/item/mecha_parts/part/vindicator_torso + name="Vindicator Torso" + icon_state = "vindicator_harness" + origin_tech = "programming=2;materials=4;biotech=3;engineering=4;powerstorage=4" + +/obj/item/mecha_parts/part/vindicator_head + name="Vindicator Head" + icon_state = "vindicator_head" + origin_tech = "programming=2;materials=4;magnets=3;engineering=4" + +/obj/item/mecha_parts/part/vindicator_left_arm + name="Vindicator Left Arm" + icon_state = "vindicator_l_arm" + origin_tech = "programming=2;materials=4;engineering=4" + +/obj/item/mecha_parts/part/vindicator_right_arm + name="Vindicator Right Arm" + icon_state = "vindicator_r_arm" + origin_tech = "programming=2;materials=4;engineering=4" + +/obj/item/mecha_parts/part/vindicator_left_leg + name="Vindicator Left Leg" + icon_state = "vindicator_l_leg" + origin_tech = "programming=2;materials=4;engineering=4" + +/obj/item/mecha_parts/part/vindicator_right_leg + name="Vindicator Right Leg" + icon_state = "vindicator_r_leg" + origin_tech = "programming=2;materials=4;engineering=4" + +/obj/item/mecha_parts/part/vindicator_armour + name="Vindicator Armour Plates" + icon_state = "vindicator_armour" + origin_tech = "materials=5;combat=4;engineering=5" + +///////// Gygax Ultra + +/obj/item/mecha_parts/chassis/ultra + name = "Gygax Ultra Chassis" + +/obj/item/mecha_parts/chassis/ultra/atom_init() + . = ..() + construct = new /datum/construction/mecha/ultra_chassis(src) + +/obj/item/mecha_parts/part/ultra_torso + name="Gygax Ultra Torso" + desc="A torso part of Gygax Ultra. Contains power unit, processing core and life support systems. Has an additional equipment slot." + icon_state = "ultra_harness" + origin_tech = "programming=3;materials=3;biotech=3;engineering=4" + +/obj/item/mecha_parts/part/ultra_head + name="Gygax Ultra Head" + desc="A Gygax Ultra head. Houses advanced surveilance and targeting sensors." + icon_state = "ultra_head" + origin_tech = "programming=2;materials=4;magnets=3;engineering=4" + +/obj/item/mecha_parts/part/ultra_left_arm + name="Gygax Ultra Left Arm" + desc="A Gygax Ultra left arm. Data and power sockets are compatible with most exosuit tools and weapons." + icon_state = "ultra_l_arm" + origin_tech = "programming=2;materials=3;engineering=4" + +/obj/item/mecha_parts/part/ultra_right_arm + name="Gygax Ultra Right Arm" + desc="A Gygax Ultra right arm. Data and power sockets are compatible with most exosuit tools and weapons." + icon_state = "ultra_r_arm" + origin_tech = "programming=2;materials=3;engineering=4" + +/obj/item/mecha_parts/part/ultra_left_leg + name="Gygax Ultra Left Leg" + icon_state = "ultra_l_leg" + origin_tech = "programming=2;materials=3;engineering=4" + +/obj/item/mecha_parts/part/ultra_right_leg + name="Gygax Ultra Right Leg" + icon_state = "ultra_r_leg" + origin_tech = "programming=2;materials=3;engineering=4" + +/obj/item/mecha_parts/part/ultra_armour + name="Gygax Ultra Armour Plates" + icon_state = "ultra_armour" + origin_tech = "materials=6;combat=5;engineering=5" diff --git a/code/game/mecha/mecha_wreckage.dm b/code/game/mecha/mecha_wreckage.dm index 89241b1ca004..1ee93453e722 100644 --- a/code/game/mecha/mecha_wreckage.dm +++ b/code/game/mecha/mecha_wreckage.dm @@ -1,318 +1,318 @@ -/////////////////////////////////// -//////// 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/salvage = list( - "welder" = list( - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ), - "wirecutter" = list( - /obj/item/stack/cable_coil, - /obj/item/stack/rods - ), - "crowbar" = list( - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ) - ) - var/salvage_num = 15 - -/obj/effect/decal/mecha_wreckage/ex_act(severity) - if(severity == 1) - qdel(src) - return - -/obj/effect/decal/mecha_wreckage/bullet_act(obj/item/projectile/Proj) - return - -/obj/effect/decal/mecha_wreckage/attackby(obj/item/weapon/W, mob/user) - var/salvage_with = "" - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if (WT.remove_fuel(3,user)) - salvage_with = "welder" - else - to_chat(user, "\blue You need more welding fuel to complete this task.") - return - if(istype(W, /obj/item/weapon/wirecutters)) - salvage_with = "wirecutter" - if(istype(W, /obj/item/weapon/crowbar)) - salvage_with = "crowbar" - if(!salvage_with) - ..() - return - if(salvage_num <= 0) - to_chat(user, "You don't see anything that can be salvaged anymore.") - return - var/salvaged = detach_part(salvage_with) - if(salvaged) - user.visible_message("[user] salvages [salvaged] from [src]", "You salvaged [salvaged] from [src]") - else - to_chat(user, "You failed to salvage anything valuable from [src].") - - -/obj/effect/decal/mecha_wreckage/proc/detach_part(var/where) - var/obj/to_salvage = pick(salvage[where]) - if(to_salvage) - var/obj/salvaged = new to_salvage(get_turf(src)) - salvage[where] -= to_salvage - salvage[where] += /obj/item/stack/rods - if(!prob(reliability)) - salvaged.make_old() - - salvage_num-- - return salvaged - return 0 - -/obj/effect/decal/mecha_wreckage/gygax - name = "Gygax wreckage" - icon_state = "gygax-broken" - salvage = list( - "welder" = list( - /obj/item/mecha_parts/part/gygax_torso, - /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, - /obj/item/mecha_parts/part/gygax_head, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ), - "wirecutter" = list( - /obj/item/stack/cable_coil, - /obj/item/weapon/circuitboard/mecha/gygax/targeting, - /obj/item/weapon/circuitboard/mecha/gygax/peripherals, - /obj/item/weapon/circuitboard/mecha/gygax/main, - /obj/item/weapon/stock_parts/scanning_module/adv, - /obj/item/weapon/stock_parts/capacitor/adv, - /obj/item/stack/rods - ), - "crowbar" = list( - /obj/item/mecha_parts/chassis/gygax, - /obj/item/mecha_parts/part/gygax_armour, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ) - ) - -/obj/effect/decal/mecha_wreckage/gygax/dark - name = "Dark Gygax wreckage" - icon_state = "darkgygax-broken" - -/obj/effect/decal/mecha_wreckage/gygax/ultra - name = "Gygax Ultra wreckage" - icon_state = "ultra-broken" - salvage = list( - "welder" = list( - /obj/item/mecha_parts/part/ultra_torso, - /obj/item/mecha_parts/part/ultra_left_arm, - /obj/item/mecha_parts/part/ultra_right_arm, - /obj/item/mecha_parts/part/ultra_left_leg, - /obj/item/mecha_parts/part/ultra_right_leg, - /obj/item/mecha_parts/part/ultra_head, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ), - "wirecutter" = list( - /obj/item/stack/cable_coil, - /obj/item/weapon/circuitboard/mecha/ultra/targeting, - /obj/item/weapon/circuitboard/mecha/ultra/peripherals, - /obj/item/weapon/circuitboard/mecha/ultra/main, - /obj/item/weapon/stock_parts/capacitor/super, - /obj/item/weapon/stock_parts/scanning_module/phasic, - /obj/item/stack/rods - ), - "crowbar" = list( - /obj/item/mecha_parts/chassis/ultra, - /obj/item/mecha_parts/part/ultra_armour, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ) - ) - -/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" - salvage = list( - "welder" = 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/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ), - "wirecutter" = list( - /obj/item/stack/cable_coil, - /obj/item/weapon/circuitboard/mecha/ripley/peripherals, - /obj/item/weapon/circuitboard/mecha/ripley/main, - /obj/item/stack/rods - ), - "crowbar" = list( - /obj/item/mecha_parts/chassis/ripley, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ) - ) - -/obj/effect/decal/mecha_wreckage/ripley/firefighter - name = "Firefighter wreckage" - icon_state = "firefighter-broken" - -/obj/effect/decal/mecha_wreckage/ripley/firefighter/atom_init() - . = ..() - salvage["crowbar"] += /obj/item/clothing/suit/fire - salvage["crowbar"] += /obj/item/mecha_parts/chassis/firefighter - salvage["crowbar"] -= /obj/item/mecha_parts/chassis/ripley - -/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" - salvage = list( - "welder" = list( - /obj/item/mecha_parts/part/honker_torso, - /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, - /obj/item/mecha_parts/part/honker_head, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ), - "wirecutter" = list( - /obj/item/stack/cable_coil, - /obj/item/weapon/circuitboard/mecha/honker/main, - /obj/item/weapon/circuitboard/mecha/honker/peripherals, - /obj/item/weapon/circuitboard/mecha/honker/targeting, - /obj/item/stack/rods - ), - "crowbar" = list( - /obj/item/mecha_parts/chassis/honker, - /obj/item/clothing/mask/gas/clown_hat, - /obj/item/clothing/shoes/clown_shoes, - /obj/item/weapon/bikehorn, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ) - ) - -/obj/effect/decal/mecha_wreckage/durand - name = "Durand wreckage" - icon_state = "durand-broken" - salvage = list( - "welder" = list( - /obj/item/mecha_parts/part/durand_torso, - /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, - /obj/item/mecha_parts/part/durand_head, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ), - "wirecutter" = list( - /obj/item/stack/cable_coil, - /obj/item/weapon/circuitboard/mecha/durand/targeting, - /obj/item/weapon/circuitboard/mecha/durand/peripherals, - /obj/item/weapon/circuitboard/mecha/durand/main, - /obj/item/weapon/stock_parts/capacitor/adv, - /obj/item/weapon/stock_parts/scanning_module/adv, - /obj/item/stack/rods - ), - "crowbar" = list( - /obj/item/mecha_parts/chassis/durand, - /obj/item/mecha_parts/part/durand_armour, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ) - ) - -/obj/effect/decal/mecha_wreckage/durand/vindicator - name = "Vindicator wreckage" - icon_state = "vindicator-broken" - salvage = list( - "welder" = list( - /obj/item/mecha_parts/part/vindicator_torso, - /obj/item/mecha_parts/part/vindicator_left_arm, - /obj/item/mecha_parts/part/vindicator_right_arm, - /obj/item/mecha_parts/part/vindicator_left_leg, - /obj/item/mecha_parts/part/vindicator_right_leg, - /obj/item/mecha_parts/part/vindicator_head, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ), - "wirecutter" = list( - /obj/item/stack/cable_coil, - /obj/item/weapon/circuitboard/mecha/vindicator/targeting, - /obj/item/weapon/circuitboard/mecha/vindicator/peripherals, - /obj/item/weapon/circuitboard/mecha/vindicator/main, - /obj/item/weapon/stock_parts/capacitor/super, - /obj/item/weapon/stock_parts/scanning_module/phasic, - /obj/item/stack/rods - ), - "crowbar" = list( - /obj/item/mecha_parts/chassis/vindicator, - /obj/item/mecha_parts/part/vindicator_armour, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ) - ) - -/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" - salvage = list( - "welder" = 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, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ), - "wirecutter" = list( - /obj/item/stack/cable_coil, - /obj/item/weapon/circuitboard/mecha/odysseus/peripherals, - /obj/item/weapon/circuitboard/mecha/odysseus/main, - /obj/item/stack/rods - ), - "crowbar" = list( - /obj/item/mecha_parts/chassis/odysseus, - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/plasteel - ) - ) +/////////////////////////////////// +//////// 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/salvage = list( + "welder" = list( + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ), + "wirecutter" = list( + /obj/item/stack/cable_coil, + /obj/item/stack/rods + ), + "crowbar" = list( + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ) + ) + var/salvage_num = 15 + +/obj/effect/decal/mecha_wreckage/ex_act(severity) + if(severity == 1) + qdel(src) + return + +/obj/effect/decal/mecha_wreckage/bullet_act(obj/item/projectile/Proj) + return + +/obj/effect/decal/mecha_wreckage/attackby(obj/item/weapon/W, mob/user) + var/salvage_with = "" + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if (WT.remove_fuel(3,user)) + salvage_with = "welder" + else + to_chat(user, "\blue You need more welding fuel to complete this task.") + return + if(istype(W, /obj/item/weapon/wirecutters)) + salvage_with = "wirecutter" + if(istype(W, /obj/item/weapon/crowbar)) + salvage_with = "crowbar" + if(!salvage_with) + ..() + return + if(salvage_num <= 0) + to_chat(user, "You don't see anything that can be salvaged anymore.") + return + var/salvaged = detach_part(salvage_with) + if(salvaged) + user.visible_message("[user] salvages [salvaged] from [src]", "You salvaged [salvaged] from [src]") + else + to_chat(user, "You failed to salvage anything valuable from [src].") + + +/obj/effect/decal/mecha_wreckage/proc/detach_part(var/where) + var/obj/to_salvage = pick(salvage[where]) + if(to_salvage) + var/obj/salvaged = new to_salvage(get_turf(src)) + salvage[where] -= to_salvage + salvage[where] += /obj/item/stack/rods + if(!prob(reliability)) + salvaged.make_old() + + salvage_num-- + return salvaged + return 0 + +/obj/effect/decal/mecha_wreckage/gygax + name = "Gygax wreckage" + icon_state = "gygax-broken" + salvage = list( + "welder" = list( + /obj/item/mecha_parts/part/gygax_torso, + /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, + /obj/item/mecha_parts/part/gygax_head, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ), + "wirecutter" = list( + /obj/item/stack/cable_coil, + /obj/item/weapon/circuitboard/mecha/gygax/targeting, + /obj/item/weapon/circuitboard/mecha/gygax/peripherals, + /obj/item/weapon/circuitboard/mecha/gygax/main, + /obj/item/weapon/stock_parts/scanning_module/adv, + /obj/item/weapon/stock_parts/capacitor/adv, + /obj/item/stack/rods + ), + "crowbar" = list( + /obj/item/mecha_parts/chassis/gygax, + /obj/item/mecha_parts/part/gygax_armour, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ) + ) + +/obj/effect/decal/mecha_wreckage/gygax/dark + name = "Dark Gygax wreckage" + icon_state = "darkgygax-broken" + +/obj/effect/decal/mecha_wreckage/gygax/ultra + name = "Gygax Ultra wreckage" + icon_state = "ultra-broken" + salvage = list( + "welder" = list( + /obj/item/mecha_parts/part/ultra_torso, + /obj/item/mecha_parts/part/ultra_left_arm, + /obj/item/mecha_parts/part/ultra_right_arm, + /obj/item/mecha_parts/part/ultra_left_leg, + /obj/item/mecha_parts/part/ultra_right_leg, + /obj/item/mecha_parts/part/ultra_head, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ), + "wirecutter" = list( + /obj/item/stack/cable_coil, + /obj/item/weapon/circuitboard/mecha/ultra/targeting, + /obj/item/weapon/circuitboard/mecha/ultra/peripherals, + /obj/item/weapon/circuitboard/mecha/ultra/main, + /obj/item/weapon/stock_parts/capacitor/super, + /obj/item/weapon/stock_parts/scanning_module/phasic, + /obj/item/stack/rods + ), + "crowbar" = list( + /obj/item/mecha_parts/chassis/ultra, + /obj/item/mecha_parts/part/ultra_armour, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ) + ) + +/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" + salvage = list( + "welder" = 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/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ), + "wirecutter" = list( + /obj/item/stack/cable_coil, + /obj/item/weapon/circuitboard/mecha/ripley/peripherals, + /obj/item/weapon/circuitboard/mecha/ripley/main, + /obj/item/stack/rods + ), + "crowbar" = list( + /obj/item/mecha_parts/chassis/ripley, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ) + ) + +/obj/effect/decal/mecha_wreckage/ripley/firefighter + name = "Firefighter wreckage" + icon_state = "firefighter-broken" + +/obj/effect/decal/mecha_wreckage/ripley/firefighter/atom_init() + . = ..() + salvage["crowbar"] += /obj/item/clothing/suit/fire + salvage["crowbar"] += /obj/item/mecha_parts/chassis/firefighter + salvage["crowbar"] -= /obj/item/mecha_parts/chassis/ripley + +/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" + salvage = list( + "welder" = list( + /obj/item/mecha_parts/part/honker_torso, + /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, + /obj/item/mecha_parts/part/honker_head, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ), + "wirecutter" = list( + /obj/item/stack/cable_coil, + /obj/item/weapon/circuitboard/mecha/honker/main, + /obj/item/weapon/circuitboard/mecha/honker/peripherals, + /obj/item/weapon/circuitboard/mecha/honker/targeting, + /obj/item/stack/rods + ), + "crowbar" = list( + /obj/item/mecha_parts/chassis/honker, + /obj/item/clothing/mask/gas/clown_hat, + /obj/item/clothing/shoes/clown_shoes, + /obj/item/weapon/bikehorn, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ) + ) + +/obj/effect/decal/mecha_wreckage/durand + name = "Durand wreckage" + icon_state = "durand-broken" + salvage = list( + "welder" = list( + /obj/item/mecha_parts/part/durand_torso, + /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, + /obj/item/mecha_parts/part/durand_head, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ), + "wirecutter" = list( + /obj/item/stack/cable_coil, + /obj/item/weapon/circuitboard/mecha/durand/targeting, + /obj/item/weapon/circuitboard/mecha/durand/peripherals, + /obj/item/weapon/circuitboard/mecha/durand/main, + /obj/item/weapon/stock_parts/capacitor/adv, + /obj/item/weapon/stock_parts/scanning_module/adv, + /obj/item/stack/rods + ), + "crowbar" = list( + /obj/item/mecha_parts/chassis/durand, + /obj/item/mecha_parts/part/durand_armour, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ) + ) + +/obj/effect/decal/mecha_wreckage/durand/vindicator + name = "Vindicator wreckage" + icon_state = "vindicator-broken" + salvage = list( + "welder" = list( + /obj/item/mecha_parts/part/vindicator_torso, + /obj/item/mecha_parts/part/vindicator_left_arm, + /obj/item/mecha_parts/part/vindicator_right_arm, + /obj/item/mecha_parts/part/vindicator_left_leg, + /obj/item/mecha_parts/part/vindicator_right_leg, + /obj/item/mecha_parts/part/vindicator_head, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ), + "wirecutter" = list( + /obj/item/stack/cable_coil, + /obj/item/weapon/circuitboard/mecha/vindicator/targeting, + /obj/item/weapon/circuitboard/mecha/vindicator/peripherals, + /obj/item/weapon/circuitboard/mecha/vindicator/main, + /obj/item/weapon/stock_parts/capacitor/super, + /obj/item/weapon/stock_parts/scanning_module/phasic, + /obj/item/stack/rods + ), + "crowbar" = list( + /obj/item/mecha_parts/chassis/vindicator, + /obj/item/mecha_parts/part/vindicator_armour, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ) + ) + +/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" + salvage = list( + "welder" = 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, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ), + "wirecutter" = list( + /obj/item/stack/cable_coil, + /obj/item/weapon/circuitboard/mecha/odysseus/peripherals, + /obj/item/weapon/circuitboard/mecha/odysseus/main, + /obj/item/stack/rods + ), + "crowbar" = list( + /obj/item/mecha_parts/chassis/odysseus, + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/plasteel + ) + ) diff --git a/code/game/mecha/medical/medical.dm b/code/game/mecha/medical/medical.dm index bfe55d651536..81816a0b7719 100644 --- a/code/game/mecha/medical/medical.dm +++ b/code/game/mecha/medical/medical.dm @@ -1,23 +1,23 @@ -/obj/mecha/medical/atom_init() - . = ..() - var/turf/T = get_turf(src) - if(T.z != ZLEVEL_CENTCOMM) - new /obj/item/mecha_parts/mecha_tracking(src) - - -/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 +/obj/mecha/medical/atom_init() + . = ..() + var/turf/T = get_turf(src) + if(T.z != ZLEVEL_CENTCOMM) + new /obj/item/mecha_parts/mecha_tracking(src) + + +/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 diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index f8fee41b6379..c2c76d74a100 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -1,86 +1,86 @@ -/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/atom_init() - . = ..() - hud = new /obj/item/clothing/glasses/hud/health/mech(src) - -/obj/mecha/medical/odysseus/moved_inside(mob/living/carbon/human/H) - 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 - ..() - -//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(mob/M) - - 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++ - - for (var/ID in patient.virus2) - if (ID in virusDB) - foundVirus = 1 - break - - holder = patient.hud_list[HEALTH_HUD] - if(patient.stat == DEAD) - 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 == DEAD) - holder.icon_state = "huddead" - else if(patient.status_flags & XENO_HOST) - holder.icon_state = "hudxeno" - else if(foundVirus || iszombie(patient)) - holder.icon_state = "hudill" - else if(patient.has_brain_worms()) - var/mob/living/simple_animal/borer/B = patient.has_brain_worms() - if(B.controlling) - holder.icon_state = "hudbrainworm" - else - holder.icon_state = "hudhealthy" - else - holder.icon_state = "hudhealthy" - - C.images += holder +/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/atom_init() + . = ..() + hud = new /obj/item/clothing/glasses/hud/health/mech(src) + +/obj/mecha/medical/odysseus/moved_inside(mob/living/carbon/human/H) + 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 + ..() + +//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(mob/M) + + 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++ + + for (var/ID in patient.virus2) + if (ID in virusDB) + foundVirus = 1 + break + + holder = patient.hud_list[HEALTH_HUD] + if(patient.stat == DEAD) + 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 == DEAD) + holder.icon_state = "huddead" + else if(patient.status_flags & XENO_HOST) + holder.icon_state = "hudxeno" + else if(foundVirus || iszombie(patient)) + holder.icon_state = "hudill" + else if(patient.has_brain_worms()) + var/mob/living/simple_animal/borer/B = patient.has_brain_worms() + if(B.controlling) + holder.icon_state = "hudbrainworm" + else + holder.icon_state = "hudhealthy" + 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 983cef6db97d..d2b0b44ed07e 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -1,152 +1,152 @@ -/obj/mecha/working/ripley - desc = "Autonomous Power Loader Unit. The workhorse of the exosuit world." - name = "APLU \"Ripley\"" - icon_state = "ripley" - initial_icon = "ripley" - step_in = 6 - max_temperature = 20000 - health = 200 - wreckage = /obj/effect/decal/mecha_wreckage/ripley - var/list/cargo = new - var/cargo_capacity = 15 - var/hides = 0 - -/obj/mecha/working/ripley/go_out() - ..() - update_icon() - -/obj/mecha/working/ripley/moved_inside(mob/living/carbon/human/H) - ..() - update_icon() - -/obj/mecha/working/ripley/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc,mob/user) - ..() - update_icon() - -/obj/mecha/working/ripley/update_icon() - ..() - if(hides) - overlays = null - if(hides < 3) - overlays += image("icon" = "mecha.dmi", "icon_state" = occupant ? "ripley-g" : "ripley-g-open") - else - overlays += image("icon" = "mecha.dmi", "icon_state" = occupant ? "ripley-g-full" : "ripley-g-full-open") - -/obj/mecha/working/ripley/firefighter - desc = "Standart APLU chassis was refitted with additional thermal protection and cistern." - name = "APLU \"Firefighter\"" - icon_state = "firefighter" - initial_icon = "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" - initial_icon = "deathripley" - step_in = 2 - opacity=0 - wreckage = /obj/effect/decal/mecha_wreckage/ripley/deathripley - step_energy_drain = 0 - -/obj/mecha/working/ripley/deathripley/atom_init() - . = ..() - if(!istype(src,/obj/mecha/working/ripley/deathripley/pirate)) - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/safety_clamp - ME.attach(src) - -/obj/mecha/working/ripley/deathripley/pirate - name = "LOOT-RIPLEY" - desc = "OH SHIT IT'S THE LOOTERS WE'RE ALL GONNA DIE!!!" - step_in = 5 - step_energy_drain = 10 - health = 750 - deflect_chance = 0 - damage_absorption = list("brute"=1,"fire"=1,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1) - add_req_access = 0 - maint_access = 0 - operation_req_access = list(access_syndicate) - internals_req_access = list(access_syndicate) - wreckage = /obj/effect/decal/mecha_wreckage/ripley/deathripley - max_equip = 2 - -/obj/mecha/working/ripley/deathripley/pirate/atom_init() - . = ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp(src) - ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/tool/drill(src) - ME.attach(src) - -/obj/mecha/working/ripley/mining - desc = "An old, dusty mining ripley." - name = "APLU \"Miner\"" - -/obj/mecha/working/ripley/mining/atom_init() - ..() - //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 hydrolic 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) - - return INITIALIZE_HINT_LATELOAD - -/obj/mecha/working/ripley/mining/atom_init_late() - for(var/obj/item/mecha_parts/mecha_tracking/B in contents)//Deletes the beacon so it can't be found easily - qdel(B) - -/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("\blue You unload [O].") - O.loc = get_turf(src) - src.cargo -= O - var/turf/T = get_turf(O) - if(T) - T.Entered(O) - 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/proc/drop_cargo() - for(var/atom/movable/A in cargo) - A.forceMove(get_turf(src)) - step_rand(A) - -/obj/mecha/working/ripley/destroy() - drop_cargo() - ..() - - -/obj/mecha/working/ripley/Destroy() - drop_cargo() - return ..() +/obj/mecha/working/ripley + desc = "Autonomous Power Loader Unit. The workhorse of the exosuit world." + name = "APLU \"Ripley\"" + icon_state = "ripley" + initial_icon = "ripley" + step_in = 6 + max_temperature = 20000 + health = 200 + wreckage = /obj/effect/decal/mecha_wreckage/ripley + var/list/cargo = new + var/cargo_capacity = 15 + var/hides = 0 + +/obj/mecha/working/ripley/go_out() + ..() + update_icon() + +/obj/mecha/working/ripley/moved_inside(mob/living/carbon/human/H) + ..() + update_icon() + +/obj/mecha/working/ripley/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc,mob/user) + ..() + update_icon() + +/obj/mecha/working/ripley/update_icon() + ..() + if(hides) + overlays = null + if(hides < 3) + overlays += image("icon" = "mecha.dmi", "icon_state" = occupant ? "ripley-g" : "ripley-g-open") + else + overlays += image("icon" = "mecha.dmi", "icon_state" = occupant ? "ripley-g-full" : "ripley-g-full-open") + +/obj/mecha/working/ripley/firefighter + desc = "Standart APLU chassis was refitted with additional thermal protection and cistern." + name = "APLU \"Firefighter\"" + icon_state = "firefighter" + initial_icon = "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" + initial_icon = "deathripley" + step_in = 2 + opacity=0 + wreckage = /obj/effect/decal/mecha_wreckage/ripley/deathripley + step_energy_drain = 0 + +/obj/mecha/working/ripley/deathripley/atom_init() + . = ..() + if(!istype(src,/obj/mecha/working/ripley/deathripley/pirate)) + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/safety_clamp + ME.attach(src) + +/obj/mecha/working/ripley/deathripley/pirate + name = "LOOT-RIPLEY" + desc = "OH SHIT IT'S THE LOOTERS WE'RE ALL GONNA DIE!!!" + step_in = 5 + step_energy_drain = 10 + health = 750 + deflect_chance = 0 + damage_absorption = list("brute"=1,"fire"=1,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1) + add_req_access = 0 + maint_access = 0 + operation_req_access = list(access_syndicate) + internals_req_access = list(access_syndicate) + wreckage = /obj/effect/decal/mecha_wreckage/ripley/deathripley + max_equip = 2 + +/obj/mecha/working/ripley/deathripley/pirate/atom_init() + . = ..() + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp(src) + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/tool/drill(src) + ME.attach(src) + +/obj/mecha/working/ripley/mining + desc = "An old, dusty mining ripley." + name = "APLU \"Miner\"" + +/obj/mecha/working/ripley/mining/atom_init() + ..() + //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 hydrolic 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) + + return INITIALIZE_HINT_LATELOAD + +/obj/mecha/working/ripley/mining/atom_init_late() + for(var/obj/item/mecha_parts/mecha_tracking/B in contents)//Deletes the beacon so it can't be found easily + qdel(B) + +/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("\blue You unload [O].") + O.loc = get_turf(src) + src.cargo -= O + var/turf/T = get_turf(O) + if(T) + T.Entered(O) + 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/proc/drop_cargo() + for(var/atom/movable/A in cargo) + A.forceMove(get_turf(src)) + step_rand(A) + +/obj/mecha/working/ripley/destroy() + drop_cargo() + ..() + + +/obj/mecha/working/ripley/Destroy() + drop_cargo() + return ..() diff --git a/code/game/mecha/working/working.dm b/code/game/mecha/working/working.dm index 134fd7dd6268..0c203b91578b 100644 --- a/code/game/mecha/working/working.dm +++ b/code/game/mecha/working/working.dm @@ -1,33 +1,33 @@ -/obj/mecha/working - internal_damage_threshold = 60 - -/obj/mecha/working/atom_init() - . = ..() - var/turf/T = get_turf(src) - if(T.z != ZLEVEL_CENTCOMM && T.z != ZLEVEL_JUNKYARD) - new /obj/item/mecha_parts/mecha_tracking(src) - -/* -/obj/mecha/working/melee_action(atom/target) - 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) - 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/atom_init() + . = ..() + var/turf/T = get_turf(src) + if(T.z != ZLEVEL_CENTCOMM && T.z != ZLEVEL_JUNKYARD) + new /obj/item/mecha_parts/mecha_tracking(src) + +/* +/obj/mecha/working/melee_action(atom/target) + 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) + 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 +*/ diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 6e7f029143af..8ff0ad6c6341 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -1,187 +1,187 @@ -//Anomalies, used for events. Note that these DO NOT work by themselves; their procs are called by the event datum. - -/obj/effect/anomaly - name = "anomaly" - icon = 'icons/effects/effects.dmi' - desc = "A mysterious anomaly, seen commonly only in the region of space that the station orbits..." - icon_state = "bhole3" - unacidable = 1 - density = 0 - anchored = 1 - luminosity = 3 - var/obj/item/device/assembly/signaler/anomaly/aSignal = null - -/obj/effect/anomaly/atom_init() - . = ..() - poi_list += src - SetLuminosity(initial(luminosity)) - aSignal = new(src) - aSignal.code = rand(1,100) - - aSignal.frequency = rand(1200, 1599) - if(IsMultiple(aSignal.frequency, 2))//signaller frequencies are always uneven! - aSignal.frequency++ - -/obj/effect/anomaly/Destroy() - poi_list -= src - return ..() - -/obj/effect/anomaly/proc/anomalyEffect() - if(prob(50)) - step(src,pick(alldirs)) - - -/obj/effect/anomaly/proc/anomalyNeutralize() - new /obj/effect/effect/bad_smoke(loc) - - for(var/atom/movable/O in src) - O.loc = src.loc - - qdel(src) - - -/obj/effect/anomaly/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/device/analyzer)) - to_chat(user, "Analyzing... [src]'s unstable field is fluctuating along frequency [aSignal.code]:[format_frequency(aSignal.frequency)].") - -/////////////////////// - -/obj/effect/anomaly/grav - name = "gravitational anomaly" - icon_state = "shield2" - density = 1 - var/boing = 0 - -/obj/effect/anomaly/grav/atom_init() - . = ..() - aSignal.origin_tech = "magnets=5;powerstorage=4" - -/obj/effect/anomaly/grav/anomalyEffect() - ..() - - boing = 1 - for(var/obj/O in orange(4, src)) - if(!O.anchored) - step_towards(O,src) - for(var/mob/living/M in orange(4, src)) - step_towards(M,src) - -/obj/effect/anomaly/grav/Bump(mob/A) - gravShock(A) - return - -/obj/effect/anomaly/grav/Bumped(mob/A) - gravShock(A) - return - -/obj/effect/anomaly/grav/proc/gravShock(mob/A) - if(boing && isliving(A) && !A.stat) - A.Weaken(2) - var/atom/target = get_edge_target_turf(A, get_dir(src, get_step_away(A, src))) - A.throw_at(target, 5, 1) - boing = 0 - return - -///////////////////// - -/obj/effect/anomaly/flux - name = "flux wave anomaly" - icon_state = "electricity2" - -/obj/effect/anomaly/flux/atom_init() - . = ..() - aSignal.origin_tech = "powerstorage=5;programming=3;phorontech=2" - -///////////////////// - -/obj/effect/anomaly/bluespace - name = "bluespace anomaly" - icon_state = "bluespace" - density = 1 - -/obj/effect/anomaly/bluespace/atom_init() - . = ..() - aSignal.origin_tech = "bluespace=5;magnets=3;powerstorage=2" - -/obj/effect/anomaly/bluespace/Bumped(atom/A) - if(isliving(A)) - do_teleport(A, locate(A.x, A.y, A.z), 10) - return - -///////////////////// - -/obj/effect/anomaly/pyro - name = "pyroclastic anomaly" - icon_state = "mustard" - -/obj/effect/anomaly/pyro/atom_init() - . = ..() - aSignal.origin_tech = "phorontech=5;powerstorage=3;biotech=3" - -/obj/effect/anomaly/pyro/anomalyEffect() - ..() - var/turf/simulated/T = get_turf(src) - if(istype(T)) - var/datum/gas_mixture/payload = new - payload.toxins = 30 - T.zone.air.merge(payload) - T.hotspot_expose(1000, CELL_VOLUME) - - -///////////////////// - -/obj/effect/anomaly/bhole - name = "vortex anomaly" - icon_state = "bhole3" - desc = "That's a nice station you have there. It'd be a shame if something happened to it." - -/obj/effect/anomaly/bhole/atom_init() - . = ..() - aSignal.origin_tech = "materials=5;combat=4;engineering=3" - -/obj/effect/anomaly/bhole/anomalyEffect() - ..() - if(!isturf(loc)) //blackhole cannot be contained inside anything. Weird stuff might happen - qdel(src) - return - - grav(rand(0,3), rand(2,3), 50, 25) - - //Throwing stuff around! - for(var/obj/O in orange(1,src)) - if(!O.anchored) - var/mob/living/target = locate() in view(5,src) - if(!target) - return - O.throw_at(target, 5, 10) - return - else - O.ex_act(2) - -/obj/effect/anomaly/bhole/proc/grav(r, ex_act_force, pull_chance, turf_removal_chance) - for(var/t = -r, t < r, t++) - affect_coord(x+t, y-r, ex_act_force, pull_chance, turf_removal_chance) - affect_coord(x-t, y+r, ex_act_force, pull_chance, turf_removal_chance) - affect_coord(x+r, y+t, ex_act_force, pull_chance, turf_removal_chance) - affect_coord(x-r, y-t, ex_act_force, pull_chance, turf_removal_chance) - return - -/obj/effect/anomaly/bhole/proc/affect_coord(x, y, ex_act_force, pull_chance, turf_removal_chance) - //Get turf at coordinate - var/turf/T = locate(x, y, z) - if(isnull(T)) return - - //Pulling and/or ex_act-ing movable atoms in that turf - if(prob(pull_chance)) - for(var/obj/O in T.contents) - if(O.anchored) - O.ex_act(ex_act_force) - else - step_towards(O,src) - for(var/mob/living/M in T.contents) - step_towards(M,src) - - //Damaging the turf - if( T && istype(T,/turf/simulated) && prob(turf_removal_chance) ) - T.ex_act(ex_act_force) - return +//Anomalies, used for events. Note that these DO NOT work by themselves; their procs are called by the event datum. + +/obj/effect/anomaly + name = "anomaly" + icon = 'icons/effects/effects.dmi' + desc = "A mysterious anomaly, seen commonly only in the region of space that the station orbits..." + icon_state = "bhole3" + unacidable = 1 + density = 0 + anchored = 1 + luminosity = 3 + var/obj/item/device/assembly/signaler/anomaly/aSignal = null + +/obj/effect/anomaly/atom_init() + . = ..() + poi_list += src + SetLuminosity(initial(luminosity)) + aSignal = new(src) + aSignal.code = rand(1,100) + + aSignal.frequency = rand(1200, 1599) + if(IsMultiple(aSignal.frequency, 2))//signaller frequencies are always uneven! + aSignal.frequency++ + +/obj/effect/anomaly/Destroy() + poi_list -= src + return ..() + +/obj/effect/anomaly/proc/anomalyEffect() + if(prob(50)) + step(src,pick(alldirs)) + + +/obj/effect/anomaly/proc/anomalyNeutralize() + new /obj/effect/effect/bad_smoke(loc) + + for(var/atom/movable/O in src) + O.loc = src.loc + + qdel(src) + + +/obj/effect/anomaly/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/device/analyzer)) + to_chat(user, "Analyzing... [src]'s unstable field is fluctuating along frequency [aSignal.code]:[format_frequency(aSignal.frequency)].") + +/////////////////////// + +/obj/effect/anomaly/grav + name = "gravitational anomaly" + icon_state = "shield2" + density = 1 + var/boing = 0 + +/obj/effect/anomaly/grav/atom_init() + . = ..() + aSignal.origin_tech = "magnets=5;powerstorage=4" + +/obj/effect/anomaly/grav/anomalyEffect() + ..() + + boing = 1 + for(var/obj/O in orange(4, src)) + if(!O.anchored) + step_towards(O,src) + for(var/mob/living/M in orange(4, src)) + step_towards(M,src) + +/obj/effect/anomaly/grav/Bump(mob/A) + gravShock(A) + return + +/obj/effect/anomaly/grav/Bumped(mob/A) + gravShock(A) + return + +/obj/effect/anomaly/grav/proc/gravShock(mob/A) + if(boing && isliving(A) && !A.stat) + A.Weaken(2) + var/atom/target = get_edge_target_turf(A, get_dir(src, get_step_away(A, src))) + A.throw_at(target, 5, 1) + boing = 0 + return + +///////////////////// + +/obj/effect/anomaly/flux + name = "flux wave anomaly" + icon_state = "electricity2" + +/obj/effect/anomaly/flux/atom_init() + . = ..() + aSignal.origin_tech = "powerstorage=5;programming=3;phorontech=2" + +///////////////////// + +/obj/effect/anomaly/bluespace + name = "bluespace anomaly" + icon_state = "bluespace" + density = 1 + +/obj/effect/anomaly/bluespace/atom_init() + . = ..() + aSignal.origin_tech = "bluespace=5;magnets=3;powerstorage=2" + +/obj/effect/anomaly/bluespace/Bumped(atom/A) + if(isliving(A)) + do_teleport(A, locate(A.x, A.y, A.z), 10) + return + +///////////////////// + +/obj/effect/anomaly/pyro + name = "pyroclastic anomaly" + icon_state = "mustard" + +/obj/effect/anomaly/pyro/atom_init() + . = ..() + aSignal.origin_tech = "phorontech=5;powerstorage=3;biotech=3" + +/obj/effect/anomaly/pyro/anomalyEffect() + ..() + var/turf/simulated/T = get_turf(src) + if(istype(T)) + var/datum/gas_mixture/payload = new + payload.toxins = 30 + T.zone.air.merge(payload) + T.hotspot_expose(1000, CELL_VOLUME) + + +///////////////////// + +/obj/effect/anomaly/bhole + name = "vortex anomaly" + icon_state = "bhole3" + desc = "That's a nice station you have there. It'd be a shame if something happened to it." + +/obj/effect/anomaly/bhole/atom_init() + . = ..() + aSignal.origin_tech = "materials=5;combat=4;engineering=3" + +/obj/effect/anomaly/bhole/anomalyEffect() + ..() + if(!isturf(loc)) //blackhole cannot be contained inside anything. Weird stuff might happen + qdel(src) + return + + grav(rand(0,3), rand(2,3), 50, 25) + + //Throwing stuff around! + for(var/obj/O in orange(1,src)) + if(!O.anchored) + var/mob/living/target = locate() in view(5,src) + if(!target) + return + O.throw_at(target, 5, 10) + return + else + O.ex_act(2) + +/obj/effect/anomaly/bhole/proc/grav(r, ex_act_force, pull_chance, turf_removal_chance) + for(var/t = -r, t < r, t++) + affect_coord(x+t, y-r, ex_act_force, pull_chance, turf_removal_chance) + affect_coord(x-t, y+r, ex_act_force, pull_chance, turf_removal_chance) + affect_coord(x+r, y+t, ex_act_force, pull_chance, turf_removal_chance) + affect_coord(x-r, y-t, ex_act_force, pull_chance, turf_removal_chance) + return + +/obj/effect/anomaly/bhole/proc/affect_coord(x, y, ex_act_force, pull_chance, turf_removal_chance) + //Get turf at coordinate + var/turf/T = locate(x, y, z) + if(isnull(T)) return + + //Pulling and/or ex_act-ing movable atoms in that turf + if(prob(pull_chance)) + for(var/obj/O in T.contents) + if(O.anchored) + O.ex_act(ex_act_force) + else + step_towards(O,src) + for(var/mob/living/M in T.contents) + step_towards(M,src) + + //Damaging the turf + if( T && istype(T,/turf/simulated) && prob(turf_removal_chance) ) + T.ex_act(ex_act_force) + return diff --git a/code/game/objects/effects/biomass_rift.dm b/code/game/objects/effects/biomass_rift.dm index e09db640b46f..57bd5b8be652 100644 --- a/code/game/objects/effects/biomass_rift.dm +++ b/code/game/objects/effects/biomass_rift.dm @@ -1,127 +1,127 @@ -/* -/obj/effect/biomass - icon = 'icons/obj/biomass.dmi' - icon_state = "stage1" - opacity = 0 - density = 0 - anchored = 1 - layer = ABOVE_HUD_LAYER //DEBUG - plane = ABOVE_HUD_PLANE - 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/atom_init() - //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/Destroy() - for(var/obj/effect/biomass/biomass in linkedBiomass) - qdel(biomass) - ..() - -/obj/effect/biomass/atom_init() - //set background = 1 - - . = ..() - if(!IsValidBiomassLoc(loc,src)) - qdel(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(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(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 , iYou get some of \the [src] on your hands.") - if (!user.blood_DNA) - user.blood_DNA = list() - user.blood_DNA |= blood_DNA.Copy() - user.bloody_hands += taken - user.hand_dirt_color = new/datum/dirt_cover(basedatum) - if(user.hand_dirt_color) - user.hand_dirt_color.add_dirt(basedatum) - else - user.hand_dirt_color = new/datum/dirt_cover(basedatum) - user.update_inv_gloves() - user.verbs += /mob/living/carbon/human/proc/bloody_doodle - -/obj/effect/decal/cleanable/blood/splatter - random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5") - amount = 2 - -/obj/effect/decal/cleanable/blood/drip - name = "drips of blood" - desc = "It's red." - gender = PLURAL - icon = 'icons/effects/drip.dmi' - icon_state = "1" - random_icon_states = list("1","2","3","4","5") - amount = 0 - var/list/drips = list() - -/obj/effect/decal/cleanable/blood/drip/atom_init() - . = ..() - drips |= icon_state - -/obj/effect/decal/cleanable/blood/writing - icon_state = "tracks" - desc = "It looks like a writing in blood." - gender = NEUTER - random_icon_states = list("writing1","writing2","writing3","writing4","writing5") - amount = 0 - var/message - -/obj/effect/decal/cleanable/blood/writing/atom_init() - . = ..() - if(random_icon_states.len) - for(var/obj/effect/decal/cleanable/blood/writing/W in loc) - random_icon_states.Remove(W.icon_state) - icon_state = pick(random_icon_states) - else - icon_state = "writing1" - -/obj/effect/decal/cleanable/blood/writing/examine(mob/user) - ..() - to_chat(user, "It reads: \"[message]\"") - -/obj/effect/decal/cleanable/blood/trail_holder - name = "blood" - icon_state = "blank" - desc = "Your instincts say you shouldn't be following these." - gender = PLURAL - density = 0 - anchored = 1 - layer = 2 - random_icon_states = null - amount = 3 - var/list/existing_dirs = list() - blood_DNA = list() - -/obj/effect/decal/cleanable/blood/gibs - name = "gibs" - desc = "They look bloody and gruesome." - gender = PLURAL - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/blood.dmi' - icon_state = "gibbl5" - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6") - var/fleshcolor = "#FFFFFF" - -/obj/effect/decal/cleanable/blood/gibs/remove_ex_blood() - return - -/obj/effect/decal/cleanable/blood/gibs/update_icon() - var/image/giblets = new(base_icon, "[icon_state]_flesh", dir) - giblets.color = fleshcolor - var/icon/blood = new(base_icon,"[icon_state]",dir) - blood.Blend(basedatum.color, ICON_MULTIPLY) - - icon = blood - overlays.Cut() - overlays += giblets - -/obj/effect/decal/cleanable/blood/gibs/up - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1") - -/obj/effect/decal/cleanable/blood/gibs/down - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1") - -/obj/effect/decal/cleanable/blood/gibs/body - random_icon_states = list("gibhead", "gibtorso") - -/obj/effect/decal/cleanable/blood/gibs/limb - random_icon_states = list("gibleg", "gibarm") - -/obj/effect/decal/cleanable/blood/gibs/core - random_icon_states = list("gibmid1", "gibmid2", "gibmid3") - - -/obj/effect/decal/cleanable/blood/gibs/proc/streak(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) - var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc) - b.basedatum = new/datum/dirt_cover(src.basedatum) - b.update_icon() - for(var/datum/disease/D in src.viruses) - var/datum/disease/ND = D.Copy(1) - b.viruses += ND - ND.holder = b - - if (step_to(src, get_step(src, direction), 0)) - break - - -/obj/effect/decal/cleanable/mucus - name = "mucus" - desc = "Disgusting mucus." - gender = PLURAL - density = 0 - anchored = 1 - layer = 2 - icon = 'icons/effects/blood.dmi' - icon_state = "mucus" - random_icon_states = list("mucus") - - var/list/datum/disease2/disease/virus2 = list() - var/dry = 0 // Keeps the lag down - -/obj/effect/decal/cleanable/mucus/atom_init() - . = ..() - addtimer(CALLBACK(src, .proc/set_dry, 1), DRYING_TIME * 2) - -/obj/effect/decal/cleanable/mucus/proc/set_dry(value) // just to change var using timer, we need a whole new proc :( - dry = value +#define DRYING_TIME 5 MINUTES //for 1 unit of depth in puddle (amount var) + +var/global/list/image/splatter_cache=list() + +/obj/effect/decal/cleanable/blood + name = "blood" + desc = "It's thick and gooey. Perhaps it's the chef's cooking?" + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/blood.dmi' + icon_state = "mfloor1" + random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7") + var/base_icon = 'icons/effects/blood.dmi' + var/list/viruses = list() + blood_DNA = list() + var/datum/dirt_cover/basedatum = /datum/dirt_cover/red_blood // Color when wet. + var/list/datum/disease2/disease/virus2 = list() + var/amount = 5 + var/drytime + +/obj/effect/decal/cleanable/blood/Destroy() + for(var/datum/disease/D in viruses) + D.cure(0) + return ..() + +/obj/effect/decal/cleanable/blood/atom_init() + ..() + + basedatum = new basedatum + return INITIALIZE_HINT_LATELOAD + +/obj/effect/decal/cleanable/blood/atom_init_late() + remove_ex_blood() + update_icon() + +/obj/effect/decal/cleanable/blood/proc/remove_ex_blood() //removes existant blood on the turf + if(istype(src, /obj/effect/decal/cleanable/blood/tracks)) + return // We handle our own drying. + + if(loc) // someone should make blood that drips thru closet or smth like that. + for(var/obj/effect/decal/cleanable/blood/B in loc) + if(B != src && B.type == type) + if (B.blood_DNA) + blood_DNA |= B.blood_DNA.Copy() + qdel(B) + + drytime = world.time + DRYING_TIME * (amount + 1) + addtimer(CALLBACK(src, .proc/dry), drytime) + +/obj/effect/decal/cleanable/blood/update_icon() + color = basedatum.color + +/obj/effect/decal/cleanable/blood/Crossed(mob/living/carbon/perp) + if(!istype(perp)) + return + if(amount < 1) + return + if(!islist(blood_DNA)) //prevent from runtime errors connected with shitspawn + blood_DNA = list() + + var/hasfeet = TRUE + var/skip = FALSE + if (ishuman(perp)) + var/mob/living/carbon/human/H = perp + var/obj/item/organ/external/l_foot = H.bodyparts_by_name[BP_L_LEG] + var/obj/item/organ/external/r_foot = H.bodyparts_by_name[BP_R_LEG] + if((!l_foot || l_foot.status & ORGAN_DESTROYED) && (!r_foot || r_foot.status & ORGAN_DESTROYED)) + hasfeet = FALSE + if(perp.shoes && !perp.buckled)//Adding blood to shoes + var/obj/item/clothing/shoes/S = perp.shoes + if(istype(S)) + if((dirt_overlay && dirt_overlay.color != basedatum.color) || (!dirt_overlay)) + S.overlays.Cut() + S.add_dirt_cover(basedatum) + S.track_blood = max(amount,S.track_blood) + if(!S.blood_DNA) + S.blood_DNA = list() + if(blood_DNA.len) + S.blood_DNA |= blood_DNA.Copy() + skip = TRUE + + if (hasfeet && !skip) // Or feet + if(perp.feet_dirt_color) + perp.feet_dirt_color.add_dirt(basedatum) + else + perp.feet_dirt_color = new/datum/dirt_cover(basedatum) + perp.track_blood = max(amount,perp.track_blood) + if(!perp.feet_blood_DNA) + perp.feet_blood_DNA = list() + perp.feet_blood_DNA |= blood_DNA.Copy() + else if (perp.buckled && istype(perp.buckled, /obj/structure/stool/bed/chair/wheelchair)) + var/obj/structure/stool/bed/chair/wheelchair/W = perp.buckled + W.bloodiness = 4 + + perp.update_inv_shoes() + if(perp.lying) + perp.crawl_in_blood(src) + amount-- + +/obj/effect/decal/cleanable/blood/proc/dry() + name = "dried [src.name]" + desc = "It's dry and crusty. Someone is not doing their job." + color = adjust_brightness(color, -50) + amount = 0 + +/obj/effect/decal/cleanable/blood/attack_hand(mob/living/carbon/human/user) + ..() + if (amount && istype(user)) + user.SetNextMove(CLICK_CD_MELEE) + add_fingerprint(user) + if (user.gloves) + return + var/taken = rand(1,amount) + amount -= taken + to_chat(user, "You get some of \the [src] on your hands.") + if (!user.blood_DNA) + user.blood_DNA = list() + user.blood_DNA |= blood_DNA.Copy() + user.bloody_hands += taken + user.hand_dirt_color = new/datum/dirt_cover(basedatum) + if(user.hand_dirt_color) + user.hand_dirt_color.add_dirt(basedatum) + else + user.hand_dirt_color = new/datum/dirt_cover(basedatum) + user.update_inv_gloves() + user.verbs += /mob/living/carbon/human/proc/bloody_doodle + +/obj/effect/decal/cleanable/blood/splatter + random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5") + amount = 2 + +/obj/effect/decal/cleanable/blood/drip + name = "drips of blood" + desc = "It's red." + gender = PLURAL + icon = 'icons/effects/drip.dmi' + icon_state = "1" + random_icon_states = list("1","2","3","4","5") + amount = 0 + var/list/drips = list() + +/obj/effect/decal/cleanable/blood/drip/atom_init() + . = ..() + drips |= icon_state + +/obj/effect/decal/cleanable/blood/writing + icon_state = "tracks" + desc = "It looks like a writing in blood." + gender = NEUTER + random_icon_states = list("writing1","writing2","writing3","writing4","writing5") + amount = 0 + var/message + +/obj/effect/decal/cleanable/blood/writing/atom_init() + . = ..() + if(random_icon_states.len) + for(var/obj/effect/decal/cleanable/blood/writing/W in loc) + random_icon_states.Remove(W.icon_state) + icon_state = pick(random_icon_states) + else + icon_state = "writing1" + +/obj/effect/decal/cleanable/blood/writing/examine(mob/user) + ..() + to_chat(user, "It reads: \"[message]\"") + +/obj/effect/decal/cleanable/blood/trail_holder + name = "blood" + icon_state = "blank" + desc = "Your instincts say you shouldn't be following these." + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + random_icon_states = null + amount = 3 + var/list/existing_dirs = list() + blood_DNA = list() + +/obj/effect/decal/cleanable/blood/gibs + name = "gibs" + desc = "They look bloody and gruesome." + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/blood.dmi' + icon_state = "gibbl5" + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6") + var/fleshcolor = "#FFFFFF" + +/obj/effect/decal/cleanable/blood/gibs/remove_ex_blood() + return + +/obj/effect/decal/cleanable/blood/gibs/update_icon() + var/image/giblets = new(base_icon, "[icon_state]_flesh", dir) + giblets.color = fleshcolor + var/icon/blood = new(base_icon,"[icon_state]",dir) + blood.Blend(basedatum.color, ICON_MULTIPLY) + + icon = blood + overlays.Cut() + overlays += giblets + +/obj/effect/decal/cleanable/blood/gibs/up + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1") + +/obj/effect/decal/cleanable/blood/gibs/down + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1") + +/obj/effect/decal/cleanable/blood/gibs/body + random_icon_states = list("gibhead", "gibtorso") + +/obj/effect/decal/cleanable/blood/gibs/limb + random_icon_states = list("gibleg", "gibarm") + +/obj/effect/decal/cleanable/blood/gibs/core + random_icon_states = list("gibmid1", "gibmid2", "gibmid3") + + +/obj/effect/decal/cleanable/blood/gibs/proc/streak(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) + var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc) + b.basedatum = new/datum/dirt_cover(src.basedatum) + b.update_icon() + for(var/datum/disease/D in src.viruses) + var/datum/disease/ND = D.Copy(1) + b.viruses += ND + ND.holder = b + + if (step_to(src, get_step(src, direction), 0)) + break + + +/obj/effect/decal/cleanable/mucus + name = "mucus" + desc = "Disgusting mucus." + gender = PLURAL + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/blood.dmi' + icon_state = "mucus" + random_icon_states = list("mucus") + + var/list/datum/disease2/disease/virus2 = list() + var/dry = 0 // Keeps the lag down + +/obj/effect/decal/cleanable/mucus/atom_init() + . = ..() + addtimer(CALLBACK(src, .proc/set_dry, 1), DRYING_TIME * 2) + +/obj/effect/decal/cleanable/mucus/proc/set_dry(value) // just to change var using timer, we need a whole new proc :( + dry = value diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index 4f0669034bc2..1f5290059f1f 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -1,166 +1,166 @@ -/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 - -/obj/effect/decal/cleanable/ash/attack_hand(mob/user) - to_chat(user, "[src] sifts through your fingers.") - user.SetNextMove(CLICK_CD_RAPID) - var/turf/simulated/floor/F = get_turf(src) - if (istype(F)) - F.dirt += 4 - qdel(src) - -/obj/effect/decal/cleanable/greenglow - -/obj/effect/decal/cleanable/greenglow/atom_init() - . = ..() - QDEL_IN(src, 1200) - -/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 - light_range = 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" - random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") - var/list/viruses = list() - -/obj/effect/decal/cleanable/vomit/Destroy() - for(var/datum/disease/D in viruses) - D.cure(0) - set_light(0) - return ..() - -/obj/effect/decal/cleanable/vomit/proc/stop_light() - sleep(rand(150,300)) - if(!src) return - set_light(0) - -/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/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/toilet_paint - name = "lettering" - desc = "A lettering." - layer = 2.1 - anchored = 1 - -var/list/toilet_overlay_cache = list() - -/obj/effect/decal/cleanable/toilet_paint/atom_init(mapload, main = random_color(), shade = random_color()) - . = ..() - - var/type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa") - - var/icon/mainOverlay = toilet_overlay_cache["[type]"] - var/icon/shadeOverlay = toilet_overlay_cache["[type]s"] - - if(!mainOverlay) - mainOverlay = toilet_overlay_cache["[type]"] = new/icon('icons/effects/crayondecal.dmi',"[type]", 2.1) - if(!shadeOverlay) - shadeOverlay = toilet_overlay_cache["[type]s"] = new/icon('icons/effects/crayondecal.dmi',"[type]s", 2.1) - shadeOverlay.Blend(shade, ICON_ADD) - - overlays += mainOverlay - overlays += shadeOverlay +/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 + +/obj/effect/decal/cleanable/ash/attack_hand(mob/user) + to_chat(user, "[src] sifts through your fingers.") + user.SetNextMove(CLICK_CD_RAPID) + var/turf/simulated/floor/F = get_turf(src) + if (istype(F)) + F.dirt += 4 + qdel(src) + +/obj/effect/decal/cleanable/greenglow + +/obj/effect/decal/cleanable/greenglow/atom_init() + . = ..() + QDEL_IN(src, 1200) + +/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 + light_range = 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" + random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") + var/list/viruses = list() + +/obj/effect/decal/cleanable/vomit/Destroy() + for(var/datum/disease/D in viruses) + D.cure(0) + set_light(0) + return ..() + +/obj/effect/decal/cleanable/vomit/proc/stop_light() + sleep(rand(150,300)) + if(!src) return + set_light(0) + +/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/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/toilet_paint + name = "lettering" + desc = "A lettering." + layer = 2.1 + anchored = 1 + +var/list/toilet_overlay_cache = list() + +/obj/effect/decal/cleanable/toilet_paint/atom_init(mapload, main = random_color(), shade = random_color()) + . = ..() + + var/type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa") + + var/icon/mainOverlay = toilet_overlay_cache["[type]"] + var/icon/shadeOverlay = toilet_overlay_cache["[type]s"] + + if(!mainOverlay) + mainOverlay = toilet_overlay_cache["[type]"] = new/icon('icons/effects/crayondecal.dmi',"[type]", 2.1) + if(!shadeOverlay) + shadeOverlay = toilet_overlay_cache["[type]s"] = new/icon('icons/effects/crayondecal.dmi',"[type]s", 2.1) + shadeOverlay.Blend(shade, ICON_ADD) + + overlays += mainOverlay + overlays += shadeOverlay diff --git a/code/game/objects/effects/decals/Cleanable/robots.dm b/code/game/objects/effects/decals/Cleanable/robots.dm index 442961e6af73..df5e099a6502 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" - basedatum = /datum/dirt_cover/oil - random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7") - - -/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(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 = new(src.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." - basedatum = /datum/dirt_cover/oil - -/obj/effect/decal/cleanable/blood/oil/dry() - return - -/obj/effect/decal/cleanable/blood/oil/process() - STOP_PROCESSING(SSobj, src) - -/obj/effect/decal/cleanable/blood/oil/streak - random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5") - amount = 2 +/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" + basedatum = /datum/dirt_cover/oil + random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7") + + +/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(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 = new(src.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." + basedatum = /datum/dirt_cover/oil + +/obj/effect/decal/cleanable/blood/oil/dry() + return + +/obj/effect/decal/cleanable/blood/oil/process() + STOP_PROCESSING(SSobj, src) + +/obj/effect/decal/cleanable/blood/oil/streak + random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5") + amount = 2 diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index daddf98a3a4e..e5e8787b4d30 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -1,14 +1,14 @@ -/obj/effect/decal/cleanable - var/list/random_icon_states = list() - var/targeted_by = null // Used so cleanbots can't claim a mess. - -/obj/effect/decal/cleanable/atom_init() - if (random_icon_states && length(random_icon_states) > 0) - icon_state = pick(random_icon_states) - . = ..() - decal_cleanable += src - - -/obj/effect/decal/cleanable/Destroy() - decal_cleanable -= src - return ..() +/obj/effect/decal/cleanable + var/list/random_icon_states = list() + var/targeted_by = null // Used so cleanbots can't claim a mess. + +/obj/effect/decal/cleanable/atom_init() + if (random_icon_states && length(random_icon_states) > 0) + icon_state = pick(random_icon_states) + . = ..() + decal_cleanable += src + + +/obj/effect/decal/cleanable/Destroy() + decal_cleanable -= src + return ..() diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index 9c126190f6a0..f2f58f5c85c7 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -1,82 +1,82 @@ -/obj/effect/decal/cleanable/crayon - name = "rune" - desc = "A rune drawn in crayon." - icon = 'icons/obj/rune.dmi' - layer = 2.1 - anchored = 1 - -var/list/crayon_overlay_cache = list() - -/obj/effect/decal/cleanable/crayon/atom_init(mapload, main = "#FFFFFF", shade = "#000000", type = "rune", e_name = "rune", override_color = 0) - . = ..() - - name = e_name - desc = "A [type] drawn in crayon." - if(type == "poseur tag") - gang_name() //Generate gang names so they get removed from the pool - type = pick(gang_name_pool) - - icon_state = type - - switch(type) - if("rune") - type = "rune[rand(1,6)]" - if("graffiti") - type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa","poseur tag") - - var/icon/mainOverlay = crayon_overlay_cache["[type]"] - if(!mainOverlay) - mainOverlay = crayon_overlay_cache["[type]"] = new/icon('icons/effects/crayondecal.dmi', "[type]", 2.1) - mainOverlay.Blend(main,ICON_ADD) - - overlays += mainOverlay - - if(type == "rune" || type == "graffiti") - - var/icon/shadeOverlay = crayon_overlay_cache["[type]s"] - - if(!shadeOverlay) - shadeOverlay = crayon_overlay_cache["[type]s"] = new/icon('icons/effects/crayondecal.dmi', "[type]s", 2.1) - shadeOverlay.Blend(shade, ICON_ADD) - - overlays += shadeOverlay - - if(override_color) - color = main - add_hiddenprint(usr) - - -/obj/effect/decal/cleanable/crayon/gang - layer = 3.6 //Harder to hide - var/gang - -/obj/effect/decal/cleanable/crayon/gang/atom_init(mapload, type, e_name = "gang tag") - var/area/territory = get_area(loc) - var/color - - if(type == "A") - gang = type - color = "#00B7EF" - icon_state = gang_name("A") - ticker.mode.A_territory_new |= list(territory.type = territory.name) - ticker.mode.A_territory_lost -= territory.type - else if(type == "B") - gang = type - color = "#DA0000" - icon_state = gang_name("B") - ticker.mode.B_territory_new |= list(territory.type = territory.name) - ticker.mode.B_territory_lost -= territory.type - - . = ..(mapload, color, color, icon_state, e_name) - -/obj/effect/decal/cleanable/crayon/gang/Destroy() - var/area/territory = get_area(src) - - if(gang == "A") - ticker.mode.A_territory_new -= territory.type - ticker.mode.A_territory_lost |= list(territory.type = territory.name) - if(gang == "B") - ticker.mode.B_territory_new -= territory.type - ticker.mode.B_territory_lost |= list(territory.type = territory.name) - - return ..() +/obj/effect/decal/cleanable/crayon + name = "rune" + desc = "A rune drawn in crayon." + icon = 'icons/obj/rune.dmi' + layer = 2.1 + anchored = 1 + +var/list/crayon_overlay_cache = list() + +/obj/effect/decal/cleanable/crayon/atom_init(mapload, main = "#FFFFFF", shade = "#000000", type = "rune", e_name = "rune", override_color = 0) + . = ..() + + name = e_name + desc = "A [type] drawn in crayon." + if(type == "poseur tag") + gang_name() //Generate gang names so they get removed from the pool + type = pick(gang_name_pool) + + icon_state = type + + switch(type) + if("rune") + type = "rune[rand(1,6)]" + if("graffiti") + type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa","poseur tag") + + var/icon/mainOverlay = crayon_overlay_cache["[type]"] + if(!mainOverlay) + mainOverlay = crayon_overlay_cache["[type]"] = new/icon('icons/effects/crayondecal.dmi', "[type]", 2.1) + mainOverlay.Blend(main,ICON_ADD) + + overlays += mainOverlay + + if(type == "rune" || type == "graffiti") + + var/icon/shadeOverlay = crayon_overlay_cache["[type]s"] + + if(!shadeOverlay) + shadeOverlay = crayon_overlay_cache["[type]s"] = new/icon('icons/effects/crayondecal.dmi', "[type]s", 2.1) + shadeOverlay.Blend(shade, ICON_ADD) + + overlays += shadeOverlay + + if(override_color) + color = main + add_hiddenprint(usr) + + +/obj/effect/decal/cleanable/crayon/gang + layer = 3.6 //Harder to hide + var/gang + +/obj/effect/decal/cleanable/crayon/gang/atom_init(mapload, type, e_name = "gang tag") + var/area/territory = get_area(loc) + var/color + + if(type == "A") + gang = type + color = "#00B7EF" + icon_state = gang_name("A") + ticker.mode.A_territory_new |= list(territory.type = territory.name) + ticker.mode.A_territory_lost -= territory.type + else if(type == "B") + gang = type + color = "#DA0000" + icon_state = gang_name("B") + ticker.mode.B_territory_new |= list(territory.type = territory.name) + ticker.mode.B_territory_lost -= territory.type + + . = ..(mapload, color, color, icon_state, e_name) + +/obj/effect/decal/cleanable/crayon/gang/Destroy() + var/area/territory = get_area(src) + + if(gang == "A") + ticker.mode.A_territory_new -= territory.type + ticker.mode.A_territory_lost |= list(territory.type = territory.name) + if(gang == "B") + ticker.mode.B_territory_new -= territory.type + ticker.mode.B_territory_lost |= list(territory.type = territory.name) + + return ..() diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm index e45ea210364c..b901e9c03e30 100644 --- a/code/game/objects/effects/decals/misc.dm +++ b/code/game/objects/effects/decals/misc.dm @@ -1,19 +1,19 @@ -/obj/effect/decal/point - name = "arrow" - desc = "It's an arrow hanging in mid-air. There may be a wizard about." - icon = 'icons/mob/screen1.dmi' - icon_state = "arrow" - layer = 16.0 - anchored = 1 - -// Used for spray that you spray at walls, tables, hydrovats etc -/obj/effect/decal/spraystill - density = 0 - anchored = 1 - layer = 50 - -//Used by spraybottles. -/obj/effect/decal/chempuff - name = "chemicals" - icon = 'icons/obj/chempuff.dmi' - pass_flags = PASSTABLE | PASSGRILLE +/obj/effect/decal/point + name = "arrow" + desc = "It's an arrow hanging in mid-air. There may be a wizard about." + icon = 'icons/mob/screen1.dmi' + icon_state = "arrow" + layer = 16.0 + anchored = 1 + +// Used for spray that you spray at walls, tables, hydrovats etc +/obj/effect/decal/spraystill + density = 0 + anchored = 1 + layer = 50 + +//Used by spraybottles. +/obj/effect/decal/chempuff + name = "chemicals" + icon = 'icons/obj/chempuff.dmi' + pass_flags = PASSTABLE | PASSGRILLE diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm index 10fb19a8a742..cff845b798f5 100644 --- a/code/game/objects/effects/decals/remains.dm +++ b/code/game/objects/effects/decals/remains.dm @@ -1,23 +1,23 @@ -/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 = 0 - -/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 = 0 - -/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 = 0 +/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 = 0 + +/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 = 0 + +/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 = 0 diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index d0b4e4cb158e..38e17653556b 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -1,755 +1,755 @@ -/* 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. - pass_flags = PASSTABLE | PASSGRILLE - -/obj/effect/effect/water - name = "water" - icon = 'icons/effects/effects.dmi' - icon_state = "extinguish" - var/life = 15.0 - mouse_opacity = 0 - -/obj/effect/Destroy() - if(reagents) - reagents.delete() - return ..() - -/obj/effect/effect/water/Move(turf/newloc) - //var/turf/T = src.loc - //if (istype(T, /turf)) - // T.firelevel = 0 //TODO: FIX - if (--src.life < 1) - //SN src = null - qdel(src) - if(newloc.density) - 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() - -/datum/effect/effect/system/Destroy() - holder = null - location = null - return ..() - -///////////////////////////////////////////// -// 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 = 'icons/effects/effects.dmi' - 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) - - start() - var/i = 0 - for(i=0, i 20) - return - spawn(0) - if(holder) - src.location = get_turf(holder) - var/obj/effect/effect/sparks/sparks = new /obj/effect/effect/sparks(src.location) - src.total_sparks++ - var/direction - if(src.cardinals) - direction = pick(cardinal) - else - direction = pick(alldirs) - 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 0) - devastation = min (MAX_EXPLOSION_RANGE, round(amount/12)) - - if (round(amount/6) > 0) - heavy = min (MAX_EXPLOSION_RANGE, round(amount/6)) - - if (round(amount/3) > 0) - light = min (MAX_EXPLOSION_RANGE, round(amount/3)) - - if (flash && flashing_factor) - flash += (round(amount/4) * flashing_factor) - - for(var/mob/M in viewers(world.view, location)) - to_chat(M, "The solution violently explodes.") - - explosion(location, devastation, heavy, light, flash) - - proc/holder_damage(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. + pass_flags = PASSTABLE | PASSGRILLE + +/obj/effect/effect/water + name = "water" + icon = 'icons/effects/effects.dmi' + icon_state = "extinguish" + var/life = 15.0 + mouse_opacity = 0 + +/obj/effect/Destroy() + if(reagents) + reagents.delete() + return ..() + +/obj/effect/effect/water/Move(turf/newloc) + //var/turf/T = src.loc + //if (istype(T, /turf)) + // T.firelevel = 0 //TODO: FIX + if (--src.life < 1) + //SN src = null + qdel(src) + if(newloc.density) + 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() + +/datum/effect/effect/system/Destroy() + holder = null + location = null + return ..() + +///////////////////////////////////////////// +// 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 = 'icons/effects/effects.dmi' + 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) + + start() + var/i = 0 + for(i=0, i 20) + return + spawn(0) + if(holder) + src.location = get_turf(holder) + var/obj/effect/effect/sparks/sparks = new /obj/effect/effect/sparks(src.location) + src.total_sparks++ + var/direction + if(src.cardinals) + direction = pick(cardinal) + else + direction = pick(alldirs) + 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 0) + devastation = min (MAX_EXPLOSION_RANGE, round(amount/12)) + + if (round(amount/6) > 0) + heavy = min (MAX_EXPLOSION_RANGE, round(amount/6)) + + if (round(amount/3) > 0) + light = min (MAX_EXPLOSION_RANGE, round(amount/3)) + + if (flash && flashing_factor) + flash += (round(amount/4) * flashing_factor) + + for(var/mob/M in viewers(world.view, location)) + to_chat(M, "The solution violently explodes.") + + explosion(location, devastation, heavy, light, flash) + + proc/holder_damage(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 0d4b15599157..cce76a296bd5 100644 --- a/code/game/objects/effects/gibs.dm +++ b/code/game/objects/effects/gibs.dm @@ -1,80 +1,80 @@ -/proc/gibs(atom/location, list/viruses, datum/dna/MobDNA) //CARN MARKER - new /obj/effect/gibspawner/generic(get_turf(location), viruses, MobDNA) - -/proc/hgibs(atom/location, list/viruses, datum/dna/MobDNA, fleshcolor, bloodcolor) - new /obj/effect/gibspawner/human(get_turf(location), viruses, MobDNA, fleshcolor, bloodcolor) - -/proc/xgibs(atom/location, list/viruses) - new /obj/effect/gibspawner/xeno(get_turf(location), viruses) - -/proc/robogibs(atom/location, 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/datum/dirt_cover/blooddatum //Used for gibbed humans. - -/obj/effect/gibspawner/atom_init(location, list/viruses, datum/dna/MobDNA, _fleshcolor, _blooddatum) - ..() - - if(_fleshcolor) - fleshcolor = _fleshcolor - if(_blooddatum) - blooddatum = new _blooddatum - - if(isturf(loc)) // basically if a badmin spawns it - Gib(loc, viruses, MobDNA) - - return INITIALIZE_HINT_QDEL - -/obj/effect/gibspawner/proc/Gib(atom/location, list/viruses = list(), 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) - qdel(D) - - 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 = new gibType(location) - - // Apply human species colouration to masks. - if(fleshcolor) - gib.fleshcolor = fleshcolor - if(blooddatum) - gib.basedatum = new/datum/dirt_cover(blooddatum) - - 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) +/proc/gibs(atom/location, list/viruses, datum/dna/MobDNA) //CARN MARKER + new /obj/effect/gibspawner/generic(get_turf(location), viruses, MobDNA) + +/proc/hgibs(atom/location, list/viruses, datum/dna/MobDNA, fleshcolor, bloodcolor) + new /obj/effect/gibspawner/human(get_turf(location), viruses, MobDNA, fleshcolor, bloodcolor) + +/proc/xgibs(atom/location, list/viruses) + new /obj/effect/gibspawner/xeno(get_turf(location), viruses) + +/proc/robogibs(atom/location, 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/datum/dirt_cover/blooddatum //Used for gibbed humans. + +/obj/effect/gibspawner/atom_init(location, list/viruses, datum/dna/MobDNA, _fleshcolor, _blooddatum) + ..() + + if(_fleshcolor) + fleshcolor = _fleshcolor + if(_blooddatum) + blooddatum = new _blooddatum + + if(isturf(loc)) // basically if a badmin spawns it + Gib(loc, viruses, MobDNA) + + return INITIALIZE_HINT_QDEL + +/obj/effect/gibspawner/proc/Gib(atom/location, list/viruses = list(), 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) + qdel(D) + + 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 = new gibType(location) + + // Apply human species colouration to masks. + if(fleshcolor) + gib.fleshcolor = fleshcolor + if(blooddatum) + gib.basedatum = new/datum/dirt_cover(blooddatum) + + 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) diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm index fe69e11ad4a6..c8c8500ba4f6 100644 --- a/code/game/objects/effects/glowshroom.dm +++ b/code/game/objects/effects/glowshroom.dm @@ -1,166 +1,166 @@ -//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 - light_power = 0.7 - light_color = "#80b82e" - var/endurance = 30 - var/potency = 30 - var/delay = 1200 - var/floor = 0 - var/yield = 3 - var/spreadChance = 40 - var/spreadIntoAdjacentChance = 60 - var/evolveChance = 2 - var/lastTick = 0 - var/spreaded = 1 - -/obj/effect/glowshroom/single - spreadChance = 0 - -/obj/effect/glowshroom/atom_init() - - . = ..() - - 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" - - START_PROCESSING(SSobj, src) - - set_light(round(potency/10), light_power, light_color) - lastTick = world.timeofday - -/obj/effect/glowshroom/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/effect/glowshroom/process() - if(!spreaded) - return - STOP_PROCESSING(SSobj, src) - if(((world.timeofday - lastTick) > delay) || ((world.timeofday - lastTick) < 0)) - lastTick = world.timeofday - 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/simulated/floor/plating/airless/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) - -/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, mob/user) - ..() - - 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 + light_power = 0.7 + light_color = "#80b82e" + var/endurance = 30 + var/potency = 30 + var/delay = 1200 + var/floor = 0 + var/yield = 3 + var/spreadChance = 40 + var/spreadIntoAdjacentChance = 60 + var/evolveChance = 2 + var/lastTick = 0 + var/spreaded = 1 + +/obj/effect/glowshroom/single + spreadChance = 0 + +/obj/effect/glowshroom/atom_init() + + . = ..() + + 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" + + START_PROCESSING(SSobj, src) + + set_light(round(potency/10), light_power, light_color) + lastTick = world.timeofday + +/obj/effect/glowshroom/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/effect/glowshroom/process() + if(!spreaded) + return + STOP_PROCESSING(SSobj, src) + if(((world.timeofday - lastTick) > delay) || ((world.timeofday - lastTick) < 0)) + lastTick = world.timeofday + 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/simulated/floor/plating/airless/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) + +/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, mob/user) + ..() + + 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 7900dcdb48c2..d0714795cfd4 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -1,276 +1,276 @@ -/obj/effect/landmark - name = "landmark" - icon = 'icons/mob/screen1.dmi' - icon_state = "x2" - anchored = TRUE - unacidable = TRUE - invisibility = INVISIBILITY_ABSTRACT - -/obj/effect/landmark/New() - ..() - tag = text("landmark*[]", name) - landmarks_list += src - -/obj/effect/landmark/Destroy() - landmarks_list -= src - return ..() - -/obj/effect/landmark/atom_init() - . = ..() - - switch(name) - if("shuttle") - shuttle_z = z - return INITIALIZE_HINT_QDEL - - if("airtunnel_stop") - airtunnel_stop = x - - if("airtunnel_start") - airtunnel_start = x - - if("airtunnel_bottom") - airtunnel_bottom = y - - if ("awaystart") - awaydestinations += src - - if("monkey") - monkeystart += loc - return INITIALIZE_HINT_QDEL - if("wizard") - wizardstart += loc - return INITIALIZE_HINT_QDEL - //prisoners - if("prisonwarp") - prisonwarp += loc - return INITIALIZE_HINT_QDEL - // 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 - return INITIALIZE_HINT_QDEL - if("blobstart") - blobstart += loc - return INITIALIZE_HINT_QDEL - if("xeno_spawn") - xeno_spawn += loc - return INITIALIZE_HINT_QDEL - if("ninjastart") - ninjastart += loc - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/start - name = "start" - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - anchored = TRUE - -/obj/effect/landmark/start/New() - ..() - if(name != "start") - tag = "start*[name]" - -/obj/effect/landmark/start/new_player - name = "New Player" - -// Must be on New() rather than Initialize, because players will -// join before SSatom initializes everything. -/obj/effect/landmark/start/new_player/New(loc) - ..() - newplayer_start += loc - -/obj/effect/landmark/start/new_player/atom_init(mapload) - ..() - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/latejoin - name = "JoinLate" - -/obj/effect/landmark/latejoin/New(loc) - ..() - latejoin += loc - -/obj/effect/landmark/latejoin/atom_init(mapload) - ..() - return INITIALIZE_HINT_QDEL - -//Costume spawner landmarks - -/obj/effect/landmark/costume/atom_init() // costume spawner, selects a random subclass and disappears - ..() - var/list/options = typesof(/obj/effect/landmark/costume) - var/PICK = options[rand(1, options.len)] - new PICK(loc) - return INITIALIZE_HINT_QDEL - -//SUBCLASSES. Spawn a bunch of items and disappear likewise -/obj/effect/landmark/costume/chicken/atom_init() - ..() - new /obj/item/clothing/suit/chickensuit(loc) - new /obj/item/clothing/head/chicken(loc) - new /obj/item/weapon/reagent_containers/food/snacks/egg(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/gladiator/atom_init() - ..() - new /obj/item/clothing/under/gladiator(loc) - new /obj/item/clothing/head/helmet/gladiator(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/madscientist/atom_init() - ..() - new /obj/item/clothing/under/gimmick/rank/captain/suit(loc) - new /obj/item/clothing/head/flatcap(loc) - new /obj/item/clothing/suit/storage/labcoat/mad(loc) - new /obj/item/clothing/glasses/gglasses(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/elpresidente/atom_init() - ..() - new /obj/item/clothing/under/gimmick/rank/captain/suit(loc) - new /obj/item/clothing/head/flatcap(loc) - new /obj/item/clothing/mask/cigarette/cigar/havana(loc) - new /obj/item/clothing/shoes/jackboots(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/nyangirl/atom_init() - ..() - new /obj/item/clothing/under/schoolgirl(loc) - new /obj/item/clothing/head/kitty(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/maid/atom_init() - ..() - new /obj/item/clothing/under/blackskirt(loc) - var/CHOICE = pick( /obj/item/clothing/head/beret , /obj/item/clothing/head/rabbitears ) - new CHOICE(loc) - new /obj/item/clothing/glasses/sunglasses/blindfold(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/butler/atom_init() - ..() - new /obj/item/clothing/suit/wcoat(loc) - new /obj/item/clothing/under/suit_jacket(loc) - new /obj/item/clothing/head/that(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/scratch/atom_init() - ..() - new /obj/item/clothing/gloves/white(loc) - new /obj/item/clothing/shoes/white(loc) - new /obj/item/clothing/under/scratch(loc) - if (prob(30)) - new /obj/item/clothing/head/cueball(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/highlander/atom_init() - ..() - new /obj/item/clothing/under/kilt(loc) - new /obj/item/clothing/head/beret(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/prig/atom_init() - ..() - new /obj/item/clothing/suit/wcoat(loc) - new /obj/item/clothing/glasses/monocle(loc) - var/CHOICE = pick( /obj/item/clothing/head/bowler, /obj/item/clothing/head/that) - new CHOICE(loc) - new /obj/item/clothing/shoes/black(loc) - new /obj/item/weapon/cane(loc) - new /obj/item/clothing/under/sl_suit(loc) - new /obj/item/clothing/mask/fakemoustache(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/plaguedoctor/atom_init() - ..() - new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(loc) - new /obj/item/clothing/head/plaguedoctorhat(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/nightowl/atom_init() - ..() - new /obj/item/clothing/under/owl(loc) - new /obj/item/clothing/mask/gas/owl_mask(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/waiter/atom_init() - ..() - new /obj/item/clothing/under/waiter(loc) - var/CHOICE = pick( /obj/item/clothing/head/kitty, /obj/item/clothing/head/rabbitears) - new CHOICE(loc) - new /obj/item/clothing/suit/apron(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/pirate/atom_init() - ..() - new /obj/item/clothing/under/pirate(loc) - new /obj/item/clothing/suit/pirate(loc) - var/CHOICE = pick( /obj/item/clothing/head/pirate , /obj/item/clothing/head/bandana ) - new CHOICE(loc) - new /obj/item/clothing/glasses/eyepatch(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/commie/atom_init() - ..() - new /obj/item/clothing/under/soviet(loc) - new /obj/item/clothing/head/ushanka(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/imperium_monk/atom_init() - ..() - new /obj/item/clothing/suit/imperium_monk(loc) - if (prob(25)) - new /obj/item/clothing/mask/gas/cyborg(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/holiday_priest/atom_init() - ..() - new /obj/item/clothing/suit/holidaypriest(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/marisawizard/fake/atom_init() - ..() - new /obj/item/clothing/head/wizard/marisa/fake(loc) - new/obj/item/clothing/suit/wizrobe/marisa/fake(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/cutewitch/atom_init() - ..() - new /obj/item/clothing/under/sundress(loc) - new /obj/item/clothing/head/witchwig(loc) - new /obj/item/weapon/staff/broom(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/fakewizard/atom_init() - ..() - new /obj/item/clothing/suit/wizrobe/fake(loc) - new /obj/item/clothing/head/wizard/fake(loc) - new /obj/item/weapon/staff/(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/sexyclown/atom_init() - ..() - new /obj/item/clothing/mask/gas/sexyclown(loc) - new /obj/item/clothing/under/sexyclown(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/costume/sexymime/atom_init() - ..() - new /obj/item/clothing/mask/gas/sexymime(loc) - new /obj/item/clothing/under/sexymime(loc) - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/blockway - density = TRUE +/obj/effect/landmark + name = "landmark" + icon = 'icons/mob/screen1.dmi' + icon_state = "x2" + anchored = TRUE + unacidable = TRUE + invisibility = INVISIBILITY_ABSTRACT + +/obj/effect/landmark/New() + ..() + tag = text("landmark*[]", name) + landmarks_list += src + +/obj/effect/landmark/Destroy() + landmarks_list -= src + return ..() + +/obj/effect/landmark/atom_init() + . = ..() + + switch(name) + if("shuttle") + shuttle_z = z + return INITIALIZE_HINT_QDEL + + if("airtunnel_stop") + airtunnel_stop = x + + if("airtunnel_start") + airtunnel_start = x + + if("airtunnel_bottom") + airtunnel_bottom = y + + if ("awaystart") + awaydestinations += src + + if("monkey") + monkeystart += loc + return INITIALIZE_HINT_QDEL + if("wizard") + wizardstart += loc + return INITIALIZE_HINT_QDEL + //prisoners + if("prisonwarp") + prisonwarp += loc + return INITIALIZE_HINT_QDEL + // 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 + return INITIALIZE_HINT_QDEL + if("blobstart") + blobstart += loc + return INITIALIZE_HINT_QDEL + if("xeno_spawn") + xeno_spawn += loc + return INITIALIZE_HINT_QDEL + if("ninjastart") + ninjastart += loc + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/start + name = "start" + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + anchored = TRUE + +/obj/effect/landmark/start/New() + ..() + if(name != "start") + tag = "start*[name]" + +/obj/effect/landmark/start/new_player + name = "New Player" + +// Must be on New() rather than Initialize, because players will +// join before SSatom initializes everything. +/obj/effect/landmark/start/new_player/New(loc) + ..() + newplayer_start += loc + +/obj/effect/landmark/start/new_player/atom_init(mapload) + ..() + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/latejoin + name = "JoinLate" + +/obj/effect/landmark/latejoin/New(loc) + ..() + latejoin += loc + +/obj/effect/landmark/latejoin/atom_init(mapload) + ..() + return INITIALIZE_HINT_QDEL + +//Costume spawner landmarks + +/obj/effect/landmark/costume/atom_init() // costume spawner, selects a random subclass and disappears + ..() + var/list/options = typesof(/obj/effect/landmark/costume) + var/PICK = options[rand(1, options.len)] + new PICK(loc) + return INITIALIZE_HINT_QDEL + +//SUBCLASSES. Spawn a bunch of items and disappear likewise +/obj/effect/landmark/costume/chicken/atom_init() + ..() + new /obj/item/clothing/suit/chickensuit(loc) + new /obj/item/clothing/head/chicken(loc) + new /obj/item/weapon/reagent_containers/food/snacks/egg(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/gladiator/atom_init() + ..() + new /obj/item/clothing/under/gladiator(loc) + new /obj/item/clothing/head/helmet/gladiator(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/madscientist/atom_init() + ..() + new /obj/item/clothing/under/gimmick/rank/captain/suit(loc) + new /obj/item/clothing/head/flatcap(loc) + new /obj/item/clothing/suit/storage/labcoat/mad(loc) + new /obj/item/clothing/glasses/gglasses(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/elpresidente/atom_init() + ..() + new /obj/item/clothing/under/gimmick/rank/captain/suit(loc) + new /obj/item/clothing/head/flatcap(loc) + new /obj/item/clothing/mask/cigarette/cigar/havana(loc) + new /obj/item/clothing/shoes/jackboots(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/nyangirl/atom_init() + ..() + new /obj/item/clothing/under/schoolgirl(loc) + new /obj/item/clothing/head/kitty(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/maid/atom_init() + ..() + new /obj/item/clothing/under/blackskirt(loc) + var/CHOICE = pick( /obj/item/clothing/head/beret , /obj/item/clothing/head/rabbitears ) + new CHOICE(loc) + new /obj/item/clothing/glasses/sunglasses/blindfold(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/butler/atom_init() + ..() + new /obj/item/clothing/suit/wcoat(loc) + new /obj/item/clothing/under/suit_jacket(loc) + new /obj/item/clothing/head/that(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/scratch/atom_init() + ..() + new /obj/item/clothing/gloves/white(loc) + new /obj/item/clothing/shoes/white(loc) + new /obj/item/clothing/under/scratch(loc) + if (prob(30)) + new /obj/item/clothing/head/cueball(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/highlander/atom_init() + ..() + new /obj/item/clothing/under/kilt(loc) + new /obj/item/clothing/head/beret(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/prig/atom_init() + ..() + new /obj/item/clothing/suit/wcoat(loc) + new /obj/item/clothing/glasses/monocle(loc) + var/CHOICE = pick( /obj/item/clothing/head/bowler, /obj/item/clothing/head/that) + new CHOICE(loc) + new /obj/item/clothing/shoes/black(loc) + new /obj/item/weapon/cane(loc) + new /obj/item/clothing/under/sl_suit(loc) + new /obj/item/clothing/mask/fakemoustache(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/plaguedoctor/atom_init() + ..() + new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(loc) + new /obj/item/clothing/head/plaguedoctorhat(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/nightowl/atom_init() + ..() + new /obj/item/clothing/under/owl(loc) + new /obj/item/clothing/mask/gas/owl_mask(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/waiter/atom_init() + ..() + new /obj/item/clothing/under/waiter(loc) + var/CHOICE = pick( /obj/item/clothing/head/kitty, /obj/item/clothing/head/rabbitears) + new CHOICE(loc) + new /obj/item/clothing/suit/apron(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/pirate/atom_init() + ..() + new /obj/item/clothing/under/pirate(loc) + new /obj/item/clothing/suit/pirate(loc) + var/CHOICE = pick( /obj/item/clothing/head/pirate , /obj/item/clothing/head/bandana ) + new CHOICE(loc) + new /obj/item/clothing/glasses/eyepatch(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/commie/atom_init() + ..() + new /obj/item/clothing/under/soviet(loc) + new /obj/item/clothing/head/ushanka(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/imperium_monk/atom_init() + ..() + new /obj/item/clothing/suit/imperium_monk(loc) + if (prob(25)) + new /obj/item/clothing/mask/gas/cyborg(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/holiday_priest/atom_init() + ..() + new /obj/item/clothing/suit/holidaypriest(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/marisawizard/fake/atom_init() + ..() + new /obj/item/clothing/head/wizard/marisa/fake(loc) + new/obj/item/clothing/suit/wizrobe/marisa/fake(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/cutewitch/atom_init() + ..() + new /obj/item/clothing/under/sundress(loc) + new /obj/item/clothing/head/witchwig(loc) + new /obj/item/weapon/staff/broom(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/fakewizard/atom_init() + ..() + new /obj/item/clothing/suit/wizrobe/fake(loc) + new /obj/item/clothing/head/wizard/fake(loc) + new /obj/item/weapon/staff/(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/sexyclown/atom_init() + ..() + new /obj/item/clothing/mask/gas/sexyclown(loc) + new /obj/item/clothing/under/sexyclown(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/costume/sexymime/atom_init() + ..() + new /obj/item/clothing/mask/gas/sexymime(loc) + new /obj/item/clothing/under/sexymime(loc) + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/blockway + density = TRUE diff --git a/code/game/objects/effects/manifest.dm b/code/game/objects/effects/manifest.dm index bbb957b13765..7096f83dd2ea 100644 --- a/code/game/objects/effects/manifest.dm +++ b/code/game/objects/effects/manifest.dm @@ -1,17 +1,17 @@ -/obj/effect/manifest - name = "manifest" - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - unacidable = TRUE // Just to be sure. - invisibility = INVISIBILITY_ABSTRACT - -/obj/effect/manifest/proc/manifest() - var/dat = "Crew Manifest:
                    " - for(var/mob/living/carbon/human/M in human_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 = TRUE // Just to be sure. + invisibility = INVISIBILITY_ABSTRACT + +/obj/effect/manifest/proc/manifest() + var/dat = "Crew Manifest:
                    " + for(var/mob/living/carbon/human/M in human_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 786ea1988490..3b7eec491b83 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -1,100 +1,100 @@ -/obj/effect/mine - name = "Mine" - desc = "I Better stay away from that thing." - density = 1 - anchored = 1 - layer = 3 - icon = 'icons/obj/weapons.dmi' - icon_state = "uglymine" - var/triggered = 0 - -/obj/effect/mine/atom_init() - . = ..() - icon_state = "uglyminearmed" - -/obj/effect/mine/Crossed(AM as mob|obj) - Bumped(AM) - -/obj/effect/mine/Bumped(mob/M) - - 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 [bicon(src)] [src]") - triggered = 1 - trigger_act(M) - -/obj/effect/mine/proc/trigger_act(obj) - explosion(loc, 0, 1, 2, 3) - spawn(0) - qdel(src) - -/obj/effect/mine/dnascramble - name = "Radiation Mine" - icon_state = "uglymine" - -/obj/effect/mine/dnascramble/trigger_act(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/phoron - name = "Phoron Mine" - icon_state = "uglymine" - -/obj/effect/mine/phoron/trigger_act(obj) - for (var/turf/simulated/floor/target in range(1,src)) - if(!target.blocks_air) - - target.assume_gas("phoron", 30) - - target.hotspot_expose(1000, CELL_VOLUME) - - spawn(0) - qdel(src) - -/obj/effect/mine/kick - name = "Kick Mine" - icon_state = "uglymine" - -/obj/effect/mine/kick/trigger_act(obj) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() - s.set_up(3, 1, src) - s.start() - del(obj:client) - spawn(0) - qdel(src) - -/obj/effect/mine/n2o - name = "N2O Mine" - icon_state = "uglymine" - -/obj/effect/mine/n2o/trigger_act(obj) - //note: im lazy - - for (var/turf/simulated/floor/target in range(1,src)) - if(!target.blocks_air) - target.assume_gas("sleeping_agent", 30) - - spawn(0) - qdel(src) - -/obj/effect/mine/stun - name = "Stun Mine" - icon_state = "uglymine" - -/obj/effect/mine/stun/trigger_act(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 + name = "Mine" + desc = "I Better stay away from that thing." + density = 1 + anchored = 1 + layer = 3 + icon = 'icons/obj/weapons.dmi' + icon_state = "uglymine" + var/triggered = 0 + +/obj/effect/mine/atom_init() + . = ..() + icon_state = "uglyminearmed" + +/obj/effect/mine/Crossed(AM as mob|obj) + Bumped(AM) + +/obj/effect/mine/Bumped(mob/M) + + 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 [bicon(src)] [src]") + triggered = 1 + trigger_act(M) + +/obj/effect/mine/proc/trigger_act(obj) + explosion(loc, 0, 1, 2, 3) + spawn(0) + qdel(src) + +/obj/effect/mine/dnascramble + name = "Radiation Mine" + icon_state = "uglymine" + +/obj/effect/mine/dnascramble/trigger_act(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/phoron + name = "Phoron Mine" + icon_state = "uglymine" + +/obj/effect/mine/phoron/trigger_act(obj) + for (var/turf/simulated/floor/target in range(1,src)) + if(!target.blocks_air) + + target.assume_gas("phoron", 30) + + target.hotspot_expose(1000, CELL_VOLUME) + + spawn(0) + qdel(src) + +/obj/effect/mine/kick + name = "Kick Mine" + icon_state = "uglymine" + +/obj/effect/mine/kick/trigger_act(obj) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + s.set_up(3, 1, src) + s.start() + del(obj:client) + spawn(0) + qdel(src) + +/obj/effect/mine/n2o + name = "N2O Mine" + icon_state = "uglymine" + +/obj/effect/mine/n2o/trigger_act(obj) + //note: im lazy + + for (var/turf/simulated/floor/target in range(1,src)) + if(!target.blocks_air) + target.assume_gas("sleeping_agent", 30) + + spawn(0) + qdel(src) + +/obj/effect/mine/stun + name = "Stun Mine" + icon_state = "uglymine" + +/obj/effect/mine/stun/trigger_act(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) diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index 1677e79b0cc5..79fadd568d3e 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -1,8 +1,8 @@ -//The effect when you wrap a dead body in gift wrap -/obj/effect/spresent - name = "strange present" - desc = "It's a ... present?" - icon = 'icons/obj/items.dmi' - icon_state = "strangepresent" - density = 1 - anchored = 0 +//The effect when you wrap a dead body in gift wrap +/obj/effect/spresent + name = "strange present" + desc = "It's a ... present?" + icon = 'icons/obj/items.dmi' + icon_state = "strangepresent" + density = 1 + anchored = 0 diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index bcc9850dde1a..53a42998e017 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 - var/i_attached //Added for possible image attachments to objects. For hallucinations and the like. - -/obj/effect/overlay/attackby() - return - -/obj/effect/overlay/beam//Not actually a projectile, just an effect. - name="beam" - icon='icons/effects/beam.dmi' - icon_state="b_beam" - var/tmp/atom/BeamSource - -/obj/effect/overlay/beam/atom_init() - . = ..() - QDEL_IN(src, 10) - -/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/singularity_act() - return - -/obj/effect/overlay/singularity_pull() - return - -/obj/effect/overlay/slice - name = "Slice" - icon = 'icons/effects/effects.dmi' - icon_state = "Slice" - layer = LIGHTING_LAYER + 1 - plane = LIGHTING_PLANE + 1 - anchored = 1 - -/obj/effect/overlay/droppod_open - layer = 4 - plane = 4 - anchored = 1 - icon = 'icons/obj/structures/droppod.dmi' - icon_state = "panel_opening" - -/obj/effect/overlay/droppod_open/atom_init(mapload, icon_modifier) - . = ..() - if(icon_modifier) - icon_state += icon_modifier - QDEL_IN(src, 27) +/obj/effect/overlay + name = "overlay" + unacidable = 1 + var/i_attached //Added for possible image attachments to objects. For hallucinations and the like. + +/obj/effect/overlay/attackby() + return + +/obj/effect/overlay/beam//Not actually a projectile, just an effect. + name="beam" + icon='icons/effects/beam.dmi' + icon_state="b_beam" + var/tmp/atom/BeamSource + +/obj/effect/overlay/beam/atom_init() + . = ..() + QDEL_IN(src, 10) + +/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/singularity_act() + return + +/obj/effect/overlay/singularity_pull() + return + +/obj/effect/overlay/slice + name = "Slice" + icon = 'icons/effects/effects.dmi' + icon_state = "Slice" + layer = LIGHTING_LAYER + 1 + plane = LIGHTING_PLANE + 1 + anchored = 1 + +/obj/effect/overlay/droppod_open + layer = 4 + plane = 4 + anchored = 1 + icon = 'icons/obj/structures/droppod.dmi' + icon_state = "panel_opening" + +/obj/effect/overlay/droppod_open/atom_init(mapload, icon_modifier) + . = ..() + if(icon_modifier) + icon_state += icon_modifier + QDEL_IN(src, 27) diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 28b22601fad6..3576f1133cf9 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -1,114 +1,114 @@ -/obj/effect/portal - name = "portal" - desc = "Looks unstable. Best to test it with the clown." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "portal" - density = TRUE - unacidable = TRUE // Can't destroy energy portals. - var/failchance = 5 - var/destroy_after_init = TRUE - var/obj/item/target = null - var/creator = null - anchored = TRUE - -/obj/effect/portal/atom_init() - . = ..() - portal_list += src - if(destroy_after_init) - QDEL_IN(src, 300) - -/obj/effect/portal/Destroy() - portal_list -= src - return ..() - -/obj/effect/portal/Bumped(mob/M) - spawn(0) - src.teleport(M) - return - return - -/obj/effect/portal/Crossed(AM as mob|obj) - spawn(0) - src.teleport(AM) - return - return - - - -/obj/effect/portal/proc/teleport(atom/movable/M, density_check = TELE_CHECK_NONE, respect_entrydir = FALSE, use_forceMove = TRUE) - if (istype(M, /obj/effect)) //sparks don't teleport - return FALSE - if (M.anchored && istype(M, /obj/mecha)) - return FALSE - if (icon_state == "portal1") - return FALSE - if (!( target )) - qdel(src) - return FALSE - if (istype(M, /atom/movable)) - if(prob(failchance)) //oh dear a problem, put em in deep space - src.icon_state = "portal1" - return do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0, use_forceMove, adest_checkdensity = density_check, arespect_entrydir = respect_entrydir, aentrydir = get_dir(M, src)) - else - return do_teleport(M, target, 1, use_forceMove, adest_checkdensity = density_check, arespect_entrydir = respect_entrydir, aentrydir = get_dir(M, src)) - -//Telescience wormhole -/obj/effect/portal/tsci_wormhole - name = "wormhole" - icon = 'icons/obj/objects.dmi' - icon_state = "anom" - destroy_after_init = FALSE - failchance = 0 - - var/obj/effect/portal/tsci_wormhole/linked_portal = null - var/obj/machinery/computer/telescience/linked_console = null - -/obj/effect/portal/tsci_wormhole/atom_init(mapload, turf/exit, other_side_portal = FALSE) - . = ..() - if(!other_side_portal) - linked_portal = new(exit, get_turf(src), TRUE) - linked_portal.linked_portal = src - target = linked_portal - linked_portal.target = src - -/obj/effect/portal/tsci_wormhole/Destroy() - target = null - if(linked_console) - linked_console.active_wormhole = null - linked_console.use_power = 1 - linked_console = null - if(linked_portal) - playsound(src, 'sound/effects/phasein.ogg', 25, 1) - playsound(linked_portal, 'sound/effects/phasein.ogg', 25, 1) - var/obj/effect/portal/tsci_wormhole/LP = linked_portal - linked_portal = null - LP.linked_portal = null - qdel(LP) - return ..() - -/obj/effect/portal/tsci_wormhole/Bumped(mob/M) - set waitfor = 0 - if(teleport(M, TELE_CHECK_ALL, TRUE, FALSE)) - handle_special_effects(M) - -/obj/effect/portal/tsci_wormhole/Crossed(AM) - set waitfor = 0 - if(teleport(AM, TELE_CHECK_ALL, TRUE, FALSE)) - handle_special_effects(AM) - -/obj/effect/portal/tsci_wormhole/proc/handle_special_effects(AM) - if(ishuman(AM)) - var/mob/living/carbon/human/H = AM - var/bad_effects = 0 - if(H.species.flags[IS_SYNTHETIC]) - return - if(prob(20)) - bad_effects += 1 - H.confused += 3 - var/msg = pick("You feel dizzy.", "Your head starts spinning.") - to_chat(H, "[msg]") - if(prob(20)) - bad_effects += 1 - H.vomit() //No msg required, since vomit() will handle this. - if(bad_effects == 2) - H.Paralyse(3) +/obj/effect/portal + name = "portal" + desc = "Looks unstable. Best to test it with the clown." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "portal" + density = TRUE + unacidable = TRUE // Can't destroy energy portals. + var/failchance = 5 + var/destroy_after_init = TRUE + var/obj/item/target = null + var/creator = null + anchored = TRUE + +/obj/effect/portal/atom_init() + . = ..() + portal_list += src + if(destroy_after_init) + QDEL_IN(src, 300) + +/obj/effect/portal/Destroy() + portal_list -= src + return ..() + +/obj/effect/portal/Bumped(mob/M) + spawn(0) + src.teleport(M) + return + return + +/obj/effect/portal/Crossed(AM as mob|obj) + spawn(0) + src.teleport(AM) + return + return + + + +/obj/effect/portal/proc/teleport(atom/movable/M, density_check = TELE_CHECK_NONE, respect_entrydir = FALSE, use_forceMove = TRUE) + if (istype(M, /obj/effect)) //sparks don't teleport + return FALSE + if (M.anchored && istype(M, /obj/mecha)) + return FALSE + if (icon_state == "portal1") + return FALSE + if (!( target )) + qdel(src) + return FALSE + if (istype(M, /atom/movable)) + if(prob(failchance)) //oh dear a problem, put em in deep space + src.icon_state = "portal1" + return do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0, use_forceMove, adest_checkdensity = density_check, arespect_entrydir = respect_entrydir, aentrydir = get_dir(M, src)) + else + return do_teleport(M, target, 1, use_forceMove, adest_checkdensity = density_check, arespect_entrydir = respect_entrydir, aentrydir = get_dir(M, src)) + +//Telescience wormhole +/obj/effect/portal/tsci_wormhole + name = "wormhole" + icon = 'icons/obj/objects.dmi' + icon_state = "anom" + destroy_after_init = FALSE + failchance = 0 + + var/obj/effect/portal/tsci_wormhole/linked_portal = null + var/obj/machinery/computer/telescience/linked_console = null + +/obj/effect/portal/tsci_wormhole/atom_init(mapload, turf/exit, other_side_portal = FALSE) + . = ..() + if(!other_side_portal) + linked_portal = new(exit, get_turf(src), TRUE) + linked_portal.linked_portal = src + target = linked_portal + linked_portal.target = src + +/obj/effect/portal/tsci_wormhole/Destroy() + target = null + if(linked_console) + linked_console.active_wormhole = null + linked_console.use_power = 1 + linked_console = null + if(linked_portal) + playsound(src, 'sound/effects/phasein.ogg', 25, 1) + playsound(linked_portal, 'sound/effects/phasein.ogg', 25, 1) + var/obj/effect/portal/tsci_wormhole/LP = linked_portal + linked_portal = null + LP.linked_portal = null + qdel(LP) + return ..() + +/obj/effect/portal/tsci_wormhole/Bumped(mob/M) + set waitfor = 0 + if(teleport(M, TELE_CHECK_ALL, TRUE, FALSE)) + handle_special_effects(M) + +/obj/effect/portal/tsci_wormhole/Crossed(AM) + set waitfor = 0 + if(teleport(AM, TELE_CHECK_ALL, TRUE, FALSE)) + handle_special_effects(AM) + +/obj/effect/portal/tsci_wormhole/proc/handle_special_effects(AM) + if(ishuman(AM)) + var/mob/living/carbon/human/H = AM + var/bad_effects = 0 + if(H.species.flags[IS_SYNTHETIC]) + return + if(prob(20)) + bad_effects += 1 + H.confused += 3 + var/msg = pick("You feel dizzy.", "Your head starts spinning.") + to_chat(H, "[msg]") + if(prob(20)) + bad_effects += 1 + H.vomit() //No msg required, since vomit() will handle this. + if(bad_effects == 2) + H.Paralyse(3) diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm index 3af7e45b7e6f..43e988748360 100644 --- a/code/game/objects/effects/spawners/bombspawner.dm +++ b/code/game/objects/effects/spawners/bombspawner.dm @@ -1,67 +1,67 @@ -/obj/effect/spawner/newbomb - name = "bomb" - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - var/btype = 0 // 0=radio, 1=prox, 2=time - -/obj/effect/spawner/newbomb/timer - btype = 2 - -/obj/effect/spawner/newbomb/timer/syndicate - -/obj/effect/spawner/newbomb/proximity - btype = 1 - -/obj/effect/spawner/newbomb/radio - btype = 0 - - -/obj/effect/spawner/newbomb/atom_init() - ..() - - var/obj/item/device/transfer_valve/V = new(loc) - var/obj/item/weapon/tank/phoron/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.gas["phoron"] = 12 - PT.air_contents.gas["carbon_dioxide"] = 8 - PT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE + 1 - PT.air_contents.update_values() - - OT.air_contents.gas["oxygen"] = 20 - OT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE + 1 - OT.air_contents.update_values() - - var/obj/item/device/assembly/S - - switch (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() - - return INITIALIZE_HINT_QDEL +/obj/effect/spawner/newbomb + name = "bomb" + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + var/btype = 0 // 0=radio, 1=prox, 2=time + +/obj/effect/spawner/newbomb/timer + btype = 2 + +/obj/effect/spawner/newbomb/timer/syndicate + +/obj/effect/spawner/newbomb/proximity + btype = 1 + +/obj/effect/spawner/newbomb/radio + btype = 0 + + +/obj/effect/spawner/newbomb/atom_init() + ..() + + var/obj/item/device/transfer_valve/V = new(loc) + var/obj/item/weapon/tank/phoron/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.gas["phoron"] = 12 + PT.air_contents.gas["carbon_dioxide"] = 8 + PT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE + 1 + PT.air_contents.update_values() + + OT.air_contents.gas["oxygen"] = 20 + OT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE + 1 + OT.air_contents.update_values() + + var/obj/item/device/assembly/S + + switch (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() + + return INITIALIZE_HINT_QDEL diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm index 09dc88031cd1..3d92540b6bbd 100644 --- a/code/game/objects/effects/spawners/gibspawner.dm +++ b/code/game/objects/effects/spawners/gibspawner.dm @@ -1,91 +1,91 @@ -/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/atom_init() - 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/atom_init() - 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/atom_init() - 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/atom_init() - 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/atom_init() + 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/atom_init() + 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/atom_init() + 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/atom_init() + 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 9dd4eb5828e3..22b3832b24d9 100644 --- a/code/game/objects/effects/spawners/vaultspawner.dm +++ b/code/game/objects/effects/spawners/vaultspawner.dm @@ -1,28 +1,28 @@ -/obj/effect/vaultspawner - var/maxX = 6 - var/maxY = 6 - var/minX = 2 - var/minY = 2 - -/obj/effect/vaultspawner/atom_init(mapload, lX = minX, uX = maxX, lY = minY, uY = maxY, type = null) - ..() - - if(!type) - type = pick("sandstone","rock","alien") - - var/lowBoundX = loc.x - var/lowBoundY = loc.y - - var/hiBoundX = loc.x + rand(lX,uX) - var/hiBoundY = loc.y + rand(lY,uY) - - var/z = loc.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) - - return INITIALIZE_HINT_QDEL +/obj/effect/vaultspawner + var/maxX = 6 + var/maxY = 6 + var/minX = 2 + var/minY = 2 + +/obj/effect/vaultspawner/atom_init(mapload, lX = minX, uX = maxX, lY = minY, uY = maxY, type = null) + ..() + + if(!type) + type = pick("sandstone","rock","alien") + + var/lowBoundX = loc.x + var/lowBoundY = loc.y + + var/hiBoundX = loc.x + rand(lX,uX) + var/hiBoundY = loc.y + rand(lY,uY) + + var/z = loc.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) + + return INITIALIZE_HINT_QDEL diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 52ee6a2e8e45..dc08766efbe7 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -1,231 +1,231 @@ -//generic procs copied from obj/effect/alien -/obj/effect/spider - name = "web" - desc = "It's stringy and sticky." - icon = 'icons/effects/effects.dmi' - anchored = 1 - density = 0 - var/health = 15 - -//similar to weeds, but only barfed out by nurses manually -/obj/effect/spider/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/spider/attackby(obj/item/weapon/W, mob/user) - if(W.attack_verb.len) - visible_message("\red \The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") - else - visible_message("\red \The [src] have been attacked with \the [W][(user ? " by [user]." : ".")]") - user.SetNextMove(CLICK_CD_MELEE) - - 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/spider/bullet_act(obj/item/projectile/Proj) - ..() - health -= Proj.damage - healthcheck() - -/obj/effect/spider/proc/healthcheck() - if(health <= 0) - qdel(src) - -/obj/effect/spider/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 300) - health -= 5 - healthcheck() - -/obj/effect/spider/stickyweb - icon_state = "stickyweb1" - -/obj/effect/spider/stickyweb/atom_init() - . = ..() - if(prob(50)) - icon_state = "stickyweb2" - -/obj/effect/spider/stickyweb/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group || (height==0)) return 1 - if(istype(mover, /mob/living/simple_animal/hostile/giant_spider)) - return 1 - else if(istype(mover, /mob/living)) - if(prob(50)) - to_chat(mover, "\red You get stuck in \the [src] for a moment.") - return 0 - else if(istype(mover, /obj/item/projectile)) - return prob(30) - return 1 - -/obj/effect/spider/eggcluster - name = "egg cluster" - desc = "They seem to pulse slightly with an inner life." - icon_state = "eggs" - var/amount_grown = 0 - -/obj/effect/spider/eggcluster/atom_init() - . = ..() - pixel_x = rand(3,-3) - pixel_y = rand(3,-3) - START_PROCESSING(SSobj, src) - -/obj/effect/spider/eggcluster/process() - amount_grown += rand(0,2) - if(amount_grown >= 100) - var/num = rand(6,24) - for(var/i=0, i[src] dies!") - new /obj/effect/decal/cleanable/spiderling_remains(src.loc) - qdel(src) - -/obj/effect/spider/spiderling/healthcheck() - if(health <= 0) - die() - -/obj/effect/spider/spiderling/process() - if(travelling_in_vent) - if(istype(src.loc, /turf)) - travelling_in_vent = 0 - entry_vent = null - else if(entry_vent) - if(get_dist(src, entry_vent) <= 1) - var/list/vents = list() - var/datum/pipeline/entry_vent_parent = entry_vent.PARENT1 - for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in entry_vent_parent.other_atmosmch) - vents.Add(temp_vent) - if(!vents.len) - entry_vent = null - return - var/obj/machinery/atmospherics/components/unary/vent_pump/exit_vent = pick(vents) - /*if(prob(50)) - src.visible_message("[src] scrambles into the ventillation ducts!")*/ - - spawn(rand(20,60)) - 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 - - if(prob(50)) - src.visible_message("\blue You hear something squeezing through the ventilation ducts.",2) - sleep(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) - //================= - - else if(prob(25)) - var/list/nearby = oview(5, src) - if(nearby.len) - var/target_atom = pick(nearby) - walk_to(src, target_atom, 5) - if(prob(25)) - src.visible_message("\blue \the [src] skitters[pick(" away"," around","")].") - else if(prob(5)) - //ventcrawl! - for(var/obj/machinery/atmospherics/components/unary/vent_pump/v in view(7,src)) - if(!v.welded) - entry_vent = v - walk_to(src, entry_vent, 5) - break - - if(prob(1)) - src.visible_message("\blue \the [src] chitters.") - if(isturf(loc) && amount_grown > 0) - amount_grown += rand(0,2) - if(amount_grown >= 100) - var/spawn_type = pick(typesof(/mob/living/simple_animal/hostile/giant_spider)) - new spawn_type(src.loc) - qdel(src) - -/obj/effect/decal/cleanable/spiderling_remains - name = "spiderling remains" - desc = "Green squishy mess." - icon = 'icons/effects/effects.dmi' - icon_state = "greenshatter" - -/obj/effect/spider/cocoon - name = "cocoon" - desc = "Something wrapped in silky spider web." - icon_state = "cocoon1" - health = 60 - -/obj/effect/spider/cocoon/atom_init() - . = ..() - icon_state = pick("cocoon1","cocoon2","cocoon3") - -/obj/effect/spider/cocoon/container_resist() - var/mob/living/user = usr - if(user.is_busy()) return - var/breakout_time = 2 - user.SetNextMove(100) - user.last_special = world.time + 100 - to_chat(user, "You struggle against the tight bonds! (This will take about [breakout_time] minutes.)") - visible_message("You see something struggling and writhing in the [src]!") - if(do_after(user,(breakout_time*60*10),target=src)) - if(!user || user.stat != CONSCIOUS || user.loc != src) - return - qdel(src) - -/obj/effect/spider/cocoon/Destroy() - src.visible_message("\red \the [src] splits open.") - for(var/atom/movable/A in contents) - A.loc = src.loc - return ..() +//generic procs copied from obj/effect/alien +/obj/effect/spider + name = "web" + desc = "It's stringy and sticky." + icon = 'icons/effects/effects.dmi' + anchored = 1 + density = 0 + var/health = 15 + +//similar to weeds, but only barfed out by nurses manually +/obj/effect/spider/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/spider/attackby(obj/item/weapon/W, mob/user) + if(W.attack_verb.len) + visible_message("\red \The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") + else + visible_message("\red \The [src] have been attacked with \the [W][(user ? " by [user]." : ".")]") + user.SetNextMove(CLICK_CD_MELEE) + + 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/spider/bullet_act(obj/item/projectile/Proj) + ..() + health -= Proj.damage + healthcheck() + +/obj/effect/spider/proc/healthcheck() + if(health <= 0) + qdel(src) + +/obj/effect/spider/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > 300) + health -= 5 + healthcheck() + +/obj/effect/spider/stickyweb + icon_state = "stickyweb1" + +/obj/effect/spider/stickyweb/atom_init() + . = ..() + if(prob(50)) + icon_state = "stickyweb2" + +/obj/effect/spider/stickyweb/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group || (height==0)) return 1 + if(istype(mover, /mob/living/simple_animal/hostile/giant_spider)) + return 1 + else if(istype(mover, /mob/living)) + if(prob(50)) + to_chat(mover, "\red You get stuck in \the [src] for a moment.") + return 0 + else if(istype(mover, /obj/item/projectile)) + return prob(30) + return 1 + +/obj/effect/spider/eggcluster + name = "egg cluster" + desc = "They seem to pulse slightly with an inner life." + icon_state = "eggs" + var/amount_grown = 0 + +/obj/effect/spider/eggcluster/atom_init() + . = ..() + pixel_x = rand(3,-3) + pixel_y = rand(3,-3) + START_PROCESSING(SSobj, src) + +/obj/effect/spider/eggcluster/process() + amount_grown += rand(0,2) + if(amount_grown >= 100) + var/num = rand(6,24) + for(var/i=0, i[src] dies!") + new /obj/effect/decal/cleanable/spiderling_remains(src.loc) + qdel(src) + +/obj/effect/spider/spiderling/healthcheck() + if(health <= 0) + die() + +/obj/effect/spider/spiderling/process() + if(travelling_in_vent) + if(istype(src.loc, /turf)) + travelling_in_vent = 0 + entry_vent = null + else if(entry_vent) + if(get_dist(src, entry_vent) <= 1) + var/list/vents = list() + var/datum/pipeline/entry_vent_parent = entry_vent.PARENT1 + for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in entry_vent_parent.other_atmosmch) + vents.Add(temp_vent) + if(!vents.len) + entry_vent = null + return + var/obj/machinery/atmospherics/components/unary/vent_pump/exit_vent = pick(vents) + /*if(prob(50)) + src.visible_message("[src] scrambles into the ventillation ducts!")*/ + + spawn(rand(20,60)) + 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 + + if(prob(50)) + src.visible_message("\blue You hear something squeezing through the ventilation ducts.",2) + sleep(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) + //================= + + else if(prob(25)) + var/list/nearby = oview(5, src) + if(nearby.len) + var/target_atom = pick(nearby) + walk_to(src, target_atom, 5) + if(prob(25)) + src.visible_message("\blue \the [src] skitters[pick(" away"," around","")].") + else if(prob(5)) + //ventcrawl! + for(var/obj/machinery/atmospherics/components/unary/vent_pump/v in view(7,src)) + if(!v.welded) + entry_vent = v + walk_to(src, entry_vent, 5) + break + + if(prob(1)) + src.visible_message("\blue \the [src] chitters.") + if(isturf(loc) && amount_grown > 0) + amount_grown += rand(0,2) + if(amount_grown >= 100) + var/spawn_type = pick(typesof(/mob/living/simple_animal/hostile/giant_spider)) + new spawn_type(src.loc) + qdel(src) + +/obj/effect/decal/cleanable/spiderling_remains + name = "spiderling remains" + desc = "Green squishy mess." + icon = 'icons/effects/effects.dmi' + icon_state = "greenshatter" + +/obj/effect/spider/cocoon + name = "cocoon" + desc = "Something wrapped in silky spider web." + icon_state = "cocoon1" + health = 60 + +/obj/effect/spider/cocoon/atom_init() + . = ..() + icon_state = pick("cocoon1","cocoon2","cocoon3") + +/obj/effect/spider/cocoon/container_resist() + var/mob/living/user = usr + if(user.is_busy()) return + var/breakout_time = 2 + user.SetNextMove(100) + user.last_special = world.time + 100 + to_chat(user, "You struggle against the tight bonds! (This will take about [breakout_time] minutes.)") + visible_message("You see something struggling and writhing in the [src]!") + if(do_after(user,(breakout_time*60*10),target=src)) + if(!user || user.stat != CONSCIOUS || user.loc != src) + return + qdel(src) + +/obj/effect/spider/cocoon/Destroy() + src.visible_message("\red \the [src] splits open.") + for(var/atom/movable/A in contents) + A.loc = src.loc + return ..() diff --git a/code/game/objects/empulse.dm b/code/game/objects/empulse.dm index 5c78f758847e..a0f420e52542 100644 --- a/code/game/objects/empulse.dm +++ b/code/game/objects/empulse.dm @@ -1,38 +1,38 @@ -proc/empulse(turf/epicenter, heavy_range, light_range, log=0) - if(!epicenter) return - - if(!istype(epicenter, /turf)) - epicenter = get_turf(epicenter.loc) - - if(log) - message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] (JMP)") - log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ") - - 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 - QDEL_IN(pulse, 20) - - if(heavy_range > light_range) - light_range = heavy_range - - for(var/mob/M in range(heavy_range, epicenter)) - M << 'sound/effects/EMPulse.ogg' - - for(var/atom/T in range(light_range, epicenter)) - var/distance = get_dist(epicenter, T) - if(distance < 0) - distance = 0 - if(distance < heavy_range) - T.emp_act(1) - else if(distance == heavy_range) - if(prob(50)) - T.emp_act(1) - else - T.emp_act(2) - else if(distance <= light_range) - T.emp_act(2) - return 1 +proc/empulse(turf/epicenter, heavy_range, light_range, log=0) + if(!epicenter) return + + if(!istype(epicenter, /turf)) + epicenter = get_turf(epicenter.loc) + + if(log) + message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] (JMP)") + log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ") + + 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 + QDEL_IN(pulse, 20) + + if(heavy_range > light_range) + light_range = heavy_range + + for(var/mob/M in range(heavy_range, epicenter)) + M << 'sound/effects/EMPulse.ogg' + + for(var/atom/T in range(light_range, epicenter)) + var/distance = get_dist(epicenter, T) + if(distance < 0) + distance = 0 + if(distance < heavy_range) + T.emp_act(1) + else if(distance == heavy_range) + if(prob(50)) + T.emp_act(1) + else + T.emp_act(2) + else if(distance <= light_range) + T.emp_act(2) + return 1 diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index ceb11027dff9..a740d5408fd0 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -1,24 +1,24 @@ -//TODO: Flash range does nothing currently - -//A very crude linear approximatiaon of pythagoras theorem. -/proc/cheap_pythag(dx, dy) - dx = abs(dx); dy = abs(dy); - 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) - -/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = 1) - set waitfor = 0 - src = null //so we don't abort once src is deleted - - //DO NOT REMOVE THIS SLEEP, IT BREAKS THINGS - //not sleeping causes us to ex_act() the thing that triggered the explosion - //doing that might cause it to trigger another explosion - //this is bad - //I would make this not ex_act the thing that triggered the explosion, - //but everything that explodes gives us their loc or a get_turf() - //and somethings expect us to ex_act them so they can qdel() - sleep(1) //tldr, let the calling proc call qdel(src) before we explode - - 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 +//TODO: Flash range does nothing currently + +//A very crude linear approximatiaon of pythagoras theorem. +/proc/cheap_pythag(dx, dy) + dx = abs(dx); dy = abs(dy); + 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) + +/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = 1) + set waitfor = 0 + src = null //so we don't abort once src is deleted + + //DO NOT REMOVE THIS SLEEP, IT BREAKS THINGS + //not sleeping causes us to ex_act() the thing that triggered the explosion + //doing that might cause it to trigger another explosion + //this is bad + //I would make this not ex_act the thing that triggered the explosion, + //but everything that explodes gives us their loc or a get_turf() + //and somethings expect us to ex_act them so they can qdel() + sleep(1) //tldr, let the calling proc call qdel(src) before we explode + + 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 diff --git a/code/game/objects/explosion_recursive.dm b/code/game/objects/explosion_recursive.dm index e2ae60edc2c8..2ee712faaa19 100644 --- a/code/game/objects/explosion_recursive.dm +++ b/code/game/objects/explosion_recursive.dm @@ -1,123 +1,123 @@ -/obj - var/explosion_resistance - -var/list/explosion_turfs = list() -var/explosion_in_progress = 0 - -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() - - explosion_turfs[epicenter] = 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) - CHECK_TICK - - //This step applies the ex_act effects for the explosion, as planned in the previous step. - for(var/turf/T in explosion_turfs) - if(explosion_turfs[T] <= 0) continue - if(!T) 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, ((explosion_turfs[T] - T.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 = T.x - var/y = T.y - var/z = T.z - T.ex_act(severity) - if(!T) - T = locate(x,y,z) - for(var/atom/A in T) - A.ex_act(severity) - CHECK_TICK - - explosion_in_progress = 0 - -/turf - var/explosion_resistance - -/turf/space - explosion_resistance = 10 - -/turf/simulated/floor - explosion_resistance = 1 - -/turf/simulated/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 - -//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) - */ - - if(explosion_turfs[src] >= power) - return //The turf already sustained and spread a power greated than what we are dealing with. No point spreading again. - explosion_turfs[src] = 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 - CHECK_TICK - - 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 +/obj + var/explosion_resistance + +var/list/explosion_turfs = list() +var/explosion_in_progress = 0 + +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() + + explosion_turfs[epicenter] = 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) + CHECK_TICK + + //This step applies the ex_act effects for the explosion, as planned in the previous step. + for(var/turf/T in explosion_turfs) + if(explosion_turfs[T] <= 0) continue + if(!T) 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, ((explosion_turfs[T] - T.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 = T.x + var/y = T.y + var/z = T.z + T.ex_act(severity) + if(!T) + T = locate(x,y,z) + for(var/atom/A in T) + A.ex_act(severity) + CHECK_TICK + + explosion_in_progress = 0 + +/turf + var/explosion_resistance + +/turf/space + explosion_resistance = 10 + +/turf/simulated/floor + explosion_resistance = 1 + +/turf/simulated/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 + +//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) + */ + + if(explosion_turfs[src] >= power) + return //The turf already sustained and spread a power greated than what we are dealing with. No point spreading again. + explosion_turfs[src] = 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 + CHECK_TICK + + 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 diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 9db3719cb824..a82d3933ab93 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1,879 +1,879 @@ -/obj/item - name = "item" - icon = 'icons/obj/items.dmi' - var/image/blood_overlay = null //this saves our blood splatter overlay, which will be processed not to go over the edges of the sprite - var/abstract = 0 - var/item_state = null - var/lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' - var/righthand_file = 'icons/mob/inhands/items_righthand.dmi' - var/r_speed = 1.0 - var/health = null - var/burn_point = null - var/burning = null - var/hitsound = null - var/wet = 0 - var/w_class = 3.0 - var/can_embed = 1 - var/slot_flags = 0 //This is used to determine on which slots an item can fit. - pass_flags = PASSTABLE -// causeerrorheresoifixthis - var/obj/item/master = null - - var/flags_pressure = 0 - var/heat_protection = 0 //flags which determine which body parts are protected from heat. Use the HEAD, UPPER_TORSO, LOWER_TORSO, etc. flags. See setup.dm - var/cold_protection = 0 //flags which determine which body parts are protected from cold. Use the HEAD, UPPER_TORSO, LOWER_TORSO, etc. flags. See setup.dm - var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags - var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags - - var/datum/action/item_action/action = null - var/action_button_name //It is also the text which gets displayed on the action button. If not set it defaults to 'Use [name]'. If it's not set, there'll be no button. - var/action_button_is_hands_free = 0 //If 1, bypass the restrained, lying, and stunned checks action buttons normally test for - - //Since any item can now be a piece of clothing, this has to be put here so all items share it. - var/flags_inv //This flag is used to determine when items in someone's inventory cover others. IE helmets making it so you can't see glasses, etc. - var/item_color = null - var/body_parts_covered = 0 //see setup.dm for appropriate bit flags - //var/heat_transfer_coefficient = 1 //0 prevents all transfers, 1 is invisible - var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets) - var/permeability_coefficient = 1 // for chemicals/diseases - var/siemens_coefficient = 1 // for electrical admittance/conductance (electrocution checks and shit) - var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up - var/canremove = 1 //Mostly for Ninja code at this point but basically will not allow the item to be removed if set to 0. /N - var/armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - var/list/materials = list() - var/list/allowed = null //suit storage stuff. - var/list/can_be_placed_into = list( - /obj/structure/table, - /obj/structure/rack, - /obj/structure/closet, - /obj/item/weapon/storage, - /obj/structure/safe, - /obj/machinery/disposal, - /obj/machinery/r_n_d/destructive_analyzer, -// /obj/machinery/r_n_d/experimentor, - /obj/machinery/autolathe - ) - var/uncleanable = 0 - var/toolspeed = 1 - - var/obj/item/device/uplink/hidden/hidden_uplink = null // All items can have an uplink hidden inside, just remember to add the triggers. - - /* Species-specific sprites, concept stolen from Paradise//vg/. - ex: - sprite_sheets = list( - TAJARAN = 'icons/cat/are/bad' - ) - If index term exists and icon_override is not set, this sprite sheet will be used. - */ - var/list/sprite_sheets = null - var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc. - - /* Species-specific sprite sheets for inventory sprites - Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called. - */ - var/list/sprite_sheets_obj = null - -/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) - if(((src in target) && !target_self) || ((!istype(target.loc, /turf)) && (!istype(target, /turf)) && (not_inside)) || is_type_in_list(target, can_be_placed_into)) - return 0 - else - return 1 - -/obj/item/device - icon = 'icons/obj/device.dmi' - -/obj/item/proc/health_analyze(mob/living/M, mob/living/user, mode) - var/message - if(((CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) - user.visible_message("[user] has analyzed the floor's vitals!", "You try to analyze the floor's vitals!") - message += "Analyzing Results for The floor:\n  Overall Status: Healthy
                    " - message += "  Damage Specifics: [0]-[0]-[0]-[0]
                    " - message += "Key: Suffocation/Toxin/Burns/Brute
                    " - message += "Body Temperature: ???" - user.show_message(message) - return - if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") - to_chat(usr, "You don't have the dexterity to do this!") - return - user.visible_message("[user] has analyzed [M]'s vitals.","You have analyzed [M]'s vitals.") - - 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]:\n  Overall Status: dead
                    " - else - message += "Analyzing Results for [M]:\n  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.stat == DEAD || (M.status_flags & FAKEDEATH))) - 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_bodyparts(1, 1) - message += "Localized Damage, Brute/Burn:
                    " - if(length(damaged)) - for(var/obj/item/organ/external/BP in damaged) - message += "  [capitalize(BP.name)]: [(BP.brute_dam > 0) ? "[BP.brute_dam]" : 0][(BP.status & ORGAN_BLEEDING) ? "\[Bleeding\]" : " "] - [(BP.burn_dam > 0) ? "[BP.burn_dam]" : 0]
                    " - else - message += "  Limbs are OK.
                    " - - 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 minimal" - BU = M.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status O.K" - BR = M.getBruteLoss() > 50 ? "Severe anatomical damage detected" : "Subject brute-force injury status O.K" - if(M.status_flags & FAKEDEATH) - OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" - message += "[OX] | [TX] | [BU] | [BR]
                    " - if(istype(M, /mob/living/carbon)) - var/mob/living/carbon/C = M - if(C.reagents.total_volume || C.is_infected_with_zombie_virus()) - message += "Warning: Unknown substance detected in subject's blood.
                    " - 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"]]
                    " -// user.show_message(text("\red Warning: Unknown pathogen detected in subject's blood.")) - if(C.roundstart_quirks.len) - message += "\tSubject has the following physiological traits: [C.get_trait_string()].
                    " - if(M.getCloneLoss()) - user.show_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\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible 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 += "Subject suffering from aberrant brain activity. Recommend further scanning.
                    " - else if(M.getBrainLoss() >= 100 || istype(M, /mob/living/carbon/human) && M:brain_op_stage == 4.0) - message += "Subject is brain dead." - 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 - - var/found_bleed - var/found_broken - for(var/obj/item/organ/external/BP in H.bodyparts) - if(BP.status & ORGAN_BROKEN) - if(((BP.body_zone == BP_L_ARM) || (BP.body_zone == BP_R_ARM) || (BP.body_zone == BP_L_LEG) || (BP.body_zone == BP_R_LEG)) && !(BP.status & ORGAN_SPLINTED)) - message += "Unsecured fracture in subject [BP.name]. Splinting recommended for transport.
                    " - if(!found_broken) - found_broken = TRUE - - if(!found_bleed && (BP.status & ORGAN_ARTERY_CUT)) - found_bleed = TRUE - - if(BP.has_infected_wound()) - message += "Infected wound detected in subject [BP.name]. Disinfection recommended.
                    " - - if(found_bleed) - message += "Arterial bleeding detected. Advanced scanner required for location.
                    " - if(found_broken) - message += "Bone fractures detected. Advanced scanner required for location.
                    " - - if(H.vessel) - var/blood_volume = round(H.vessel.get_reagent_amount("blood")) - var/blood_percent = blood_volume / 560 - var/blood_type = H.dna.b_type - blood_percent *= 100 - if(blood_volume <= 500 && blood_volume > 336) - message += "Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl.Type: [blood_type]
                    " - else if(blood_volume <= 336) - message += "Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl.Type: [blood_type]
                    " - else - message += "Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]
                    " - message += "Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.
                    " - add_fingerprint(user) - user.show_message(message) - return - -/obj/item/Destroy() - flags &= ~DROPDEL // prevent recursive dels - if(ismob(loc)) - var/mob/m = loc - m.drop_from_inventory(src) - return ..() - -/obj/item/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/item/blob_act() - return - -//user: The mob that is suiciding -//damagetype: The type of damage the item will inflict on the user -//BRUTELOSS = 1 -//FIRELOSS = 2 -//TOXLOSS = 4 -//OXYLOSS = 8 -//Output a creative message and then return the damagetype done -/obj/item/proc/suicide_act(mob/user) - return - -/obj/item/verb/move_to_top() - set name = "Move To Top" - set category = "Object" - set src in oview(1) - - if(!istype(src.loc, /turf) || usr.stat || usr.restrained() ) - return - - var/turf/T = src.loc - - src.loc = null - - src.loc = T - -/obj/item/examine(mob/user) - ..() - var/size - switch(src.w_class) - if(1.0) - size = "tiny" - if(2.0) - size = "small" - if(3.0) - size = "normal-sized" - if(4.0) - size = "bulky" - if(5.0) - size = "huge" - else - - var/open_span = "[src.wet ? "" : ""]" - var/close_span = "[src.wet ? "" : ""]" - var/wet_status = "[src.wet ? " wet" : ""]" - - to_chat(user, "[open_span]It's a[wet_status] [size] item.[close_span]") - -/obj/item/attack_hand(mob/user) - if (!user || anchored) - return - - if(HULK in user.mutations)//#Z2 Hulk nerfz! - if(istype(src, /obj/item/weapon/melee/)) - if(src.w_class < 4) - to_chat(user, "\red \The [src] is far too small for you to pick up.") - return - else if(istype(src, /obj/item/weapon/gun/)) - if(prob(20)) - user.say(pick(";RAAAAAAAARGH! WEAPON!", ";HNNNNNNNNNGGGGGGH! I HATE WEAPONS!!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGUUUUUNNNNHH!", ";AAAAAAARRRGH!" )) - user.visible_message("\blue [user] crushes \a [src] with hands.", "\blue You crush the [src].") - qdel(src) - //user << "\red \The [src] is far too small for you to pick up." - return - else if(istype(src, /obj/item/clothing/)) - if(prob(20)) - to_chat(user, "\red [pick("You are not interested in [src].", "This is nothing.", "Humans stuff...", "A cat? A scary cat...", - "A Captain? Let's smash his skull! I don't like Captains!", - "Awww! Such lovely doggy! BUT I HATE DOGGIES!!", "A woman... A lying woman! I love womans! Fuck womans...")]") - return - else if(istype(src, /obj/item/weapon/book/)) - to_chat(user, "\red A book! I LOVE BOOKS!!") - else if(istype(src, /obj/item/weapon/reagent_containers/food)) - if(prob(20)) - to_chat(user, "\red I LOVE FOOD!!") - else if(src.w_class < 4) - to_chat(user, "\red \The [src] is far too small for you to pick up.") - return - - if(istype(src.loc, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = src.loc - S.remove_from_storage(src) - - src.throwing = 0 - if(src.loc == user) - //canremove==0 means that object may not be removed. You can still wear it. This only applies to clothing. /N - if(!src.canremove) - return - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/V = H.wear_suit - V.attack_reaction(H, REACTION_ITEM_TAKEOFF) - if(istype(src, /obj/item/clothing/suit/space)) // If the item to be unequipped is a rigid suit - if(!user.delay_clothing_u_equip(src)) - return 0 - else - user.remove_from_mob(src) - else - user.remove_from_mob(src) - - else - if(isliving(src.loc)) - return - user.SetNextMove(CLICK_CD_RAPID) - - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/V = H.wear_suit - V.attack_reaction(H, REACTION_ITEM_TAKE) - - if(QDELETED(src) || freeze_movement) // remove_from_mob() may remove DROPDEL items, so... - return - - src.pickup(user) - add_fingerprint(user) - user.put_in_active_hand(src) - return - - -/obj/item/attack_paw(mob/user) - if (!user || anchored) - return - - if(isalien(user)) // -- TLE - var/mob/living/carbon/alien/A = user - - if(!A.has_fine_manipulation || w_class >= 4) - if(src in A.contents) // To stop Aliens having items stuck in their pockets - A.drop_from_inventory(src) - to_chat(user, "Your claws aren't capable of such fine manipulation.") - return - - if (istype(src.loc, /obj/item/weapon/storage)) - for(var/mob/M in range(1, src.loc)) - if (M.s_active == src.loc) - if (M.client) - M.client.screen -= src - src.throwing = 0 - if (src.loc == user) - //canremove==0 means that object may not be removed. You can still wear it. This only applies to clothing. /N - if(istype(src, /obj/item/clothing) && !src:canremove) - return - else - user.remove_from_mob(src) - else - if(istype(src.loc, /mob/living)) - return - - user.next_move = max(user.next_move+2,world.time + 2) - - if(QDELETED(src) || freeze_movement) // no item - no pickup, you dummy! - return - - src.pickup(user) - user.put_in_active_hand(src) - return - - -/obj/item/attack_ai(mob/user) - if (istype(src.loc, /obj/item/weapon/robot_module)) - //If the item is part of a cyborg module, equip it - if(!isrobot(user)) - return - var/mob/living/silicon/robot/R = user - R.activate_module(src) - R.hud_used.update_robot_modules_display() - -// Due to storage type consolidation this should get used more now. -// I have cleaned it up a little, but it could probably use more. -Sayu -/obj/item/attackby(obj/item/weapon/W, mob/user, params) - if(istype(W, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = W - if(S.use_to_pickup) - if(S.collection_mode) //Mode is set to collect all items on a tile and we clicked on a valid one. - if(isturf(loc)) - S.gather_all(loc, user) - else if(S.can_be_inserted(src)) - S.handle_item_insertion(src) - return FALSE - -/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback) - callback = CALLBACK(src, .proc/after_throw, callback) // Replace their callback with our own. - . = ..(target, range, speed, thrower, spin, diagonals_first, callback) - -/obj/item/proc/after_throw(datum/callback/callback) - if (callback) //call the original callback - . = callback.Invoke() - -/obj/item/proc/talk_into(mob/M, text) - return - -/obj/item/proc/moved(mob/user, old_loc) - return - -// apparently called whenever an item is removed from a slot, container, or anything else. -/obj/item/proc/dropped(mob/user) - if(DROPDEL & flags) - qdel(src) - -// called just as an item is picked up (loc is not yet changed) -/obj/item/proc/pickup(mob/user) - return - -// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called. -/obj/item/proc/on_exit_storage(obj/item/weapon/storage/S) - return - -// called when this item is added into a storage item, which is passed on as S. The loc variable is already set to the storage item. -/obj/item/proc/on_enter_storage(obj/item/weapon/storage/S) - return - -// called when "found" in pockets and storage items. Returns 1 if the search should end. -/obj/item/proc/on_found(mob/finder) - return - -// called after an item is placed in an equipment slot -// user is mob that equipped it -// slot uses the slot_X defines found in setup.dm -// for items that can be placed in multiple slots -// note this isn't called during the initial dressing of a player -/obj/item/proc/equipped(mob/user, slot) - return - -//the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't. -//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen. -//Set disable_warning to 1 if you wish it to not give you outputs. -/obj/item/proc/mob_can_equip(M, slot, disable_warning = 0) - if(!slot) - return FALSE - if(!M) - return FALSE - - if(ishuman(M)) - //START HUMAN - var/mob/living/carbon/human/H = M - if(!H.has_bodypart_for_slot(slot)) - return FALSE - if(!H.specie_has_slot(slot)) - if(!disable_warning) - to_chat(H, "Your species can not wear clothing of this type.") - return FALSE - //fat mutation - if(istype(src, /obj/item/clothing/under) || istype(src, /obj/item/clothing/suit)) - if(FAT in H.mutations) - //testing("[M] TOO FAT TO WEAR [src]!") - if(!(flags & ONESIZEFITSALL)) - if(!disable_warning) - to_chat(H, "\red You're too fat to wear the [name].") - return 0 - - switch(slot) - if(slot_l_hand) - if(H.l_hand) - return 0 - return 1 - if(slot_r_hand) - if(H.r_hand) - return 0 - return 1 - if(slot_wear_mask) - if(H.wear_mask) - return 0 - if( !(slot_flags & SLOT_MASK) ) - return 0 - return 1 - if(slot_back) - if(H.back) - return 0 - if( !(slot_flags & SLOT_BACK) ) - return 0 - return 1 - if(slot_wear_suit) - if(H.wear_suit) - return 0 - if( !(slot_flags & SLOT_OCLOTHING) ) - return 0 - return 1 - if(slot_gloves) - if(H.gloves) - return 0 - if( !(slot_flags & SLOT_GLOVES) ) - return 0 - return 1 - if(slot_shoes) - if(H.shoes) - return 0 - if( !(slot_flags & SLOT_FEET) ) - return 0 - return 1 - if(slot_belt) - if(H.belt) - return 0 - if(!H.w_uniform) - if(!disable_warning) - to_chat(H, "\red You need a jumpsuit before you can attach this [name].") - return 0 - if( !(slot_flags & SLOT_BELT) ) - return - return 1 - if(slot_glasses) - if(H.glasses) - return 0 - if( !(slot_flags & SLOT_EYES) ) - return 0 - return 1 - if(slot_head) - if(H.head) - return 0 - if( !(slot_flags & SLOT_HEAD) ) - return 0 - return 1 - if(slot_l_ear) - if(H.l_ear) - return 0 - if( w_class < 2 ) - return 1 - if( !(slot_flags & SLOT_EARS) ) - return 0 - if( (slot_flags & SLOT_TWOEARS) && H.r_ear ) - return 0 - return 1 - if(slot_r_ear) - if(H.r_ear) - return 0 - if( w_class < 2 ) - return 1 - if( !(slot_flags & SLOT_EARS) ) - return 0 - if( (slot_flags & SLOT_TWOEARS) && H.l_ear ) - return 0 - return 1 - if(slot_w_uniform) - if(H.w_uniform) - return 0 - if( !(slot_flags & SLOT_ICLOTHING) ) - return 0 - return 1 - if(slot_wear_id) - if(H.wear_id) - return 0 - if(!H.w_uniform) - if(!disable_warning) - to_chat(H, "\red You need a jumpsuit before you can attach this [name].") - return 0 - if( !(slot_flags & SLOT_ID) ) - return 0 - return 1 - if(slot_l_store) - if(H.l_store) - return 0 - if(!H.w_uniform) - if(!disable_warning) - to_chat(H, "\red You need a jumpsuit before you can attach this [name].") - return 0 - if(slot_flags & SLOT_DENYPOCKET) - return 0 - if( w_class <= 2 || (slot_flags & SLOT_POCKET) ) - return 1 - if(slot_r_store) - if(H.r_store) - return 0 - if(!H.w_uniform) - if(!disable_warning) - to_chat(H, "\red You need a jumpsuit before you can attach this [name].") - return 0 - if(slot_flags & SLOT_DENYPOCKET) - return 0 - if( w_class <= 2 || (slot_flags & SLOT_POCKET) ) - return 1 - return 0 - if(slot_s_store) - if(H.s_store) - return 0 - if(!H.wear_suit) - if(!disable_warning) - to_chat(H, "\red You need a suit before you can attach this [name].") - return 0 - if(!H.wear_suit.allowed) - if(!disable_warning) - to_chat(usr, "You somehow have a suit with no defined allowed items for suit storage, stop that.") - return 0 - if( istype(src, /obj/item/device/pda) || istype(src, /obj/item/weapon/pen) || is_type_in_list(src, H.wear_suit.allowed) ) - return 1 - return 0 - if(slot_handcuffed) - if(H.handcuffed) - return 0 - if(!istype(src, /obj/item/weapon/handcuffs)) - return 0 - return 1 - if(slot_legcuffed) - if(H.legcuffed) - return 0 - if(!istype(src, /obj/item/weapon/legcuffs)) - return 0 - return 1 - if(slot_in_backpack) - if (H.back && istype(H.back, /obj/item/weapon/storage/backpack)) - var/obj/item/weapon/storage/backpack/B = H.back - if(B.can_be_inserted(src, M, 1)) - return 1 - return 0 - if(slot_tie) - if(!H.w_uniform) - if(!disable_warning) - to_chat(H, "You need a jumpsuit before you can attach this [name].") - return FALSE - var/obj/item/clothing/under/uniform = H.w_uniform - if(uniform.accessories.len && !uniform.can_attach_accessory(src)) - if (!disable_warning) - to_chat(H, "You already have an accessory of this type attached to your [uniform].") - return FALSE - if( !(slot_flags & SLOT_TIE) ) - return FALSE - return TRUE - return 0 //Unsupported slot - //END HUMAN - - else if(ismonkey(M)) - //START MONKEY - var/mob/living/carbon/monkey/MO = M - switch(slot) - if(slot_l_hand) - if(MO.l_hand) - return 0 - return 1 - if(slot_r_hand) - if(MO.r_hand) - return 0 - return 1 - if(slot_wear_mask) - if(MO.wear_mask) - return 0 - if( !(slot_flags & SLOT_MASK) ) - return 0 - return 1 - if(slot_back) - if(MO.back) - return 0 - if( !(slot_flags & SLOT_BACK) ) - return 0 - return 1 - return 0 //Unsupported slot - - //END MONKEY - else if(isIAN(M)) - var/mob/living/carbon/ian/C = M - switch(slot) - if(slot_head) - if(C.head) - return FALSE - if(istype(src, /obj/item/clothing/mask/facehugger)) - return TRUE - if( !(slot_flags & SLOT_HEAD) ) - return FALSE - return TRUE - if(slot_mouth) - if(C.mouth) - return FALSE - return TRUE - if(slot_neck) - if(C.neck) - return FALSE - if(istype(src, /obj/item/weapon/handcuffs)) - return TRUE - if( !(slot_flags & SLOT_ID) ) - return FALSE - return TRUE - if(slot_back) - if(C.back) - return FALSE - if(istype(src, /obj/item/clothing/suit/armor/vest)) - return TRUE - if( !(slot_flags & SLOT_BACK) ) - return FALSE - return TRUE - return FALSE - -/obj/item/verb/verb_pickup() - set src in oview(1) - set category = "Object" - set name = "Pick up" - - if(!(usr)) //BS12 EDIT - return - if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr)) - return - if((!istype(usr, /mob/living/carbon)) || (istype(usr, /mob/living/carbon/brain)))//Is humanoid, and is not a brain - to_chat(usr, "\red You can't pick things up!") - return - if( usr.stat || usr.restrained() )//Is not asleep/dead and is not restrained - to_chat(usr, "\red You can't pick things up!") - return - if(src.anchored) //Object isn't anchored - to_chat(usr, "\red You can't pick that up!") - return - if(!usr.hand && usr.r_hand) //Right hand is not full - to_chat(usr, "\red Your right hand is full.") - return - if(usr.hand && usr.l_hand) //Left hand is not full - to_chat(usr, "\red Your left hand is full.") - return - if(!istype(src.loc, /turf)) //Object is on a turf - to_chat(usr, "\red You can't pick that up!") - return - //All checks are done, time to pick it up! - usr.UnarmedAttack(src) - return - - -//This proc is executed when someone clicks the on-screen UI button. To make the UI button show, set the 'icon_action_button' to the icon_state of the image of the button in screen1_action.dmi -//The default action is attack_self(). -//Checks before we get to here are: mob is alive, mob is not restrained, paralyzed, asleep, resting, laying, item is on the mob. -/obj/item/proc/ui_action_click() - attack_self(usr) - -/obj/item/proc/IsReflect(def_zone, hol_dir, hit_dir) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit - return FALSE - -/obj/item/proc/Get_shield_chance() - return 0 - -/obj/item/proc/get_loc_turf() - var/atom/L = loc - while(L && !istype(L, /turf/)) - L = L.loc - return loc - -/obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user) - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) - // you can't stab someone in the eyes wearing a mask! - to_chat(user, "\red You're going to need to remove the eye covering first.") - return - - var/mob/living/carbon/monkey/Mo = M - if(istype(Mo) && ( \ - (Mo.wear_mask && Mo.wear_mask.flags & MASKCOVERSEYES) \ - )) - // you can't stab someone in the eyes wearing a mask! - to_chat(user, "\red You're going to need to remove the eye covering first.") - return - - if(istype(M, /mob/living/carbon/alien) || istype(M, /mob/living/carbon/slime))//Aliens don't have eyes./N slimes also don't have eyes! - to_chat(user, "\red You cannot locate any eyes on this creature!") - return - - user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG - - src.add_fingerprint(user) - //if((CLUMSY in user.mutations) && prob(50)) - // M = user - /* - to_chat(M, "\red You stab yourself in the eye.") - M.sdisabilities |= BLIND - M.weakened += 4 - M.adjustBruteLoss(10) - */ - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] has been stabbed in the eye with [src] by [user].", 1) - to_chat(M, "\red [user] stabs you in the eye with [src]!") - to_chat(user, "\red You stab [M] in the eye with [src]!") - else - user.visible_message( \ - "\red [user] has stabbed themself with [src]!", \ - "\red You stab yourself in the eyes with [src]!" \ - ) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/internal/eyes/IO = H.organs_by_name[O_EYES] - IO.damage += rand(3,4) - if(IO.damage >= IO.min_bruised_damage) - if(H.stat != DEAD) - if(IO.robotic <= 1) //robot eyes bleeding might be a bit silly - to_chat(H, "\red Your eyes start to bleed profusely!") - if(prob(50)) - if(H.stat != DEAD) - to_chat(H, "\red You drop what you're holding and clutch at your eyes!") - H.drop_item() - H.eye_blurry += 10 - H.Paralyse(1) - H.Weaken(4) - if (IO.damage >= IO.min_broken_damage) - if(H.stat != DEAD) - to_chat(H, "\red You go blind!") - var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] - BP.take_damage(7) - else - M.take_bodypart_damage(7) - M.eye_blurry += rand(3,4) - return - -/obj/item/clean_blood() - . = ..() - if(uncleanable) - return - if(blood_overlay) - overlays.Remove(blood_overlay) - if(istype(src, /obj/item/clothing/gloves)) - var/obj/item/clothing/gloves/G = src - G.transfer_blood = 0 - -/obj/item/add_dirt_cover() - if(!blood_overlay) - generate_dirt_cover() - ..() - if(dirt_overlay) - if(blood_overlay.color != dirt_overlay.color) - overlays.Remove(blood_overlay) - blood_overlay.color = dirt_overlay.color - overlays += blood_overlay - -/obj/item/add_blood(mob/living/carbon/human/M) - if (!..()) - return 0 - - //if we haven't made our blood_overlay already - //add_dirt_cover(new M.species.blood_color) - - if(blood_DNA[M.dna.unique_enzymes]) - return 0 //already bloodied with this blood. Cannot add more. - blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - return 1 //we applied blood to the item - -var/global/list/items_blood_overlay_by_type = list() -/obj/item/proc/generate_dirt_cover() - if(blood_overlay) - return - - var/image/IMG = items_blood_overlay_by_type[type] - if(IMG) - blood_overlay = IMG - else - var/icon/ICO = new /icon(icon, icon_state) - ICO.Blend(new /icon('icons/effects/blood.dmi', rgb(255, 255, 255)), ICON_ADD) // fills the icon_state with white (except where it's transparent) - ICO.Blend(new /icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) // adds blood and the remaining white areas become transparant - IMG = image("icon" = ICO) - items_blood_overlay_by_type[type] = IMG - blood_overlay = IMG - -/obj/item/proc/showoff(mob/user) - for (var/mob/M in view(user)) - M.show_message("[user] holds up [src]. Take a closer look.",1) - -/mob/living/carbon/verb/showoff() - set name = "Show Held Item" - set category = "Object" - - var/obj/item/I = get_active_hand() - if(I && !I.abstract) - I.showoff(src) +/obj/item + name = "item" + icon = 'icons/obj/items.dmi' + var/image/blood_overlay = null //this saves our blood splatter overlay, which will be processed not to go over the edges of the sprite + var/abstract = 0 + var/item_state = null + var/lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + var/righthand_file = 'icons/mob/inhands/items_righthand.dmi' + var/r_speed = 1.0 + var/health = null + var/burn_point = null + var/burning = null + var/hitsound = null + var/wet = 0 + var/w_class = 3.0 + var/can_embed = 1 + var/slot_flags = 0 //This is used to determine on which slots an item can fit. + pass_flags = PASSTABLE +// causeerrorheresoifixthis + var/obj/item/master = null + + var/flags_pressure = 0 + var/heat_protection = 0 //flags which determine which body parts are protected from heat. Use the HEAD, UPPER_TORSO, LOWER_TORSO, etc. flags. See setup.dm + var/cold_protection = 0 //flags which determine which body parts are protected from cold. Use the HEAD, UPPER_TORSO, LOWER_TORSO, etc. flags. See setup.dm + var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags + var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags + + var/datum/action/item_action/action = null + var/action_button_name //It is also the text which gets displayed on the action button. If not set it defaults to 'Use [name]'. If it's not set, there'll be no button. + var/action_button_is_hands_free = 0 //If 1, bypass the restrained, lying, and stunned checks action buttons normally test for + + //Since any item can now be a piece of clothing, this has to be put here so all items share it. + var/flags_inv //This flag is used to determine when items in someone's inventory cover others. IE helmets making it so you can't see glasses, etc. + var/item_color = null + var/body_parts_covered = 0 //see setup.dm for appropriate bit flags + //var/heat_transfer_coefficient = 1 //0 prevents all transfers, 1 is invisible + var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets) + var/permeability_coefficient = 1 // for chemicals/diseases + var/siemens_coefficient = 1 // for electrical admittance/conductance (electrocution checks and shit) + var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up + var/canremove = 1 //Mostly for Ninja code at this point but basically will not allow the item to be removed if set to 0. /N + var/armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + var/list/materials = list() + var/list/allowed = null //suit storage stuff. + var/list/can_be_placed_into = list( + /obj/structure/table, + /obj/structure/rack, + /obj/structure/closet, + /obj/item/weapon/storage, + /obj/structure/safe, + /obj/machinery/disposal, + /obj/machinery/r_n_d/destructive_analyzer, +// /obj/machinery/r_n_d/experimentor, + /obj/machinery/autolathe + ) + var/uncleanable = 0 + var/toolspeed = 1 + + var/obj/item/device/uplink/hidden/hidden_uplink = null // All items can have an uplink hidden inside, just remember to add the triggers. + + /* Species-specific sprites, concept stolen from Paradise//vg/. + ex: + sprite_sheets = list( + TAJARAN = 'icons/cat/are/bad' + ) + If index term exists and icon_override is not set, this sprite sheet will be used. + */ + var/list/sprite_sheets = null + var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc. + + /* Species-specific sprite sheets for inventory sprites + Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called. + */ + var/list/sprite_sheets_obj = null + +/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) + if(((src in target) && !target_self) || ((!istype(target.loc, /turf)) && (!istype(target, /turf)) && (not_inside)) || is_type_in_list(target, can_be_placed_into)) + return 0 + else + return 1 + +/obj/item/device + icon = 'icons/obj/device.dmi' + +/obj/item/proc/health_analyze(mob/living/M, mob/living/user, mode) + var/message + if(((CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) + user.visible_message("[user] has analyzed the floor's vitals!", "You try to analyze the floor's vitals!") + message += "Analyzing Results for The floor:\n  Overall Status: Healthy
                    " + message += "  Damage Specifics: [0]-[0]-[0]-[0]
                    " + message += "Key: Suffocation/Toxin/Burns/Brute
                    " + message += "Body Temperature: ???" + user.show_message(message) + return + if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + to_chat(usr, "You don't have the dexterity to do this!") + return + user.visible_message("[user] has analyzed [M]'s vitals.","You have analyzed [M]'s vitals.") + + 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]:\n  Overall Status: dead
                    " + else + message += "Analyzing Results for [M]:\n  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.stat == DEAD || (M.status_flags & FAKEDEATH))) + 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_bodyparts(1, 1) + message += "Localized Damage, Brute/Burn:
                    " + if(length(damaged)) + for(var/obj/item/organ/external/BP in damaged) + message += "  [capitalize(BP.name)]: [(BP.brute_dam > 0) ? "[BP.brute_dam]" : 0][(BP.status & ORGAN_BLEEDING) ? "\[Bleeding\]" : " "] - [(BP.burn_dam > 0) ? "[BP.burn_dam]" : 0]
                    " + else + message += "  Limbs are OK.
                    " + + 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 minimal" + BU = M.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status O.K" + BR = M.getBruteLoss() > 50 ? "Severe anatomical damage detected" : "Subject brute-force injury status O.K" + if(M.status_flags & FAKEDEATH) + OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" + message += "[OX] | [TX] | [BU] | [BR]
                    " + if(istype(M, /mob/living/carbon)) + var/mob/living/carbon/C = M + if(C.reagents.total_volume || C.is_infected_with_zombie_virus()) + message += "Warning: Unknown substance detected in subject's blood.
                    " + 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"]]
                    " +// user.show_message(text("\red Warning: Unknown pathogen detected in subject's blood.")) + if(C.roundstart_quirks.len) + message += "\tSubject has the following physiological traits: [C.get_trait_string()].
                    " + if(M.getCloneLoss()) + user.show_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\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible 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 += "Subject suffering from aberrant brain activity. Recommend further scanning.
                    " + else if(M.getBrainLoss() >= 100 || istype(M, /mob/living/carbon/human) && M:brain_op_stage == 4.0) + message += "Subject is brain dead." + 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 + + var/found_bleed + var/found_broken + for(var/obj/item/organ/external/BP in H.bodyparts) + if(BP.status & ORGAN_BROKEN) + if(((BP.body_zone == BP_L_ARM) || (BP.body_zone == BP_R_ARM) || (BP.body_zone == BP_L_LEG) || (BP.body_zone == BP_R_LEG)) && !(BP.status & ORGAN_SPLINTED)) + message += "Unsecured fracture in subject [BP.name]. Splinting recommended for transport.
                    " + if(!found_broken) + found_broken = TRUE + + if(!found_bleed && (BP.status & ORGAN_ARTERY_CUT)) + found_bleed = TRUE + + if(BP.has_infected_wound()) + message += "Infected wound detected in subject [BP.name]. Disinfection recommended.
                    " + + if(found_bleed) + message += "Arterial bleeding detected. Advanced scanner required for location.
                    " + if(found_broken) + message += "Bone fractures detected. Advanced scanner required for location.
                    " + + if(H.vessel) + var/blood_volume = round(H.vessel.get_reagent_amount("blood")) + var/blood_percent = blood_volume / 560 + var/blood_type = H.dna.b_type + blood_percent *= 100 + if(blood_volume <= 500 && blood_volume > 336) + message += "Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl.Type: [blood_type]
                    " + else if(blood_volume <= 336) + message += "Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl.Type: [blood_type]
                    " + else + message += "Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]
                    " + message += "Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.
                    " + add_fingerprint(user) + user.show_message(message) + return + +/obj/item/Destroy() + flags &= ~DROPDEL // prevent recursive dels + if(ismob(loc)) + var/mob/m = loc + m.drop_from_inventory(src) + return ..() + +/obj/item/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/item/blob_act() + return + +//user: The mob that is suiciding +//damagetype: The type of damage the item will inflict on the user +//BRUTELOSS = 1 +//FIRELOSS = 2 +//TOXLOSS = 4 +//OXYLOSS = 8 +//Output a creative message and then return the damagetype done +/obj/item/proc/suicide_act(mob/user) + return + +/obj/item/verb/move_to_top() + set name = "Move To Top" + set category = "Object" + set src in oview(1) + + if(!istype(src.loc, /turf) || usr.stat || usr.restrained() ) + return + + var/turf/T = src.loc + + src.loc = null + + src.loc = T + +/obj/item/examine(mob/user) + ..() + var/size + switch(src.w_class) + if(1.0) + size = "tiny" + if(2.0) + size = "small" + if(3.0) + size = "normal-sized" + if(4.0) + size = "bulky" + if(5.0) + size = "huge" + else + + var/open_span = "[src.wet ? "" : ""]" + var/close_span = "[src.wet ? "" : ""]" + var/wet_status = "[src.wet ? " wet" : ""]" + + to_chat(user, "[open_span]It's a[wet_status] [size] item.[close_span]") + +/obj/item/attack_hand(mob/user) + if (!user || anchored) + return + + if(HULK in user.mutations)//#Z2 Hulk nerfz! + if(istype(src, /obj/item/weapon/melee/)) + if(src.w_class < 4) + to_chat(user, "\red \The [src] is far too small for you to pick up.") + return + else if(istype(src, /obj/item/weapon/gun/)) + if(prob(20)) + user.say(pick(";RAAAAAAAARGH! WEAPON!", ";HNNNNNNNNNGGGGGGH! I HATE WEAPONS!!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGUUUUUNNNNHH!", ";AAAAAAARRRGH!" )) + user.visible_message("\blue [user] crushes \a [src] with hands.", "\blue You crush the [src].") + qdel(src) + //user << "\red \The [src] is far too small for you to pick up." + return + else if(istype(src, /obj/item/clothing/)) + if(prob(20)) + to_chat(user, "\red [pick("You are not interested in [src].", "This is nothing.", "Humans stuff...", "A cat? A scary cat...", + "A Captain? Let's smash his skull! I don't like Captains!", + "Awww! Such lovely doggy! BUT I HATE DOGGIES!!", "A woman... A lying woman! I love womans! Fuck womans...")]") + return + else if(istype(src, /obj/item/weapon/book/)) + to_chat(user, "\red A book! I LOVE BOOKS!!") + else if(istype(src, /obj/item/weapon/reagent_containers/food)) + if(prob(20)) + to_chat(user, "\red I LOVE FOOD!!") + else if(src.w_class < 4) + to_chat(user, "\red \The [src] is far too small for you to pick up.") + return + + if(istype(src.loc, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = src.loc + S.remove_from_storage(src) + + src.throwing = 0 + if(src.loc == user) + //canremove==0 means that object may not be removed. You can still wear it. This only applies to clothing. /N + if(!src.canremove) + return + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit)) + var/obj/item/clothing/suit/V = H.wear_suit + V.attack_reaction(H, REACTION_ITEM_TAKEOFF) + if(istype(src, /obj/item/clothing/suit/space)) // If the item to be unequipped is a rigid suit + if(!user.delay_clothing_u_equip(src)) + return 0 + else + user.remove_from_mob(src) + else + user.remove_from_mob(src) + + else + if(isliving(src.loc)) + return + user.SetNextMove(CLICK_CD_RAPID) + + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit)) + var/obj/item/clothing/suit/V = H.wear_suit + V.attack_reaction(H, REACTION_ITEM_TAKE) + + if(QDELETED(src) || freeze_movement) // remove_from_mob() may remove DROPDEL items, so... + return + + src.pickup(user) + add_fingerprint(user) + user.put_in_active_hand(src) + return + + +/obj/item/attack_paw(mob/user) + if (!user || anchored) + return + + if(isalien(user)) // -- TLE + var/mob/living/carbon/alien/A = user + + if(!A.has_fine_manipulation || w_class >= 4) + if(src in A.contents) // To stop Aliens having items stuck in their pockets + A.drop_from_inventory(src) + to_chat(user, "Your claws aren't capable of such fine manipulation.") + return + + if (istype(src.loc, /obj/item/weapon/storage)) + for(var/mob/M in range(1, src.loc)) + if (M.s_active == src.loc) + if (M.client) + M.client.screen -= src + src.throwing = 0 + if (src.loc == user) + //canremove==0 means that object may not be removed. You can still wear it. This only applies to clothing. /N + if(istype(src, /obj/item/clothing) && !src:canremove) + return + else + user.remove_from_mob(src) + else + if(istype(src.loc, /mob/living)) + return + + user.next_move = max(user.next_move+2,world.time + 2) + + if(QDELETED(src) || freeze_movement) // no item - no pickup, you dummy! + return + + src.pickup(user) + user.put_in_active_hand(src) + return + + +/obj/item/attack_ai(mob/user) + if (istype(src.loc, /obj/item/weapon/robot_module)) + //If the item is part of a cyborg module, equip it + if(!isrobot(user)) + return + var/mob/living/silicon/robot/R = user + R.activate_module(src) + R.hud_used.update_robot_modules_display() + +// Due to storage type consolidation this should get used more now. +// I have cleaned it up a little, but it could probably use more. -Sayu +/obj/item/attackby(obj/item/weapon/W, mob/user, params) + if(istype(W, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = W + if(S.use_to_pickup) + if(S.collection_mode) //Mode is set to collect all items on a tile and we clicked on a valid one. + if(isturf(loc)) + S.gather_all(loc, user) + else if(S.can_be_inserted(src)) + S.handle_item_insertion(src) + return FALSE + +/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback) + callback = CALLBACK(src, .proc/after_throw, callback) // Replace their callback with our own. + . = ..(target, range, speed, thrower, spin, diagonals_first, callback) + +/obj/item/proc/after_throw(datum/callback/callback) + if (callback) //call the original callback + . = callback.Invoke() + +/obj/item/proc/talk_into(mob/M, text) + return + +/obj/item/proc/moved(mob/user, old_loc) + return + +// apparently called whenever an item is removed from a slot, container, or anything else. +/obj/item/proc/dropped(mob/user) + if(DROPDEL & flags) + qdel(src) + +// called just as an item is picked up (loc is not yet changed) +/obj/item/proc/pickup(mob/user) + return + +// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called. +/obj/item/proc/on_exit_storage(obj/item/weapon/storage/S) + return + +// called when this item is added into a storage item, which is passed on as S. The loc variable is already set to the storage item. +/obj/item/proc/on_enter_storage(obj/item/weapon/storage/S) + return + +// called when "found" in pockets and storage items. Returns 1 if the search should end. +/obj/item/proc/on_found(mob/finder) + return + +// called after an item is placed in an equipment slot +// user is mob that equipped it +// slot uses the slot_X defines found in setup.dm +// for items that can be placed in multiple slots +// note this isn't called during the initial dressing of a player +/obj/item/proc/equipped(mob/user, slot) + return + +//the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't. +//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen. +//Set disable_warning to 1 if you wish it to not give you outputs. +/obj/item/proc/mob_can_equip(M, slot, disable_warning = 0) + if(!slot) + return FALSE + if(!M) + return FALSE + + if(ishuman(M)) + //START HUMAN + var/mob/living/carbon/human/H = M + if(!H.has_bodypart_for_slot(slot)) + return FALSE + if(!H.specie_has_slot(slot)) + if(!disable_warning) + to_chat(H, "Your species can not wear clothing of this type.") + return FALSE + //fat mutation + if(istype(src, /obj/item/clothing/under) || istype(src, /obj/item/clothing/suit)) + if(FAT in H.mutations) + //testing("[M] TOO FAT TO WEAR [src]!") + if(!(flags & ONESIZEFITSALL)) + if(!disable_warning) + to_chat(H, "\red You're too fat to wear the [name].") + return 0 + + switch(slot) + if(slot_l_hand) + if(H.l_hand) + return 0 + return 1 + if(slot_r_hand) + if(H.r_hand) + return 0 + return 1 + if(slot_wear_mask) + if(H.wear_mask) + return 0 + if( !(slot_flags & SLOT_MASK) ) + return 0 + return 1 + if(slot_back) + if(H.back) + return 0 + if( !(slot_flags & SLOT_BACK) ) + return 0 + return 1 + if(slot_wear_suit) + if(H.wear_suit) + return 0 + if( !(slot_flags & SLOT_OCLOTHING) ) + return 0 + return 1 + if(slot_gloves) + if(H.gloves) + return 0 + if( !(slot_flags & SLOT_GLOVES) ) + return 0 + return 1 + if(slot_shoes) + if(H.shoes) + return 0 + if( !(slot_flags & SLOT_FEET) ) + return 0 + return 1 + if(slot_belt) + if(H.belt) + return 0 + if(!H.w_uniform) + if(!disable_warning) + to_chat(H, "\red You need a jumpsuit before you can attach this [name].") + return 0 + if( !(slot_flags & SLOT_BELT) ) + return + return 1 + if(slot_glasses) + if(H.glasses) + return 0 + if( !(slot_flags & SLOT_EYES) ) + return 0 + return 1 + if(slot_head) + if(H.head) + return 0 + if( !(slot_flags & SLOT_HEAD) ) + return 0 + return 1 + if(slot_l_ear) + if(H.l_ear) + return 0 + if( w_class < 2 ) + return 1 + if( !(slot_flags & SLOT_EARS) ) + return 0 + if( (slot_flags & SLOT_TWOEARS) && H.r_ear ) + return 0 + return 1 + if(slot_r_ear) + if(H.r_ear) + return 0 + if( w_class < 2 ) + return 1 + if( !(slot_flags & SLOT_EARS) ) + return 0 + if( (slot_flags & SLOT_TWOEARS) && H.l_ear ) + return 0 + return 1 + if(slot_w_uniform) + if(H.w_uniform) + return 0 + if( !(slot_flags & SLOT_ICLOTHING) ) + return 0 + return 1 + if(slot_wear_id) + if(H.wear_id) + return 0 + if(!H.w_uniform) + if(!disable_warning) + to_chat(H, "\red You need a jumpsuit before you can attach this [name].") + return 0 + if( !(slot_flags & SLOT_ID) ) + return 0 + return 1 + if(slot_l_store) + if(H.l_store) + return 0 + if(!H.w_uniform) + if(!disable_warning) + to_chat(H, "\red You need a jumpsuit before you can attach this [name].") + return 0 + if(slot_flags & SLOT_DENYPOCKET) + return 0 + if( w_class <= 2 || (slot_flags & SLOT_POCKET) ) + return 1 + if(slot_r_store) + if(H.r_store) + return 0 + if(!H.w_uniform) + if(!disable_warning) + to_chat(H, "\red You need a jumpsuit before you can attach this [name].") + return 0 + if(slot_flags & SLOT_DENYPOCKET) + return 0 + if( w_class <= 2 || (slot_flags & SLOT_POCKET) ) + return 1 + return 0 + if(slot_s_store) + if(H.s_store) + return 0 + if(!H.wear_suit) + if(!disable_warning) + to_chat(H, "\red You need a suit before you can attach this [name].") + return 0 + if(!H.wear_suit.allowed) + if(!disable_warning) + to_chat(usr, "You somehow have a suit with no defined allowed items for suit storage, stop that.") + return 0 + if( istype(src, /obj/item/device/pda) || istype(src, /obj/item/weapon/pen) || is_type_in_list(src, H.wear_suit.allowed) ) + return 1 + return 0 + if(slot_handcuffed) + if(H.handcuffed) + return 0 + if(!istype(src, /obj/item/weapon/handcuffs)) + return 0 + return 1 + if(slot_legcuffed) + if(H.legcuffed) + return 0 + if(!istype(src, /obj/item/weapon/legcuffs)) + return 0 + return 1 + if(slot_in_backpack) + if (H.back && istype(H.back, /obj/item/weapon/storage/backpack)) + var/obj/item/weapon/storage/backpack/B = H.back + if(B.can_be_inserted(src, M, 1)) + return 1 + return 0 + if(slot_tie) + if(!H.w_uniform) + if(!disable_warning) + to_chat(H, "You need a jumpsuit before you can attach this [name].") + return FALSE + var/obj/item/clothing/under/uniform = H.w_uniform + if(uniform.accessories.len && !uniform.can_attach_accessory(src)) + if (!disable_warning) + to_chat(H, "You already have an accessory of this type attached to your [uniform].") + return FALSE + if( !(slot_flags & SLOT_TIE) ) + return FALSE + return TRUE + return 0 //Unsupported slot + //END HUMAN + + else if(ismonkey(M)) + //START MONKEY + var/mob/living/carbon/monkey/MO = M + switch(slot) + if(slot_l_hand) + if(MO.l_hand) + return 0 + return 1 + if(slot_r_hand) + if(MO.r_hand) + return 0 + return 1 + if(slot_wear_mask) + if(MO.wear_mask) + return 0 + if( !(slot_flags & SLOT_MASK) ) + return 0 + return 1 + if(slot_back) + if(MO.back) + return 0 + if( !(slot_flags & SLOT_BACK) ) + return 0 + return 1 + return 0 //Unsupported slot + + //END MONKEY + else if(isIAN(M)) + var/mob/living/carbon/ian/C = M + switch(slot) + if(slot_head) + if(C.head) + return FALSE + if(istype(src, /obj/item/clothing/mask/facehugger)) + return TRUE + if( !(slot_flags & SLOT_HEAD) ) + return FALSE + return TRUE + if(slot_mouth) + if(C.mouth) + return FALSE + return TRUE + if(slot_neck) + if(C.neck) + return FALSE + if(istype(src, /obj/item/weapon/handcuffs)) + return TRUE + if( !(slot_flags & SLOT_ID) ) + return FALSE + return TRUE + if(slot_back) + if(C.back) + return FALSE + if(istype(src, /obj/item/clothing/suit/armor/vest)) + return TRUE + if( !(slot_flags & SLOT_BACK) ) + return FALSE + return TRUE + return FALSE + +/obj/item/verb/verb_pickup() + set src in oview(1) + set category = "Object" + set name = "Pick up" + + if(!(usr)) //BS12 EDIT + return + if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr)) + return + if((!istype(usr, /mob/living/carbon)) || (istype(usr, /mob/living/carbon/brain)))//Is humanoid, and is not a brain + to_chat(usr, "\red You can't pick things up!") + return + if( usr.stat || usr.restrained() )//Is not asleep/dead and is not restrained + to_chat(usr, "\red You can't pick things up!") + return + if(src.anchored) //Object isn't anchored + to_chat(usr, "\red You can't pick that up!") + return + if(!usr.hand && usr.r_hand) //Right hand is not full + to_chat(usr, "\red Your right hand is full.") + return + if(usr.hand && usr.l_hand) //Left hand is not full + to_chat(usr, "\red Your left hand is full.") + return + if(!istype(src.loc, /turf)) //Object is on a turf + to_chat(usr, "\red You can't pick that up!") + return + //All checks are done, time to pick it up! + usr.UnarmedAttack(src) + return + + +//This proc is executed when someone clicks the on-screen UI button. To make the UI button show, set the 'icon_action_button' to the icon_state of the image of the button in screen1_action.dmi +//The default action is attack_self(). +//Checks before we get to here are: mob is alive, mob is not restrained, paralyzed, asleep, resting, laying, item is on the mob. +/obj/item/proc/ui_action_click() + attack_self(usr) + +/obj/item/proc/IsReflect(def_zone, hol_dir, hit_dir) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit + return FALSE + +/obj/item/proc/Get_shield_chance() + return 0 + +/obj/item/proc/get_loc_turf() + var/atom/L = loc + while(L && !istype(L, /turf/)) + L = L.loc + return loc + +/obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user) + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) + // you can't stab someone in the eyes wearing a mask! + to_chat(user, "\red You're going to need to remove the eye covering first.") + return + + var/mob/living/carbon/monkey/Mo = M + if(istype(Mo) && ( \ + (Mo.wear_mask && Mo.wear_mask.flags & MASKCOVERSEYES) \ + )) + // you can't stab someone in the eyes wearing a mask! + to_chat(user, "\red You're going to need to remove the eye covering first.") + return + + if(istype(M, /mob/living/carbon/alien) || istype(M, /mob/living/carbon/slime))//Aliens don't have eyes./N slimes also don't have eyes! + to_chat(user, "\red You cannot locate any eyes on this creature!") + return + + user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" + M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" + msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG + + src.add_fingerprint(user) + //if((CLUMSY in user.mutations) && prob(50)) + // M = user + /* + to_chat(M, "\red You stab yourself in the eye.") + M.sdisabilities |= BLIND + M.weakened += 4 + M.adjustBruteLoss(10) + */ + if(M != user) + for(var/mob/O in (viewers(M) - user - M)) + O.show_message("\red [M] has been stabbed in the eye with [src] by [user].", 1) + to_chat(M, "\red [user] stabs you in the eye with [src]!") + to_chat(user, "\red You stab [M] in the eye with [src]!") + else + user.visible_message( \ + "\red [user] has stabbed themself with [src]!", \ + "\red You stab yourself in the eyes with [src]!" \ + ) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/internal/eyes/IO = H.organs_by_name[O_EYES] + IO.damage += rand(3,4) + if(IO.damage >= IO.min_bruised_damage) + if(H.stat != DEAD) + if(IO.robotic <= 1) //robot eyes bleeding might be a bit silly + to_chat(H, "\red Your eyes start to bleed profusely!") + if(prob(50)) + if(H.stat != DEAD) + to_chat(H, "\red You drop what you're holding and clutch at your eyes!") + H.drop_item() + H.eye_blurry += 10 + H.Paralyse(1) + H.Weaken(4) + if (IO.damage >= IO.min_broken_damage) + if(H.stat != DEAD) + to_chat(H, "\red You go blind!") + var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] + BP.take_damage(7) + else + M.take_bodypart_damage(7) + M.eye_blurry += rand(3,4) + return + +/obj/item/clean_blood() + . = ..() + if(uncleanable) + return + if(blood_overlay) + overlays.Remove(blood_overlay) + if(istype(src, /obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = src + G.transfer_blood = 0 + +/obj/item/add_dirt_cover() + if(!blood_overlay) + generate_dirt_cover() + ..() + if(dirt_overlay) + if(blood_overlay.color != dirt_overlay.color) + overlays.Remove(blood_overlay) + blood_overlay.color = dirt_overlay.color + overlays += blood_overlay + +/obj/item/add_blood(mob/living/carbon/human/M) + if (!..()) + return 0 + + //if we haven't made our blood_overlay already + //add_dirt_cover(new M.species.blood_color) + + if(blood_DNA[M.dna.unique_enzymes]) + return 0 //already bloodied with this blood. Cannot add more. + blood_DNA[M.dna.unique_enzymes] = M.dna.b_type + return 1 //we applied blood to the item + +var/global/list/items_blood_overlay_by_type = list() +/obj/item/proc/generate_dirt_cover() + if(blood_overlay) + return + + var/image/IMG = items_blood_overlay_by_type[type] + if(IMG) + blood_overlay = IMG + else + var/icon/ICO = new /icon(icon, icon_state) + ICO.Blend(new /icon('icons/effects/blood.dmi', rgb(255, 255, 255)), ICON_ADD) // fills the icon_state with white (except where it's transparent) + ICO.Blend(new /icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) // adds blood and the remaining white areas become transparant + IMG = image("icon" = ICO) + items_blood_overlay_by_type[type] = IMG + blood_overlay = IMG + +/obj/item/proc/showoff(mob/user) + for (var/mob/M in view(user)) + M.show_message("[user] holds up [src]. Take a closer look.",1) + +/mob/living/carbon/verb/showoff() + set name = "Show Held Item" + set category = "Object" + + var/obj/item/I = get_active_hand() + if(I && !I.abstract) + I.showoff(src) diff --git a/code/game/objects/items/apc_frame.dm b/code/game/objects/items/apc_frame.dm index 143c6a1dddbb..aa0160463257 100644 --- a/code/game/objects/items/apc_frame.dm +++ b/code/game/objects/items/apc_frame.dm @@ -1,42 +1,42 @@ -// APC HULL - -/obj/item/apc_frame - name = "APC frame" - desc = "Used for repairing or building APCs." - icon = 'icons/obj/apc_repair.dmi' - icon_state = "apc_frame" - flags = CONDUCT - -/obj/item/apc_frame/attackby(obj/item/weapon/W, mob/user) - ..() - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/metal( get_turf(src.loc), 2 ) - qdel(src) - -/obj/item/apc_frame/proc/try_build(turf/on_wall) - if (get_dist(on_wall,usr)>1) - return - var/ndir = get_dir(usr,on_wall) - if (!(ndir in cardinal)) - return - var/turf/loc = get_turf(usr) - var/area/A = loc.loc - if (!istype(loc, /turf/simulated/floor)) - to_chat(usr, "\red APC cannot be placed on this spot.") - return - if (A.requires_power == 0 || istype(A,/area/space)) - to_chat(usr, "\red APC cannot be placed in this area.") - return - if (A.get_apc()) - to_chat(usr, "\red This area already has APC.") - return //only one APC per area - for(var/obj/machinery/power/terminal/T in loc) - if (T.master) - to_chat(usr, "\red There is another network terminal here.") - return - else - new /obj/item/stack/cable_coil/random(loc, 10) - to_chat(usr, "You cut the cables and disassemble the unused power terminal.") - qdel(T) - new /obj/machinery/power/apc(loc, ndir, 1) - qdel(src) +// APC HULL + +/obj/item/apc_frame + name = "APC frame" + desc = "Used for repairing or building APCs." + icon = 'icons/obj/apc_repair.dmi' + icon_state = "apc_frame" + flags = CONDUCT + +/obj/item/apc_frame/attackby(obj/item/weapon/W, mob/user) + ..() + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/metal( get_turf(src.loc), 2 ) + qdel(src) + +/obj/item/apc_frame/proc/try_build(turf/on_wall) + if (get_dist(on_wall,usr)>1) + return + var/ndir = get_dir(usr,on_wall) + if (!(ndir in cardinal)) + return + var/turf/loc = get_turf(usr) + var/area/A = loc.loc + if (!istype(loc, /turf/simulated/floor)) + to_chat(usr, "\red APC cannot be placed on this spot.") + return + if (A.requires_power == 0 || istype(A,/area/space)) + to_chat(usr, "\red APC cannot be placed in this area.") + return + if (A.get_apc()) + to_chat(usr, "\red This area already has APC.") + return //only one APC per area + for(var/obj/machinery/power/terminal/T in loc) + if (T.master) + to_chat(usr, "\red There is another network terminal here.") + return + else + new /obj/item/stack/cable_coil/random(loc, 10) + to_chat(usr, "You cut the cables and disassemble the unused power terminal.") + qdel(T) + new /obj/machinery/power/apc(loc, ndir, 1) + qdel(src) diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 35d64d5b4509..88b5047703a0 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -1,109 +1,109 @@ -//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" - w_class = 2.0 - - 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/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" - var/item_path = /obj/item/bodybag - density = 0 - - - attackby(W, mob/user) - if (istype(W, /obj/item/weapon/pen)) - var/t = sanitize(input(user, "What would you like the label to be?", input_default(src.name), null) as text, MAX_NAME_LEN) - if (user.get_active_hand() != W) - return - if (!in_range(src, user) && src.loc != user) - return - if (t) - src.name = "body bag - " - src.name += t - src.overlays += image(src.icon, "bodybag_label") - else - src.name = "body bag" - //..() //Doesn't need to run the parent. Since when can fucking bodybags be welded shut? -Agouri - return - else if(istype(W, /obj/item/weapon/wirecutters)) - to_chat(user, "You cut the tag off the bodybag") - src.name = "body bag" - src.overlays.Cut() - return - - - close() - if(..()) - density = 0 - return 1 - return 0 - - - MouseDrop(over_object, src_location, over_location) - ..() - if(!iscarbon(usr) && !isrobot(usr)) - return - if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) - if(opened) return 0 - if(contents.len) return 0 - visible_message("[usr] folds up the [src.name]") - new item_path(get_turf(src)) - qdel(src) - return - -/obj/structure/closet/bodybag/update_icon() - if(!opened) - icon_state = icon_closed - else - icon_state = icon_opened - - -/obj/item/bodybag/cryobag - name = "stasis bag" - desc = "A folded, non-reusable bag designed to prevent additional damage to an occupant at the cost of genetic damage." - icon = 'icons/obj/cryobag.dmi' - icon_state = "bodybag_folded" - - 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 to prevent additional damage to an occupant at the cost of genetic damage." - icon = 'icons/obj/cryobag.dmi' - item_path = /obj/item/bodybag/cryobag - var/used = 0 - - 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) - - MouseDrop(over_object, src_location, over_location) - if(!iscarbon(usr) && !isrobot(usr)) - return - if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) - to_chat(usr, "\red You can't fold that up anymore..") - ..() +//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" + w_class = 2.0 + + 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/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" + var/item_path = /obj/item/bodybag + density = 0 + + + attackby(W, mob/user) + if (istype(W, /obj/item/weapon/pen)) + var/t = sanitize(input(user, "What would you like the label to be?", input_default(src.name), null) as text, MAX_NAME_LEN) + if (user.get_active_hand() != W) + return + if (!in_range(src, user) && src.loc != user) + return + if (t) + src.name = "body bag - " + src.name += t + src.overlays += image(src.icon, "bodybag_label") + else + src.name = "body bag" + //..() //Doesn't need to run the parent. Since when can fucking bodybags be welded shut? -Agouri + return + else if(istype(W, /obj/item/weapon/wirecutters)) + to_chat(user, "You cut the tag off the bodybag") + src.name = "body bag" + src.overlays.Cut() + return + + + close() + if(..()) + density = 0 + return 1 + return 0 + + + MouseDrop(over_object, src_location, over_location) + ..() + if(!iscarbon(usr) && !isrobot(usr)) + return + if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) + if(opened) return 0 + if(contents.len) return 0 + visible_message("[usr] folds up the [src.name]") + new item_path(get_turf(src)) + qdel(src) + return + +/obj/structure/closet/bodybag/update_icon() + if(!opened) + icon_state = icon_closed + else + icon_state = icon_opened + + +/obj/item/bodybag/cryobag + name = "stasis bag" + desc = "A folded, non-reusable bag designed to prevent additional damage to an occupant at the cost of genetic damage." + icon = 'icons/obj/cryobag.dmi' + icon_state = "bodybag_folded" + + 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 to prevent additional damage to an occupant at the cost of genetic damage." + icon = 'icons/obj/cryobag.dmi' + item_path = /obj/item/bodybag/cryobag + var/used = 0 + + 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) + + MouseDrop(over_object, src_location, over_location) + if(!iscarbon(usr) && !isrobot(usr)) + return + if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) + to_chat(usr, "\red You can't fold that up anymore..") + ..() diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm index d55b44ee8f14..0815c36f1db7 100644 --- a/code/game/objects/items/candle.dm +++ b/code/game/objects/items/candle.dm @@ -1,202 +1,202 @@ -var/global/list/obj/item/candle/ghost/ghost_candles = list() -#define CANDLE_LUMINOSITY 3 - -/obj/item/candle - name = "white candle" - desc = "In Greek myth, Prometheus stole fire from the Gods and gave it to \ - humankind. The jewelry he kept for himself." - - icon = 'icons/obj/candle.dmi' - icon_state = "white_candle" - item_state = "white_candle" - - var/candle_color - w_class = 1 - - var/wax = 0 - var/lit = FALSE - light_color = LIGHT_COLOR_FIRE - - var/infinite = FALSE - var/start_lit = FALSE - - var/faded_candle = /obj/item/trash/candle - -/obj/item/candle/atom_init() - . = ..() - wax = rand(600, 800) - if(start_lit) - // No visible message - light(show_message = FALSE) - update_icon() - -/obj/item/candle/proc/light(flavor_text = "[usr] lights the [name].") - if(!lit) - lit = TRUE - //src.damtype = "fire" - visible_message(flavor_text) - set_light(CANDLE_LUMINOSITY, 1) - START_PROCESSING(SSobj, src) - playsound(get_turf(src), 'sound/items/matchstick_light.ogg', 50, 0) - -/obj/item/candle/update_icon() - var/lighning_stage - if(wax > 450) - lighning_stage = 1 - else if(wax > 200) - lighning_stage = 2 - else - lighning_stage = 3 - icon_state = "[initial(icon_state)][lighning_stage][lit ? "_lit" : ""]" - if(lit) - item_state = "[initial(icon_state)]_lit" - else - item_state = "[initial(icon_state)]" - if(istype(loc, /mob)) - var/mob/M = loc - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.l_hand == src) - M.update_inv_l_hand() - if(H.r_hand == src) - M.update_inv_r_hand() - -/obj/item/candle/attackby(obj/item/weapon/W, mob/user) - ..() - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.isOn()) // Badasses dont get blinded by lighting their candle with a welding tool - light("[user] casually lights the [name] with [W].") - else if(istype(W, /obj/item/weapon/lighter)) - var/obj/item/weapon/lighter/L = W - if(L.lit) - light() - else if(istype(W, /obj/item/weapon/match)) - var/obj/item/weapon/match/M = W - if(M.lit) - light() - else if(istype(W, /obj/item/candle)) - var/obj/item/candle/C = W - if(C.lit) - light() - -/obj/item/candle/process() - if(!lit) - return - if(!infinite) - wax-- - if(!wax) - dropped() - fade() - qdel(src) - return - update_icon() - if(istype(loc, /turf)) // start a fire if possible - var/turf/T = loc - T.hotspot_expose(700, 5) - -/obj/item/candle/proc/fade() - var/obj/item/candle/C = new faded_candle(src.loc) - if(istype(loc, /mob)) - var/mob/M = loc - M.put_in_hands(C) - -/obj/item/candle/attack_self(mob/user) - if(lit) - user.visible_message("[user] blows out the [src].") - lit = FALSE - update_icon() - set_light(0) - STOP_PROCESSING(SSobj, src) - - // Ghost candle -/obj/item/candle/ghost - name = "black candle" - - icon_state = "black_candle" - item_state = "black_candle" - - light_color = LIGHT_COLOR_GHOST_CANDLE - - faded_candle = /obj/item/trash/candle/ghost - -/obj/item/candle/ghost/atom_init() - . = ..() - ghost_candles += src - -/obj/item/candle/ghost/Destroy() - ghost_candles -= src - return ..() - -/obj/item/candle/ghost/attack_ghost() - if(!lit) - src.light("\The [name] suddenly lights up.") - if(prob(10)) - spook() - -/obj/item/candle/ghost/attack_self(mob/user) - if(lit) - to_chat(user, "You can't just extinguish it.") - -/obj/item/candle/ghost/proc/spook() - visible_message("Out of the tip of the flame, a face appears.") - playsound(get_turf(src), 'sound/effects/screech.ogg', 50, 0) - for(var/mob/living/carbon/M in hearers(4, get_turf(src))) - if(!iscultist(M)) - M.confused += 10 - M.make_jittery(150) - for(var/obj/machinery/light/L in range(4, get_turf(src))) - L.on = TRUE - L.broken() - -/obj/item/candle/ghost/attackby(obj/item/weapon/W, mob/living/carbon/human/user) - ..() - if(istype(W, /obj/item/device/occult_scanner)) - var/obj/item/device/occult_scanner/OS = W - OS.scanned_type = src.type - to_chat(user, "[src] has been succesfully scanned by [OS]") - if(istype(W, /obj/item/weapon/book/tome)) - spook() - light() - if(user.getBrainLoss() >= 60 || user.mind.assigned_role == "Chaplain" || user.mind.role_alt_title == "Paranormal Investigator") - if(!lit && istype(W, /obj/item/weapon/storage/bible)) - var/obj/item/weapon/storage/bible/B = W - if(B.icon_state == "necronomicon") - spook() - light() - else - for(var/mob/living/carbon/M in range(4, src)) - to_chat(M, "You feel slight delight, as all curses pass away...") - M.apply_damages(-1,-1,-1,-1,0,0) - light() - if(istype(W, /obj/item/weapon/nullrod)) - var/obj/item/candle/C = new /obj/item/candle(loc) - if(lit) - C.light("") - C.wax = wax - if(istype(loc, /mob)) - user.put_in_hands(C) - qdel(src) - if(istype(W, /obj/item/trash/candle)) - to_chat(user, "The wax begins to corrupt and pulse like veins as it merges itself with the [src], impressive.") - user.confused += 10 // Sights of this are not pleasant. - if(prob(10) && user.nutrition > 20) - user.vomit() - wax += 50 - user.drop_item() - qdel(W) - -/obj/item/candle/red - name = "red candle" - - icon_state = "red_candle" - item_state = "red_candle" - - faded_candle = /obj/item/trash/candle/red - - // Infinite candle (Admin item) -/obj/item/candle/infinite - infinite = TRUE - start_lit = TRUE - +var/global/list/obj/item/candle/ghost/ghost_candles = list() +#define CANDLE_LUMINOSITY 3 + +/obj/item/candle + name = "white candle" + desc = "In Greek myth, Prometheus stole fire from the Gods and gave it to \ + humankind. The jewelry he kept for himself." + + icon = 'icons/obj/candle.dmi' + icon_state = "white_candle" + item_state = "white_candle" + + var/candle_color + w_class = 1 + + var/wax = 0 + var/lit = FALSE + light_color = LIGHT_COLOR_FIRE + + var/infinite = FALSE + var/start_lit = FALSE + + var/faded_candle = /obj/item/trash/candle + +/obj/item/candle/atom_init() + . = ..() + wax = rand(600, 800) + if(start_lit) + // No visible message + light(show_message = FALSE) + update_icon() + +/obj/item/candle/proc/light(flavor_text = "[usr] lights the [name].") + if(!lit) + lit = TRUE + //src.damtype = "fire" + visible_message(flavor_text) + set_light(CANDLE_LUMINOSITY, 1) + START_PROCESSING(SSobj, src) + playsound(get_turf(src), 'sound/items/matchstick_light.ogg', 50, 0) + +/obj/item/candle/update_icon() + var/lighning_stage + if(wax > 450) + lighning_stage = 1 + else if(wax > 200) + lighning_stage = 2 + else + lighning_stage = 3 + icon_state = "[initial(icon_state)][lighning_stage][lit ? "_lit" : ""]" + if(lit) + item_state = "[initial(icon_state)]_lit" + else + item_state = "[initial(icon_state)]" + if(istype(loc, /mob)) + var/mob/M = loc + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.l_hand == src) + M.update_inv_l_hand() + if(H.r_hand == src) + M.update_inv_r_hand() + +/obj/item/candle/attackby(obj/item/weapon/W, mob/user) + ..() + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.isOn()) // Badasses dont get blinded by lighting their candle with a welding tool + light("[user] casually lights the [name] with [W].") + else if(istype(W, /obj/item/weapon/lighter)) + var/obj/item/weapon/lighter/L = W + if(L.lit) + light() + else if(istype(W, /obj/item/weapon/match)) + var/obj/item/weapon/match/M = W + if(M.lit) + light() + else if(istype(W, /obj/item/candle)) + var/obj/item/candle/C = W + if(C.lit) + light() + +/obj/item/candle/process() + if(!lit) + return + if(!infinite) + wax-- + if(!wax) + dropped() + fade() + qdel(src) + return + update_icon() + if(istype(loc, /turf)) // start a fire if possible + var/turf/T = loc + T.hotspot_expose(700, 5) + +/obj/item/candle/proc/fade() + var/obj/item/candle/C = new faded_candle(src.loc) + if(istype(loc, /mob)) + var/mob/M = loc + M.put_in_hands(C) + +/obj/item/candle/attack_self(mob/user) + if(lit) + user.visible_message("[user] blows out the [src].") + lit = FALSE + update_icon() + set_light(0) + STOP_PROCESSING(SSobj, src) + + // Ghost candle +/obj/item/candle/ghost + name = "black candle" + + icon_state = "black_candle" + item_state = "black_candle" + + light_color = LIGHT_COLOR_GHOST_CANDLE + + faded_candle = /obj/item/trash/candle/ghost + +/obj/item/candle/ghost/atom_init() + . = ..() + ghost_candles += src + +/obj/item/candle/ghost/Destroy() + ghost_candles -= src + return ..() + +/obj/item/candle/ghost/attack_ghost() + if(!lit) + src.light("\The [name] suddenly lights up.") + if(prob(10)) + spook() + +/obj/item/candle/ghost/attack_self(mob/user) + if(lit) + to_chat(user, "You can't just extinguish it.") + +/obj/item/candle/ghost/proc/spook() + visible_message("Out of the tip of the flame, a face appears.") + playsound(get_turf(src), 'sound/effects/screech.ogg', 50, 0) + for(var/mob/living/carbon/M in hearers(4, get_turf(src))) + if(!iscultist(M)) + M.confused += 10 + M.make_jittery(150) + for(var/obj/machinery/light/L in range(4, get_turf(src))) + L.on = TRUE + L.broken() + +/obj/item/candle/ghost/attackby(obj/item/weapon/W, mob/living/carbon/human/user) + ..() + if(istype(W, /obj/item/device/occult_scanner)) + var/obj/item/device/occult_scanner/OS = W + OS.scanned_type = src.type + to_chat(user, "[src] has been succesfully scanned by [OS]") + if(istype(W, /obj/item/weapon/book/tome)) + spook() + light() + if(user.getBrainLoss() >= 60 || user.mind.assigned_role == "Chaplain" || user.mind.role_alt_title == "Paranormal Investigator") + if(!lit && istype(W, /obj/item/weapon/storage/bible)) + var/obj/item/weapon/storage/bible/B = W + if(B.icon_state == "necronomicon") + spook() + light() + else + for(var/mob/living/carbon/M in range(4, src)) + to_chat(M, "You feel slight delight, as all curses pass away...") + M.apply_damages(-1,-1,-1,-1,0,0) + light() + if(istype(W, /obj/item/weapon/nullrod)) + var/obj/item/candle/C = new /obj/item/candle(loc) + if(lit) + C.light("") + C.wax = wax + if(istype(loc, /mob)) + user.put_in_hands(C) + qdel(src) + if(istype(W, /obj/item/trash/candle)) + to_chat(user, "The wax begins to corrupt and pulse like veins as it merges itself with the [src], impressive.") + user.confused += 10 // Sights of this are not pleasant. + if(prob(10) && user.nutrition > 20) + user.vomit() + wax += 50 + user.drop_item() + qdel(W) + +/obj/item/candle/red + name = "red candle" + + icon_state = "red_candle" + item_state = "red_candle" + + faded_candle = /obj/item/trash/candle/red + + // Infinite candle (Admin item) +/obj/item/candle/infinite + infinite = TRUE + start_lit = TRUE + #undef CANDLE_LUMINOSITY \ No newline at end of file diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 4806e18f2ef6..fe6c3c475b0b 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -1,252 +1,252 @@ -/obj/item/toy/crayon/red - icon_state = "crayonred" - colour = "#DA0000" - shadeColour = "#810C0C" - colourName = "red" - -/obj/item/toy/crayon/orange - icon_state = "crayonorange" - colour = "#FF9300" - shadeColour = "#A55403" - colourName = "orange" - -/obj/item/toy/crayon/yellow - icon_state = "crayonyellow" - colour = "#FFF200" - shadeColour = "#886422" - colourName = "yellow" - -/obj/item/toy/crayon/green - icon_state = "crayongreen" - colour = "#A8E61D" - shadeColour = "#61840F" - colourName = "green" - -/obj/item/toy/crayon/blue - icon_state = "crayonblue" - colour = "#00B7EF" - shadeColour = "#0082A8" - colourName = "blue" - -/obj/item/toy/crayon/purple - icon_state = "crayonpurple" - colour = "#DA00FF" - shadeColour = "#810CFF" - colourName = "purple" - -/obj/item/toy/crayon/mime - icon_state = "crayonmime" - desc = "A very sad-looking crayon." - colour = "#FFFFFF" - shadeColour = "#000000" - colourName = "mime" - -/obj/item/toy/crayon/mime/attack_self(mob/living/user) //inversion - if(colour != "#FFFFFF" && shadeColour != "#000000") - colour = "#FFFFFF" - shadeColour = "#000000" - to_chat(user, "You will now draw in white and black with this crayon.") - else - colour = "#000000" - shadeColour = "#FFFFFF" - to_chat(user, "You will now draw in black and white with this crayon.") - return - -/obj/item/toy/crayon/rainbow - icon_state = "crayonrainbow" - colour = "#FFF000" - shadeColour = "#000FFF" - colourName = "rainbow" - -/obj/item/toy/crayon/rainbow/attack_self(mob/living/user) - colour = input(user, "Please select the main colour.", "Crayon colour") as color - shadeColour = input(user, "Please select the shade colour.", "Crayon colour") as color - return - -/obj/item/toy/crayon/afterattack(atom/target, mob/user, proximity) - if(!proximity) return - if(!uses) - to_chat(user, "There is no more of [src.name] left!") - if(!instant) - qdel(src) - return - if(istype(target, /obj/effect/decal/cleanable)) - target = target.loc - if(is_type_in_list(target,validSurfaces)) - var/drawtype = input("Choose what you'd like to draw.", "Crayon scribbles") in list("graffiti","rune","letter") - switch(drawtype) - if("letter") - drawtype = input("Choose the letter.", "Crayon scribbles") in list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z") - to_chat(user, "You start [instant ? "spraying" : "drawing"] a letter on the [target.name].") - if("graffiti") - to_chat(user, "You start [instant ? "spraying" : "drawing"] graffiti on the [target.name].") - if("rune") - to_chat(user, "You start [instant ? "spraying" : "drawing"] a rune on the [target.name].") - - ////////////////////////// GANG FUNCTIONS - var/area/territory - var/gangID - if(gang) - //Determine gang affiliation - if(user.mind in (ticker.mode.A_bosses | ticker.mode.A_gang)) - gangID = "A" - else if(user.mind in (ticker.mode.B_bosses | ticker.mode.B_gang)) - gangID = "B" - - //Check area validity. Reject space, player-created areas, and non-station z-levels. - if (gangID) - territory = get_area(target) - if(territory && (territory.z == ZLEVEL_STATION) && territory.valid_territory) - //Check if this area is already tagged by a gang - if(!(locate(/obj/effect/decal/cleanable/crayon/gang) in target)) //Ignore the check if the tile being sprayed has a gang tag - if(territory_claimed(territory, user)) - return - /* - //Prevent people spraying from outside of the territory (ie. Maint walls) - var/area/user_area = get_area(user.loc) - if(istype(user_area) && (user_area.type != territory.type)) - to_chat(user, "You cannot tag [territory] from the outside.") - return - */ - if(locate(/obj/machinery/power/apc) in (user.loc.contents | target.contents)) - to_chat(user, "You cannot tag here.") - return - else - to_chat(user, "[territory] is unsuitable for tagging.") - return - ///////////////////////////////////////// - - if(!in_range(user, target)) - to_chat(user, "You must stay close to your drawing if you want to draw something.") - return - if(instant) - playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5) - if(instant > 0 || (!user.is_busy(src) && do_after(user, 50, target = target))) - - //Gang functions - if(gangID) - //Delete any old markings on this tile, including other gang tags - if(!(locate(/obj/effect/decal/cleanable/crayon/gang) in target)) //Ignore the check if the tile being sprayed has a gang tag - if(territory_claimed(territory, user)) - return - for(var/obj/effect/decal/cleanable/crayon/old_marking in target) - qdel(old_marking) - new /obj/effect/decal/cleanable/crayon/gang(target,gangID,"graffiti") - to_chat(user, "You tagged [territory] for your gang!") - - else - new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype) - - if(drawtype in list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z")) - to_chat(user, "You finish [instant ? "spraying" : "drawing"] a letter on the [target.name].") - else - to_chat(user, "You finish [instant ? "spraying" : "drawing"] [drawtype] on the [target.name].") - if(instant<0) - playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5) - uses = max(0,uses-1) - if(!uses) - to_chat(user, "There is no more of [src.name] left!") - if(!instant) - qdel(src) - return - -/obj/item/toy/crayon/attack(mob/M, mob/user) - if(edible && (M == user)) - to_chat(user, "You take a bite of the [src.name]. Delicious!") - user.nutrition += 5 - uses = max(0,uses-5) - if(!uses) - to_chat(user, "There is no more of [src.name] left!") - qdel(src) - else - ..() - -/obj/item/toy/crayon/proc/territory_claimed(area/territory,mob/user) - var/occupying_gang - if(territory.type in (ticker.mode.A_territory | ticker.mode.A_territory_new)) - occupying_gang = gang_name("A") - if(territory.type in (ticker.mode.B_territory | ticker.mode.B_territory_new)) - occupying_gang = gang_name("B") - if(occupying_gang) - to_chat(user, "[territory] has already been tagged by the [occupying_gang] gang! You must get rid of or spray over the old tag first!") - return 1 - return 0 - - -//Spraycan stuff - -/obj/item/toy/crayon/spraycan - icon_state = "spraycan_cap" - desc = "A metallic container containing tasty paint." - var/capped = 1 - instant = 1 - edible = 0 - validSurfaces = list(/turf/simulated/floor,/turf/simulated/wall) - -/obj/item/toy/crayon/spraycan/atom_init() - . = ..() - name = "spray can" - update_icon() - -/obj/item/toy/crayon/spraycan/examine(mob/user) - ..() - if(uses) - to_chat(user, "It has [uses] uses left.") - else - to_chat(user, "It is empty.") - -/obj/item/toy/crayon/spraycan/attack_self(mob/living/user) - var/choice = input(user,"Spraycan options") as null|anything in list("Toggle Cap","Change Drawing","Change Color") - switch(choice) - if("Toggle Cap") - to_chat(user, "You [capped ? "Remove" : "Replace"] the cap of the [src]") - capped = capped ? 0 : 1 - icon_state = "spraycan[capped ? "_cap" : ""]" - update_icon() - if("Change Drawing") - ..() - if("Change Color") - colour = input(user,"Choose Color") as color - update_icon() - -/obj/item/toy/crayon/spraycan/afterattack(atom/target, mob/user, proximity) - if(!proximity) - return - if(capped) - to_chat(user, "Take the cap off first!") - return - if(iscarbon(target) && uses - 10 > 0) - uses -= 10 - var/mob/living/carbon/C = target - user.visible_message(" [user] sprays [src] into the face of [target]!") - if(C.client) - C.eye_blurry = max(C.eye_blurry, 3) - C.eye_blind = max(C.eye_blind, 1) - if(ishuman(C)) - var/mob/living/carbon/human/H = C - H.lip_style = "spray_face" - H.lip_color = colour - H.update_body() - else if(istype(target, /obj/machinery/nuclearbomb)) - var/obj/machinery/nuclearbomb/N = target - var/choice = input(user, "Spraycan options") as null|anything in list("fish", "peace", "shark", "nuke", "nt", "heart", "woman", "smile") - if(!choice) - return - uses -= 5 - N.overlays -= image('icons/effects/Nuke_sprays.dmi', N.spray_icon_state) - N.overlays += image('icons/effects/Nuke_sprays.dmi', choice) - N.spray_icon_state = choice - playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5) - ..() - -/obj/item/toy/crayon/spraycan/update_icon() - overlays.Cut() - var/image/I = image('icons/obj/crayons.dmi',icon_state = "[capped ? "spraycan_cap_colors" : "spraycan_colors"]") - I.color = colour - overlays += I - -/obj/item/toy/crayon/spraycan/gang - desc = "A modified container containing suspicious paint." - gang = 1 - uses = 20 - instant = -1 +/obj/item/toy/crayon/red + icon_state = "crayonred" + colour = "#DA0000" + shadeColour = "#810C0C" + colourName = "red" + +/obj/item/toy/crayon/orange + icon_state = "crayonorange" + colour = "#FF9300" + shadeColour = "#A55403" + colourName = "orange" + +/obj/item/toy/crayon/yellow + icon_state = "crayonyellow" + colour = "#FFF200" + shadeColour = "#886422" + colourName = "yellow" + +/obj/item/toy/crayon/green + icon_state = "crayongreen" + colour = "#A8E61D" + shadeColour = "#61840F" + colourName = "green" + +/obj/item/toy/crayon/blue + icon_state = "crayonblue" + colour = "#00B7EF" + shadeColour = "#0082A8" + colourName = "blue" + +/obj/item/toy/crayon/purple + icon_state = "crayonpurple" + colour = "#DA00FF" + shadeColour = "#810CFF" + colourName = "purple" + +/obj/item/toy/crayon/mime + icon_state = "crayonmime" + desc = "A very sad-looking crayon." + colour = "#FFFFFF" + shadeColour = "#000000" + colourName = "mime" + +/obj/item/toy/crayon/mime/attack_self(mob/living/user) //inversion + if(colour != "#FFFFFF" && shadeColour != "#000000") + colour = "#FFFFFF" + shadeColour = "#000000" + to_chat(user, "You will now draw in white and black with this crayon.") + else + colour = "#000000" + shadeColour = "#FFFFFF" + to_chat(user, "You will now draw in black and white with this crayon.") + return + +/obj/item/toy/crayon/rainbow + icon_state = "crayonrainbow" + colour = "#FFF000" + shadeColour = "#000FFF" + colourName = "rainbow" + +/obj/item/toy/crayon/rainbow/attack_self(mob/living/user) + colour = input(user, "Please select the main colour.", "Crayon colour") as color + shadeColour = input(user, "Please select the shade colour.", "Crayon colour") as color + return + +/obj/item/toy/crayon/afterattack(atom/target, mob/user, proximity) + if(!proximity) return + if(!uses) + to_chat(user, "There is no more of [src.name] left!") + if(!instant) + qdel(src) + return + if(istype(target, /obj/effect/decal/cleanable)) + target = target.loc + if(is_type_in_list(target,validSurfaces)) + var/drawtype = input("Choose what you'd like to draw.", "Crayon scribbles") in list("graffiti","rune","letter") + switch(drawtype) + if("letter") + drawtype = input("Choose the letter.", "Crayon scribbles") in list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z") + to_chat(user, "You start [instant ? "spraying" : "drawing"] a letter on the [target.name].") + if("graffiti") + to_chat(user, "You start [instant ? "spraying" : "drawing"] graffiti on the [target.name].") + if("rune") + to_chat(user, "You start [instant ? "spraying" : "drawing"] a rune on the [target.name].") + + ////////////////////////// GANG FUNCTIONS + var/area/territory + var/gangID + if(gang) + //Determine gang affiliation + if(user.mind in (ticker.mode.A_bosses | ticker.mode.A_gang)) + gangID = "A" + else if(user.mind in (ticker.mode.B_bosses | ticker.mode.B_gang)) + gangID = "B" + + //Check area validity. Reject space, player-created areas, and non-station z-levels. + if (gangID) + territory = get_area(target) + if(territory && (territory.z == ZLEVEL_STATION) && territory.valid_territory) + //Check if this area is already tagged by a gang + if(!(locate(/obj/effect/decal/cleanable/crayon/gang) in target)) //Ignore the check if the tile being sprayed has a gang tag + if(territory_claimed(territory, user)) + return + /* + //Prevent people spraying from outside of the territory (ie. Maint walls) + var/area/user_area = get_area(user.loc) + if(istype(user_area) && (user_area.type != territory.type)) + to_chat(user, "You cannot tag [territory] from the outside.") + return + */ + if(locate(/obj/machinery/power/apc) in (user.loc.contents | target.contents)) + to_chat(user, "You cannot tag here.") + return + else + to_chat(user, "[territory] is unsuitable for tagging.") + return + ///////////////////////////////////////// + + if(!in_range(user, target)) + to_chat(user, "You must stay close to your drawing if you want to draw something.") + return + if(instant) + playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5) + if(instant > 0 || (!user.is_busy(src) && do_after(user, 50, target = target))) + + //Gang functions + if(gangID) + //Delete any old markings on this tile, including other gang tags + if(!(locate(/obj/effect/decal/cleanable/crayon/gang) in target)) //Ignore the check if the tile being sprayed has a gang tag + if(territory_claimed(territory, user)) + return + for(var/obj/effect/decal/cleanable/crayon/old_marking in target) + qdel(old_marking) + new /obj/effect/decal/cleanable/crayon/gang(target,gangID,"graffiti") + to_chat(user, "You tagged [territory] for your gang!") + + else + new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype) + + if(drawtype in list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z")) + to_chat(user, "You finish [instant ? "spraying" : "drawing"] a letter on the [target.name].") + else + to_chat(user, "You finish [instant ? "spraying" : "drawing"] [drawtype] on the [target.name].") + if(instant<0) + playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5) + uses = max(0,uses-1) + if(!uses) + to_chat(user, "There is no more of [src.name] left!") + if(!instant) + qdel(src) + return + +/obj/item/toy/crayon/attack(mob/M, mob/user) + if(edible && (M == user)) + to_chat(user, "You take a bite of the [src.name]. Delicious!") + user.nutrition += 5 + uses = max(0,uses-5) + if(!uses) + to_chat(user, "There is no more of [src.name] left!") + qdel(src) + else + ..() + +/obj/item/toy/crayon/proc/territory_claimed(area/territory,mob/user) + var/occupying_gang + if(territory.type in (ticker.mode.A_territory | ticker.mode.A_territory_new)) + occupying_gang = gang_name("A") + if(territory.type in (ticker.mode.B_territory | ticker.mode.B_territory_new)) + occupying_gang = gang_name("B") + if(occupying_gang) + to_chat(user, "[territory] has already been tagged by the [occupying_gang] gang! You must get rid of or spray over the old tag first!") + return 1 + return 0 + + +//Spraycan stuff + +/obj/item/toy/crayon/spraycan + icon_state = "spraycan_cap" + desc = "A metallic container containing tasty paint." + var/capped = 1 + instant = 1 + edible = 0 + validSurfaces = list(/turf/simulated/floor,/turf/simulated/wall) + +/obj/item/toy/crayon/spraycan/atom_init() + . = ..() + name = "spray can" + update_icon() + +/obj/item/toy/crayon/spraycan/examine(mob/user) + ..() + if(uses) + to_chat(user, "It has [uses] uses left.") + else + to_chat(user, "It is empty.") + +/obj/item/toy/crayon/spraycan/attack_self(mob/living/user) + var/choice = input(user,"Spraycan options") as null|anything in list("Toggle Cap","Change Drawing","Change Color") + switch(choice) + if("Toggle Cap") + to_chat(user, "You [capped ? "Remove" : "Replace"] the cap of the [src]") + capped = capped ? 0 : 1 + icon_state = "spraycan[capped ? "_cap" : ""]" + update_icon() + if("Change Drawing") + ..() + if("Change Color") + colour = input(user,"Choose Color") as color + update_icon() + +/obj/item/toy/crayon/spraycan/afterattack(atom/target, mob/user, proximity) + if(!proximity) + return + if(capped) + to_chat(user, "Take the cap off first!") + return + if(iscarbon(target) && uses - 10 > 0) + uses -= 10 + var/mob/living/carbon/C = target + user.visible_message(" [user] sprays [src] into the face of [target]!") + if(C.client) + C.eye_blurry = max(C.eye_blurry, 3) + C.eye_blind = max(C.eye_blind, 1) + if(ishuman(C)) + var/mob/living/carbon/human/H = C + H.lip_style = "spray_face" + H.lip_color = colour + H.update_body() + else if(istype(target, /obj/machinery/nuclearbomb)) + var/obj/machinery/nuclearbomb/N = target + var/choice = input(user, "Spraycan options") as null|anything in list("fish", "peace", "shark", "nuke", "nt", "heart", "woman", "smile") + if(!choice) + return + uses -= 5 + N.overlays -= image('icons/effects/Nuke_sprays.dmi', N.spray_icon_state) + N.overlays += image('icons/effects/Nuke_sprays.dmi', choice) + N.spray_icon_state = choice + playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5) + ..() + +/obj/item/toy/crayon/spraycan/update_icon() + overlays.Cut() + var/image/I = image('icons/obj/crayons.dmi',icon_state = "[capped ? "spraycan_cap_colors" : "spraycan_colors"]") + I.color = colour + overlays += I + +/obj/item/toy/crayon/spraycan/gang + desc = "A modified container containing suspicious paint." + gang = 1 + uses = 20 + instant = -1 diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 85ee0b129e62..304ce51b6a49 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1,1295 +1,1295 @@ -#define ALLOWED_ID_OVERLAYS list("id","gold","silver","centcom","ert","ert-leader","syndicate","syndicate-command")//List of overlays in pda.dmi -//The advanced pea-green monochrome lcd of tomorrow. - -/obj/item/device/pda - name = "\improper PDA" - desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge." - icon = 'icons/obj/pda.dmi' - icon_state = "pda" - item_state = "electronic" - w_class = 2.0 - 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. - - var/lastmode = 0 - var/ui_tick = 0 - var/nanoUI[0] - - //Secondary variables - var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner. - var/fon = 0 //Is the flashlight function on? - var/f_lum = 2 //Luminosity for the flashlight function - var/message_silent = 0 //To beep or not to beep, that is the question - var/toff = 0 //If 1, messenger disabled - var/tnote[0] //Current Texts - var/last_text //No text spamming - var/last_honk //Also no honk spamming that's bad too - var/ttone = "beep" //The PDA 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/active_conversation = null // New variable that allows us to only view a single conversation. - var/list/conversations = list() // For keeping up with who we have PDA messsages from. - var/newmessage = 0 //To remove hackish overlay check - - var/list/cartmodes = list(40, 42, 43, 433, 44, 441, 45, 451, 46, 48, 47, 49) // If you add more cartridge modes add them to this list as well. - var/list/no_auto_update = list(1, 40, 43, 44, 441, 45, 451) // These modes we turn off autoupdate - var/list/update_every_five = list(3, 41, 433, 46, 47, 48, 49) // These we update every 5 ticks - - 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/ownrank = null // this one is rank, never alt title - - var/obj/item/device/paicard/pai = null // A slot for a personal AI device - -/obj/item/device/pda/atom_init() - . = ..() - PDAs += src - PDAs = sortAtom(PDAs) - if(default_cartridge) - cartridge = new default_cartridge(src) - new /obj/item/weapon/pen(src) - -/obj/item/device/pda/Destroy() - PDAs -= src - if (src.id && prob(90)) //IDs are kept in 90% of the cases - src.id.loc = get_turf(src.loc) - return ..() - -/obj/item/device/pda/examine(mob/user) - ..() - if(src in user) - if (SSshuttle.online) - to_chat(user, "The time [worldtime2text()] and shuttle ETA [shuttleeta2text()] are displayed in the corner of the screen.") - else - to_chat(user, "The time [worldtime2text()] is displayed in the corner of the screen.") - - -/obj/item/device/pda/medical - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-m" - -/obj/item/device/pda/viro - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-v" - -/obj/item/device/pda/engineering - default_cartridge = /obj/item/weapon/cartridge/engineering - icon_state = "pda-e" - -/obj/item/device/pda/security - default_cartridge = /obj/item/weapon/cartridge/security - icon_state = "pda-s" - -/obj/item/device/pda/detective - default_cartridge = /obj/item/weapon/cartridge/detective - icon_state = "pda-det" - -/obj/item/device/pda/warden - default_cartridge = /obj/item/weapon/cartridge/security - icon_state = "pda-warden" - -/obj/item/device/pda/janitor - default_cartridge = /obj/item/weapon/cartridge/janitor - icon_state = "pda-j" - ttone = "slip" - -/obj/item/device/pda/science - default_cartridge = /obj/item/weapon/cartridge/signal/science - icon_state = "pda-tox" - ttone = "boom" - -/obj/item/device/pda/clown - 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 - default_cartridge = /obj/item/weapon/cartridge/mime - icon_state = "pda-mime" - message_silent = 1 - ttone = "silence" - -/obj/item/device/pda/heads - default_cartridge = /obj/item/weapon/cartridge/head - icon_state = "pda-h" - -/obj/item/device/pda/heads/hop - default_cartridge = /obj/item/weapon/cartridge/hop - icon_state = "pda-hop" - -/obj/item/device/pda/heads/hos - default_cartridge = /obj/item/weapon/cartridge/hos - icon_state = "pda-hos" - -/obj/item/device/pda/heads/ce - default_cartridge = /obj/item/weapon/cartridge/ce - icon_state = "pda-ce" - -/obj/item/device/pda/heads/cmo - default_cartridge = /obj/item/weapon/cartridge/cmo - icon_state = "pda-cmo" - -/obj/item/device/pda/heads/rd - default_cartridge = /obj/item/weapon/cartridge/rd - icon_state = "pda-rd" - -/obj/item/device/pda/captain - default_cartridge = /obj/item/weapon/cartridge/captain - icon_state = "pda-c" - detonate = 0 - //toff = 1 - -/obj/item/device/pda/cargo - default_cartridge = /obj/item/weapon/cartridge/quartermaster - icon_state = "pda-cargo" - -/obj/item/device/pda/quartermaster - default_cartridge = /obj/item/weapon/cartridge/quartermaster - icon_state = "pda-q" - -/obj/item/device/pda/shaftminer - 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 - icon_state = "pda-holy" - ttone = "holy" - -/obj/item/device/pda/lawyer - default_cartridge = /obj/item/weapon/cartridge/lawyer - icon_state = "pda-lawyer" - ttone = "..." - -/obj/item/device/pda/lawyer2 - default_cartridge = /obj/item/weapon/cartridge/lawyer - icon_state = "pda-lawyer-old" - ttone = "..." - -/obj/item/device/pda/botanist - //default_cartridge = /obj/item/weapon/cartridge/botanist - icon_state = "pda-hydro" - -/obj/item/device/pda/roboticist - icon_state = "pda-robot" - -/obj/item/device/pda/librarian - 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!" - message_silent = 1 //Quiet in the library! - -/obj/item/device/pda/reporter - icon_state = "pda-libc" - -/obj/item/device/pda/forensic - default_cartridge = /obj/item/weapon/cartridge/detective - icon = 'icons/obj/pda.dmi' - icon_state = "pda-forensic" - -/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 - icon_state = "pda-chef" - -/obj/item/device/pda/barber - icon_state = "pda-barber" - -/obj/item/device/pda/bar - icon_state = "pda-bar" - -/obj/item/device/pda/atmos - default_cartridge = /obj/item/weapon/cartridge/atmos - icon_state = "pda-atmo" - -/obj/item/device/pda/chemist - default_cartridge = /obj/item/weapon/cartridge/chemistry - icon_state = "pda-chem" - -/obj/item/device/pda/geneticist - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-gene" - - -// Special AI/pAI PDAs that cannot explode. -/obj/item/device/pda/silicon - icon_state = "NONE" - ttone = "data" - detonate = 0 - - -/obj/item/device/pda/silicon/proc/set_name_and_job(newname, newjob, newrank) - owner = newname - ownjob = newjob - if(newrank) - ownrank = newrank - else - ownrank = ownjob - name = newname + " (" + ownjob + ")" - - -//AI verb and proc for sending PDA messages. -/obj/item/device/pda/silicon/verb/cmd_send_pdamesg() - set category = "AI Commands" - set name = "Send Message" - set src in usr - set hidden = 1 - if(usr.stat == DEAD) - 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/silicon/verb/cmd_toggle_pda_receiver() - set category = "AI Commands" - set name = "Toggle Sender/Receiver" - set src in usr - if(usr.stat == DEAD) - 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/silicon/verb/cmd_toggle_pda_silent() - set category = "AI Commands" - set name = "Toggle Ringer" - set src in usr - if(usr.stat == DEAD) - to_chat(usr, "You can't do that because you are dead!") - return - message_silent = !message_silent - to_chat(usr, "PDA ringer toggled [(message_silent ? "Off" : "On")]!") - - -/obj/item/device/pda/silicon/verb/cmd_show_message_log() - set category = "AI Commands" - set name = "Show Message Log" - set src in usr - set hidden = 1 - if(usr.stat == DEAD) - to_chat(usr, "You can't do that because you are dead!") - return - var/HTML = "AI PDA Message Log" - for(var/index in tnote) - if(index["sent"]) - HTML += addtext("→ To ", index["owner"],":
                    ", index["message"], "
                    ") - else - HTML += addtext("← From ", index["owner"],":
                    ", index["message"], "
                    ") - HTML +="" - usr << browse(entity_ja(HTML), "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") - - -/obj/item/device/pda/silicon/can_use() - return 1 - - -/obj/item/device/pda/silicon/attack_self(mob/user) - if ((honkamt > 0) && (prob(60)))//For clown virus. - honkamt-- - playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) - return - -//Special PDA for robots - -/obj/item/device/pda/silicon/robot/cmd_toggle_pda_receiver() - set category = "Robot Commands" - set hidden = 1 - ..() - -/obj/item/device/pda/silicon/robot/cmd_toggle_pda_silent() - set category = "Robot Commands" - set hidden = 1 - ..() - -/obj/item/device/pda/silicon/pai - ttone = "assist" - - -/* - * The Actual PDA - */ - -/obj/item/device/pda/proc/can_use() - - if(!ismob(loc)) - return 0 - - var/mob/M = loc - if(M.stat || M.restrained() || M.paralysis || M.stunned || M.weakened) - return 0 - if((src in M.contents) || ( istype(loc, /turf) && in_range(src, M) )) - return 1 - else - 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()) - return attack_self(M) - return - - -/obj/item/device/pda/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) - ui_tick++ - var/datum/nanoui/old_ui = nanomanager.get_open_ui(user, src, "main") - var/auto_update = 1 - if(mode in no_auto_update) - auto_update = 0 - if(old_ui && (mode == lastmode && ui_tick % 5 && mode in update_every_five)) - return - - lastmode = mode - - var/title = "Personal Data Assistant" - - var/data[0] // This is the data that will be sent to the PDA - - data["owner"] = owner // Who is your daddy... - data["ownjob"] = ownjob // ...and what does he do? - - data["mode"] = mode // The current view - data["scanmode"] = scanmode // Scanners - data["fon"] = fon // Flashlight on? - data["pai"] = (isnull(pai) ? 0 : 1) // pAI inserted? - data["note"] = note // current pda notes - data["message_silent"] = message_silent // does the pda make noise when it receives a message? - data["toff"] = toff // is the messenger function turned off? - data["active_conversation"] = active_conversation // Which conversation are we following right now? - - - data["idInserted"] = (id ? 1 : 0) - data["idLink"] = (id ? text("[id.registered_name], [id.assignment]") : "--------") - - data["cart_loaded"] = cartridge ? 1:0 - if(cartridge) - var/cartdata[0] - cartdata["access"] = list(\ - "access_security" = cartridge.access_security,\ - "access_engine" = cartridge.access_engine,\ - "access_atmos" = cartridge.access_atmos,\ - "access_medical" = cartridge.access_medical,\ - "access_clown" = cartridge.access_clown,\ - "access_mime" = cartridge.access_mime,\ - "access_janitor" = cartridge.access_janitor,\ - "access_quartermaster" = cartridge.access_quartermaster,\ - "access_hydroponics" = cartridge.access_hydroponics,\ - "access_reagent_scanner" = cartridge.access_reagent_scanner,\ - "access_remote_door" = cartridge.access_remote_door,\ - "access_status_display" = cartridge.access_status_display,\ - "access_detonate_pda" = cartridge.access_detonate_pda\ - ) - - if(mode in cartmodes) - data["records"] = cartridge.create_NanoUI_values() - - if(mode == 0) - cartdata["name"] = cartridge.name - if(isnull(cartridge.radio)) - cartdata["radio"] = 0 - else - if(istype(cartridge.radio, /obj/item/radio/integrated/beepsky)) - cartdata["radio"] = 1 - if(istype(cartridge.radio, /obj/item/radio/integrated/signal)) - cartdata["radio"] = 2 - if(istype(cartridge.radio, /obj/item/radio/integrated/mule)) - cartdata["radio"] = 3 - - if(mode == 2) - cartdata["type"] = cartridge.type - cartdata["charges"] = cartridge.charges ? cartridge.charges : 0 - data["cartridge"] = cartdata - - data["stationTime"] = worldtime2text() - data["new_Message"] = newmessage - if (SSshuttle.online) - data["shuttle_eta"] = shuttleeta2text() - - if(mode==2) - var/convopdas[0] - var/pdas[0] - var/count = 0 - for (var/obj/item/device/pda/P in PDAs) - if (!P.owner||P.toff||P == src||P.hidden) continue - if(conversations.Find("\ref[P]")) - convopdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "1"))) - else - pdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "0"))) - count++ - - data["convopdas"] = convopdas - data["pdas"] = pdas - data["pda_count"] = count - - if(mode==21) - data["messagescount"] = tnote.len - data["messages"] = tnote - else - data["messagescount"] = null - data["messages"] = null - - if(active_conversation) - for(var/c in tnote) - if(c["target"] == active_conversation) - data["convo_name"] = sanitize(c["owner"]) - data["convo_job"] = sanitize(c["job"]) - break - if(mode==41) - data_core.get_manifest_json() - - - if(mode==3) - var/turf/T = get_turf(user.loc) - if(!isnull(T)) - var/datum/gas_mixture/environment = T.return_air() - - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles - - if (total_moles) - var/o2_level = environment.gas["oxygen"] / total_moles - var/n2_level = environment.gas["nitrogen"] / total_moles - var/co2_level = environment.gas["carbon_dioxide"] / total_moles - var/phoron_level = environment.gas["phoron"] / total_moles - var/unknown_level = 1 - (o2_level + n2_level + co2_level + phoron_level) - data["aircontents"] = list( - "pressure" = "[round(pressure,0.1)]", - "nitrogen" = "[round(n2_level*100,0.1)]", - "oxygen" = "[round(o2_level*100,0.1)]", - "carbon_dioxide" = "[round(co2_level*100,0.1)]", - "phoron" = "[round(phoron_level*100,0.01)]", - "other" = "[round(unknown_level, 0.01)]", - "temp" = "[round(environment.temperature-T0C,0.1)]", - "reading" = 1 - ) - if(isnull(data["aircontents"])) - data["aircontents"] = list("reading" = 0) - - nanoUI = data - // update the ui if it exists, returns null if no ui is passed/found - if(ui) - ui.load_cached_data(ManifestJSON) - - 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, "pda.tmpl", title, 520, 400) - // when the ui is first opened this is the data it will use - - ui.load_cached_data(ManifestJSON) - - ui.set_initial_data(data) - // open the new ui window - ui.open() - // auto update every Master Controller tick - ui.set_auto_update(auto_update) - -//NOTE: graphic resources are loaded on client login -/obj/item/device/pda/attack_self(mob/user) - - user.set_machine(src) - - if(active_uplink_check(user)) - return - - ui_interact(user) //NanoUI requires this proc - return - -/obj/item/device/pda/Topic(href, href_list) - if(href_list["cartmenu"] && !isnull(cartridge)) - cartridge.Topic(href, href_list) - return 1 - if(href_list["radiomenu"] && !isnull(cartridge) && !isnull(cartridge.radio)) - cartridge.radio.Topic(href, href_list) - return 1 - - - ..() - var/mob/user = usr - var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") - 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 (usr.stat == DEAD) - return 0 - if(!can_use()) //Why reinvent the wheel? There's a proc that does exactly that. - U.unset_machine() - if(ui) - ui.close() - return 0 - - add_fingerprint(U) - U.set_machine(src) - - switch(href_list["choice"]) - -//BASIC FUNCTIONS=================================== - - if("Close")//Self explanatory - U.unset_machine() - ui.close() - return 0 - if("Refresh")//Refresh, goes to the end of the proc. - if("Return")//Return - if(mode<=9) - mode = 0 - else - mode = round(mode/10) - if(mode==2) - active_conversation = null - if(mode==4)//Fix for cartridges. Redirects to hub. - mode = 0 - else if(mode >= 40 && mode <= 49)//Fix for cartridges. Redirects to refresh the menu. - cartridge.mode = mode - if ("Authenticate")//Checks for ID - id_check(U, 1) - if("UpdateInfo") - ownjob = id.assignment - ownrank = id.rank - 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 - mode = 0 - 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 messages - mode = 21 - if("3")//Atmos scan - mode = 3 - if("4")//Redirects to hub - mode = 0 - if("chatroom") // chatroom hub - mode = 5 - if("41") //Manifest - mode = 41 - - -//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 - -//MESSENGER/NOTE FUNCTIONS=================================== - - if ("Edit") - var/n = sanitize(input(U, "Please enter message", name, input_default(notehtml)) as message, extra = FALSE) - if (in_range(src, U) && loc == U && mode == 1) - note = html_decode(n) - notehtml = note - note = replacetext(note, "\n", "
                    ") - else - ui.close() - if("Toggle Messenger") - toff = !toff - if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status - message_silent = !message_silent - if("Clear")//Clears messages - if(href_list["option"] == "All") - tnote.Cut() - conversations.Cut() - if(href_list["option"] == "Convo") - var/new_tnote[0] - for(var/i in tnote) - if(i["target"] != active_conversation) - new_tnote[++new_tnote.len] = i - tnote = new_tnote - conversations.Remove(active_conversation) - - active_conversation = null - if(mode==21) - mode=2 - - if("Ringtone") - var/t = sanitize(input(U, "Please enter new ringtone", name, input_default(ttone)) as text, 20) - if (t && in_range(src, U) && loc == U) - if(src.hidden_uplink && hidden_uplink.check_trigger(U, lowertext(t), lowertext(lock_code))) - to_chat(U, "The PDA softly beeps.") - ui.close() - else - ttone = t - else - ui.close() - return 0 - if("Message") - - var/obj/item/device/pda/P = locate(href_list["target"]) - src.create_message(U, P, !href_list["notap"]) - if(mode == 2) - if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp. - active_conversation = href_list["target"] - mode = 21 - - if("Select Conversation") - var/P = href_list["convo"] - for(var/n in conversations) - if(P == n) - active_conversation=P - mode=21 - 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.charges > 0) - cartridge.charges-- - U.show_message("\blue Virus sent!", 1) - P.honkamt = (rand(15,20)) - else - to_chat(U, "PDA not found.") - else - ui.close() - return 0 - 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.charges > 0) - cartridge.charges-- - U.show_message("\blue Virus sent!", 1) - P.message_silent = 1 - P.ttone = "silence" - else - to_chat(U, "PDA not found.") - else - ui.close() - return 0 - - -//SYNDICATE FUNCTIONS=================================== - - if("Toggle Door") - if(cartridge && cartridge.access_remote_door) - for(var/obj/machinery/door/poddoor/M in poddoor_list) - if(M.id == cartridge.remote_door_id) - if(M.density) - M.open() - else - M.close() - - if("Detonate")//Detonate PDA... maybe - // 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(src) - if(pos.z in signal.data["level"]) - useTC = 2 - - if(istype(cartridge, /obj/item/weapon/cartridge/syndicate)) - if(!(useMS && useTC)) - U.show_message("\red An error flashes on your [src]: Connection unavailable", 1) - return - if(useTC != 2) // Does our recepient have a broadcaster on their level? - U.show_message("\red An error flashes on your [src]: Recipient unavailable", 1) - return - var/obj/item/device/pda/P = locate(href_list["target"]) - if(!isnull(P)) - if (!P.toff && cartridge.charges > 0) - cartridge.charges-- - - var/difficulty = 2 - - 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 - if(P.hidden_uplink) - difficulty += 3 - - if(prob(difficulty)) - U.show_message("\red An error flashes on your [src].", 1) - else if (prob(difficulty * 7)) - U.show_message("\red Energy feeds back into your [src]!", 1) - ui.close() - detonate_act(src) - 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. (JMP)") - else - U.show_message("\blue Success!", 1) - log_admin("[key_name(U)] just attempted to blow up [P] with the Detomatix cartridge and succeeded") - message_admins("[key_name_admin(U)] just attempted to blow up [P] with the Detomatix cartridge and succeeded. (JMP)") - detonate_act(P) - else - to_chat(U, "No charges left.") - else - to_chat(U, "PDA not found.") - else - U.unset_machine() - ui.close() - return 0 - -//pAI FUNCTIONS=================================== - if("pai") - if(pai) - if(pai.loc != src) - pai = null - else - switch(href_list["option"]) - if("1") // Configure pAI device - pai.attack_self(U) - if("2") // Eject pAI device - var/turf/T = get_turf_or_move(src.loc) - if(T) - pai.loc = T - pai = null - - else - mode = text2num(href_list["choice"]) - if(cartridge) - cartridge.mode = mode - -//EXTRA FUNCTIONS=================================== - - if (mode == 2||mode == 21)//To clear message overlays. - newmessage = 0 - update_icon() - - if ((honkamt > 0) && (prob(60)))//For clown virus. - honkamt-- - playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) - - return 1 // return 1 tells it to refresh the UI in NanoUI - -/obj/item/device/pda/update_icon() - ..() - - overlays.Cut() - if(newmessage) - overlays += image('icons/obj/pda.dmi', "pda-r") - if(id) - var/id_overlay = get_id_overlay(id) - if(id_overlay) - overlays += image('icons/obj/pda.dmi', id_overlay) - -/obj/item/device/pda/proc/get_id_overlay(obj/item/weapon/card/id/I) - if(!I) - return - if(I.icon_state in ALLOWED_ID_OVERLAYS) - return I.icon_state - return "id" - -/obj/item/device/pda/proc/detonate_act(obj/item/device/pda/P) - //TODO: sometimes these attacks show up on the message server - var/i = rand(1,100) - var/j = rand(0,1) //Possibility of losing the PDA after the detonation - var/message = "" - var/mob/living/M = null - if(ismob(P.loc)) - M = P.loc - - //switch(i) //Yes, the overlapping cases are intended. - if(i<=10) //The traditional explosion - P.explode() - j=1 - message += "Your [P] suddenly explodes!" - if(i>=10 && i<= 20) //The PDA burns a hole in the holder. - j=1 - if(M && isliving(M)) - M.apply_damage( rand(30,60) , BURN) - message += "You feel a searing heat! Your [P] is burning!" - if(i>=20 && i<=25) //EMP - empulse(P.loc, 3, 6, 1) - message += "Your [P] emits a wave of electromagnetic energy!" - if(i>=25 && i<=40) //Smoke - var/datum/effect/effect/system/smoke_spread/S = new /datum/effect/effect/system/smoke_spread - S.attach(P.loc) - S.set_up(n = 10, c = 0, loca = P.loc, direct = 0) - playsound(P.loc, 'sound/effects/smoke.ogg', 50, 1, -3) - S.start() - message += "Large clouds of smoke billow forth from your [P]!" - if(i>=40 && i<=45) //Bad smoke - var/datum/effect/effect/system/smoke_spread/bad/B = new /datum/effect/effect/system/smoke_spread/bad - B.attach(P.loc) - B.set_up(n = 10, c = 0, loca = P.loc, direct = 0) - playsound(P.loc, 'sound/effects/smoke.ogg', 50, 1, -3) - B.start() - message += "Large clouds of noxious smoke billow forth from your [P]!" - if(i>=65 && i<=75) //Weaken - if(M && isliving(M)) - M.apply_effects(0,1) - message += "Your [P] flashes with a blinding white light! You feel weaker." - if(i>=75 && i<=85) //Stun and stutter - if(M && isliving(M)) - M.apply_effects(1,0,0,0,1) - message += "Your [P] flashes with a blinding white light! You feel weaker." - if(i>=85) //Sparks - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(n = 2, c = 1, loca = P.loc) - s.start() - message += "Your [P] begins to spark violently!" - if(i>45 && i<65 && prob(50)) //Nothing happens - message += "Your [P] bleeps loudly." - j = prob(10) - - if(j) //This kills the PDA - P.Destroy() - if(message) - message += "It melts in a puddle of plastic." - else - message += "Your [P] shatters in a thousand pieces!" - - if(M && isliving(M)) - message = "\red" + message - M.show_message(message, 1) - -/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(mob/living/U = usr, obj/item/device/pda/P, tap = 1) - if(tap) - U.visible_message("[U] taps on \his PDA's screen.") - U.last_target_click = world.time - var/t = sanitize(input(U, "Please enter message", name, null) as text) - t = replacetext(t, """, "\"") - - 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()) - 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 dependent 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 recipient have a broadcaster on their level? - to_chat(U, "ERROR: Cannot reach recipient.") - return - - useMS.send_pda_message("[P.owner]","[owner]","[t]") - tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]"))) - P.tnote.Add(list(list("sent" = 0, "owner" = "[owner]", "job" = "[ownjob]", "message" = "[t]", "target" = "\ref[src]"))) - for(var/mob/M in player_list) - if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) // src.client is so that ghosts don't have to listen to mice - if(isnewplayer(M)) - continue - M.show_message("PDA Message - [owner] -> [P.owner]: [t]") - - if(!conversations.Find("\ref[P]")) - conversations.Add("\ref[P]") - if(!P.conversations.Find("\ref[src]")) - P.conversations.Add("\ref[src]") - - 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 ai_list) - // Allows other AIs to intercept the message but the AI won't intercept their own message. - if(ai.pda != P && ai.pda != src) - ai.show_message("Intercepted message from [who]: [t]") - - nanomanager.update_user_uis(U, src) // Update the sending user's PDA UI so that they can see the new message - - if (!P.message_silent) - playsound(P.loc, 'sound/machines/twobeep.ogg', 50, 1) - for (var/mob/O in hearers(3, P.loc)) - if(!P.message_silent) O.show_message(text("[bicon(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) - to_chat(L, "[bicon(P)] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)") - nanomanager.update_user_uis(L, P) // Update the receiving user's PDA UI so that they can see the new message - - nanomanager.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message - - log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") - P.overlays.Cut() - P.overlays += image('icons/obj/pda.dmi', "pda-r") - P.newmessage = 1 - else - to_chat(U, "ERROR: Messaging server is not responding.") - -/obj/item/device/pda/verb/verb_reset_pda() - set category = "Object" - set name = "Reset PDA" - set src in usr - - if(issilicon(usr)) - return - - if(can_use(usr)) - mode = 0 - nanomanager.update_uis(src) - to_chat(usr, "You press the reset button on \the [src].") - else - to_chat(usr, "You cannot do this while restrained.") - -/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() - update_icon() - 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/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].") - playsound(src, 'sound/items/penclick.ogg', 20, 1, 1) - 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/proc/id_check(mob/user, choice)//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)) - user.drop_item() - I.loc = 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 - user.drop_item() - I.loc = src - id = I - user.put_in_hands(old_id) - update_icon() - return - -// access to status display signals -/obj/item/device/pda/attackby(obj/item/C, mob/user) - ..() - if(istype(C, /obj/item/weapon/cartridge) && !cartridge) - cartridge = C - user.drop_item() - cartridge.loc = src - to_chat(user, "You insert [cartridge] into [src].") - nanomanager.update_uis(src) // update all UIs attached to 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 - ownrank = idcard.rank - 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)) ) - id_check(user, 2) - to_chat(user, "You put the ID into \the [src]'s slot.") - 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) - user.drop_item() - C.loc = src - pai = C - to_chat(user, "You slot \the [C] into [src].") - nanomanager.update_uis(src) // update all UIs attached to src - 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 - user.drop_item() - C.loc = src - to_chat(user, "You slide \the [C] into \the [src].") - return - -/obj/item/device/pda/attack(mob/living/C, mob/living/user) - if (istype(C, /mob/living/carbon)) - switch(scanmode) - if(1) - - for (var/mob/O in viewers(C, null)) - O.show_message("\red [user] has analyzed [C]'s vitals!", 1) - - user.show_message("\blue Analyzing Results for [C]:") - user.show_message("\blue   Overall Status: [C.stat > 1 ? "dead" : "[C.health - C.halloss]% healthy"]", 1) - user.show_message("\blue   Damage Specifics: [C.getOxyLoss() > 50 ? "\red" : "\blue"][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "\red" : "\blue"][C.getToxLoss()]-[C.getFireLoss() > 50 ? "\red" : "\blue"][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "\red" : "\blue"][C.getBruteLoss()]", 1) - user.show_message("\blue   Key: Suffocation/Toxin/Burns/Brute", 1) - user.show_message("\blue   Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)", 1) - if(C.tod && (C.stat == DEAD || (C.status_flags & FAKEDEATH))) - user.show_message("\blue   Time of Death: [C.tod]") - if(istype(C, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = C - var/list/damaged = H.get_damaged_bodyparts(1, 1) - user.show_message("\blue Localized Damage, Brute/Burn:",1) - if(length(damaged)>0) - for(var/obj/item/organ/external/BP in damaged) - user.show_message(text("\blue   []: []\blue-[]",capitalize(BP.name),(BP.brute_dam > 0)?"\red [BP.brute_dam]":0,(BP.burn_dam > 0)?"\red [BP.burn_dam]":0),1) - else - user.show_message("\blue   Limbs are OK.",1) - - for(var/datum/disease/D in C.viruses) - if(!D.hidden[SCANNER]) - user.show_message(text("\red Warning: [D.form] Detected\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure]")) - - if(2) - if (!istype(C:dna, /datum/dna)) - to_chat(user, "\blue No fingerprints found on [C]") - else if(!istype(C, /mob/living/carbon/monkey)) - if(!isnull(C:gloves)) - to_chat(user, "\blue No fingerprints found on [C]") - else - to_chat(user, text("\blue [C]'s Fingerprints: [md5(C:dna.uni_identity)]")) - if ( !(C:blood_DNA) ) - to_chat(user, "\blue No blood found on [C]") - if(C:blood_DNA) - C:blood_DNA = null - else - to_chat(user, "\blue Blood found on [C]. Analysing...") - spawn(15) - for(var/blood in C:blood_DNA) - to_chat(user, "\blue Blood type: [C:blood_DNA[blood]]\nDNA: [blood]") - - if(4) - for (var/mob/O in viewers(C, null)) - O.show_message("\red [user] has analyzed [C]'s radiation levels!", 1) - - user.show_message("\blue Analyzing Results for [C]:") - if(C.radiation) - user.show_message("\green Radiation Level: \black [C.radiation]") - else - user.show_message("\blue No radiation detected.") - -/obj/item/device/pda/afterattack(atom/A, mob/user, proximity) - if(!proximity) return - switch(scanmode) - - if(3) - if(!isobj(A)) - return - if(!isnull(A.reagents)) - if(A.reagents.reagent_list.len > 0) - var/reagents_length = A.reagents.reagent_list.len - to_chat(user, "\blue [reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.") - for (var/re in A.reagents.reagent_list) - to_chat(user, "\blue   [re]") - else - to_chat(user, "\blue No active chemical agents found in [A].") - else - to_chat(user, "\blue No significant chemical agents found in [A].") - - if(5) - analyze_gases(A, user) - - if (!scanmode && istype(A, /obj/item/weapon/paper) && owner) - note = A:info - to_chat(user, "\blue Paper scanned.")//concept of scanning paper copyright brainoblivion 2009 - - -/obj/item/device/pda/proc/explode() //This needs tuning. //Sure did. - if(!src.detonate) return - var/turf/T = get_turf(src.loc) - if(T) - T.hotspot_expose(700,125) - explosion(T, 0, 0, 1, rand(1,2)) - return - -/obj/item/device/pda/clown/Crossed(mob/living/carbon/C) //Clown PDA is slippery. - if(istype(C)) - if (C.slip("the PDA", 4, 2) && ishuman(C) && src.cartridge.charges < 5) - cartridge.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 - -// 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) +#define ALLOWED_ID_OVERLAYS list("id","gold","silver","centcom","ert","ert-leader","syndicate","syndicate-command")//List of overlays in pda.dmi +//The advanced pea-green monochrome lcd of tomorrow. + +/obj/item/device/pda + name = "\improper PDA" + desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge." + icon = 'icons/obj/pda.dmi' + icon_state = "pda" + item_state = "electronic" + w_class = 2.0 + 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. + + var/lastmode = 0 + var/ui_tick = 0 + var/nanoUI[0] + + //Secondary variables + var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner. + var/fon = 0 //Is the flashlight function on? + var/f_lum = 2 //Luminosity for the flashlight function + var/message_silent = 0 //To beep or not to beep, that is the question + var/toff = 0 //If 1, messenger disabled + var/tnote[0] //Current Texts + var/last_text //No text spamming + var/last_honk //Also no honk spamming that's bad too + var/ttone = "beep" //The PDA 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/active_conversation = null // New variable that allows us to only view a single conversation. + var/list/conversations = list() // For keeping up with who we have PDA messsages from. + var/newmessage = 0 //To remove hackish overlay check + + var/list/cartmodes = list(40, 42, 43, 433, 44, 441, 45, 451, 46, 48, 47, 49) // If you add more cartridge modes add them to this list as well. + var/list/no_auto_update = list(1, 40, 43, 44, 441, 45, 451) // These modes we turn off autoupdate + var/list/update_every_five = list(3, 41, 433, 46, 47, 48, 49) // These we update every 5 ticks + + 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/ownrank = null // this one is rank, never alt title + + var/obj/item/device/paicard/pai = null // A slot for a personal AI device + +/obj/item/device/pda/atom_init() + . = ..() + PDAs += src + PDAs = sortAtom(PDAs) + if(default_cartridge) + cartridge = new default_cartridge(src) + new /obj/item/weapon/pen(src) + +/obj/item/device/pda/Destroy() + PDAs -= src + if (src.id && prob(90)) //IDs are kept in 90% of the cases + src.id.loc = get_turf(src.loc) + return ..() + +/obj/item/device/pda/examine(mob/user) + ..() + if(src in user) + if (SSshuttle.online) + to_chat(user, "The time [worldtime2text()] and shuttle ETA [shuttleeta2text()] are displayed in the corner of the screen.") + else + to_chat(user, "The time [worldtime2text()] is displayed in the corner of the screen.") + + +/obj/item/device/pda/medical + default_cartridge = /obj/item/weapon/cartridge/medical + icon_state = "pda-m" + +/obj/item/device/pda/viro + default_cartridge = /obj/item/weapon/cartridge/medical + icon_state = "pda-v" + +/obj/item/device/pda/engineering + default_cartridge = /obj/item/weapon/cartridge/engineering + icon_state = "pda-e" + +/obj/item/device/pda/security + default_cartridge = /obj/item/weapon/cartridge/security + icon_state = "pda-s" + +/obj/item/device/pda/detective + default_cartridge = /obj/item/weapon/cartridge/detective + icon_state = "pda-det" + +/obj/item/device/pda/warden + default_cartridge = /obj/item/weapon/cartridge/security + icon_state = "pda-warden" + +/obj/item/device/pda/janitor + default_cartridge = /obj/item/weapon/cartridge/janitor + icon_state = "pda-j" + ttone = "slip" + +/obj/item/device/pda/science + default_cartridge = /obj/item/weapon/cartridge/signal/science + icon_state = "pda-tox" + ttone = "boom" + +/obj/item/device/pda/clown + 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 + default_cartridge = /obj/item/weapon/cartridge/mime + icon_state = "pda-mime" + message_silent = 1 + ttone = "silence" + +/obj/item/device/pda/heads + default_cartridge = /obj/item/weapon/cartridge/head + icon_state = "pda-h" + +/obj/item/device/pda/heads/hop + default_cartridge = /obj/item/weapon/cartridge/hop + icon_state = "pda-hop" + +/obj/item/device/pda/heads/hos + default_cartridge = /obj/item/weapon/cartridge/hos + icon_state = "pda-hos" + +/obj/item/device/pda/heads/ce + default_cartridge = /obj/item/weapon/cartridge/ce + icon_state = "pda-ce" + +/obj/item/device/pda/heads/cmo + default_cartridge = /obj/item/weapon/cartridge/cmo + icon_state = "pda-cmo" + +/obj/item/device/pda/heads/rd + default_cartridge = /obj/item/weapon/cartridge/rd + icon_state = "pda-rd" + +/obj/item/device/pda/captain + default_cartridge = /obj/item/weapon/cartridge/captain + icon_state = "pda-c" + detonate = 0 + //toff = 1 + +/obj/item/device/pda/cargo + default_cartridge = /obj/item/weapon/cartridge/quartermaster + icon_state = "pda-cargo" + +/obj/item/device/pda/quartermaster + default_cartridge = /obj/item/weapon/cartridge/quartermaster + icon_state = "pda-q" + +/obj/item/device/pda/shaftminer + 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 + icon_state = "pda-holy" + ttone = "holy" + +/obj/item/device/pda/lawyer + default_cartridge = /obj/item/weapon/cartridge/lawyer + icon_state = "pda-lawyer" + ttone = "..." + +/obj/item/device/pda/lawyer2 + default_cartridge = /obj/item/weapon/cartridge/lawyer + icon_state = "pda-lawyer-old" + ttone = "..." + +/obj/item/device/pda/botanist + //default_cartridge = /obj/item/weapon/cartridge/botanist + icon_state = "pda-hydro" + +/obj/item/device/pda/roboticist + icon_state = "pda-robot" + +/obj/item/device/pda/librarian + 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!" + message_silent = 1 //Quiet in the library! + +/obj/item/device/pda/reporter + icon_state = "pda-libc" + +/obj/item/device/pda/forensic + default_cartridge = /obj/item/weapon/cartridge/detective + icon = 'icons/obj/pda.dmi' + icon_state = "pda-forensic" + +/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 + icon_state = "pda-chef" + +/obj/item/device/pda/barber + icon_state = "pda-barber" + +/obj/item/device/pda/bar + icon_state = "pda-bar" + +/obj/item/device/pda/atmos + default_cartridge = /obj/item/weapon/cartridge/atmos + icon_state = "pda-atmo" + +/obj/item/device/pda/chemist + default_cartridge = /obj/item/weapon/cartridge/chemistry + icon_state = "pda-chem" + +/obj/item/device/pda/geneticist + default_cartridge = /obj/item/weapon/cartridge/medical + icon_state = "pda-gene" + + +// Special AI/pAI PDAs that cannot explode. +/obj/item/device/pda/silicon + icon_state = "NONE" + ttone = "data" + detonate = 0 + + +/obj/item/device/pda/silicon/proc/set_name_and_job(newname, newjob, newrank) + owner = newname + ownjob = newjob + if(newrank) + ownrank = newrank + else + ownrank = ownjob + name = newname + " (" + ownjob + ")" + + +//AI verb and proc for sending PDA messages. +/obj/item/device/pda/silicon/verb/cmd_send_pdamesg() + set category = "AI Commands" + set name = "Send Message" + set src in usr + set hidden = 1 + if(usr.stat == DEAD) + 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/silicon/verb/cmd_toggle_pda_receiver() + set category = "AI Commands" + set name = "Toggle Sender/Receiver" + set src in usr + if(usr.stat == DEAD) + 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/silicon/verb/cmd_toggle_pda_silent() + set category = "AI Commands" + set name = "Toggle Ringer" + set src in usr + if(usr.stat == DEAD) + to_chat(usr, "You can't do that because you are dead!") + return + message_silent = !message_silent + to_chat(usr, "PDA ringer toggled [(message_silent ? "Off" : "On")]!") + + +/obj/item/device/pda/silicon/verb/cmd_show_message_log() + set category = "AI Commands" + set name = "Show Message Log" + set src in usr + set hidden = 1 + if(usr.stat == DEAD) + to_chat(usr, "You can't do that because you are dead!") + return + var/HTML = "AI PDA Message Log" + for(var/index in tnote) + if(index["sent"]) + HTML += addtext("→ To ", index["owner"],":
                    ", index["message"], "
                    ") + else + HTML += addtext("← From ", index["owner"],":
                    ", index["message"], "
                    ") + HTML +="" + usr << browse(entity_ja(HTML), "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") + + +/obj/item/device/pda/silicon/can_use() + return 1 + + +/obj/item/device/pda/silicon/attack_self(mob/user) + if ((honkamt > 0) && (prob(60)))//For clown virus. + honkamt-- + playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) + return + +//Special PDA for robots + +/obj/item/device/pda/silicon/robot/cmd_toggle_pda_receiver() + set category = "Robot Commands" + set hidden = 1 + ..() + +/obj/item/device/pda/silicon/robot/cmd_toggle_pda_silent() + set category = "Robot Commands" + set hidden = 1 + ..() + +/obj/item/device/pda/silicon/pai + ttone = "assist" + + +/* + * The Actual PDA + */ + +/obj/item/device/pda/proc/can_use() + + if(!ismob(loc)) + return 0 + + var/mob/M = loc + if(M.stat || M.restrained() || M.paralysis || M.stunned || M.weakened) + return 0 + if((src in M.contents) || ( istype(loc, /turf) && in_range(src, M) )) + return 1 + else + 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()) + return attack_self(M) + return + + +/obj/item/device/pda/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) + ui_tick++ + var/datum/nanoui/old_ui = nanomanager.get_open_ui(user, src, "main") + var/auto_update = 1 + if(mode in no_auto_update) + auto_update = 0 + if(old_ui && (mode == lastmode && ui_tick % 5 && mode in update_every_five)) + return + + lastmode = mode + + var/title = "Personal Data Assistant" + + var/data[0] // This is the data that will be sent to the PDA + + data["owner"] = owner // Who is your daddy... + data["ownjob"] = ownjob // ...and what does he do? + + data["mode"] = mode // The current view + data["scanmode"] = scanmode // Scanners + data["fon"] = fon // Flashlight on? + data["pai"] = (isnull(pai) ? 0 : 1) // pAI inserted? + data["note"] = note // current pda notes + data["message_silent"] = message_silent // does the pda make noise when it receives a message? + data["toff"] = toff // is the messenger function turned off? + data["active_conversation"] = active_conversation // Which conversation are we following right now? + + + data["idInserted"] = (id ? 1 : 0) + data["idLink"] = (id ? text("[id.registered_name], [id.assignment]") : "--------") + + data["cart_loaded"] = cartridge ? 1:0 + if(cartridge) + var/cartdata[0] + cartdata["access"] = list(\ + "access_security" = cartridge.access_security,\ + "access_engine" = cartridge.access_engine,\ + "access_atmos" = cartridge.access_atmos,\ + "access_medical" = cartridge.access_medical,\ + "access_clown" = cartridge.access_clown,\ + "access_mime" = cartridge.access_mime,\ + "access_janitor" = cartridge.access_janitor,\ + "access_quartermaster" = cartridge.access_quartermaster,\ + "access_hydroponics" = cartridge.access_hydroponics,\ + "access_reagent_scanner" = cartridge.access_reagent_scanner,\ + "access_remote_door" = cartridge.access_remote_door,\ + "access_status_display" = cartridge.access_status_display,\ + "access_detonate_pda" = cartridge.access_detonate_pda\ + ) + + if(mode in cartmodes) + data["records"] = cartridge.create_NanoUI_values() + + if(mode == 0) + cartdata["name"] = cartridge.name + if(isnull(cartridge.radio)) + cartdata["radio"] = 0 + else + if(istype(cartridge.radio, /obj/item/radio/integrated/beepsky)) + cartdata["radio"] = 1 + if(istype(cartridge.radio, /obj/item/radio/integrated/signal)) + cartdata["radio"] = 2 + if(istype(cartridge.radio, /obj/item/radio/integrated/mule)) + cartdata["radio"] = 3 + + if(mode == 2) + cartdata["type"] = cartridge.type + cartdata["charges"] = cartridge.charges ? cartridge.charges : 0 + data["cartridge"] = cartdata + + data["stationTime"] = worldtime2text() + data["new_Message"] = newmessage + if (SSshuttle.online) + data["shuttle_eta"] = shuttleeta2text() + + if(mode==2) + var/convopdas[0] + var/pdas[0] + var/count = 0 + for (var/obj/item/device/pda/P in PDAs) + if (!P.owner||P.toff||P == src||P.hidden) continue + if(conversations.Find("\ref[P]")) + convopdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "1"))) + else + pdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "0"))) + count++ + + data["convopdas"] = convopdas + data["pdas"] = pdas + data["pda_count"] = count + + if(mode==21) + data["messagescount"] = tnote.len + data["messages"] = tnote + else + data["messagescount"] = null + data["messages"] = null + + if(active_conversation) + for(var/c in tnote) + if(c["target"] == active_conversation) + data["convo_name"] = sanitize(c["owner"]) + data["convo_job"] = sanitize(c["job"]) + break + if(mode==41) + data_core.get_manifest_json() + + + if(mode==3) + var/turf/T = get_turf(user.loc) + if(!isnull(T)) + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles + + if (total_moles) + var/o2_level = environment.gas["oxygen"] / total_moles + var/n2_level = environment.gas["nitrogen"] / total_moles + var/co2_level = environment.gas["carbon_dioxide"] / total_moles + var/phoron_level = environment.gas["phoron"] / total_moles + var/unknown_level = 1 - (o2_level + n2_level + co2_level + phoron_level) + data["aircontents"] = list( + "pressure" = "[round(pressure,0.1)]", + "nitrogen" = "[round(n2_level*100,0.1)]", + "oxygen" = "[round(o2_level*100,0.1)]", + "carbon_dioxide" = "[round(co2_level*100,0.1)]", + "phoron" = "[round(phoron_level*100,0.01)]", + "other" = "[round(unknown_level, 0.01)]", + "temp" = "[round(environment.temperature-T0C,0.1)]", + "reading" = 1 + ) + if(isnull(data["aircontents"])) + data["aircontents"] = list("reading" = 0) + + nanoUI = data + // update the ui if it exists, returns null if no ui is passed/found + if(ui) + ui.load_cached_data(ManifestJSON) + + 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, "pda.tmpl", title, 520, 400) + // when the ui is first opened this is the data it will use + + ui.load_cached_data(ManifestJSON) + + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + ui.set_auto_update(auto_update) + +//NOTE: graphic resources are loaded on client login +/obj/item/device/pda/attack_self(mob/user) + + user.set_machine(src) + + if(active_uplink_check(user)) + return + + ui_interact(user) //NanoUI requires this proc + return + +/obj/item/device/pda/Topic(href, href_list) + if(href_list["cartmenu"] && !isnull(cartridge)) + cartridge.Topic(href, href_list) + return 1 + if(href_list["radiomenu"] && !isnull(cartridge) && !isnull(cartridge.radio)) + cartridge.radio.Topic(href, href_list) + return 1 + + + ..() + var/mob/user = usr + var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") + 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 (usr.stat == DEAD) + return 0 + if(!can_use()) //Why reinvent the wheel? There's a proc that does exactly that. + U.unset_machine() + if(ui) + ui.close() + return 0 + + add_fingerprint(U) + U.set_machine(src) + + switch(href_list["choice"]) + +//BASIC FUNCTIONS=================================== + + if("Close")//Self explanatory + U.unset_machine() + ui.close() + return 0 + if("Refresh")//Refresh, goes to the end of the proc. + if("Return")//Return + if(mode<=9) + mode = 0 + else + mode = round(mode/10) + if(mode==2) + active_conversation = null + if(mode==4)//Fix for cartridges. Redirects to hub. + mode = 0 + else if(mode >= 40 && mode <= 49)//Fix for cartridges. Redirects to refresh the menu. + cartridge.mode = mode + if ("Authenticate")//Checks for ID + id_check(U, 1) + if("UpdateInfo") + ownjob = id.assignment + ownrank = id.rank + 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 + mode = 0 + 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 messages + mode = 21 + if("3")//Atmos scan + mode = 3 + if("4")//Redirects to hub + mode = 0 + if("chatroom") // chatroom hub + mode = 5 + if("41") //Manifest + mode = 41 + + +//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 + +//MESSENGER/NOTE FUNCTIONS=================================== + + if ("Edit") + var/n = sanitize(input(U, "Please enter message", name, input_default(notehtml)) as message, extra = FALSE) + if (in_range(src, U) && loc == U && mode == 1) + note = html_decode(n) + notehtml = note + note = replacetext(note, "\n", "
                    ") + else + ui.close() + if("Toggle Messenger") + toff = !toff + if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status + message_silent = !message_silent + if("Clear")//Clears messages + if(href_list["option"] == "All") + tnote.Cut() + conversations.Cut() + if(href_list["option"] == "Convo") + var/new_tnote[0] + for(var/i in tnote) + if(i["target"] != active_conversation) + new_tnote[++new_tnote.len] = i + tnote = new_tnote + conversations.Remove(active_conversation) + + active_conversation = null + if(mode==21) + mode=2 + + if("Ringtone") + var/t = sanitize(input(U, "Please enter new ringtone", name, input_default(ttone)) as text, 20) + if (t && in_range(src, U) && loc == U) + if(src.hidden_uplink && hidden_uplink.check_trigger(U, lowertext(t), lowertext(lock_code))) + to_chat(U, "The PDA softly beeps.") + ui.close() + else + ttone = t + else + ui.close() + return 0 + if("Message") + + var/obj/item/device/pda/P = locate(href_list["target"]) + src.create_message(U, P, !href_list["notap"]) + if(mode == 2) + if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp. + active_conversation = href_list["target"] + mode = 21 + + if("Select Conversation") + var/P = href_list["convo"] + for(var/n in conversations) + if(P == n) + active_conversation=P + mode=21 + 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.charges > 0) + cartridge.charges-- + U.show_message("\blue Virus sent!", 1) + P.honkamt = (rand(15,20)) + else + to_chat(U, "PDA not found.") + else + ui.close() + return 0 + 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.charges > 0) + cartridge.charges-- + U.show_message("\blue Virus sent!", 1) + P.message_silent = 1 + P.ttone = "silence" + else + to_chat(U, "PDA not found.") + else + ui.close() + return 0 + + +//SYNDICATE FUNCTIONS=================================== + + if("Toggle Door") + if(cartridge && cartridge.access_remote_door) + for(var/obj/machinery/door/poddoor/M in poddoor_list) + if(M.id == cartridge.remote_door_id) + if(M.density) + M.open() + else + M.close() + + if("Detonate")//Detonate PDA... maybe + // 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(src) + if(pos.z in signal.data["level"]) + useTC = 2 + + if(istype(cartridge, /obj/item/weapon/cartridge/syndicate)) + if(!(useMS && useTC)) + U.show_message("\red An error flashes on your [src]: Connection unavailable", 1) + return + if(useTC != 2) // Does our recepient have a broadcaster on their level? + U.show_message("\red An error flashes on your [src]: Recipient unavailable", 1) + return + var/obj/item/device/pda/P = locate(href_list["target"]) + if(!isnull(P)) + if (!P.toff && cartridge.charges > 0) + cartridge.charges-- + + var/difficulty = 2 + + 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 + if(P.hidden_uplink) + difficulty += 3 + + if(prob(difficulty)) + U.show_message("\red An error flashes on your [src].", 1) + else if (prob(difficulty * 7)) + U.show_message("\red Energy feeds back into your [src]!", 1) + ui.close() + detonate_act(src) + 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. (JMP)") + else + U.show_message("\blue Success!", 1) + log_admin("[key_name(U)] just attempted to blow up [P] with the Detomatix cartridge and succeeded") + message_admins("[key_name_admin(U)] just attempted to blow up [P] with the Detomatix cartridge and succeeded. (JMP)") + detonate_act(P) + else + to_chat(U, "No charges left.") + else + to_chat(U, "PDA not found.") + else + U.unset_machine() + ui.close() + return 0 + +//pAI FUNCTIONS=================================== + if("pai") + if(pai) + if(pai.loc != src) + pai = null + else + switch(href_list["option"]) + if("1") // Configure pAI device + pai.attack_self(U) + if("2") // Eject pAI device + var/turf/T = get_turf_or_move(src.loc) + if(T) + pai.loc = T + pai = null + + else + mode = text2num(href_list["choice"]) + if(cartridge) + cartridge.mode = mode + +//EXTRA FUNCTIONS=================================== + + if (mode == 2||mode == 21)//To clear message overlays. + newmessage = 0 + update_icon() + + if ((honkamt > 0) && (prob(60)))//For clown virus. + honkamt-- + playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) + + return 1 // return 1 tells it to refresh the UI in NanoUI + +/obj/item/device/pda/update_icon() + ..() + + overlays.Cut() + if(newmessage) + overlays += image('icons/obj/pda.dmi', "pda-r") + if(id) + var/id_overlay = get_id_overlay(id) + if(id_overlay) + overlays += image('icons/obj/pda.dmi', id_overlay) + +/obj/item/device/pda/proc/get_id_overlay(obj/item/weapon/card/id/I) + if(!I) + return + if(I.icon_state in ALLOWED_ID_OVERLAYS) + return I.icon_state + return "id" + +/obj/item/device/pda/proc/detonate_act(obj/item/device/pda/P) + //TODO: sometimes these attacks show up on the message server + var/i = rand(1,100) + var/j = rand(0,1) //Possibility of losing the PDA after the detonation + var/message = "" + var/mob/living/M = null + if(ismob(P.loc)) + M = P.loc + + //switch(i) //Yes, the overlapping cases are intended. + if(i<=10) //The traditional explosion + P.explode() + j=1 + message += "Your [P] suddenly explodes!" + if(i>=10 && i<= 20) //The PDA burns a hole in the holder. + j=1 + if(M && isliving(M)) + M.apply_damage( rand(30,60) , BURN) + message += "You feel a searing heat! Your [P] is burning!" + if(i>=20 && i<=25) //EMP + empulse(P.loc, 3, 6, 1) + message += "Your [P] emits a wave of electromagnetic energy!" + if(i>=25 && i<=40) //Smoke + var/datum/effect/effect/system/smoke_spread/S = new /datum/effect/effect/system/smoke_spread + S.attach(P.loc) + S.set_up(n = 10, c = 0, loca = P.loc, direct = 0) + playsound(P.loc, 'sound/effects/smoke.ogg', 50, 1, -3) + S.start() + message += "Large clouds of smoke billow forth from your [P]!" + if(i>=40 && i<=45) //Bad smoke + var/datum/effect/effect/system/smoke_spread/bad/B = new /datum/effect/effect/system/smoke_spread/bad + B.attach(P.loc) + B.set_up(n = 10, c = 0, loca = P.loc, direct = 0) + playsound(P.loc, 'sound/effects/smoke.ogg', 50, 1, -3) + B.start() + message += "Large clouds of noxious smoke billow forth from your [P]!" + if(i>=65 && i<=75) //Weaken + if(M && isliving(M)) + M.apply_effects(0,1) + message += "Your [P] flashes with a blinding white light! You feel weaker." + if(i>=75 && i<=85) //Stun and stutter + if(M && isliving(M)) + M.apply_effects(1,0,0,0,1) + message += "Your [P] flashes with a blinding white light! You feel weaker." + if(i>=85) //Sparks + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(n = 2, c = 1, loca = P.loc) + s.start() + message += "Your [P] begins to spark violently!" + if(i>45 && i<65 && prob(50)) //Nothing happens + message += "Your [P] bleeps loudly." + j = prob(10) + + if(j) //This kills the PDA + P.Destroy() + if(message) + message += "It melts in a puddle of plastic." + else + message += "Your [P] shatters in a thousand pieces!" + + if(M && isliving(M)) + message = "\red" + message + M.show_message(message, 1) + +/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(mob/living/U = usr, obj/item/device/pda/P, tap = 1) + if(tap) + U.visible_message("[U] taps on \his PDA's screen.") + U.last_target_click = world.time + var/t = sanitize(input(U, "Please enter message", name, null) as text) + t = replacetext(t, """, "\"") + + 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()) + 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 dependent 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 recipient have a broadcaster on their level? + to_chat(U, "ERROR: Cannot reach recipient.") + return + + useMS.send_pda_message("[P.owner]","[owner]","[t]") + tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]"))) + P.tnote.Add(list(list("sent" = 0, "owner" = "[owner]", "job" = "[ownjob]", "message" = "[t]", "target" = "\ref[src]"))) + for(var/mob/M in player_list) + if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) // src.client is so that ghosts don't have to listen to mice + if(isnewplayer(M)) + continue + M.show_message("PDA Message - [owner] -> [P.owner]: [t]") + + if(!conversations.Find("\ref[P]")) + conversations.Add("\ref[P]") + if(!P.conversations.Find("\ref[src]")) + P.conversations.Add("\ref[src]") + + 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 ai_list) + // Allows other AIs to intercept the message but the AI won't intercept their own message. + if(ai.pda != P && ai.pda != src) + ai.show_message("Intercepted message from [who]: [t]") + + nanomanager.update_user_uis(U, src) // Update the sending user's PDA UI so that they can see the new message + + if (!P.message_silent) + playsound(P.loc, 'sound/machines/twobeep.ogg', 50, 1) + for (var/mob/O in hearers(3, P.loc)) + if(!P.message_silent) O.show_message(text("[bicon(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) + to_chat(L, "[bicon(P)] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)") + nanomanager.update_user_uis(L, P) // Update the receiving user's PDA UI so that they can see the new message + + nanomanager.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message + + log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") + P.overlays.Cut() + P.overlays += image('icons/obj/pda.dmi', "pda-r") + P.newmessage = 1 + else + to_chat(U, "ERROR: Messaging server is not responding.") + +/obj/item/device/pda/verb/verb_reset_pda() + set category = "Object" + set name = "Reset PDA" + set src in usr + + if(issilicon(usr)) + return + + if(can_use(usr)) + mode = 0 + nanomanager.update_uis(src) + to_chat(usr, "You press the reset button on \the [src].") + else + to_chat(usr, "You cannot do this while restrained.") + +/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() + update_icon() + 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/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].") + playsound(src, 'sound/items/penclick.ogg', 20, 1, 1) + 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/proc/id_check(mob/user, choice)//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)) + user.drop_item() + I.loc = 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 + user.drop_item() + I.loc = src + id = I + user.put_in_hands(old_id) + update_icon() + return + +// access to status display signals +/obj/item/device/pda/attackby(obj/item/C, mob/user) + ..() + if(istype(C, /obj/item/weapon/cartridge) && !cartridge) + cartridge = C + user.drop_item() + cartridge.loc = src + to_chat(user, "You insert [cartridge] into [src].") + nanomanager.update_uis(src) // update all UIs attached to 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 + ownrank = idcard.rank + 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)) ) + id_check(user, 2) + to_chat(user, "You put the ID into \the [src]'s slot.") + 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) + user.drop_item() + C.loc = src + pai = C + to_chat(user, "You slot \the [C] into [src].") + nanomanager.update_uis(src) // update all UIs attached to src + 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 + user.drop_item() + C.loc = src + to_chat(user, "You slide \the [C] into \the [src].") + return + +/obj/item/device/pda/attack(mob/living/C, mob/living/user) + if (istype(C, /mob/living/carbon)) + switch(scanmode) + if(1) + + for (var/mob/O in viewers(C, null)) + O.show_message("\red [user] has analyzed [C]'s vitals!", 1) + + user.show_message("\blue Analyzing Results for [C]:") + user.show_message("\blue   Overall Status: [C.stat > 1 ? "dead" : "[C.health - C.halloss]% healthy"]", 1) + user.show_message("\blue   Damage Specifics: [C.getOxyLoss() > 50 ? "\red" : "\blue"][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "\red" : "\blue"][C.getToxLoss()]-[C.getFireLoss() > 50 ? "\red" : "\blue"][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "\red" : "\blue"][C.getBruteLoss()]", 1) + user.show_message("\blue   Key: Suffocation/Toxin/Burns/Brute", 1) + user.show_message("\blue   Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)", 1) + if(C.tod && (C.stat == DEAD || (C.status_flags & FAKEDEATH))) + user.show_message("\blue   Time of Death: [C.tod]") + if(istype(C, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = C + var/list/damaged = H.get_damaged_bodyparts(1, 1) + user.show_message("\blue Localized Damage, Brute/Burn:",1) + if(length(damaged)>0) + for(var/obj/item/organ/external/BP in damaged) + user.show_message(text("\blue   []: []\blue-[]",capitalize(BP.name),(BP.brute_dam > 0)?"\red [BP.brute_dam]":0,(BP.burn_dam > 0)?"\red [BP.burn_dam]":0),1) + else + user.show_message("\blue   Limbs are OK.",1) + + for(var/datum/disease/D in C.viruses) + if(!D.hidden[SCANNER]) + user.show_message(text("\red Warning: [D.form] Detected\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure]")) + + if(2) + if (!istype(C:dna, /datum/dna)) + to_chat(user, "\blue No fingerprints found on [C]") + else if(!istype(C, /mob/living/carbon/monkey)) + if(!isnull(C:gloves)) + to_chat(user, "\blue No fingerprints found on [C]") + else + to_chat(user, text("\blue [C]'s Fingerprints: [md5(C:dna.uni_identity)]")) + if ( !(C:blood_DNA) ) + to_chat(user, "\blue No blood found on [C]") + if(C:blood_DNA) + C:blood_DNA = null + else + to_chat(user, "\blue Blood found on [C]. Analysing...") + spawn(15) + for(var/blood in C:blood_DNA) + to_chat(user, "\blue Blood type: [C:blood_DNA[blood]]\nDNA: [blood]") + + if(4) + for (var/mob/O in viewers(C, null)) + O.show_message("\red [user] has analyzed [C]'s radiation levels!", 1) + + user.show_message("\blue Analyzing Results for [C]:") + if(C.radiation) + user.show_message("\green Radiation Level: \black [C.radiation]") + else + user.show_message("\blue No radiation detected.") + +/obj/item/device/pda/afterattack(atom/A, mob/user, proximity) + if(!proximity) return + switch(scanmode) + + if(3) + if(!isobj(A)) + return + if(!isnull(A.reagents)) + if(A.reagents.reagent_list.len > 0) + var/reagents_length = A.reagents.reagent_list.len + to_chat(user, "\blue [reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.") + for (var/re in A.reagents.reagent_list) + to_chat(user, "\blue   [re]") + else + to_chat(user, "\blue No active chemical agents found in [A].") + else + to_chat(user, "\blue No significant chemical agents found in [A].") + + if(5) + analyze_gases(A, user) + + if (!scanmode && istype(A, /obj/item/weapon/paper) && owner) + note = A:info + to_chat(user, "\blue Paper scanned.")//concept of scanning paper copyright brainoblivion 2009 + + +/obj/item/device/pda/proc/explode() //This needs tuning. //Sure did. + if(!src.detonate) return + var/turf/T = get_turf(src.loc) + if(T) + T.hotspot_expose(700,125) + explosion(T, 0, 0, 1, rand(1,2)) + return + +/obj/item/device/pda/clown/Crossed(mob/living/carbon/C) //Clown PDA is slippery. + if(istype(C)) + if (C.slip("the PDA", 4, 2) && ishuman(C) && src.cartridge.charges < 5) + cartridge.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 + +// 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) diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index e786933e67aa..82265b06b72d 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -1,606 +1,606 @@ -/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" - w_class = 1 - - var/obj/item/radio/integrated/radio = null - var/access_security = 0 - var/access_engine = 0 - var/access_atmos = 0 - var/access_medical = 0 - 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_detonate_pda = 0 - var/access_hydroponics = 0 - var/charges = 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/computer/monitor/powmonitor = null // Power Monitor - var/list/powermonitors = list() - var/message1 // used for status_displays - var/message2 - var/list/stored_data = list() - -/obj/item/weapon/cartridge/Destroy() - if(radio) - qdel(radio) - return ..() - -/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/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/security - name = "R.O.B.U.S.T. Cartridge" - icon_state = "cart-s" - access_security = 1 - -/obj/item/weapon/cartridge/security/atom_init() - . = ..() - 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 - - -/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 - charges = 5 - -/obj/item/weapon/cartridge/mime - name = "Gestur-O 1000" - icon_state = "cart-mi" - access_mime = 1 - 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/science - 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/atom_init() - . = ..() - 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/atom_init() - . = ..() - radio = new /obj/item/radio/integrated/mule(src) - -/obj/item/weapon/cartridge/head - name = "Easy-Record DELUXE" - icon_state = "cart-h" - access_status_display = 1 - -/obj/item/weapon/cartridge/hop - name = "HumanResources9001" - icon_state = "cart-h" - access_status_display = 1 - access_quartermaster = 1 - access_janitor = 1 - access_security = 1 - -/obj/item/weapon/cartridge/hop/atom_init() - . = ..() - 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_status_display = 1 - access_security = 1 - -/obj/item/weapon/cartridge/hos/atom_init() - . = ..() - radio = new /obj/item/radio/integrated/beepsky(src) - -/obj/item/weapon/cartridge/ce - name = "Power-On DELUXE" - icon_state = "cart-ce" - access_status_display = 1 - access_engine = 1 - access_atmos = 1 - -/obj/item/weapon/cartridge/cmo - name = "Med-U DELUXE" - icon_state = "cart-cmo" - 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_status_display = 1 - access_reagent_scanner = 1 - access_atmos = 1 - -/obj/item/weapon/cartridge/rd/atom_init() - . = ..() - 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_quartermaster = 1 - access_janitor = 1 - access_engine = 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 - access_detonate_pda = 1 - remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing. - charges = 4 - -/obj/item/weapon/cartridge/proc/post_status(command, data1, data2) - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) - if(!frequency) - return - - var/datum/signal/status_signal = new - 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 = null - if(istype(PDA.loc,/mob/living)) - user = PDA.loc - else if(PDA.fingerprintslast) - var/client/user_client = directory[PDA.fingerprintslast] - if(user_client && user_client.mob) - user = user_client.mob - - if(user) - log_admin("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") - message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2] [ADMIN_FLW(user)]") - else - var/turf/PDA_turf = get_turf(PDA) - log_admin("STATUS: UNKNOWN set status screen with [PDA]. Message: [data1] [data2]") - message_admins("STATUS: UNKNOWN set status screen with [PDA]. Message: [data1] [data2] [PDA.loc ? "[ADMIN_JMP(PDA_turf)]" : ""] ") - - if("alert") - status_signal.data["picture_state"] = data1 - - frequency.post_signal(src, status_signal) - - -/* - This generates the nano values of the cart menus. - Because we close the UI when we insert a new cart - we don't have to worry about null values on items - the user can't access. Well, unless they are href hacking. - But in that case their UI will just lock up. -*/ - - -/obj/item/weapon/cartridge/proc/create_NanoUI_values(mob/user) - var/values[0] - - /* Signaler (Mode: 40) */ - - - if(istype(radio,/obj/item/radio/integrated/signal) && (mode==40)) - var/obj/item/radio/integrated/signal/R = radio - values["signal_freq"] = format_frequency(R.frequency) - values["signal_code"] = R.code - - - /* Station Display (Mode: 42) */ - - if(mode==42) - values["message1"] = message1 ? message1 : "(none)" - values["message2"] = message2 ? message2 : "(none)" - - - - /* Power Monitor (Mode: 43 / 433) */ - if(mode==43) - var/pMonData[0] - for(var/obj/machinery/computer/monitor/pMon in computer_list) - if(!(pMon.stat & (NOPOWER|BROKEN)) ) - pMonData[++pMonData.len] = list ("Name" = pMon.name, "ref" = "\ref[pMon]") - if(isnull(powmonitor)) - powmonitor = pMon - - values["powermonitors"] = pMonData - - if(mode==433) - if(powmonitor) - values["powermonitor_detected"] = TRUE - values["poweravail"] = powmonitor.powernet.avail - values["powerload"] = num2text(powmonitor.powernet.viewload,10) - - 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 - - var/list/Status = list("Off","AOff","On","AOn") // Status: off, auto-off, on, auto-on - var/list/chg = list("N","C","F") // Charging: nope, charging, full - var/apcData[0] - for(var/obj/machinery/power/apc/A in L) - apcData[++apcData.len] = list("Name" = html_encode(A.area.name), "Equipment" = Status[A.equipment+1], "Lights" = Status[A.lighting+1], "Environment" = Status[A.environ+1], "CellStatus" = A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : "N/C", "Load" = add_lspace(A.lastused_total, 6)) - - values["apcs"] = apcData - else - values["powermonitor_detected"] = FALSE - - - - - /* General Records (Mode: 44 / 441 / 45 / 451) */ - if(mode == 44 || mode == 441 || mode == 45 || mode ==451) - if(istype(active1, /datum/data/record) && (active1 in data_core.general)) - values["general"] = active1.fields - values["general_exists"] = 1 - - else - values["general_exists"] = 0 - - - - /* Medical Records (Mode: 44 / 441) */ - - if(mode == 44 || mode == 441) - var/medData[0] - for(var/datum/data/record/R in sortRecord(data_core.general)) - medData[++medData.len] = list(Name = R.fields["name"],"ref" = "\ref[R]") - values["medical_records"] = medData - - if(istype(active2, /datum/data/record) && (active2 in data_core.medical)) - values["medical"] = active2.fields - values["medical_exists"] = 1 - else - values["medical_exists"] = 0 - - /* Security Records (Mode:45 / 451) */ - - if(mode == 45 || mode == 451) - var/secData[0] - for (var/datum/data/record/R in sortRecord(data_core.general)) - secData[++secData.len] = list(Name = R.fields["name"], "ref" = "\ref[R]") - values["security_records"] = secData - - if(istype(active3, /datum/data/record) && (active3 in data_core.security)) - values["security"] = active3.fields - values["security_exists"] = 1 - else - values["security_exists"] = 0 - - /* Security Bot Control (Mode: 46) */ - - if(mode==46) - var/botsData[0] - var/beepskyData[0] - if(istype(radio,/obj/item/radio/integrated/beepsky)) - var/obj/item/radio/integrated/beepsky/SC = radio - beepskyData["active"] = SC.active - if(SC.active && !isnull(SC.botstatus)) - var/area/loca = SC.botstatus["loca"] - var/loca_name = sanitize(loca.name) - beepskyData["botstatus"] = list("loca" = loca_name, "mode" = SC.botstatus["mode"]) - else - beepskyData["botstatus"] = list("loca" = null, "mode" = -1) - var/botsCount=0 - if(SC.botlist && SC.botlist.len) - for(var/obj/machinery/bot/B in SC.botlist) - botsCount++ - if(B.loc) - botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]") - - if(!botsData.len) - botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - - beepskyData["bots"] = botsData - beepskyData["count"] = botsCount - - else - beepskyData["active"] = 0 - botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - beepskyData["botstatus"] = list("loca" = null, "mode" = null) - beepskyData["bots"] = botsData - beepskyData["count"] = 0 - - values["beepsky"] = beepskyData - - - /* MULEBOT Control (Mode: 48) */ - - if(mode==48) - var/muleData[0] - var/mulebotsData[0] - if(istype(radio,/obj/item/radio/integrated/mule)) - var/obj/item/radio/integrated/mule/QC = radio - muleData["active"] = QC.active - if(QC.active && !isnull(QC.botstatus)) - var/area/loca = QC.botstatus["loca"] - var/loca_name = sanitize(loca.name) - muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"])) - - else - muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) - - - var/mulebotsCount=0 - for(var/obj/machinery/bot/B in QC.botlist) - mulebotsCount++ - if(B.loc) - mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]") - - if(!mulebotsData.len) - mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - - muleData["bots"] = mulebotsData - muleData["count"] = mulebotsCount - - else - muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) - muleData["active"] = 0 - mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - muleData["bots"] = mulebotsData - muleData["count"] = 0 - - values["mulebot"] = muleData - - - - /* Supply Shuttle Requests Menu (Mode: 47) */ - - if(mode==47) - var/supplyData[0] - supplyData["shuttle_moving"] = SSshuttle.moving - supplyData["shuttle_eta"] = SSshuttle.eta - supplyData["shuttle_loc"] = SSshuttle.at_station ? "Station" : "Dock" - var/supplyOrderCount = 0 - var/supplyOrderData[0] - for(var/S in SSshuttle.shoppinglist) - var/datum/supply_order/SO = S - - supplyOrderData[++supplyOrderData.len] = list("Number" = SO.id, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.orderer, "Comment" = html_encode(SO.reason)) - if(!supplyOrderData.len) - supplyOrderData[++supplyOrderData.len] = list("Number" = null, "Name" = null, "OrderedBy"=null) - - supplyData["approved"] = supplyOrderData - supplyData["approved_count"] = supplyOrderCount - - var/requestCount = 0 - var/requestData[0] - for(var/S in SSshuttle.requestlist) - var/datum/supply_order/SO = S - requestCount++ - requestData[++requestData.len] = list("Number" = SO.id, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.orderer, "Comment" = html_encode(SO.reason)) - if(!requestData.len) - requestData[++requestData.len] = list("Number" = null, "Name" = null, "orderedBy" = null, "Comment" = null) - - supplyData["requests"] = requestData - supplyData["requests_count"] = requestCount - - - values["supply"] = supplyData - - - - /* Janitor Supplies Locator (Mode: 49) */ - if(mode==49) - var/JaniData[0] - var/turf/cl = get_turf(src) - - if(cl) - JaniData["user_loc"] = list("x" = cl.x, "y" = cl.y) - else - JaniData["user_loc"] = list("x" = 0, "y" = 0) - var/MopData[0] - for(var/obj/item/weapon/mop/M in mop_list) - var/turf/ml = get_turf(M) - if(ml) - if(ml.z != cl.z) - continue - var/direction = get_dir(src, M) - MopData[++MopData.len] = list ("x" = ml.x, "y" = ml.y, "dir" = uppertext(dir2text(direction)), "status" = M.reagents.total_volume ? "Wet" : "Dry") - - if(!MopData.len) - MopData[++MopData.len] = list("x" = 0, "y" = 0, dir=null, status = null) - - - var/BucketData[0] - for(var/obj/structure/mopbucket/B in mopbucket_list) - var/turf/bl = get_turf(B) - if(bl) - if(bl.z != cl.z) - continue - var/direction = get_dir(src,B) - BucketData[++BucketData.len] = list ("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100) - - if(!BucketData.len) - BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null) - - var/CbotData[0] - for(var/obj/machinery/bot/cleanbot/B in bots_list) - var/turf/bl = get_turf(B) - if(bl) - if(bl.z != cl.z) - continue - var/direction = get_dir(src,B) - CbotData[++CbotData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.on ? "Online" : "Offline") - - - if(!CbotData.len) - CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null) - var/CartData[0] - for(var/obj/structure/janitorialcart/B in janitorialcart_list) - var/turf/bl = get_turf(B) - if(bl) - if(bl.z != cl.z) - continue - var/direction = get_dir(src,B) - CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100) - if(!CartData.len) - CartData[++CartData.len] = list("x" = 0, "y" = 0, dir=null, status = null) - - - - - JaniData["mops"] = MopData - JaniData["buckets"] = BucketData - JaniData["cleanbots"] = CbotData - JaniData["carts"] = CartData - values["janitor"] = JaniData - - return values - - - - - -/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 = sanitize_safe(input("Line 1", "Enter Message Text", message1) as text|null, MAX_LNAME_LEN) - updateSelfDialog() - if("setmsg2") - message2 = sanitize_safe(input("Line 2", "Enter Message Text", message2) as text|null, MAX_LNAME_LEN) - updateSelfDialog() - else - post_status(href_list["statdisp"]) - if("Power Select") - var/pref = href_list["target"] - powmonitor = locate(pref) - loc:mode = 433 - mode = 433 - - return 1 +/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" + w_class = 1 + + var/obj/item/radio/integrated/radio = null + var/access_security = 0 + var/access_engine = 0 + var/access_atmos = 0 + var/access_medical = 0 + 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_detonate_pda = 0 + var/access_hydroponics = 0 + var/charges = 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/computer/monitor/powmonitor = null // Power Monitor + var/list/powermonitors = list() + var/message1 // used for status_displays + var/message2 + var/list/stored_data = list() + +/obj/item/weapon/cartridge/Destroy() + if(radio) + qdel(radio) + return ..() + +/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/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/security + name = "R.O.B.U.S.T. Cartridge" + icon_state = "cart-s" + access_security = 1 + +/obj/item/weapon/cartridge/security/atom_init() + . = ..() + 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 + + +/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 + charges = 5 + +/obj/item/weapon/cartridge/mime + name = "Gestur-O 1000" + icon_state = "cart-mi" + access_mime = 1 + 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/science + 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/atom_init() + . = ..() + 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/atom_init() + . = ..() + radio = new /obj/item/radio/integrated/mule(src) + +/obj/item/weapon/cartridge/head + name = "Easy-Record DELUXE" + icon_state = "cart-h" + access_status_display = 1 + +/obj/item/weapon/cartridge/hop + name = "HumanResources9001" + icon_state = "cart-h" + access_status_display = 1 + access_quartermaster = 1 + access_janitor = 1 + access_security = 1 + +/obj/item/weapon/cartridge/hop/atom_init() + . = ..() + 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_status_display = 1 + access_security = 1 + +/obj/item/weapon/cartridge/hos/atom_init() + . = ..() + radio = new /obj/item/radio/integrated/beepsky(src) + +/obj/item/weapon/cartridge/ce + name = "Power-On DELUXE" + icon_state = "cart-ce" + access_status_display = 1 + access_engine = 1 + access_atmos = 1 + +/obj/item/weapon/cartridge/cmo + name = "Med-U DELUXE" + icon_state = "cart-cmo" + 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_status_display = 1 + access_reagent_scanner = 1 + access_atmos = 1 + +/obj/item/weapon/cartridge/rd/atom_init() + . = ..() + 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_quartermaster = 1 + access_janitor = 1 + access_engine = 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 + access_detonate_pda = 1 + remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing. + charges = 4 + +/obj/item/weapon/cartridge/proc/post_status(command, data1, data2) + + var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) + if(!frequency) + return + + var/datum/signal/status_signal = new + 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 = null + if(istype(PDA.loc,/mob/living)) + user = PDA.loc + else if(PDA.fingerprintslast) + var/client/user_client = directory[PDA.fingerprintslast] + if(user_client && user_client.mob) + user = user_client.mob + + if(user) + log_admin("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") + message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2] [ADMIN_FLW(user)]") + else + var/turf/PDA_turf = get_turf(PDA) + log_admin("STATUS: UNKNOWN set status screen with [PDA]. Message: [data1] [data2]") + message_admins("STATUS: UNKNOWN set status screen with [PDA]. Message: [data1] [data2] [PDA.loc ? "[ADMIN_JMP(PDA_turf)]" : ""] ") + + if("alert") + status_signal.data["picture_state"] = data1 + + frequency.post_signal(src, status_signal) + + +/* + This generates the nano values of the cart menus. + Because we close the UI when we insert a new cart + we don't have to worry about null values on items + the user can't access. Well, unless they are href hacking. + But in that case their UI will just lock up. +*/ + + +/obj/item/weapon/cartridge/proc/create_NanoUI_values(mob/user) + var/values[0] + + /* Signaler (Mode: 40) */ + + + if(istype(radio,/obj/item/radio/integrated/signal) && (mode==40)) + var/obj/item/radio/integrated/signal/R = radio + values["signal_freq"] = format_frequency(R.frequency) + values["signal_code"] = R.code + + + /* Station Display (Mode: 42) */ + + if(mode==42) + values["message1"] = message1 ? message1 : "(none)" + values["message2"] = message2 ? message2 : "(none)" + + + + /* Power Monitor (Mode: 43 / 433) */ + if(mode==43) + var/pMonData[0] + for(var/obj/machinery/computer/monitor/pMon in computer_list) + if(!(pMon.stat & (NOPOWER|BROKEN)) ) + pMonData[++pMonData.len] = list ("Name" = pMon.name, "ref" = "\ref[pMon]") + if(isnull(powmonitor)) + powmonitor = pMon + + values["powermonitors"] = pMonData + + if(mode==433) + if(powmonitor) + values["powermonitor_detected"] = TRUE + values["poweravail"] = powmonitor.powernet.avail + values["powerload"] = num2text(powmonitor.powernet.viewload,10) + + 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 + + var/list/Status = list("Off","AOff","On","AOn") // Status: off, auto-off, on, auto-on + var/list/chg = list("N","C","F") // Charging: nope, charging, full + var/apcData[0] + for(var/obj/machinery/power/apc/A in L) + apcData[++apcData.len] = list("Name" = html_encode(A.area.name), "Equipment" = Status[A.equipment+1], "Lights" = Status[A.lighting+1], "Environment" = Status[A.environ+1], "CellStatus" = A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : "N/C", "Load" = add_lspace(A.lastused_total, 6)) + + values["apcs"] = apcData + else + values["powermonitor_detected"] = FALSE + + + + + /* General Records (Mode: 44 / 441 / 45 / 451) */ + if(mode == 44 || mode == 441 || mode == 45 || mode ==451) + if(istype(active1, /datum/data/record) && (active1 in data_core.general)) + values["general"] = active1.fields + values["general_exists"] = 1 + + else + values["general_exists"] = 0 + + + + /* Medical Records (Mode: 44 / 441) */ + + if(mode == 44 || mode == 441) + var/medData[0] + for(var/datum/data/record/R in sortRecord(data_core.general)) + medData[++medData.len] = list(Name = R.fields["name"],"ref" = "\ref[R]") + values["medical_records"] = medData + + if(istype(active2, /datum/data/record) && (active2 in data_core.medical)) + values["medical"] = active2.fields + values["medical_exists"] = 1 + else + values["medical_exists"] = 0 + + /* Security Records (Mode:45 / 451) */ + + if(mode == 45 || mode == 451) + var/secData[0] + for (var/datum/data/record/R in sortRecord(data_core.general)) + secData[++secData.len] = list(Name = R.fields["name"], "ref" = "\ref[R]") + values["security_records"] = secData + + if(istype(active3, /datum/data/record) && (active3 in data_core.security)) + values["security"] = active3.fields + values["security_exists"] = 1 + else + values["security_exists"] = 0 + + /* Security Bot Control (Mode: 46) */ + + if(mode==46) + var/botsData[0] + var/beepskyData[0] + if(istype(radio,/obj/item/radio/integrated/beepsky)) + var/obj/item/radio/integrated/beepsky/SC = radio + beepskyData["active"] = SC.active + if(SC.active && !isnull(SC.botstatus)) + var/area/loca = SC.botstatus["loca"] + var/loca_name = sanitize(loca.name) + beepskyData["botstatus"] = list("loca" = loca_name, "mode" = SC.botstatus["mode"]) + else + beepskyData["botstatus"] = list("loca" = null, "mode" = -1) + var/botsCount=0 + if(SC.botlist && SC.botlist.len) + for(var/obj/machinery/bot/B in SC.botlist) + botsCount++ + if(B.loc) + botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]") + + if(!botsData.len) + botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) + + beepskyData["bots"] = botsData + beepskyData["count"] = botsCount + + else + beepskyData["active"] = 0 + botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) + beepskyData["botstatus"] = list("loca" = null, "mode" = null) + beepskyData["bots"] = botsData + beepskyData["count"] = 0 + + values["beepsky"] = beepskyData + + + /* MULEBOT Control (Mode: 48) */ + + if(mode==48) + var/muleData[0] + var/mulebotsData[0] + if(istype(radio,/obj/item/radio/integrated/mule)) + var/obj/item/radio/integrated/mule/QC = radio + muleData["active"] = QC.active + if(QC.active && !isnull(QC.botstatus)) + var/area/loca = QC.botstatus["loca"] + var/loca_name = sanitize(loca.name) + muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"])) + + else + muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) + + + var/mulebotsCount=0 + for(var/obj/machinery/bot/B in QC.botlist) + mulebotsCount++ + if(B.loc) + mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]") + + if(!mulebotsData.len) + mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) + + muleData["bots"] = mulebotsData + muleData["count"] = mulebotsCount + + else + muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) + muleData["active"] = 0 + mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) + muleData["bots"] = mulebotsData + muleData["count"] = 0 + + values["mulebot"] = muleData + + + + /* Supply Shuttle Requests Menu (Mode: 47) */ + + if(mode==47) + var/supplyData[0] + supplyData["shuttle_moving"] = SSshuttle.moving + supplyData["shuttle_eta"] = SSshuttle.eta + supplyData["shuttle_loc"] = SSshuttle.at_station ? "Station" : "Dock" + var/supplyOrderCount = 0 + var/supplyOrderData[0] + for(var/S in SSshuttle.shoppinglist) + var/datum/supply_order/SO = S + + supplyOrderData[++supplyOrderData.len] = list("Number" = SO.id, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.orderer, "Comment" = html_encode(SO.reason)) + if(!supplyOrderData.len) + supplyOrderData[++supplyOrderData.len] = list("Number" = null, "Name" = null, "OrderedBy"=null) + + supplyData["approved"] = supplyOrderData + supplyData["approved_count"] = supplyOrderCount + + var/requestCount = 0 + var/requestData[0] + for(var/S in SSshuttle.requestlist) + var/datum/supply_order/SO = S + requestCount++ + requestData[++requestData.len] = list("Number" = SO.id, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.orderer, "Comment" = html_encode(SO.reason)) + if(!requestData.len) + requestData[++requestData.len] = list("Number" = null, "Name" = null, "orderedBy" = null, "Comment" = null) + + supplyData["requests"] = requestData + supplyData["requests_count"] = requestCount + + + values["supply"] = supplyData + + + + /* Janitor Supplies Locator (Mode: 49) */ + if(mode==49) + var/JaniData[0] + var/turf/cl = get_turf(src) + + if(cl) + JaniData["user_loc"] = list("x" = cl.x, "y" = cl.y) + else + JaniData["user_loc"] = list("x" = 0, "y" = 0) + var/MopData[0] + for(var/obj/item/weapon/mop/M in mop_list) + var/turf/ml = get_turf(M) + if(ml) + if(ml.z != cl.z) + continue + var/direction = get_dir(src, M) + MopData[++MopData.len] = list ("x" = ml.x, "y" = ml.y, "dir" = uppertext(dir2text(direction)), "status" = M.reagents.total_volume ? "Wet" : "Dry") + + if(!MopData.len) + MopData[++MopData.len] = list("x" = 0, "y" = 0, dir=null, status = null) + + + var/BucketData[0] + for(var/obj/structure/mopbucket/B in mopbucket_list) + var/turf/bl = get_turf(B) + if(bl) + if(bl.z != cl.z) + continue + var/direction = get_dir(src,B) + BucketData[++BucketData.len] = list ("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100) + + if(!BucketData.len) + BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null) + + var/CbotData[0] + for(var/obj/machinery/bot/cleanbot/B in bots_list) + var/turf/bl = get_turf(B) + if(bl) + if(bl.z != cl.z) + continue + var/direction = get_dir(src,B) + CbotData[++CbotData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.on ? "Online" : "Offline") + + + if(!CbotData.len) + CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null) + var/CartData[0] + for(var/obj/structure/janitorialcart/B in janitorialcart_list) + var/turf/bl = get_turf(B) + if(bl) + if(bl.z != cl.z) + continue + var/direction = get_dir(src,B) + CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100) + if(!CartData.len) + CartData[++CartData.len] = list("x" = 0, "y" = 0, dir=null, status = null) + + + + + JaniData["mops"] = MopData + JaniData["buckets"] = BucketData + JaniData["cleanbots"] = CbotData + JaniData["carts"] = CartData + values["janitor"] = JaniData + + return values + + + + + +/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 = sanitize_safe(input("Line 1", "Enter Message Text", message1) as text|null, MAX_LNAME_LEN) + updateSelfDialog() + if("setmsg2") + message2 = sanitize_safe(input("Line 2", "Enter Message Text", message2) as text|null, MAX_LNAME_LEN) + updateSelfDialog() + else + post_status(href_list["statdisp"]) + if("Power Select") + var/pref = href_list["target"] + powmonitor = locate(pref) + loc:mode = 433 + mode = 433 + + return 1 diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm index ee258d086822..a14eda382ad1 100644 --- a/code/game/objects/items/devices/PDA/radio.dm +++ b/code/game/objects/items/devices/PDA/radio.dm @@ -1,259 +1,259 @@ -/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/atom_init() - . = ..() - if (istype(loc.loc, /obj/item/device/pda)) - hostpda = loc.loc - -/obj/item/radio/integrated/proc/post_signal(freq, key, value, key2, value2, key3, value3, s_filter) - - //world << "Post: [freq]: [key]=[value], [key2]=[value2]" - var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) - - if(!frequency) return - - var/datum/signal/signal = new() - 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) - - 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/atom_init() - . = ..() - radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) - - // 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) - 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) - -/obj/item/radio/integrated/beepsky/Destroy() - if(radio_controller) - radio_controller.remove_object(src, control_freq) - return ..() - -/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/atom_init() - ..() - radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) - radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) - return INITIALIZE_HINT_LATELOAD - -/obj/item/radio/integrated/mule/atom_init_late() // if this even necessary - 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) - return ..() - - // 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) - 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/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) - - - -/* - * 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/atom_init() - . = ..() - 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]") - message_admins("[key_name_admin(usr)] used [src], location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code] (JMP)") - log_game("[usr.ckey]([usr]) used [src], location ([T.x],[T.y],[T.z]),frequency: [format_frequency(frequency)], code:[code]") - - var/datum/signal/signal = new - signal.source = src - signal.encryption = code - signal.data["message"] = message - - radio_connection.post_signal(src, signal) - - return - -/obj/item/radio/integrated/signal/Destroy() - if(radio_controller) - radio_controller.remove_object(src, frequency) - return ..() +/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/atom_init() + . = ..() + if (istype(loc.loc, /obj/item/device/pda)) + hostpda = loc.loc + +/obj/item/radio/integrated/proc/post_signal(freq, key, value, key2, value2, key3, value3, s_filter) + + //world << "Post: [freq]: [key]=[value], [key2]=[value2]" + var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq) + + if(!frequency) return + + var/datum/signal/signal = new() + 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) + + 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/atom_init() + . = ..() + radio_controller.add_object(src, control_freq, filter = RADIO_SECBOT) + + // 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) + 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) + +/obj/item/radio/integrated/beepsky/Destroy() + if(radio_controller) + radio_controller.remove_object(src, control_freq) + return ..() + +/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/atom_init() + ..() + radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT) + radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS) + return INITIALIZE_HINT_LATELOAD + +/obj/item/radio/integrated/mule/atom_init_late() // if this even necessary + 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) + return ..() + + // 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) + 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/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) + + + +/* + * 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/atom_init() + . = ..() + 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]") + message_admins("[key_name_admin(usr)] used [src], location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code] (JMP)") + log_game("[usr.ckey]([usr]) used [src], location ([T.x],[T.y],[T.z]),frequency: [format_frequency(frequency)], code:[code]") + + var/datum/signal/signal = new + signal.source = src + signal.encryption = code + signal.data["message"] = message + + radio_connection.post_signal(src, signal) + + return + +/obj/item/radio/integrated/signal/Destroy() + if(radio_controller) + radio_controller.remove_object(src, frequency) + return ..() diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 79534b440a3b..de41064d456b 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -1,135 +1,135 @@ -/obj/item/device/aicard - name = "inteliCard" - icon = 'icons/obj/pda.dmi' - icon_state = "aicard" // aicard-full - item_state = "electronic" - w_class = 2.0 - slot_flags = SLOT_BELT - var/flush = null - origin_tech = "programming=4;materials=4" - - - attack(mob/living/silicon/ai/M, mob/user) - 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])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to card [M.name] ([M.ckey]) (JMP)") - - transfer_ai("AICORE", "AICARD", M, user) - return - - attack(mob/living/silicon/decoy/M, mob/user) - if (!istype (M, /mob/living/silicon/decoy)) - return ..() - else - M.death() - to_chat(user, "ERROR ERROR ERROR") - - 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.health+100)/2]%
                    " - - 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 == DEAD) - 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 += "Subspace Transceiver is: [A.aiRadio.disabledAi ? "Disabled" : "Enabled"]" - dat += "
                    " - dat += {"[A.aiRadio.disabledAi ? "Enable" : "Disable"] Subspace Transceiver"} - dat += "
                    " - dat += {" Close"} - user << browse(entity_ja(dat), "window=aicard") - onclose(user, "aicard") - return - - Topic(href, href_list) - var/mob/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 ("Radio") - for(var/mob/living/silicon/ai/A in src) - A.aiRadio.disabledAi = !A.aiRadio.disabledAi - to_chat(A, "Your Subspace Transceiver has been: [A.aiRadio.disabledAi ? "disabled" : "enabled"]") - to_chat(U, "You [A.aiRadio.disabledAi ? "Disable" : "Enable"] the AI's Subspace Transceiver") - - 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!") - while (A.stat != DEAD) - 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 + name = "inteliCard" + icon = 'icons/obj/pda.dmi' + icon_state = "aicard" // aicard-full + item_state = "electronic" + w_class = 2.0 + slot_flags = SLOT_BELT + var/flush = null + origin_tech = "programming=4;materials=4" + + + attack(mob/living/silicon/ai/M, mob/user) + 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])") + msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to card [M.name] ([M.ckey]) (JMP)") + + transfer_ai("AICORE", "AICARD", M, user) + return + + attack(mob/living/silicon/decoy/M, mob/user) + if (!istype (M, /mob/living/silicon/decoy)) + return ..() + else + M.death() + to_chat(user, "ERROR ERROR ERROR") + + 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.health+100)/2]%
                    " + + 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 == DEAD) + 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 += "Subspace Transceiver is: [A.aiRadio.disabledAi ? "Disabled" : "Enabled"]" + dat += "
                    " + dat += {"[A.aiRadio.disabledAi ? "Enable" : "Disable"] Subspace Transceiver"} + dat += "
                    " + dat += {" Close"} + user << browse(entity_ja(dat), "window=aicard") + onclose(user, "aicard") + return + + Topic(href, href_list) + var/mob/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 ("Radio") + for(var/mob/living/silicon/ai/A in src) + A.aiRadio.disabledAi = !A.aiRadio.disabledAi + to_chat(A, "Your Subspace Transceiver has been: [A.aiRadio.disabledAi ? "disabled" : "enabled"]") + to_chat(U, "You [A.aiRadio.disabledAi ? "Disable" : "Enable"] the AI's Subspace Transceiver") + + 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!") + while (A.stat != DEAD) + 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) + + + + + diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index 81b53563ff60..cad056dd96df 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -1,178 +1,178 @@ -/obj/item/device/chameleon - name = "chameleon-projector" - icon_state = "shield0" - flags = CONDUCT - slot_flags = SLOT_BELT - item_state = "electronic" - throwforce = 5 - throw_speed = 1 - throw_range = 5 - w_class = 2 - origin_tech = "syndicate=4;magnets=4" - var/can_use = TRUE - var/toggled = FALSE - var/obj/effect/dummy/chameleon/active_dummy = null - -/obj/item/device/chameleon/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/item/device/chameleon/atom_init_late() - active_dummy = new - active_dummy.master = src - init_disguise() - -/obj/item/device/chameleon/Destroy() - if(active_dummy) - active_dummy.master = null - qdel(active_dummy) - active_dummy = null - return ..() - -/obj/item/device/chameleon/proc/init_disguise() - var/list/possible_disguise = list( - /obj/item/weapon/cigbutt, - /obj/item/trash/chips, - /obj/item/trash/candy, - /obj/item/trash/popcorn, - /obj/item/weapon/caution/cone - ) - var/random_type = pick(possible_disguise) - var/obj/O = new random_type(src) - copy_item(O) - qdel(O) - -/obj/item/device/chameleon/dropped() - disrupt() - -/obj/item/device/chameleon/equipped() - disrupt() - -/obj/item/device/chameleon/attack_self() - toggle() - -/obj/item/device/chameleon/afterattack(atom/target, mob/user, proximity) - if(!proximity) - return - if(!active_dummy) - active_dummy = new - if(active_dummy.current_type != target.type) - if(istype(target,/obj/item) && !istype(target, /obj/item/weapon/disk/nuclear)) - playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1, -6) - to_chat(user, "\The [target] scanned.") - copy_item(target) - else - to_chat(user, "\The [target] already scanned.") - -/obj/item/device/chameleon/proc/copy_item(obj/O) - var/obj/effect/dummy/chameleon/C = active_dummy - C.name = O.name - C.desc = O.desc - C.appearance = O.appearance - C.dir = O.dir - C.current_type = O.type - C.layer = initial(O.layer) // scanning things in your inventory - C.plane = initial(O.plane) - -/obj/item/device/chameleon/proc/toggle() - if(!can_use || !active_dummy) - return - - if(toggled) - deactivate() - else - activate(usr) - - play_transform_effect() - to_chat(usr, "You [toggled ? "activate" : "deactivate"] the [src].") - -/obj/item/device/chameleon/proc/play_transform_effect() - playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) - 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) - -/obj/item/device/chameleon/proc/activate(mob/M) - var/obj/effect/dummy/chameleon/C = active_dummy - C.loc = M.loc - M.forceMove(C) - toggled = TRUE - -/obj/item/device/chameleon/proc/deactivate() - var/obj/effect/dummy/chameleon/C = active_dummy - for(var/atom/movable/A in C) - A.loc = C.loc - if(ismob(A)) - var/mob/M = A - M.reset_view(null) - C.loc = master - toggled = FALSE - -/obj/item/device/chameleon/proc/disrupt() - if(toggled) - for(var/mob/M in active_dummy) - to_chat(M, "Your chameleon-projector deactivates.") - deactivate() - 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() - can_use = FALSE - spawn(50) - can_use = TRUE - - -/obj/effect/dummy/chameleon - name = "" - desc = "" - density = FALSE - anchored = TRUE - var/can_move = TRUE - var/current_type = null - var/obj/item/device/chameleon/master = null - -/obj/effect/dummy/chameleon/Destroy() - if(master) - master.disrupt() - master.active_dummy = null - master = null - return ..() - -/obj/effect/dummy/chameleon/attackby() - master.disrupt() - -/obj/effect/dummy/chameleon/attack_hand() - master.disrupt() - -/obj/effect/dummy/chameleon/ex_act() - master.disrupt() - -/obj/effect/dummy/chameleon/emp_act() - master.disrupt() - -/obj/effect/dummy/chameleon/bullet_act() - master.disrupt() - -/obj/effect/dummy/chameleon/relaymove(mob/user, direction) - - // We can't move when we are in space or inside of an object. - if(istype(loc, /turf/space) || !isturf(loc)) - return - - if(can_move) - can_move = FALSE - switch(user.bodytemperature) - if(300 to INFINITY) - spawn(10) can_move = TRUE - if(295 to 300) - spawn(13) can_move = TRUE - if(280 to 295) - spawn(16) can_move = TRUE - if(260 to 280) - spawn(20) can_move = TRUE - else - spawn(25) can_move = TRUE - step(src, direction) - return +/obj/item/device/chameleon + name = "chameleon-projector" + icon_state = "shield0" + flags = CONDUCT + slot_flags = SLOT_BELT + item_state = "electronic" + throwforce = 5 + throw_speed = 1 + throw_range = 5 + w_class = 2 + origin_tech = "syndicate=4;magnets=4" + var/can_use = TRUE + var/toggled = FALSE + var/obj/effect/dummy/chameleon/active_dummy = null + +/obj/item/device/chameleon/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/item/device/chameleon/atom_init_late() + active_dummy = new + active_dummy.master = src + init_disguise() + +/obj/item/device/chameleon/Destroy() + if(active_dummy) + active_dummy.master = null + qdel(active_dummy) + active_dummy = null + return ..() + +/obj/item/device/chameleon/proc/init_disguise() + var/list/possible_disguise = list( + /obj/item/weapon/cigbutt, + /obj/item/trash/chips, + /obj/item/trash/candy, + /obj/item/trash/popcorn, + /obj/item/weapon/caution/cone + ) + var/random_type = pick(possible_disguise) + var/obj/O = new random_type(src) + copy_item(O) + qdel(O) + +/obj/item/device/chameleon/dropped() + disrupt() + +/obj/item/device/chameleon/equipped() + disrupt() + +/obj/item/device/chameleon/attack_self() + toggle() + +/obj/item/device/chameleon/afterattack(atom/target, mob/user, proximity) + if(!proximity) + return + if(!active_dummy) + active_dummy = new + if(active_dummy.current_type != target.type) + if(istype(target,/obj/item) && !istype(target, /obj/item/weapon/disk/nuclear)) + playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1, -6) + to_chat(user, "\The [target] scanned.") + copy_item(target) + else + to_chat(user, "\The [target] already scanned.") + +/obj/item/device/chameleon/proc/copy_item(obj/O) + var/obj/effect/dummy/chameleon/C = active_dummy + C.name = O.name + C.desc = O.desc + C.appearance = O.appearance + C.dir = O.dir + C.current_type = O.type + C.layer = initial(O.layer) // scanning things in your inventory + C.plane = initial(O.plane) + +/obj/item/device/chameleon/proc/toggle() + if(!can_use || !active_dummy) + return + + if(toggled) + deactivate() + else + activate(usr) + + play_transform_effect() + to_chat(usr, "You [toggled ? "activate" : "deactivate"] the [src].") + +/obj/item/device/chameleon/proc/play_transform_effect() + playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6) + 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) + +/obj/item/device/chameleon/proc/activate(mob/M) + var/obj/effect/dummy/chameleon/C = active_dummy + C.loc = M.loc + M.forceMove(C) + toggled = TRUE + +/obj/item/device/chameleon/proc/deactivate() + var/obj/effect/dummy/chameleon/C = active_dummy + for(var/atom/movable/A in C) + A.loc = C.loc + if(ismob(A)) + var/mob/M = A + M.reset_view(null) + C.loc = master + toggled = FALSE + +/obj/item/device/chameleon/proc/disrupt() + if(toggled) + for(var/mob/M in active_dummy) + to_chat(M, "Your chameleon-projector deactivates.") + deactivate() + 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() + can_use = FALSE + spawn(50) + can_use = TRUE + + +/obj/effect/dummy/chameleon + name = "" + desc = "" + density = FALSE + anchored = TRUE + var/can_move = TRUE + var/current_type = null + var/obj/item/device/chameleon/master = null + +/obj/effect/dummy/chameleon/Destroy() + if(master) + master.disrupt() + master.active_dummy = null + master = null + return ..() + +/obj/effect/dummy/chameleon/attackby() + master.disrupt() + +/obj/effect/dummy/chameleon/attack_hand() + master.disrupt() + +/obj/effect/dummy/chameleon/ex_act() + master.disrupt() + +/obj/effect/dummy/chameleon/emp_act() + master.disrupt() + +/obj/effect/dummy/chameleon/bullet_act() + master.disrupt() + +/obj/effect/dummy/chameleon/relaymove(mob/user, direction) + + // We can't move when we are in space or inside of an object. + if(istype(loc, /turf/space) || !isturf(loc)) + return + + if(can_move) + can_move = FALSE + switch(user.bodytemperature) + if(300 to INFINITY) + spawn(10) can_move = TRUE + if(295 to 300) + spawn(13) can_move = TRUE + if(280 to 295) + spawn(16) can_move = TRUE + if(260 to 280) + spawn(20) can_move = TRUE + else + spawn(25) can_move = TRUE + step(src, direction) + return diff --git a/code/game/objects/items/devices/debugger.dm b/code/game/objects/items/devices/debugger.dm index 5852903ebcfd..134ed68cffaa 100644 --- a/code/game/objects/items/devices/debugger.dm +++ b/code/game/objects/items/devices/debugger.dm @@ -1,93 +1,93 @@ -/** - * 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" - icon_state = "hacktool-g" - desc = "You can use this on airlocks or APCs to try to hack them without cutting wires." - flags = CONDUCT - force = 5.0 - w_class = 2.0 - throwforce = 5.0 - throw_range = 15 - throw_speed = 3 - m_amt = 50 - g_amt = 20 - 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, "\red There is a software error with the device.") - return 0 - else - to_chat(user, "\blue The device's software appears to be fine.") - return 1 - else if(istype(O, /obj/machinery/door)) - var/obj/machinery/door/D = O - if(D.operating == -1) - to_chat(user, "\red There is a software error with the device.") - return 0 - else - to_chat(user, "\blue The device's software appears to be fine.") - return 1 - else if(istype(O, /obj/machinery)) - var/obj/machinery/A = O - if(A.emagged) - to_chat(user, "\red There is a software error with the device.") - return 0 - else - to_chat(user, "\blue The device's software appears to be fine.") - return 1 - -/obj/item/device/debugger/afterattack(obj/O, mob/user, proximity) - if(!proximity) return - if(user.is_busy()) return - if(istype(O, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/apc = O - if(apc.opened || apc.wiresexposed) - to_chat(user, "Error... Close that F$@^$#$ cover NOW!") - else if(apc.stat & (BROKEN|MAINT)) - to_chat(user, "Error... Device's maintenance protocols engaged...") - else - to_chat(user, "Hi there, please wait... Accessing device's software.") - if(do_after(user, 30, target = apc) && is_used_on(apc,user)) - to_chat(user, "My time has come, please wait... Starting HackHim3000...") - if(do_after(user, 20, target = apc)) - to_chat(user, "Faster than light, please wait... Hack in progress...") - if(do_after(user, 50, target = apc) && !(apc.emagged || apc.malfhack || apc.opened || apc.wiresexposed || apc.stat & (BROKEN|MAINT))) - flick("apc-spark", apc) - sleep(6) - apc.emagged = 1 - apc.locked = 0 - to_chat(user, "Happy?.. It is done.") - apc.update_icon() - else - to_chat(user, "Please... Do not interrupt hacking process.") - return - else if(istype(O, /obj/machinery/door)) - var/obj/machinery/door/D = O - if(!D.density) - to_chat(user, "Error... Close that F$@^$#$ door NOW!") - else - to_chat(user, "Hi there, please wait... Accessing door's software.") - if(do_after(user, 30, target = D) && is_used_on(D,user)) - to_chat(user, "My time has come, please wait... Starting HackHim3000...") - if(do_after(user, 20, target = D)) - to_chat(user, "Faster than light, please wait... Hack in progress...") - if(do_after(user, 100, target = D) && D.density && !(D.operating == -1)) - flick("door_spark", D) - sleep(6) - D.open() - D.operating = -1 - else - to_chat(user, "Please... Do not interrupt hacking process.") - return - else - ..() +/** + * 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" + icon_state = "hacktool-g" + desc = "You can use this on airlocks or APCs to try to hack them without cutting wires." + flags = CONDUCT + force = 5.0 + w_class = 2.0 + throwforce = 5.0 + throw_range = 15 + throw_speed = 3 + m_amt = 50 + g_amt = 20 + 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, "\red There is a software error with the device.") + return 0 + else + to_chat(user, "\blue The device's software appears to be fine.") + return 1 + else if(istype(O, /obj/machinery/door)) + var/obj/machinery/door/D = O + if(D.operating == -1) + to_chat(user, "\red There is a software error with the device.") + return 0 + else + to_chat(user, "\blue The device's software appears to be fine.") + return 1 + else if(istype(O, /obj/machinery)) + var/obj/machinery/A = O + if(A.emagged) + to_chat(user, "\red There is a software error with the device.") + return 0 + else + to_chat(user, "\blue The device's software appears to be fine.") + return 1 + +/obj/item/device/debugger/afterattack(obj/O, mob/user, proximity) + if(!proximity) return + if(user.is_busy()) return + if(istype(O, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/apc = O + if(apc.opened || apc.wiresexposed) + to_chat(user, "Error... Close that F$@^$#$ cover NOW!") + else if(apc.stat & (BROKEN|MAINT)) + to_chat(user, "Error... Device's maintenance protocols engaged...") + else + to_chat(user, "Hi there, please wait... Accessing device's software.") + if(do_after(user, 30, target = apc) && is_used_on(apc,user)) + to_chat(user, "My time has come, please wait... Starting HackHim3000...") + if(do_after(user, 20, target = apc)) + to_chat(user, "Faster than light, please wait... Hack in progress...") + if(do_after(user, 50, target = apc) && !(apc.emagged || apc.malfhack || apc.opened || apc.wiresexposed || apc.stat & (BROKEN|MAINT))) + flick("apc-spark", apc) + sleep(6) + apc.emagged = 1 + apc.locked = 0 + to_chat(user, "Happy?.. It is done.") + apc.update_icon() + else + to_chat(user, "Please... Do not interrupt hacking process.") + return + else if(istype(O, /obj/machinery/door)) + var/obj/machinery/door/D = O + if(!D.density) + to_chat(user, "Error... Close that F$@^$#$ door NOW!") + else + to_chat(user, "Hi there, please wait... Accessing door's software.") + if(do_after(user, 30, target = D) && is_used_on(D,user)) + to_chat(user, "My time has come, please wait... Starting HackHim3000...") + if(do_after(user, 20, target = D)) + to_chat(user, "Faster than light, please wait... Hack in progress...") + if(do_after(user, 100, target = D) && D.density && !(D.operating == -1)) + flick("door_spark", D) + sleep(6) + D.open() + D.operating = -1 + else + to_chat(user, "Please... Do not interrupt hacking process.") + return + else + ..() diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 73694f1dcab0..5238ae803d28 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -1,218 +1,218 @@ -/obj/item/device/flash - name = "flash" - desc = "Used for blinding and being an asshole." - icon_state = "flash" - item_state = "flashbang" //looks exactly like a flash (and nothing like a flashbang) - throwforce = 5 - w_class = 2.0 - throw_speed = 4 - throw_range = 10 - flags = CONDUCT - origin_tech = "magnets=2;combat=1" - - action_button_name = "Toggle Flash" - - 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(mob/user) - if(user && (CLUMSY in user.mutations) && prob(50)) - to_chat(user, "\red \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, mob/user) - if(!user || !M) return //sanity - - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return - - M.attack_log += text("\[[time_stamp()]\] Has been flashed (attempt) with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey]) (JMP)") - - 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 - to_chat(user, "The bulb has burnt out!") - icon_state = "flashburnt" - return - times_used++ - else //can only use it 5 times a minute - to_chat(user, "*click* *click*") - return - playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) - var/flashfail = 0 - - if(iscarbon(M)) - var/safety = M:eyecheck() - if(safety <= 0) - M.Weaken(10) - M.flash_eyes() - - if(ishuman(M) && ishuman(user) && M.stat!=DEAD) - - if(user.mind && (user.mind in ticker.mode.head_revolutionaries) && ticker.mode.name == "revolution") - if(M.client) - if(M.stat == CONSCIOUS) - M.mind_initialize() //give them a mind datum if they don't have one. - var/resisted - if(!ismindshielded(M) && !jobban_isbanned(M, ROLE_REV) && !jobban_isbanned(M, "Syndicate") && !role_available_in_minutes(M, ROLE_REV)) - if(user.mind in ticker.mode.head_revolutionaries) - M.mind.has_been_rev = 1 - if(!ticker.mode.add_revolutionary(M.mind)) - resisted = 1 - else - resisted = 1 - - if(resisted) - to_chat(user, "This mind seems resistant to the flash!") - else - flashfail = 1 - - else if(issilicon(M)) - //M.Weaken(rand(5,10)) - var/power = rand(7,13) - M.confused = min(M.confused + power, 20) - M.eye_blind = min(M.eye_blind + power, 20) - else - flashfail = 1 - - if(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) - - 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!") - - return - - - - -/obj/item/device/flash/attack_self(mob/living/carbon/user, flag = 0, emp = 0) - if(!user || !clown_check(user)) - return - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - 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(src.loc, 'sound/weapons/flash.ogg', 100, 1) - 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) - - for(var/mob/living/carbon/M in oviewers(3, null)) - var/safety = M:eyecheck() - if(!safety) - if(!M.blinded) - M.flash_eyes() - - 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)) - var/mob/living/carbon/M = loc - var/safety = M.eyecheck() - if(safety <= 0) - M.Weaken(10) - M.flash_eyes() - 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, mob/user) - ..() - if(!broken) - broken = 1 - to_chat(user, "\red The bulb has burnt out!") - icon_state = "flashburnt" - -/obj/item/device/flash/synthetic/attack_self(mob/living/carbon/user, flag = 0, emp = 0) - ..() - if(!broken) - broken = 1 - to_chat(user, "\red The bulb has burnt out!") - icon_state = "flashburnt" +/obj/item/device/flash + name = "flash" + desc = "Used for blinding and being an asshole." + icon_state = "flash" + item_state = "flashbang" //looks exactly like a flash (and nothing like a flashbang) + throwforce = 5 + w_class = 2.0 + throw_speed = 4 + throw_range = 10 + flags = CONDUCT + origin_tech = "magnets=2;combat=1" + + action_button_name = "Toggle Flash" + + 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(mob/user) + if(user && (CLUMSY in user.mutations) && prob(50)) + to_chat(user, "\red \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, mob/user) + if(!user || !M) return //sanity + + if(!user.IsAdvancedToolUser()) + to_chat(user, "You don't have the dexterity to do this!") + return + + M.attack_log += text("\[[time_stamp()]\] Has been flashed (attempt) with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [M.name] ([M.ckey])") + msg_admin_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey]) (JMP)") + + 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 + to_chat(user, "The bulb has burnt out!") + icon_state = "flashburnt" + return + times_used++ + else //can only use it 5 times a minute + to_chat(user, "*click* *click*") + return + playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) + var/flashfail = 0 + + if(iscarbon(M)) + var/safety = M:eyecheck() + if(safety <= 0) + M.Weaken(10) + M.flash_eyes() + + if(ishuman(M) && ishuman(user) && M.stat!=DEAD) + + if(user.mind && (user.mind in ticker.mode.head_revolutionaries) && ticker.mode.name == "revolution") + if(M.client) + if(M.stat == CONSCIOUS) + M.mind_initialize() //give them a mind datum if they don't have one. + var/resisted + if(!ismindshielded(M) && !jobban_isbanned(M, ROLE_REV) && !jobban_isbanned(M, "Syndicate") && !role_available_in_minutes(M, ROLE_REV)) + if(user.mind in ticker.mode.head_revolutionaries) + M.mind.has_been_rev = 1 + if(!ticker.mode.add_revolutionary(M.mind)) + resisted = 1 + else + resisted = 1 + + if(resisted) + to_chat(user, "This mind seems resistant to the flash!") + else + flashfail = 1 + + else if(issilicon(M)) + //M.Weaken(rand(5,10)) + var/power = rand(7,13) + M.confused = min(M.confused + power, 20) + M.eye_blind = min(M.eye_blind + power, 20) + else + flashfail = 1 + + if(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) + + 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!") + + return + + + + +/obj/item/device/flash/attack_self(mob/living/carbon/user, flag = 0, emp = 0) + if(!user || !clown_check(user)) + return + if(!user.IsAdvancedToolUser()) + to_chat(user, "You don't have the dexterity to do this!") + 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(src.loc, 'sound/weapons/flash.ogg', 100, 1) + 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) + + for(var/mob/living/carbon/M in oviewers(3, null)) + var/safety = M:eyecheck() + if(!safety) + if(!M.blinded) + M.flash_eyes() + + 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)) + var/mob/living/carbon/M = loc + var/safety = M.eyecheck() + if(safety <= 0) + M.Weaken(10) + M.flash_eyes() + 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, mob/user) + ..() + if(!broken) + broken = 1 + to_chat(user, "\red The bulb has burnt out!") + icon_state = "flashburnt" + +/obj/item/device/flash/synthetic/attack_self(mob/living/carbon/user, flag = 0, emp = 0) + ..() + if(!broken) + broken = 1 + to_chat(user, "\red The bulb has burnt out!") + icon_state = "flashburnt" diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 50d59248aac6..879661420941 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -1,284 +1,284 @@ -/obj/item/device/flashlight - name = "flashlight" - desc = "A hand-held emergency light." - icon = 'icons/obj/lighting.dmi' - icon_state = "flashlight" - item_state = "flashlight" - w_class = 2 - flags = CONDUCT - slot_flags = SLOT_BELT - m_amt = 50 - g_amt = 20 - action_button_name = "Toggle Flashlight" - var/on = 0 - var/brightness_on = 5 //luminosity when on - -/obj/item/device/flashlight/atom_init() - . = ..() - 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(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) - action_button_name = null - return 1 - -/obj/item/device/flashlight/Destroy() - if(on) - set_light(0) - return ..() - - -/obj/item/device/flashlight/attack(mob/living/M, mob/living/user, def_zone) - add_fingerprint(user) - if(on && def_zone == O_EYES) - - if(((CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly - return ..() //just hit them in the head - - if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") //don't have dexterity - 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) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) - to_chat(user, "You're going to need to remove that [(H.head && H.head.flags & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) ? "mask": "glasses"] first.") - return - - if(M == user) //they're using it on themselves - if(!M.blinded) - M.flash_eyes() - 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(XRAY in M.mutations) //mob has X-RAY vision - M.flash_eyes() //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) - M.flash_eyes() //flash the affected mob - to_chat(user, "[M]'s pupils narrow.") - else - return ..() - -/obj/item/device/flashlight/seclite - name = "seclite" - desc = "A robust flashlight used by security." - icon_state = "seclite" - item_state = "seclite" - force = 7 // Not as good as a stun baton. - hitsound = 'sound/weapons/genhit1.ogg' - -/obj/item/device/flashlight/pen - name = "penlight" - desc = "A pen-sized light, used by medical staff." - icon_state = "penlight" - item_state = "" - flags = CONDUCT - brightness_on = 2 - w_class = 1 - -/obj/item/device/flashlight/drone - name = "low-power flashlight" - desc = "A miniature lamp, that might be used by small robots." - icon_state = "penlight" - item_state = "" - flags = CONDUCT - brightness_on = 2 - w_class = 1 - - -// 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 = 4 - w_class = 4 - flags = CONDUCT - m_amt = 0 - g_amt = 0 - on = 1 - - -// 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 = 4 - - -/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 - 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 - light_color = LIGHT_COLOR_FLARE - light_power = 2 - action_button_name = "Toggle Flare" - - -/obj/item/device/flashlight/flare/atom_init() - fuel = rand(800, 1000) // 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) - fuel = max(fuel - 1, 0) - if(!fuel || !on) - turn_off() - if(!fuel) - icon_state = "[initial(icon_state)]-empty" - item_state = icon_state - STOP_PROCESSING(SSobj, 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(null) - -/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. - if(.) - user.visible_message("[user] activates the flare.", "You pull the cord on the flare, activating it!") - src.force = on_damage - src.damtype = "fire" - item_state = icon_state - if(user.hand) - user.update_inv_l_hand() - else - user.update_inv_r_hand() - START_PROCESSING(SSobj, src) - -/obj/item/device/flashlight/slime - gender = PLURAL - name = "glowing slime extract" - desc = "A glowing ball of what appears to be amber." - icon = 'icons/obj/lighting.dmi' - icon_state = "floor1" //not a slime extract sprite but... something close enough! - item_state = "slime" - w_class = 1 - m_amt = 0 - g_amt = 0 - brightness_on = 6 - on = 1 //Bio-luminesence has one setting, on. - -/obj/item/device/flashlight/slime/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/item/device/flashlight/slime/atom_init_late() - update_brightness() - icon_state = initial(icon_state) - -/obj/item/device/flashlight/slime/attack_self(mob/user) - return //Bio-luminescence does not toggle. - -/obj/item/device/flashlight/emp - origin_tech = "magnets=3;syndicate=1" - var/emp_max_charges = 4 - var/emp_cur_charges = 4 - var/charge_tick = 0 - - -/obj/item/device/flashlight/emp/atom_init() - . = ..() - START_PROCESSING(SSobj, src) - -/obj/item/device/flashlight/emp/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/device/flashlight/emp/process() - charge_tick++ - if(charge_tick < 10) - return 0 - charge_tick = 0 - emp_cur_charges = min(emp_cur_charges+1, emp_max_charges) - return 1 - -/obj/item/device/flashlight/emp/attack(mob/living/M, mob/living/user, def_zone) - if(on && def_zone == O_EYES) // call original attack proc only if aiming at the eyes - ..() - return - -/obj/item/device/flashlight/emp/afterattack(atom/movable/A, mob/user, proximity) - if(!proximity) - return - - if(emp_cur_charges) - emp_cur_charges-- - - if(ismob(A)) - var/mob/M = A - msg_admin_attack("[user] ([user.ckey]) attacked [M.name] ([M.ckey]) with Emp-light JMP)") - M.attack_log += text("\[[time_stamp()]\] Has been attacked with Emp-light by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] attacked with Emp-light [M.name]'s ([M.ckey])") - M.visible_message("[user] blinks \the [src] at the [A]") - else - A.visible_message("[user] blinks \the [src] at \the [A].") - to_chat(user, "\The [src] now has [emp_cur_charges] charge\s.
                    ") - A.emp_act(1) - else - to_chat(user, "\The [src] needs time to recharge!") - return +/obj/item/device/flashlight + name = "flashlight" + desc = "A hand-held emergency light." + icon = 'icons/obj/lighting.dmi' + icon_state = "flashlight" + item_state = "flashlight" + w_class = 2 + flags = CONDUCT + slot_flags = SLOT_BELT + m_amt = 50 + g_amt = 20 + action_button_name = "Toggle Flashlight" + var/on = 0 + var/brightness_on = 5 //luminosity when on + +/obj/item/device/flashlight/atom_init() + . = ..() + 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(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) + action_button_name = null + return 1 + +/obj/item/device/flashlight/Destroy() + if(on) + set_light(0) + return ..() + + +/obj/item/device/flashlight/attack(mob/living/M, mob/living/user, def_zone) + add_fingerprint(user) + if(on && def_zone == O_EYES) + + if(((CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly + return ..() //just hit them in the head + + if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") //don't have dexterity + 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) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) + to_chat(user, "You're going to need to remove that [(H.head && H.head.flags & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) ? "mask": "glasses"] first.") + return + + if(M == user) //they're using it on themselves + if(!M.blinded) + M.flash_eyes() + 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(XRAY in M.mutations) //mob has X-RAY vision + M.flash_eyes() //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) + M.flash_eyes() //flash the affected mob + to_chat(user, "[M]'s pupils narrow.") + else + return ..() + +/obj/item/device/flashlight/seclite + name = "seclite" + desc = "A robust flashlight used by security." + icon_state = "seclite" + item_state = "seclite" + force = 7 // Not as good as a stun baton. + hitsound = 'sound/weapons/genhit1.ogg' + +/obj/item/device/flashlight/pen + name = "penlight" + desc = "A pen-sized light, used by medical staff." + icon_state = "penlight" + item_state = "" + flags = CONDUCT + brightness_on = 2 + w_class = 1 + +/obj/item/device/flashlight/drone + name = "low-power flashlight" + desc = "A miniature lamp, that might be used by small robots." + icon_state = "penlight" + item_state = "" + flags = CONDUCT + brightness_on = 2 + w_class = 1 + + +// 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 = 4 + w_class = 4 + flags = CONDUCT + m_amt = 0 + g_amt = 0 + on = 1 + + +// 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 = 4 + + +/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 + 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 + light_color = LIGHT_COLOR_FLARE + light_power = 2 + action_button_name = "Toggle Flare" + + +/obj/item/device/flashlight/flare/atom_init() + fuel = rand(800, 1000) // 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) + fuel = max(fuel - 1, 0) + if(!fuel || !on) + turn_off() + if(!fuel) + icon_state = "[initial(icon_state)]-empty" + item_state = icon_state + STOP_PROCESSING(SSobj, 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(null) + +/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. + if(.) + user.visible_message("[user] activates the flare.", "You pull the cord on the flare, activating it!") + src.force = on_damage + src.damtype = "fire" + item_state = icon_state + if(user.hand) + user.update_inv_l_hand() + else + user.update_inv_r_hand() + START_PROCESSING(SSobj, src) + +/obj/item/device/flashlight/slime + gender = PLURAL + name = "glowing slime extract" + desc = "A glowing ball of what appears to be amber." + icon = 'icons/obj/lighting.dmi' + icon_state = "floor1" //not a slime extract sprite but... something close enough! + item_state = "slime" + w_class = 1 + m_amt = 0 + g_amt = 0 + brightness_on = 6 + on = 1 //Bio-luminesence has one setting, on. + +/obj/item/device/flashlight/slime/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/item/device/flashlight/slime/atom_init_late() + update_brightness() + icon_state = initial(icon_state) + +/obj/item/device/flashlight/slime/attack_self(mob/user) + return //Bio-luminescence does not toggle. + +/obj/item/device/flashlight/emp + origin_tech = "magnets=3;syndicate=1" + var/emp_max_charges = 4 + var/emp_cur_charges = 4 + var/charge_tick = 0 + + +/obj/item/device/flashlight/emp/atom_init() + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/device/flashlight/emp/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/device/flashlight/emp/process() + charge_tick++ + if(charge_tick < 10) + return 0 + charge_tick = 0 + emp_cur_charges = min(emp_cur_charges+1, emp_max_charges) + return 1 + +/obj/item/device/flashlight/emp/attack(mob/living/M, mob/living/user, def_zone) + if(on && def_zone == O_EYES) // call original attack proc only if aiming at the eyes + ..() + return + +/obj/item/device/flashlight/emp/afterattack(atom/movable/A, mob/user, proximity) + if(!proximity) + return + + if(emp_cur_charges) + emp_cur_charges-- + + if(ismob(A)) + var/mob/M = A + msg_admin_attack("[user] ([user.ckey]) attacked [M.name] ([M.ckey]) with Emp-light JMP)") + M.attack_log += text("\[[time_stamp()]\] Has been attacked with Emp-light by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] attacked with Emp-light [M.name]'s ([M.ckey])") + M.visible_message("[user] blinks \the [src] at the [A]") + else + A.visible_message("[user] blinks \the [src] at \the [A].") + to_chat(user, "\The [src] now has [emp_cur_charges] charge\s.
                    ") + A.emp_act(1) + else + to_chat(user, "\The [src] needs time to recharge!") + return diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index 6962ea9986f6..468e2e59142c 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -1,203 +1,203 @@ - -// 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 on the floor for the -// user to then pickup with a trash bag. If it's empty then it will just place a light in the fixture. -// -// HOW TO REFILL THE DEVICE -// -// It will need to be manually refilled with lights. -// If it's part of a robot module, it will charge when the Robot is inside a Recharge Station. -// -// 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. Refill with working lightbulbs." - - icon = 'icons/obj/janitor.dmi' - icon_state = "lightreplacer0" - item_state = "electronic" - - flags = CONDUCT - slot_flags = SLOT_BELT - origin_tech = "magnets=3;materials=2" - - var/max_uses = 20 - var/uses = 0 - var/emagged = 0 - var/failmsg = "" - // How much to increase per each glass? - var/increment = 5 - // How much to take from the glass? - var/decrement = 1 - var/charge = 1 - -/obj/item/device/lightreplacer/atom_init() - uses = max_uses / 2 - failmsg = "The [name]'s refill light blinks red." - . = ..() - -/obj/item/device/lightreplacer/examine(mob/user) - ..() - if(src in view(1, user)) - to_chat(user, "It has [uses] lights remaining.") - -/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)) - var/obj/item/stack/sheet/glass/G = W - if(G.get_amount() - decrement >= 0 && uses < max_uses) - var/remaining = max(G.get_amount() - decrement, 0) - if(!remaining && !(G.get_amount() - decrement) == 0) - to_chat(user, "There isn't enough glass.") - return - G.set_amount(remaining) - AddUses(increment) - to_chat(user, "You insert a piece of glass into the [src.name]. You have [uses] lights remaining.") - return - - if(istype(W, /obj/item/weapon/light)) - var/obj/item/weapon/light/L = W - if(L.status == 0) // LIGHT OKAY - if(uses < max_uses) - AddUses(1) - to_chat(user, "You insert the [L.name] into the [src.name]. You have [uses] lights remaining.") - user.drop_item() - qdel(L) - return - else - to_chat(user, "You need a working light.") - return - - -/obj/item/device/lightreplacer/attack_self(mob/user) - /* // 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 - */ - to_chat(usr, "It has [uses] lights remaining.") - -/obj/item/device/lightreplacer/update_icon() - icon_state = "lightreplacer[emagged]" - - -/obj/item/device/lightreplacer/proc/Use(mob/user) - - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - AddUses(-1) - return 1 - -// Negative numbers will subtract -/obj/item/device/lightreplacer/proc/AddUses(amount = 1) - uses = min(max(uses + amount, 0), max_uses) - -/obj/item/device/lightreplacer/proc/Charge(mob/user) - charge += 1 - if(charge > 7) - AddUses(1) - charge = 1 - -/obj/item/device/lightreplacer/proc/ReplaceLight(obj/machinery/light/target, mob/living/U) - - if(target.status != LIGHT_OK) - if(CanUse(U)) - if(!Use(U)) return - to_chat(U, "You replace the [target.fitting] with the [src].") - - 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.switchcount = target.switchcount - target.switchcount = 0 - L1.update() - - target.status = LIGHT_EMPTY - target.update() - - var/obj/item/weapon/light/L2 = new target.light_type() - - target.status = L2.status - target.switchcount = L2.switchcount - target.rigged = emagged - target.brightness_range = L2.brightness_range - target.brightness_power = L2.brightness_power - target.brightness_color = L2.brightness_color - target.on = target.has_power() - target.update() - qdel(L2) - - if(target.on && target.rigged) - target.explode() - return - - else - to_chat(U, failmsg) - return - else - to_chat(U, "There is a working [target.fitting] already inserted.") - return - -/obj/item/device/lightreplacer/proc/Emag() - emagged = !emagged - playsound(src.loc, "sparks", 100, 1) - if(emagged) - name = "Shortcircuited [initial(name)]" - else - name = initial(name) - update_icon() - -//Can you use it? - -/obj/item/device/lightreplacer/proc/CanUse(mob/living/user) - src.add_fingerprint(user) - //Not sure what else to check for. Maybe if clumsy? - if(uses > 0) - return 1 - else - return 0 - -#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 on the floor for the +// user to then pickup with a trash bag. If it's empty then it will just place a light in the fixture. +// +// HOW TO REFILL THE DEVICE +// +// It will need to be manually refilled with lights. +// If it's part of a robot module, it will charge when the Robot is inside a Recharge Station. +// +// 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. Refill with working lightbulbs." + + icon = 'icons/obj/janitor.dmi' + icon_state = "lightreplacer0" + item_state = "electronic" + + flags = CONDUCT + slot_flags = SLOT_BELT + origin_tech = "magnets=3;materials=2" + + var/max_uses = 20 + var/uses = 0 + var/emagged = 0 + var/failmsg = "" + // How much to increase per each glass? + var/increment = 5 + // How much to take from the glass? + var/decrement = 1 + var/charge = 1 + +/obj/item/device/lightreplacer/atom_init() + uses = max_uses / 2 + failmsg = "The [name]'s refill light blinks red." + . = ..() + +/obj/item/device/lightreplacer/examine(mob/user) + ..() + if(src in view(1, user)) + to_chat(user, "It has [uses] lights remaining.") + +/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)) + var/obj/item/stack/sheet/glass/G = W + if(G.get_amount() - decrement >= 0 && uses < max_uses) + var/remaining = max(G.get_amount() - decrement, 0) + if(!remaining && !(G.get_amount() - decrement) == 0) + to_chat(user, "There isn't enough glass.") + return + G.set_amount(remaining) + AddUses(increment) + to_chat(user, "You insert a piece of glass into the [src.name]. You have [uses] lights remaining.") + return + + if(istype(W, /obj/item/weapon/light)) + var/obj/item/weapon/light/L = W + if(L.status == 0) // LIGHT OKAY + if(uses < max_uses) + AddUses(1) + to_chat(user, "You insert the [L.name] into the [src.name]. You have [uses] lights remaining.") + user.drop_item() + qdel(L) + return + else + to_chat(user, "You need a working light.") + return + + +/obj/item/device/lightreplacer/attack_self(mob/user) + /* // 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 + */ + to_chat(usr, "It has [uses] lights remaining.") + +/obj/item/device/lightreplacer/update_icon() + icon_state = "lightreplacer[emagged]" + + +/obj/item/device/lightreplacer/proc/Use(mob/user) + + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + AddUses(-1) + return 1 + +// Negative numbers will subtract +/obj/item/device/lightreplacer/proc/AddUses(amount = 1) + uses = min(max(uses + amount, 0), max_uses) + +/obj/item/device/lightreplacer/proc/Charge(mob/user) + charge += 1 + if(charge > 7) + AddUses(1) + charge = 1 + +/obj/item/device/lightreplacer/proc/ReplaceLight(obj/machinery/light/target, mob/living/U) + + if(target.status != LIGHT_OK) + if(CanUse(U)) + if(!Use(U)) return + to_chat(U, "You replace the [target.fitting] with the [src].") + + 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.switchcount = target.switchcount + target.switchcount = 0 + L1.update() + + target.status = LIGHT_EMPTY + target.update() + + var/obj/item/weapon/light/L2 = new target.light_type() + + target.status = L2.status + target.switchcount = L2.switchcount + target.rigged = emagged + target.brightness_range = L2.brightness_range + target.brightness_power = L2.brightness_power + target.brightness_color = L2.brightness_color + target.on = target.has_power() + target.update() + qdel(L2) + + if(target.on && target.rigged) + target.explode() + return + + else + to_chat(U, failmsg) + return + else + to_chat(U, "There is a working [target.fitting] already inserted.") + return + +/obj/item/device/lightreplacer/proc/Emag() + emagged = !emagged + playsound(src.loc, "sparks", 100, 1) + if(emagged) + name = "Shortcircuited [initial(name)]" + else + name = initial(name) + update_icon() + +//Can you use it? + +/obj/item/device/lightreplacer/proc/CanUse(mob/living/user) + src.add_fingerprint(user) + //Not sure what else to check for. Maybe if clumsy? + if(uses > 0) + return 1 + else + return 0 + +#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 202f1a3fb8e7..26d42b1b8f11 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -1,21 +1,21 @@ -/** - * 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/multitool - name = "multitool" - desc = "Used for pulsing wires to test which to cut. Not recommended by doctors." - icon_state = "multitool" - flags = CONDUCT - 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." - m_amt = 50 - g_amt = 20 - origin_tech = "magnets=1;engineering=1" - var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage +/** + * 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/multitool + name = "multitool" + desc = "Used for pulsing wires to test which to cut. Not recommended by doctors." + icon_state = "multitool" + flags = CONDUCT + 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." + m_amt = 50 + g_amt = 20 + origin_tech = "magnets=1;engineering=1" + var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index 79cbbb60db81..91ba2b1adf8b 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -1,306 +1,306 @@ -/obj/item/device/paicard - name = "personal AI device" - icon = 'icons/obj/pda.dmi' - icon_state = "pai" - item_state = "electronic" - w_class = 2.0 - slot_flags = SLOT_BELT - origin_tech = "programming=2" - var/obj/item/device/radio/radio - var/looking_for_personality = 0 - var/mob/living/silicon/pai/pai - -/obj/item/device/paicard/atom_init() - . = ..() - paicard_list += src - overlays += "pai-off" - -/obj/item/device/paicard/Destroy() - paicard_list -= src - //Will stop people throwing friend pAIs into the singularity so they can respawn - if(!isnull(pai)) - pai.death(0) - return ..() - -/obj/item/device/paicard/attack_self(mob/user) - if (!in_range(src, user)) - return - user.set_machine(src) - var/dat = {" - - - - - - - "} - - if(pai) - dat += {" - Personal AI Device

                    - - - - - - - - - - - - - -
                    Installed Personality:[pai.name]
                    Prime directive:[pai.pai_law0]
                    Additional directives:[pai.pai_laws]
                    -
                    - "} - dat += {" - - -
                    - Configure Directives -
                    - "} - if(pai && (!pai.master_dna || !pai.master)) - dat += {" - - -
                    - Imprint Master DNA -
                    - "} - dat += "
                    " - if(radio) - dat += "Radio Uplink" - dat += {" - - - - - - - - - - - - - -
                    Transmit:[(radio.wires & 4) ? "En" : "Dis" ]abled - -
                    Receive:[(radio.wires & 2) ? "En" : "Dis" ]abled - -
                    Signal Pulser:[(radio.wires & 1) ? "En" : "Dis" ]abled - -
                    -
                    - "} - else - dat += "Radio Uplink
                    " - dat += "Radio firmware not loaded. Please install a pAI personality to load firmware.
                    " - dat += {" - - -
                    Wipe current pAI personality - -
                    - "} - else - if(looking_for_personality) - dat += {" - pAI Request Module

                    -

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

                    - Searching for personalities, please wait...

                    - - - - - -
                    - Refresh available personalities -

                    - "} - else - dat += {" - pAI Request Module

                    -

                    No personality is installed.

                    - - - - -
                    Request personality -
                    -
                    -

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

                    - "} - user << browse(entity_ja(dat), "window=paicard") - onclose(user, "paicard") - return - -/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 (radio.wires & t1) - radio.wires &= ~t1 - else - radio.wires |= t1 - if(href_list["setlaws"]) - var/newlaws = 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", input_default(pai.pai_laws)) as message) - 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.Cut() - src.overlays += "pai-off" - -/obj/item/device/paicard/proc/setEmotion(emotion) - if(pai) - src.overlays.Cut() - switch(emotion) - if(1) src.overlays += "pai-happy" - if(2) src.overlays += "pai-cat" - if(3) src.overlays += "pai-extremely-happy" - if(4) src.overlays += "pai-face" - if(5) src.overlays += "pai-laugh" - if(6) src.overlays += "pai-off" - if(7) src.overlays += "pai-sad" - if(8) src.overlays += "pai-angry" - if(9) src.overlays += "pai-what" - -/obj/item/device/paicard/proc/alertUpdate() - var/turf/T = get_turf_or_move(src.loc) - for (var/mob/M in viewers(T)) - M.show_message("\blue [src] flashes a message across its screen, \"Additional personalities available for download.\"", 3, "\blue [src] bleeps electronically.", 2) - -/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 + slot_flags = SLOT_BELT + origin_tech = "programming=2" + var/obj/item/device/radio/radio + var/looking_for_personality = 0 + var/mob/living/silicon/pai/pai + +/obj/item/device/paicard/atom_init() + . = ..() + paicard_list += src + overlays += "pai-off" + +/obj/item/device/paicard/Destroy() + paicard_list -= src + //Will stop people throwing friend pAIs into the singularity so they can respawn + if(!isnull(pai)) + pai.death(0) + return ..() + +/obj/item/device/paicard/attack_self(mob/user) + if (!in_range(src, user)) + return + user.set_machine(src) + var/dat = {" + + + + + + + "} + + if(pai) + dat += {" + Personal AI Device

                    + + + + + + + + + + + + + +
                    Installed Personality:[pai.name]
                    Prime directive:[pai.pai_law0]
                    Additional directives:[pai.pai_laws]
                    +
                    + "} + dat += {" + + +
                    + Configure Directives +
                    + "} + if(pai && (!pai.master_dna || !pai.master)) + dat += {" + + +
                    + Imprint Master DNA +
                    + "} + dat += "
                    " + if(radio) + dat += "Radio Uplink" + dat += {" + + + + + + + + + + + + + +
                    Transmit:[(radio.wires & 4) ? "En" : "Dis" ]abled + +
                    Receive:[(radio.wires & 2) ? "En" : "Dis" ]abled + +
                    Signal Pulser:[(radio.wires & 1) ? "En" : "Dis" ]abled + +
                    +
                    + "} + else + dat += "Radio Uplink
                    " + dat += "Radio firmware not loaded. Please install a pAI personality to load firmware.
                    " + dat += {" + + +
                    Wipe current pAI personality + +
                    + "} + else + if(looking_for_personality) + dat += {" + pAI Request Module

                    +

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

                    + Searching for personalities, please wait...

                    + + + + + +
                    + Refresh available personalities +

                    + "} + else + dat += {" + pAI Request Module

                    +

                    No personality is installed.

                    + + + + +
                    Request personality +
                    +
                    +

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

                    + "} + user << browse(entity_ja(dat), "window=paicard") + onclose(user, "paicard") + return + +/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 (radio.wires & t1) + radio.wires &= ~t1 + else + radio.wires |= t1 + if(href_list["setlaws"]) + var/newlaws = 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", input_default(pai.pai_laws)) as message) + 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.Cut() + src.overlays += "pai-off" + +/obj/item/device/paicard/proc/setEmotion(emotion) + if(pai) + src.overlays.Cut() + switch(emotion) + if(1) src.overlays += "pai-happy" + if(2) src.overlays += "pai-cat" + if(3) src.overlays += "pai-extremely-happy" + if(4) src.overlays += "pai-face" + if(5) src.overlays += "pai-laugh" + if(6) src.overlays += "pai-off" + if(7) src.overlays += "pai-sad" + if(8) src.overlays += "pai-angry" + if(9) src.overlays += "pai-what" + +/obj/item/device/paicard/proc/alertUpdate() + var/turf/T = get_turf_or_move(src.loc) + for (var/mob/M in viewers(T)) + M.show_message("\blue [src] flashes a message across its screen, \"Additional personalities available for download.\"", 3, "\blue [src] bleeps electronically.", 2) + +/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 278154595f37..073bfbab9a27 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -1,120 +1,120 @@ -// 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 = CONDUCT - throwforce = 5 - throw_speed = 1 - throw_range = 2 - m_amt = 750 - w_amt = 750 - 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(obj/item/I, 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 - 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 - to_chat(M, "[user] attaches the power sink to the cable.") - return - else - to_chat(user, "Device must be placed over an exposed cable to attach to it.") - return - else - if (mode == 2) - STOP_PROCESSING(SSobj, 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.") - 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 - ..() - - - - attack_paw() - return - - attack_ai() - return - - attack_hand(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 - to_chat(M, "[user] activates the power sink!") - mode = 2 - icon_state = "powersink1" - START_PROCESSING(SSobj, 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 - to_chat(M, "[user] deactivates the power sink!") - mode = 1 - set_light(0) - icon_state = "powersink0" - STOP_PROCESSING(SSobj, 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.newload += 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(power_drained > max_power * 0.95) - playsound(src, 'sound/effects/screech.ogg', 100, 1, 1) - if(power_drained >= max_power) - STOP_PROCESSING(SSobj, src) - explosion(src.loc, 3,6,9,12) - qdel(src) +// 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 = CONDUCT + throwforce = 5 + throw_speed = 1 + throw_range = 2 + m_amt = 750 + w_amt = 750 + 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(obj/item/I, 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 + 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 + to_chat(M, "[user] attaches the power sink to the cable.") + return + else + to_chat(user, "Device must be placed over an exposed cable to attach to it.") + return + else + if (mode == 2) + STOP_PROCESSING(SSobj, 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.") + 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 + ..() + + + + attack_paw() + return + + attack_ai() + return + + attack_hand(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 + to_chat(M, "[user] activates the power sink!") + mode = 2 + icon_state = "powersink1" + START_PROCESSING(SSobj, 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 + to_chat(M, "[user] deactivates the power sink!") + mode = 1 + set_light(0) + icon_state = "powersink0" + STOP_PROCESSING(SSobj, 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.newload += 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(power_drained > max_power * 0.95) + playsound(src, 'sound/effects/screech.ogg', 100, 1, 1) + if(power_drained >= max_power) + STOP_PROCESSING(SSobj, src) + explosion(src.loc, 3,6,9,12) + qdel(src) diff --git a/code/game/objects/items/devices/radio/beacon.dm b/code/game/objects/items/devices/radio/beacon.dm index c1ee9aea5509..2680ad70d20c 100644 --- a/code/game/objects/items/devices/radio/beacon.dm +++ b/code/game/objects/items/devices/radio/beacon.dm @@ -1,153 +1,153 @@ -/obj/item/device/radio/beacon - name = "Tracking Beacon" - desc = "A beacon used by a teleporter." - icon_state = "beacon" - item_state = "beacon" - var/code = "electronic" - origin_tech = "bluespace=1" - -/obj/item/device/radio/beacon/atom_init() - . = ..() - radio_beacon_list += src - -/obj/item/device/radio/beacon/Destroy() - radio_beacon_list -= src - return ..() - -/obj/item/device/radio/beacon/hear_talk() - return - - -/obj/item/device/radio/beacon/send_hear() - return null - - -/obj/item/device/radio/beacon/verb/alter_signal(t as text) - set name = "Alter Beacon's Signal" - set category = "Object" - set src in usr - - if ((usr.canmove && !( usr.restrained() ))) - src.code = t - if (!( src.code )) - src.code = "beacon" - src.add_fingerprint(usr) - return - - -/obj/item/device/radio/beacon/bacon //Probably a better way of doing this, I'm lazy. - proc/digest_delay() - spawn(600) - qdel(src) - - -// SINGULO BEACON SPAWNER - -/obj/item/device/radio/beacon/syndicate - name = "suspicious beacon" - desc = "A label on it reads: Activate to have a singularity beacon teleported to your location." - origin_tech = "bluespace=1;syndicate=7" - -/obj/item/device/radio/beacon/syndicate/attack_self(mob/user) - if(user) - to_chat(user, "\blue Locked In") - new /obj/machinery/singularity_beacon/syndicate( user.loc ) - playsound(src, 'sound/effects/pop.ogg', 100, 1, 1) - qdel(src) - return - -//Medical beacon stuff -/obj/item/device/beacon/medical - name = "Medical Tracking Beacon" - desc = "A beacon used by a body teleporter." - icon = 'icons/obj/radio.dmi' - icon_state = "beacon_med" - item_state = "signaler" - origin_tech = "bluespace=1" - -/obj/item/device/beacon/medical/atom_init() - . = ..() - beacon_medical_list += src - - -/obj/item/device/beacon/medical/Destroy() - beacon_medical_list -= src - return ..() - -/obj/item/weapon/medical/teleporter - name = "Body Teleporter" - desc = "A device used for teleporting injured(critical) or dead people." - w_class = ITEM_SIZE_SMALL - gender = PLURAL - icon = 'icons/obj/device.dmi' - icon_state = "medicon" - item_state = "signaler" - flags = NOBLUDGEON - origin_tech = "bluespace=1" - var/timer = 10 - var/atom/target = null - -/obj/item/weapon/medical/teleporter/afterattack(atom/target, mob/user, flag) - if (!flag) - return - if (!ishuman(target)) - to_chat(user, "\blue Can only be planted on human.") - return - var/found = 0 - var/target_beacon - for(var/obj/item/device/beacon/medical/medical in beacon_medical_list) - if(medical) - if(isturf(medical.loc)) - var/area/A = get_area(medical) - if(istype(A, /area/medical/sleeper)) - target_beacon = medical - found = 1 - break - if(!found) - to_chat(user, "\red No beacon located in medical treatment centre.") - return - - var/mob/living/carbon/human/H = target - if(H.health >= config.health_threshold_crit) - to_chat(user, "\blue [H.name] is in good condition.") - return - if(user.is_busy()) return - to_chat(user, "Planting...") - - user.visible_message("\red [user.name] is trying to plant some kind of device on [target.name]!") - - if(do_after(user, 50, target = target) && in_range(user, H)) - user.drop_item() - target = H - loc = null - //var/location - H.attack_log += "\[[time_stamp()]\] Had the [name] planted on them by [user.real_name] ([user.ckey])" - playsound(H.loc, 'sound/items/timer.ogg', 5, 0) - user.visible_message("\red [user.name] finished planting an [name] on [H.name]!") - var/I = image('icons/obj/device.dmi', "medicon") - H.overlays += I - to_chat(user, "Device has been planted. Timer counting down from [timer].") - addtimer(CALLBACK(src, .proc/teleport, H, target_beacon, I), timer * 10) - -/obj/item/weapon/medical/teleporter/attack(mob/M, mob/user, def_zone) - return - -/obj/item/weapon/medical/teleporter/proc/teleport(mob/H, obj/beacon, I) - if(H) - if(beacon) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, H) - s2.set_up(3, 1, beacon) - s.start() - s2.start() - H.loc = get_turf(beacon) - if (src) - qdel(src) - H.overlays -= I - qdel(I) - - - - - +/obj/item/device/radio/beacon + name = "Tracking Beacon" + desc = "A beacon used by a teleporter." + icon_state = "beacon" + item_state = "beacon" + var/code = "electronic" + origin_tech = "bluespace=1" + +/obj/item/device/radio/beacon/atom_init() + . = ..() + radio_beacon_list += src + +/obj/item/device/radio/beacon/Destroy() + radio_beacon_list -= src + return ..() + +/obj/item/device/radio/beacon/hear_talk() + return + + +/obj/item/device/radio/beacon/send_hear() + return null + + +/obj/item/device/radio/beacon/verb/alter_signal(t as text) + set name = "Alter Beacon's Signal" + set category = "Object" + set src in usr + + if ((usr.canmove && !( usr.restrained() ))) + src.code = t + if (!( src.code )) + src.code = "beacon" + src.add_fingerprint(usr) + return + + +/obj/item/device/radio/beacon/bacon //Probably a better way of doing this, I'm lazy. + proc/digest_delay() + spawn(600) + qdel(src) + + +// SINGULO BEACON SPAWNER + +/obj/item/device/radio/beacon/syndicate + name = "suspicious beacon" + desc = "A label on it reads: Activate to have a singularity beacon teleported to your location." + origin_tech = "bluespace=1;syndicate=7" + +/obj/item/device/radio/beacon/syndicate/attack_self(mob/user) + if(user) + to_chat(user, "\blue Locked In") + new /obj/machinery/singularity_beacon/syndicate( user.loc ) + playsound(src, 'sound/effects/pop.ogg', 100, 1, 1) + qdel(src) + return + +//Medical beacon stuff +/obj/item/device/beacon/medical + name = "Medical Tracking Beacon" + desc = "A beacon used by a body teleporter." + icon = 'icons/obj/radio.dmi' + icon_state = "beacon_med" + item_state = "signaler" + origin_tech = "bluespace=1" + +/obj/item/device/beacon/medical/atom_init() + . = ..() + beacon_medical_list += src + + +/obj/item/device/beacon/medical/Destroy() + beacon_medical_list -= src + return ..() + +/obj/item/weapon/medical/teleporter + name = "Body Teleporter" + desc = "A device used for teleporting injured(critical) or dead people." + w_class = ITEM_SIZE_SMALL + gender = PLURAL + icon = 'icons/obj/device.dmi' + icon_state = "medicon" + item_state = "signaler" + flags = NOBLUDGEON + origin_tech = "bluespace=1" + var/timer = 10 + var/atom/target = null + +/obj/item/weapon/medical/teleporter/afterattack(atom/target, mob/user, flag) + if (!flag) + return + if (!ishuman(target)) + to_chat(user, "\blue Can only be planted on human.") + return + var/found = 0 + var/target_beacon + for(var/obj/item/device/beacon/medical/medical in beacon_medical_list) + if(medical) + if(isturf(medical.loc)) + var/area/A = get_area(medical) + if(istype(A, /area/medical/sleeper)) + target_beacon = medical + found = 1 + break + if(!found) + to_chat(user, "\red No beacon located in medical treatment centre.") + return + + var/mob/living/carbon/human/H = target + if(H.health >= config.health_threshold_crit) + to_chat(user, "\blue [H.name] is in good condition.") + return + if(user.is_busy()) return + to_chat(user, "Planting...") + + user.visible_message("\red [user.name] is trying to plant some kind of device on [target.name]!") + + if(do_after(user, 50, target = target) && in_range(user, H)) + user.drop_item() + target = H + loc = null + //var/location + H.attack_log += "\[[time_stamp()]\] Had the [name] planted on them by [user.real_name] ([user.ckey])" + playsound(H.loc, 'sound/items/timer.ogg', 5, 0) + user.visible_message("\red [user.name] finished planting an [name] on [H.name]!") + var/I = image('icons/obj/device.dmi', "medicon") + H.overlays += I + to_chat(user, "Device has been planted. Timer counting down from [timer].") + addtimer(CALLBACK(src, .proc/teleport, H, target_beacon, I), timer * 10) + +/obj/item/weapon/medical/teleporter/attack(mob/M, mob/user, def_zone) + return + +/obj/item/weapon/medical/teleporter/proc/teleport(mob/H, obj/beacon, I) + if(H) + if(beacon) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, H) + s2.set_up(3, 1, beacon) + s.start() + s2.start() + H.loc = get_turf(beacon) + if (src) + qdel(src) + H.overlays -= I + qdel(I) + + + + + diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm index fde34d6666ad..f9e3e65abb26 100644 --- a/code/game/objects/items/devices/radio/electropack.dm +++ b/code/game/objects/items/devices/radio/electropack.dm @@ -1,127 +1,127 @@ -/obj/item/device/radio/electropack - name = "electropack" - desc = "Dance my monkeys! DANCE!!!" - icon_state = "electropack0" - item_state = "electropack" - frequency = 1449 - flags = CONDUCT - slot_flags = SLOT_BACK - w_class = 5.0 - g_amt = 2500 - m_amt = 10000 - var/code = 2 - -/obj/item/device/radio/electropack/attack_hand(mob/user) - if(src == user.back) - to_chat(user, "You need help taking this off!") - return - ..() - -/obj/item/device/radio/electropack/attackby(obj/item/weapon/W, mob/user) - ..() - 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(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) - sleep(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 && !wires.is_index_cut(RADIO_WIRE_SIGNAL)) - master.receive_signal() - return - -/obj/item/device/radio/electropack/attack_self(mob/user, 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(entity_ja(dat), "window=radio") - onclose(user, "radio") - return +/obj/item/device/radio/electropack + name = "electropack" + desc = "Dance my monkeys! DANCE!!!" + icon_state = "electropack0" + item_state = "electropack" + frequency = 1449 + flags = CONDUCT + slot_flags = SLOT_BACK + w_class = 5.0 + g_amt = 2500 + m_amt = 10000 + var/code = 2 + +/obj/item/device/radio/electropack/attack_hand(mob/user) + if(src == user.back) + to_chat(user, "You need help taking this off!") + return + ..() + +/obj/item/device/radio/electropack/attackby(obj/item/weapon/W, mob/user) + ..() + 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(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) + sleep(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 && !wires.is_index_cut(RADIO_WIRE_SIGNAL)) + master.receive_signal() + return + +/obj/item/device/radio/electropack/attack_self(mob/user, 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(entity_ja(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 a436126adc93..b8a3fc48d6f0 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -1,301 +1,301 @@ -/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" - g_amt = 0 - m_amt = 75 - 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 - - var/ks1type = /obj/item/device/encryptionkey - var/ks2type = null - -/obj/item/device/radio/headset/atom_init() - . = ..() - if(ks1type) - keyslot1 = new ks1type(src) - if(ks2type) - keyslot2 = new ks2type(src) - recalculateChannels() - -/obj/item/device/radio/headset/Destroy() - qdel(keyslot1) - qdel(keyslot2) - keyslot1 = null - keyslot2 = null - return ..() - -/obj/item/device/radio/headset/receive_range(freq, level, aiOverride = 0) - if (aiOverride) - return ..(freq, level) - if(ishuman(src.loc)) - var/mob/living/carbon/human/H = src.loc - if(H.l_ear == src || H.r_ear == src) - return ..(freq, level) - return -1 - -/obj/item/device/radio/headset/syndicate - syndie = 1 - ks1type = /obj/item/device/encryptionkey/syndicate - grid = TRUE - -/obj/item/device/radio/headset/syndicate/alt - icon_state = "syndie_headset" - item_state = "syndie_headset" - -/obj/item/device/radio/headset/binary - origin_tech = "syndicate=3" - ks1type = /obj/item/device/encryptionkey/binary - -/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 = 'icons/obj/radio.dmi' - icon_state = "sec_headset" - item_state = "headset" - ks2type = /obj/item/device/encryptionkey/headset_sec - -/obj/item/device/radio/headset/headset_sec/marinad - name = "marine headset" - icon_state = "marinad" - item_state = "headset" - desc = "Buzzz.... That's nine-nine charlie, requesting backup. Buzzz.... To access the security channel, use :s." - -/obj/item/device/radio/headset/headset_int - name = "internal affairs radio headset" - desc = "The headset of the NanoTrasen dog. To access the security channel, use :s. For command, use :c." - icon = 'icons/obj/radio.dmi' - icon_state = "int_headset" - item_state = "int_headset" - ks2type = /obj/item/device/encryptionkey/headset_int - -/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" - ks2type = /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" - ks2type = /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 = 'icons/obj/radio.dmi' - icon_state = "med_headset" - item_state = "headset" - ks2type = /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 = 'icons/obj/radio.dmi' - icon_state = "sci_headset" - item_state = "headset" - ks2type = /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 = 'icons/obj/radio.dmi' - icon_state = "medsci_headset" - item_state = "headset" - ks2type = /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" - ks2type = /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, :m - medical, :n - science." - icon = 'icons/obj/radio.dmi' - icon_state = "cap_headset" - item_state = "headset" - ks2type = /obj/item/device/encryptionkey/heads/captain - grid = TRUE - -/obj/item/device/radio/headset/heads/ai_integrated //No need to care about icons, it should be hidden inside the AI anyway. - name = "AI Subspace Transceiver" - desc = "Integrated AI radio transceiver." - icon = 'icons/obj/robot_component.dmi' - icon_state = "radio" - item_state = "headset" - ks2type = /obj/item/device/encryptionkey/heads/ai_integrated - var/myAi = null // Atlantis: Reference back to the AI which has this radio. - var/disabledAi = 0 // Atlantis: Used to manually disable AI's integrated radio via intellicard menu. - -/obj/item/device/radio/headset/heads/ai_integrated/receive_range(freq, level) - if (disabledAi) - return -1 //Transciever Disabled. - return ..(freq, level, 1) - -/obj/item/device/radio/headset/heads/ai_integrated/emp_act() - return - -/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 = 'icons/obj/radio.dmi' - icon_state = "rd_headset" - item_state = "headset" - ks2type = /obj/item/device/encryptionkey/heads/rd - grid = TRUE - -/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 = 'icons/obj/radio.dmi' - icon_state = "hos_headset" - item_state = "headset" - ks2type = /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 = 'icons/obj/radio.dmi' - icon_state = "ce_headset" - item_state = "headset" - ks2type = /obj/item/device/encryptionkey/heads/ce - grid = TRUE - -/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 = 'icons/obj/radio.dmi' - icon_state = "cmo_headset" - item_state = "headset" - ks2type = /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, :c - command, :s - security" - icon = 'icons/obj/radio.dmi' - icon_state = "hop_headset" - item_state = "headset" - ks2type = /obj/item/device/encryptionkey/heads/hop -/* -/obj/item/device/radio/headset/headset_mine - name = "mining radio headset" - desc = "Headset used by miners. How useless. To access the mining channel, use :d." - icon_state = "mine_headset" - item_state = "headset" - ks2type = /obj/item/device/encryptionkey/headset_mine - -/obj/item/device/radio/headset/heads/qm - name = "quartermaster's headset" - desc = "The headset of the man who control your toiletpaper supply. To access the cargo channel, use :q. For mining, use :d." - icon_state = "cargo_headset" - item_state = "headset" - ks2type = /obj/item/device/encryptionkey/heads/qm -*/ -/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 = 'icons/obj/radio.dmi' - icon_state = "cargo_headset" - item_state = "headset" - ks2type = /obj/item/device/encryptionkey/headset_cargo - -/obj/item/device/radio/headset/ert - name = "CentCom Response Team headset" - desc = "The headset of the boss's boss. Channels are as follows: :h - Response Team :c - command, :s - security, :e - engineering, :u - supply, :m - medical, :n - science." - icon_state = "com_headset" - item_state = "headset" - freerange = 1 - ks2type = /obj/item/device/encryptionkey/ert - grid = TRUE - -/obj/item/device/radio/headset/deathsquad - grid = TRUE - -/obj/item/device/radio/headset/deathsquad/atom_init() - . = ..() - set_frequency(1341) - -/obj/item/device/radio/headset/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/device/radio_grid)) - if(grid) - to_chat(user, "There is already installed Shielded grid!") - return - to_chat(user, "You attach [W] to [src]!") - user.drop_item() - var/obj/item/device/radio_grid/new_grid = W - new_grid.attach(src) - else if(istype(W, /obj/item/weapon/wirecutters)) - if(!grid) - to_chat(user, "Nothing to cut here!") - return - to_chat(user, "You pop out Shielded grid from [src]!") - var/obj/item/device/radio_grid/new_grid = new(get_turf(loc)) - new_grid.dettach(src) - else if(istype(W, /obj/item/weapon/screwdriver)) - if(!keyslot1 && !keyslot2) - to_chat(user, "This headset doesn't have any encryption keys! How useless...") - return - for(var/ch_name in channels) - radio_controller.remove_object(src, radiochannels[ch_name]) - secure_radio_connections[ch_name] = null - var/turf/T = get_turf(user) - if(keyslot1) - keyslot1.loc = T - keyslot1 = null - if(keyslot2) - keyslot2.loc = T - keyslot2 = null - recalculateChannels() - playsound(user, 'sound/items/Screwdriver.ogg', 50, 1) - to_chat(user, "You pop out the encryption keys in the headset!") - else if(istype(W, /obj/item/device/encryptionkey/)) - if(keyslot1 && keyslot2) - to_chat(user, "The headset can't hold another key!") - return - if(!keyslot1) - user.drop_item() - W.loc = src - keyslot1 = W - else - user.drop_item() - W.loc = src - keyslot2 = W - recalculateChannels() - -/obj/item/device/radio/headset/proc/recalculateChannels() - channels = list() - translate_binary = 0 - translate_hive = 0 - syndie = 0 - for(var/obj/item/device/encryptionkey/Slot in list(keyslot1, keyslot2)) - for(var/ch_name in Slot.channels) - if(ch_name in channels) - continue - channels += ch_name - channels[ch_name] = Slot.channels[ch_name] - if(Slot.translate_binary) - translate_binary = 1 - if(Slot.translate_hive) - translate_hive = 1 - if(Slot.syndie) - syndie = 1 - for (var/ch_name in channels) - if(!radio_controller) - sleep(30) // Waiting for the radio_controller to be created. - if(!radio_controller) - name = "broken radio headset" - return - secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT) +/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" + g_amt = 0 + m_amt = 75 + 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 + + var/ks1type = /obj/item/device/encryptionkey + var/ks2type = null + +/obj/item/device/radio/headset/atom_init() + . = ..() + if(ks1type) + keyslot1 = new ks1type(src) + if(ks2type) + keyslot2 = new ks2type(src) + recalculateChannels() + +/obj/item/device/radio/headset/Destroy() + qdel(keyslot1) + qdel(keyslot2) + keyslot1 = null + keyslot2 = null + return ..() + +/obj/item/device/radio/headset/receive_range(freq, level, aiOverride = 0) + if (aiOverride) + return ..(freq, level) + if(ishuman(src.loc)) + var/mob/living/carbon/human/H = src.loc + if(H.l_ear == src || H.r_ear == src) + return ..(freq, level) + return -1 + +/obj/item/device/radio/headset/syndicate + syndie = 1 + ks1type = /obj/item/device/encryptionkey/syndicate + grid = TRUE + +/obj/item/device/radio/headset/syndicate/alt + icon_state = "syndie_headset" + item_state = "syndie_headset" + +/obj/item/device/radio/headset/binary + origin_tech = "syndicate=3" + ks1type = /obj/item/device/encryptionkey/binary + +/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 = 'icons/obj/radio.dmi' + icon_state = "sec_headset" + item_state = "headset" + ks2type = /obj/item/device/encryptionkey/headset_sec + +/obj/item/device/radio/headset/headset_sec/marinad + name = "marine headset" + icon_state = "marinad" + item_state = "headset" + desc = "Buzzz.... That's nine-nine charlie, requesting backup. Buzzz.... To access the security channel, use :s." + +/obj/item/device/radio/headset/headset_int + name = "internal affairs radio headset" + desc = "The headset of the NanoTrasen dog. To access the security channel, use :s. For command, use :c." + icon = 'icons/obj/radio.dmi' + icon_state = "int_headset" + item_state = "int_headset" + ks2type = /obj/item/device/encryptionkey/headset_int + +/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" + ks2type = /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" + ks2type = /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 = 'icons/obj/radio.dmi' + icon_state = "med_headset" + item_state = "headset" + ks2type = /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 = 'icons/obj/radio.dmi' + icon_state = "sci_headset" + item_state = "headset" + ks2type = /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 = 'icons/obj/radio.dmi' + icon_state = "medsci_headset" + item_state = "headset" + ks2type = /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" + ks2type = /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, :m - medical, :n - science." + icon = 'icons/obj/radio.dmi' + icon_state = "cap_headset" + item_state = "headset" + ks2type = /obj/item/device/encryptionkey/heads/captain + grid = TRUE + +/obj/item/device/radio/headset/heads/ai_integrated //No need to care about icons, it should be hidden inside the AI anyway. + name = "AI Subspace Transceiver" + desc = "Integrated AI radio transceiver." + icon = 'icons/obj/robot_component.dmi' + icon_state = "radio" + item_state = "headset" + ks2type = /obj/item/device/encryptionkey/heads/ai_integrated + var/myAi = null // Atlantis: Reference back to the AI which has this radio. + var/disabledAi = 0 // Atlantis: Used to manually disable AI's integrated radio via intellicard menu. + +/obj/item/device/radio/headset/heads/ai_integrated/receive_range(freq, level) + if (disabledAi) + return -1 //Transciever Disabled. + return ..(freq, level, 1) + +/obj/item/device/radio/headset/heads/ai_integrated/emp_act() + return + +/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 = 'icons/obj/radio.dmi' + icon_state = "rd_headset" + item_state = "headset" + ks2type = /obj/item/device/encryptionkey/heads/rd + grid = TRUE + +/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 = 'icons/obj/radio.dmi' + icon_state = "hos_headset" + item_state = "headset" + ks2type = /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 = 'icons/obj/radio.dmi' + icon_state = "ce_headset" + item_state = "headset" + ks2type = /obj/item/device/encryptionkey/heads/ce + grid = TRUE + +/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 = 'icons/obj/radio.dmi' + icon_state = "cmo_headset" + item_state = "headset" + ks2type = /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, :c - command, :s - security" + icon = 'icons/obj/radio.dmi' + icon_state = "hop_headset" + item_state = "headset" + ks2type = /obj/item/device/encryptionkey/heads/hop +/* +/obj/item/device/radio/headset/headset_mine + name = "mining radio headset" + desc = "Headset used by miners. How useless. To access the mining channel, use :d." + icon_state = "mine_headset" + item_state = "headset" + ks2type = /obj/item/device/encryptionkey/headset_mine + +/obj/item/device/radio/headset/heads/qm + name = "quartermaster's headset" + desc = "The headset of the man who control your toiletpaper supply. To access the cargo channel, use :q. For mining, use :d." + icon_state = "cargo_headset" + item_state = "headset" + ks2type = /obj/item/device/encryptionkey/heads/qm +*/ +/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 = 'icons/obj/radio.dmi' + icon_state = "cargo_headset" + item_state = "headset" + ks2type = /obj/item/device/encryptionkey/headset_cargo + +/obj/item/device/radio/headset/ert + name = "CentCom Response Team headset" + desc = "The headset of the boss's boss. Channels are as follows: :h - Response Team :c - command, :s - security, :e - engineering, :u - supply, :m - medical, :n - science." + icon_state = "com_headset" + item_state = "headset" + freerange = 1 + ks2type = /obj/item/device/encryptionkey/ert + grid = TRUE + +/obj/item/device/radio/headset/deathsquad + grid = TRUE + +/obj/item/device/radio/headset/deathsquad/atom_init() + . = ..() + set_frequency(1341) + +/obj/item/device/radio/headset/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/device/radio_grid)) + if(grid) + to_chat(user, "There is already installed Shielded grid!") + return + to_chat(user, "You attach [W] to [src]!") + user.drop_item() + var/obj/item/device/radio_grid/new_grid = W + new_grid.attach(src) + else if(istype(W, /obj/item/weapon/wirecutters)) + if(!grid) + to_chat(user, "Nothing to cut here!") + return + to_chat(user, "You pop out Shielded grid from [src]!") + var/obj/item/device/radio_grid/new_grid = new(get_turf(loc)) + new_grid.dettach(src) + else if(istype(W, /obj/item/weapon/screwdriver)) + if(!keyslot1 && !keyslot2) + to_chat(user, "This headset doesn't have any encryption keys! How useless...") + return + for(var/ch_name in channels) + radio_controller.remove_object(src, radiochannels[ch_name]) + secure_radio_connections[ch_name] = null + var/turf/T = get_turf(user) + if(keyslot1) + keyslot1.loc = T + keyslot1 = null + if(keyslot2) + keyslot2.loc = T + keyslot2 = null + recalculateChannels() + playsound(user, 'sound/items/Screwdriver.ogg', 50, 1) + to_chat(user, "You pop out the encryption keys in the headset!") + else if(istype(W, /obj/item/device/encryptionkey/)) + if(keyslot1 && keyslot2) + to_chat(user, "The headset can't hold another key!") + return + if(!keyslot1) + user.drop_item() + W.loc = src + keyslot1 = W + else + user.drop_item() + W.loc = src + keyslot2 = W + recalculateChannels() + +/obj/item/device/radio/headset/proc/recalculateChannels() + channels = list() + translate_binary = 0 + translate_hive = 0 + syndie = 0 + for(var/obj/item/device/encryptionkey/Slot in list(keyslot1, keyslot2)) + for(var/ch_name in Slot.channels) + if(ch_name in channels) + continue + channels += ch_name + channels[ch_name] = Slot.channels[ch_name] + if(Slot.translate_binary) + translate_binary = 1 + if(Slot.translate_hive) + translate_hive = 1 + if(Slot.syndie) + syndie = 1 + for (var/ch_name in channels) + if(!radio_controller) + sleep(30) // Waiting for the radio_controller to be created. + if(!radio_controller) + name = "broken radio headset" + return + secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT) diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index af0d813f2fa3..be040387e708 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -1,74 +1,74 @@ -/obj/item/device/radio/intercom - name = "station intercom" - desc = "Talk through this." - icon_state = "intercom" - anchored = 1 - w_class = 4.0 - canhear_range = 2 - flags = CONDUCT | NOBLOODY - var/number = 0 - var/anyai = 1 - var/mob/living/silicon/ai/ai = list() - var/last_tick //used to delay the powercheck - -/obj/item/device/radio/intercom/atom_init() - . = ..() - START_PROCESSING(SSobj, src) - -/obj/item/device/radio/intercom/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/device/radio/intercom/attack_ai(mob/user) - src.add_fingerprint(user) - INVOKE_ASYNC(src, .proc/attack_self, user) - -/obj/item/device/radio/intercom/attack_paw(mob/user) - to_chat(user, "The console controls are far too complicated for your tiny brain!") - return - - -/obj/item/device/radio/intercom/attack_hand(mob/user) - src.add_fingerprint(user) - INVOKE_ASYNC(src, .proc/attack_self, user) - -/obj/item/device/radio/intercom/receive_range(freq, level) - if (!on) - return -1 - if (wires.is_index_cut(RADIO_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_talk(mob/M, msg) - if(!src.anyai && !(M in src.ai)) - return - ..() - -/obj/item/device/radio/intercom/process() - if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0)) - last_tick = world.timeofday - - if(!src.loc) - on = 0 - else - var/area/A = src.loc.loc - if(!A || !isarea(A) || !A.master) - on = 0 - else - on = A.master.powered(EQUIP) // set "on" to the power status - - if(!on) - icon_state = "intercom-p" - else - icon_state = "intercom" +/obj/item/device/radio/intercom + name = "station intercom" + desc = "Talk through this." + icon_state = "intercom" + anchored = 1 + w_class = 4.0 + canhear_range = 2 + flags = CONDUCT | NOBLOODY + var/number = 0 + var/anyai = 1 + var/mob/living/silicon/ai/ai = list() + var/last_tick //used to delay the powercheck + +/obj/item/device/radio/intercom/atom_init() + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/device/radio/intercom/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/device/radio/intercom/attack_ai(mob/user) + src.add_fingerprint(user) + INVOKE_ASYNC(src, .proc/attack_self, user) + +/obj/item/device/radio/intercom/attack_paw(mob/user) + to_chat(user, "The console controls are far too complicated for your tiny brain!") + return + + +/obj/item/device/radio/intercom/attack_hand(mob/user) + src.add_fingerprint(user) + INVOKE_ASYNC(src, .proc/attack_self, user) + +/obj/item/device/radio/intercom/receive_range(freq, level) + if (!on) + return -1 + if (wires.is_index_cut(RADIO_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_talk(mob/M, msg) + if(!src.anyai && !(M in src.ai)) + return + ..() + +/obj/item/device/radio/intercom/process() + if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0)) + last_tick = world.timeofday + + if(!src.loc) + on = 0 + else + var/area/A = src.loc.loc + if(!A || !isarea(A) || !A.master) + on = 0 + else + on = A.master.powered(EQUIP) // set "on" to the power status + + if(!on) + icon_state = "intercom-p" + else + icon_state = "intercom" diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index abe9c317d0f7..849577a37149 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -1,846 +1,846 @@ -var/GLOBAL_RADIO_TYPE = 1 // radio type to use - // 0 = old radios - // 1 = new radios (subspace technology) - - -/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/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 - var/grid = FALSE // protect from EMP - flags = CONDUCT - slot_flags = SLOT_BELT - throw_speed = 2 - throw_range = 9 - w_class = 2 - g_amt = 25 - m_amt = 75 - var/const/FREQ_LISTENING = 1 - //FREQ_BROADCASTING = 2 - -/obj/item/device/radio - var/datum/radio_frequency/radio_connection - var/list/datum/radio_frequency/secure_radio_connections = new - - proc/set_frequency(new_frequency) - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) - -/obj/item/device/radio/atom_init() - . = ..() - - wires = new(src) - - 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/ch_name in channels) - secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT) - -/obj/item/device/radio/Destroy() - QDEL_NULL(wires) - if(radio_controller) - radio_controller.remove_object(src, frequency) - for (var/ch_name in channels) - radio_controller.remove_object(src, radiochannels[ch_name]) - if(secure_radio_connections) - for(var/ch_name in channels) - secure_radio_connections[ch_name] = radio_controller.remove_object(src, radiochannels[ch_name]) - return ..() - -/obj/item/device/radio/attack_self(mob/user) - user.set_machine(src) - if(!wires.interact(user)) - interact(user) - -/obj/item/device/radio/interact(mob/user) - if(!on) - return - - if(active_uplink_check(user)) - return - - var/dat - - 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]) - - var/datum/browser/popup = new(user, "window=radio", "[src]") - popup.set_content(dat) - popup.open() - return - -/obj/item/device/radio/proc/text_sec_channel(chan_name, chan_stat) - var/list = !!(chan_stat&FREQ_LISTENING)!=0 - return {" - [chan_name]
                    - Speaker: [list ? "Engaged" : "Disengaged"]
                    - "} - -/obj/item/device/radio/Topic(href, href_list) - //..() - if ((usr.stat && !IsAdminGhost(usr)) || !on) - return - - if (!(issilicon(usr) || IsAdminGhost(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["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) - 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/autosay(message, from, channel) //BS12 EDIT - var/datum/radio_frequency/connection = null - if(channel && channels && channels.len > 0) - if (channel == "department") - //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, A, - 0, "*garbled automated announcement*", src, - message, from, "Automated Announcement", from, "synthesized voice", - 4, 0, list(1), 1459) - qdel(A) - return - -/obj/item/device/radio/talk_into(mob/living/M, message, channel, verb = "says", datum/language/speaking = null) - if(!on) return // the device has to be on - // Fix for permacell radios, but kinda eh about actually fixing them. - if(!M || !message) return - - // 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(wires.is_index_cut(RADIO_WIRE_TRANSMIT)) // The device has to have all its wires and shit intact - return - - - if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl - - /* 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. - */ - - //#### Grab the connection datum ####// - var/datum/radio_frequency/connection = null - if(channel == "headset") - channel = null - if(channel) // If a channel is specified, look for it. - if(channels && channels.len > 0) - if (channel == "department") - //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"" - channel = channels[1] - connection = secure_radio_connections[channel] - if (!channels[channel]) // if the channel is turned off, don't broadcast - return - else - // If we were to send to a channel we don't have, drop it. - else // If a channel isn't specified, send to common. - connection = radio_connection - channel = null - if (!istype(connection)) - return - if (!connection) - return - - var/turf/position = get_turf(src) - - //#### Tagging the signal with all appropriate identity values ####// - - // ||-- The mob's name identity --|| - var/displayname = M.name // grab the display name (name you get when you hover over someone's icon) - var/real_name = M.real_name // mob's real name - var/mobkey = "none" // player key associated with mob - var/voicemask = 0 // the speaker is wearing a voice mask - if(M.client) - mobkey = M.key // assign the mob's key - - - var/jobname // the mob's "job" - - // --- Human: use their actual job --- - if (ishuman(M)) - jobname = M:get_assignment() - - // --- Carbon Nonhuman --- - else if (iscarbon(M)) // Nonhuman carbon mob - jobname = "No id" - - // --- AI --- - else if (isAI(M)) - jobname = "AI" - - // --- Cyborg --- - else if (isrobot(M)) - jobname = "Cyborg" - - // --- Personal AI (pAI) --- - else if (istype(M, /mob/living/silicon/pai)) - jobname = "Personal AI" - - // --- Unidentifiable mob --- - else - jobname = "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 = new - 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" = M, // store a reference to the mob - "mobtype" = M.type, // the mob's type - "realname" = real_name, // the mob's real name - "name" = displayname, // the mob's display name - "job" = jobname, // the mob's job - "key" = mobkey, // the mob's key - "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood - "vname" = M.voice_name, // the name to display if the voice wasn't understood - "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" = message, // the actual sent message - "connection" = connection, // the radio connection to use - "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" = speaking, - "verb" = verb - ) - signal.frequency = connection.frequency // Quick frequency set - - //#### 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 - 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 = new - signal.transmission_method = 2 - - - /* --- Try to send a normal subspace broadcast first */ - - signal.data = list( - - "mob" = M, // store a reference to the mob - "mobtype" = M.type, // the mob's type - "realname" = real_name, // the mob's real name - "name" = displayname, // the mob's display name - "job" = jobname, // the mob's job - "key" = mobkey, // the mob's key - "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood - "vname" = M.voice_name, // the name to display if the voice wasn't understood - "vmask" = voicemask, // 1 if the mob is using a voice gas mas - - "compression" = 0, // uncompressed radio signal - "message" = message, // the actual sent message - "connection" = connection, // the radio connection to use - "radio" = src, // stores the radio used for transmission - "slow" = 0, - "traffic" = 0, - "type" = 0, - "server" = null, - "reject" = 0, - "level" = position.z, - "language" = speaking, - "verb" = verb - ) - signal.frequency = connection.frequency // Quick frequency set - - for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - R.receive_signal(signal) - - - sleep(rand(10,25)) // wait a little... - - if(signal.data["done"] && position.z in signal.data["level"]) - // we're done here. - 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: - - //THIS IS TEMPORARY. - if(!connection) return //~Carn - - Broadcast_Message(connection, M, voicemask, pick(M.speak_emote), - src, message, displayname, jobname, real_name, M.voice_name, - filter_type, signal.data["compression"], list(position.z), connection.frequency,verb,speaking) - - - - else // OLD RADIO SYSTEMS: By Goons? - - var/datum/radio_frequency/connection = null - if(channel && channels && channels.len > 0) - if (channel == "department") - //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 - var/display_freq = connection.frequency - - //world << "DEBUG: used channel=\"[channel]\" frequency= \"[display_freq]\" connection.devices.len = [connection.devices.len]" - - var/eqjobname - - if (ishuman(M)) - eqjobname = M:get_assignment() - else if (iscarbon(M)) - eqjobname = "No id" //only humans can wear ID - else if (isAI(M)) - eqjobname = "AI" - else if (isrobot(M)) - eqjobname = "Cyborg"//Androids don't really describe these too well, in my opinion. - else if (istype(M, /mob/living/silicon/pai)) - eqjobname = "Personal AI" - else - eqjobname = "Unknown" - - if (wires.is_index_cut(RADIO_WIRE_TRANSMIT)) - return - - var/list/receive = list() - - //for (var/obj/item/device/radio/R in radio_connection.devices) - for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) // Modified for security headset code -- TLE - //if(R.accept_rad(src, message)) - receive |= R.send_hear(display_freq, 0) - - //world << "DEBUG: receive.len=[receive.len]" - var/list/heard_masked = list() // masked name or no real name - var/list/heard_normal = list() // normal message - var/list/heard_voice = list() // voice message - var/list/heard_garbled = list() // garbled message - - for (var/mob/R in receive) - if (R.client && !(R.client.prefs.chat_toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. - continue - if (R.say_understands(M)) - if (ishuman(M) && M.GetVoice() != M.real_name) - heard_masked += R - else - heard_normal += R - else - heard_voice += R - - if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled)) - var/part_a = "" - //var/part_b = " [bicon(src)]\[[format_frequency(frequency)]\] " - var/freq_text - switch(display_freq) - if(SYND_FREQ) - freq_text = "#unkn" - if(COMM_FREQ) - freq_text = "Command" - if(1351) - freq_text = "Science" - if(1355) - freq_text = "Medical" - if(1357) - freq_text = "Engineering" - if(1359) - freq_text = "Security" - if(1347) - freq_text = "Supply" - //There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO - - if(!freq_text) - freq_text = format_frequency(display_freq) - - var/part_b = " [bicon(src)]\[[freq_text]\] " // Tweaked for security headsets -- TLE - var/part_c = "" - - if (display_freq==SYND_FREQ) - part_a = "" - else if (display_freq==COMM_FREQ) - part_a = "" - else if (display_freq in DEPT_FREQS) - part_a = "" - - var/quotedmsg = M.say_quote(message) - - //This following recording is intended for research and feedback in the use of department radio channels. - - var/part_blackbox_b = " \[[freq_text]\] " // Tweaked for security headsets -- TLE - var/blackbox_msg = "[part_a][M.name][part_blackbox_b][quotedmsg][part_c]" - //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]" - if(istype(blackbox)) - //BR.messages_admin += blackbox_admin_msg - switch(display_freq) - if(1459) - blackbox.msg_common += blackbox_msg - if(1351) - blackbox.msg_science += blackbox_msg - if(1353) - blackbox.msg_command += blackbox_msg - if(1355) - blackbox.msg_medical += blackbox_msg - if(1357) - blackbox.msg_engineering += blackbox_msg - if(1359) - blackbox.msg_security += blackbox_msg - if(1441) - blackbox.msg_deathsquad += blackbox_msg - if(1213) - blackbox.msg_syndicate += blackbox_msg - if(1349) - blackbox.msg_mining += blackbox_msg - if(1347) - blackbox.msg_cargo += blackbox_msg - else - blackbox.messages += blackbox_msg - - //End of research and feedback code. - - if (length(heard_masked)) - var/N = M.name - var/J = eqjobname - if(ishuman(M) && M.GetVoice() != M.real_name) - N = M.GetVoice() - J = "Unknown" - var/rendered = "[part_a][N][part_b][quotedmsg][part_c]" - for (var/mob/R in heard_masked) - if(istype(R, /mob/living/silicon/ai)) - R.show_message("[part_a][N] ([J]) [part_b][quotedmsg][part_c]", 2) - else - R.show_message(rendered, 2) - - if (length(heard_normal)) - var/rendered = "[part_a][M.real_name][part_b][quotedmsg][part_c]" - - for (var/mob/R in heard_normal) - if(istype(R, /mob/living/silicon/ai)) - R.show_message("[part_a][M.real_name] ([eqjobname]) [part_b][quotedmsg][part_c]", 2) - else - R.show_message(rendered, 2) - - if (length(heard_voice)) - var/rendered = "[part_a][M.voice_name][part_b][pick(M.speak_emote)][part_c]" - - for (var/mob/R in heard_voice) - if(istype(R, /mob/living/silicon/ai)) - R.show_message("[part_a][M.voice_name] ([eqjobname]) [part_b][pick(M.speak_emote)][part_c]", 2) - else - R.show_message(rendered, 2) - - if (length(heard_garbled)) - quotedmsg = M.say_quote(stars(message)) - var/rendered = "[part_a][M.voice_name][part_b][quotedmsg][part_c]" - - for (var/mob/R in heard_voice) - if(istype(R, /mob/living/silicon/ai)) - R.show_message("[part_a][M.voice_name][part_b][quotedmsg][part_c]", 2) - else - R.show_message(rendered, 2) - -/obj/item/device/radio/hear_talk(mob/M, msg, verb = "says", datum/language/speaking = null) - - if (broadcasting) - if(get_dist(src, M) <= canhear_range) - talk_into(M, msg,null,verb,speaking) - - -/* -/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R, 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 (wires.is_index_cut(RADIO_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) - var/datum/radio_frequency/RF = secure_radio_connections[ch_name] - if (RF.frequency==freq && (channels[ch_name]&FREQ_LISTENING)) - 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_mobs_in_view(canhear_range, src) - - -/obj/item/device/radio/examine(mob/user) - ..() - if (src in view(1, user)) - to_chat(user, "\the [src] can[b_stat ? "" : " not"] be attached or modified!") - -/obj/item/device/radio/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/device/radio_grid)) - if(grid) - to_chat(user, "There is already installed Shielded grid!") - return - to_chat(user, "You attach [W] to [src]!") - user.drop_item() - var/obj/item/device/radio_grid/new_grid = W - new_grid.attach(src) - else if(istype(W, /obj/item/weapon/wirecutters)) - if(!grid) - to_chat(user, "Nothing to cut here!") - return - to_chat(user, "You pop out Shielded grid from [src]!") - var/obj/item/device/radio_grid/new_grid = new(get_turf(loc)) - new_grid.dettach(src) - else if (istype(W, /obj/item/weapon/screwdriver)) - b_stat = !b_stat - add_fingerprint(user) - playsound(user, 'sound/items/Screwdriver.ogg', 50, 1) - if(!istype(src, /obj/item/device/radio/beacon)) - to_chat(user, "The radio can [b_stat ? "now" : "no longer"] be attached and modified!") - else - ..() - -/obj/item/device/radio/emp_act(severity) - if(!grid) - on = 0 - ..() -/* broadcasting = 0 - listening = 0 - for (var/ch_name in channels) - channels[ch_name] = 0 */ - - -/////////////////////////////// -//////////Borg Radios////////// -/////////////////////////////// -//Giving borgs their own radio to have some more room to work with -Sieve - -/obj/item/device/radio/borg - var/mob/living/silicon/robot/myborg = null // Cyborg which owns this radio. Used for power checks - var/obj/item/device/encryptionkey/keyslot = null//Borg radios can handle a single encryption key - icon = 'icons/obj/robot_component.dmi' // Cyborgs radio icons should look like the component. - icon_state = "radio" - canhear_range = 0 // Should prevent everyone around the cyborg hearing potentionally secret stuff from department channels (espicially sec) - -/obj/item/device/radio/borg/attackby(obj/item/weapon/W, mob/user) -// ..() - 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(keyslot) - - - for(var/ch_name in channels) - radio_controller.remove_object(src, radiochannels[ch_name]) - secure_radio_connections[ch_name] = null - - - if(keyslot) - var/turf/T = get_turf(user) - if(T) - keyslot.loc = T - keyslot = null - - recalculateChannels() - to_chat(user, "You pop out the encryption key in the radio!") - - else - to_chat(user, "This radio doesn't have any encryption keys!") - - if(istype(W, /obj/item/device/encryptionkey/)) - if(keyslot) - to_chat(user, "The radio can't hold another key!") - return - - if(!keyslot) - user.drop_item() - W.loc = src - keyslot = W - - recalculateChannels() - - return - -/obj/item/device/radio/borg/proc/recalculateChannels() - src.channels = list() - src.syndie = 0 - - var/mob/living/silicon/robot/D = src.loc - if(D.module) - for(var/ch_name in D.module.channels) - if(ch_name in src.channels) - continue - src.channels += ch_name - src.channels[ch_name] += D.module.channels[ch_name] - if(keyslot) - for(var/ch_name in keyslot.channels) - if(ch_name in src.channels) - continue - src.channels += ch_name - src.channels[ch_name] += keyslot.channels[ch_name] - - if(keyslot.syndie) - src.syndie = 1 - - - for (var/ch_name in src.channels) - if(!radio_controller) - sleep(30) // Waiting for the radio_controller to be created. - if(!radio_controller) - src.name = "broken radio" - return - - secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT) - - return - -/obj/item/device/radio/borg/Topic(href, href_list) - if(usr.stat || !on) - return - if (href_list["mode"]) - if(subspace_transmission != 1) - subspace_transmission = 1 - to_chat(usr, "Subspace Transmission is disabled") - else - subspace_transmission = 0 - to_chat(usr, "Subspace Transmission is enabled") - if(subspace_transmission == 1)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled - channels = list() - else - recalculateChannels() - ..() - -/obj/item/device/radio/borg/interact(mob/user) - if(!on) - return - - var/dat = "[src]" - dat += {" - Speaker: [listening ? "Engaged" : "Disengaged"]
                    - Frequency: - - - - - [format_frequency(frequency)] - + - +
                    - Toggle Broadcast Mode
                    - "} - - if(!subspace_transmission)//Don't even bother if subspace isn't turned on - for (var/ch_name in channels) - dat+=text_sec_channel(ch_name, channels[ch_name]) - user << browse(entity_ja(dat), "window=radio") - onclose(user, "radio") - return - - -/obj/item/device/radio/proc/config(op) - if(radio_controller) - for (var/ch_name in channels) - radio_controller.remove_object(src, radiochannels[ch_name]) - secure_radio_connections = new - channels = op - if(radio_controller) - for (var/ch_name in op) - secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT) - return - -/obj/item/device/radio/off - listening = 0 - -/obj/item/device/radio_grid - name = "Shielded grid" - desc = "A metal grid, attached to circuit to protect it from emitting." - w_class = 2 - icon = 'icons/obj/radio.dmi' - icon_state = "radio_grid" - -/obj/item/device/radio_grid/proc/attach(obj/item/device/radio/radio) - radio.on = TRUE - radio.grid = TRUE - qdel(src) - -/obj/item/device/radio_grid/proc/dettach(obj/item/device/radio/radio) - playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) - if(prob(30)) - radio.on = FALSE - radio.grid = FALSE +var/GLOBAL_RADIO_TYPE = 1 // radio type to use + // 0 = old radios + // 1 = new radios (subspace technology) + + +/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/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 + var/grid = FALSE // protect from EMP + flags = CONDUCT + slot_flags = SLOT_BELT + throw_speed = 2 + throw_range = 9 + w_class = 2 + g_amt = 25 + m_amt = 75 + var/const/FREQ_LISTENING = 1 + //FREQ_BROADCASTING = 2 + +/obj/item/device/radio + var/datum/radio_frequency/radio_connection + var/list/datum/radio_frequency/secure_radio_connections = new + + proc/set_frequency(new_frequency) + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) + +/obj/item/device/radio/atom_init() + . = ..() + + wires = new(src) + + 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/ch_name in channels) + secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT) + +/obj/item/device/radio/Destroy() + QDEL_NULL(wires) + if(radio_controller) + radio_controller.remove_object(src, frequency) + for (var/ch_name in channels) + radio_controller.remove_object(src, radiochannels[ch_name]) + if(secure_radio_connections) + for(var/ch_name in channels) + secure_radio_connections[ch_name] = radio_controller.remove_object(src, radiochannels[ch_name]) + return ..() + +/obj/item/device/radio/attack_self(mob/user) + user.set_machine(src) + if(!wires.interact(user)) + interact(user) + +/obj/item/device/radio/interact(mob/user) + if(!on) + return + + if(active_uplink_check(user)) + return + + var/dat + + 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]) + + var/datum/browser/popup = new(user, "window=radio", "[src]") + popup.set_content(dat) + popup.open() + return + +/obj/item/device/radio/proc/text_sec_channel(chan_name, chan_stat) + var/list = !!(chan_stat&FREQ_LISTENING)!=0 + return {" + [chan_name]
                    + Speaker: [list ? "Engaged" : "Disengaged"]
                    + "} + +/obj/item/device/radio/Topic(href, href_list) + //..() + if ((usr.stat && !IsAdminGhost(usr)) || !on) + return + + if (!(issilicon(usr) || IsAdminGhost(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["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) + 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/autosay(message, from, channel) //BS12 EDIT + var/datum/radio_frequency/connection = null + if(channel && channels && channels.len > 0) + if (channel == "department") + //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, A, + 0, "*garbled automated announcement*", src, + message, from, "Automated Announcement", from, "synthesized voice", + 4, 0, list(1), 1459) + qdel(A) + return + +/obj/item/device/radio/talk_into(mob/living/M, message, channel, verb = "says", datum/language/speaking = null) + if(!on) return // the device has to be on + // Fix for permacell radios, but kinda eh about actually fixing them. + if(!M || !message) return + + // 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(wires.is_index_cut(RADIO_WIRE_TRANSMIT)) // The device has to have all its wires and shit intact + return + + + if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl + + /* 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. + */ + + //#### Grab the connection datum ####// + var/datum/radio_frequency/connection = null + if(channel == "headset") + channel = null + if(channel) // If a channel is specified, look for it. + if(channels && channels.len > 0) + if (channel == "department") + //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"" + channel = channels[1] + connection = secure_radio_connections[channel] + if (!channels[channel]) // if the channel is turned off, don't broadcast + return + else + // If we were to send to a channel we don't have, drop it. + else // If a channel isn't specified, send to common. + connection = radio_connection + channel = null + if (!istype(connection)) + return + if (!connection) + return + + var/turf/position = get_turf(src) + + //#### Tagging the signal with all appropriate identity values ####// + + // ||-- The mob's name identity --|| + var/displayname = M.name // grab the display name (name you get when you hover over someone's icon) + var/real_name = M.real_name // mob's real name + var/mobkey = "none" // player key associated with mob + var/voicemask = 0 // the speaker is wearing a voice mask + if(M.client) + mobkey = M.key // assign the mob's key + + + var/jobname // the mob's "job" + + // --- Human: use their actual job --- + if (ishuman(M)) + jobname = M:get_assignment() + + // --- Carbon Nonhuman --- + else if (iscarbon(M)) // Nonhuman carbon mob + jobname = "No id" + + // --- AI --- + else if (isAI(M)) + jobname = "AI" + + // --- Cyborg --- + else if (isrobot(M)) + jobname = "Cyborg" + + // --- Personal AI (pAI) --- + else if (istype(M, /mob/living/silicon/pai)) + jobname = "Personal AI" + + // --- Unidentifiable mob --- + else + jobname = "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 = new + 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" = M, // store a reference to the mob + "mobtype" = M.type, // the mob's type + "realname" = real_name, // the mob's real name + "name" = displayname, // the mob's display name + "job" = jobname, // the mob's job + "key" = mobkey, // the mob's key + "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood + "vname" = M.voice_name, // the name to display if the voice wasn't understood + "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" = message, // the actual sent message + "connection" = connection, // the radio connection to use + "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" = speaking, + "verb" = verb + ) + signal.frequency = connection.frequency // Quick frequency set + + //#### 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 + 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 = new + signal.transmission_method = 2 + + + /* --- Try to send a normal subspace broadcast first */ + + signal.data = list( + + "mob" = M, // store a reference to the mob + "mobtype" = M.type, // the mob's type + "realname" = real_name, // the mob's real name + "name" = displayname, // the mob's display name + "job" = jobname, // the mob's job + "key" = mobkey, // the mob's key + "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood + "vname" = M.voice_name, // the name to display if the voice wasn't understood + "vmask" = voicemask, // 1 if the mob is using a voice gas mas + + "compression" = 0, // uncompressed radio signal + "message" = message, // the actual sent message + "connection" = connection, // the radio connection to use + "radio" = src, // stores the radio used for transmission + "slow" = 0, + "traffic" = 0, + "type" = 0, + "server" = null, + "reject" = 0, + "level" = position.z, + "language" = speaking, + "verb" = verb + ) + signal.frequency = connection.frequency // Quick frequency set + + for(var/obj/machinery/telecomms/receiver/R in telecomms_list) + R.receive_signal(signal) + + + sleep(rand(10,25)) // wait a little... + + if(signal.data["done"] && position.z in signal.data["level"]) + // we're done here. + 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: + + //THIS IS TEMPORARY. + if(!connection) return //~Carn + + Broadcast_Message(connection, M, voicemask, pick(M.speak_emote), + src, message, displayname, jobname, real_name, M.voice_name, + filter_type, signal.data["compression"], list(position.z), connection.frequency,verb,speaking) + + + + else // OLD RADIO SYSTEMS: By Goons? + + var/datum/radio_frequency/connection = null + if(channel && channels && channels.len > 0) + if (channel == "department") + //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 + var/display_freq = connection.frequency + + //world << "DEBUG: used channel=\"[channel]\" frequency= \"[display_freq]\" connection.devices.len = [connection.devices.len]" + + var/eqjobname + + if (ishuman(M)) + eqjobname = M:get_assignment() + else if (iscarbon(M)) + eqjobname = "No id" //only humans can wear ID + else if (isAI(M)) + eqjobname = "AI" + else if (isrobot(M)) + eqjobname = "Cyborg"//Androids don't really describe these too well, in my opinion. + else if (istype(M, /mob/living/silicon/pai)) + eqjobname = "Personal AI" + else + eqjobname = "Unknown" + + if (wires.is_index_cut(RADIO_WIRE_TRANSMIT)) + return + + var/list/receive = list() + + //for (var/obj/item/device/radio/R in radio_connection.devices) + for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) // Modified for security headset code -- TLE + //if(R.accept_rad(src, message)) + receive |= R.send_hear(display_freq, 0) + + //world << "DEBUG: receive.len=[receive.len]" + var/list/heard_masked = list() // masked name or no real name + var/list/heard_normal = list() // normal message + var/list/heard_voice = list() // voice message + var/list/heard_garbled = list() // garbled message + + for (var/mob/R in receive) + if (R.client && !(R.client.prefs.chat_toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. + continue + if (R.say_understands(M)) + if (ishuman(M) && M.GetVoice() != M.real_name) + heard_masked += R + else + heard_normal += R + else + heard_voice += R + + if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled)) + var/part_a = "" + //var/part_b = " [bicon(src)]\[[format_frequency(frequency)]\] " + var/freq_text + switch(display_freq) + if(SYND_FREQ) + freq_text = "#unkn" + if(COMM_FREQ) + freq_text = "Command" + if(1351) + freq_text = "Science" + if(1355) + freq_text = "Medical" + if(1357) + freq_text = "Engineering" + if(1359) + freq_text = "Security" + if(1347) + freq_text = "Supply" + //There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO + + if(!freq_text) + freq_text = format_frequency(display_freq) + + var/part_b = " [bicon(src)]\[[freq_text]\] " // Tweaked for security headsets -- TLE + var/part_c = "" + + if (display_freq==SYND_FREQ) + part_a = "" + else if (display_freq==COMM_FREQ) + part_a = "" + else if (display_freq in DEPT_FREQS) + part_a = "" + + var/quotedmsg = M.say_quote(message) + + //This following recording is intended for research and feedback in the use of department radio channels. + + var/part_blackbox_b = " \[[freq_text]\] " // Tweaked for security headsets -- TLE + var/blackbox_msg = "[part_a][M.name][part_blackbox_b][quotedmsg][part_c]" + //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]" + if(istype(blackbox)) + //BR.messages_admin += blackbox_admin_msg + switch(display_freq) + if(1459) + blackbox.msg_common += blackbox_msg + if(1351) + blackbox.msg_science += blackbox_msg + if(1353) + blackbox.msg_command += blackbox_msg + if(1355) + blackbox.msg_medical += blackbox_msg + if(1357) + blackbox.msg_engineering += blackbox_msg + if(1359) + blackbox.msg_security += blackbox_msg + if(1441) + blackbox.msg_deathsquad += blackbox_msg + if(1213) + blackbox.msg_syndicate += blackbox_msg + if(1349) + blackbox.msg_mining += blackbox_msg + if(1347) + blackbox.msg_cargo += blackbox_msg + else + blackbox.messages += blackbox_msg + + //End of research and feedback code. + + if (length(heard_masked)) + var/N = M.name + var/J = eqjobname + if(ishuman(M) && M.GetVoice() != M.real_name) + N = M.GetVoice() + J = "Unknown" + var/rendered = "[part_a][N][part_b][quotedmsg][part_c]" + for (var/mob/R in heard_masked) + if(istype(R, /mob/living/silicon/ai)) + R.show_message("[part_a][N] ([J]) [part_b][quotedmsg][part_c]", 2) + else + R.show_message(rendered, 2) + + if (length(heard_normal)) + var/rendered = "[part_a][M.real_name][part_b][quotedmsg][part_c]" + + for (var/mob/R in heard_normal) + if(istype(R, /mob/living/silicon/ai)) + R.show_message("[part_a][M.real_name] ([eqjobname]) [part_b][quotedmsg][part_c]", 2) + else + R.show_message(rendered, 2) + + if (length(heard_voice)) + var/rendered = "[part_a][M.voice_name][part_b][pick(M.speak_emote)][part_c]" + + for (var/mob/R in heard_voice) + if(istype(R, /mob/living/silicon/ai)) + R.show_message("[part_a][M.voice_name] ([eqjobname]) [part_b][pick(M.speak_emote)][part_c]", 2) + else + R.show_message(rendered, 2) + + if (length(heard_garbled)) + quotedmsg = M.say_quote(stars(message)) + var/rendered = "[part_a][M.voice_name][part_b][quotedmsg][part_c]" + + for (var/mob/R in heard_voice) + if(istype(R, /mob/living/silicon/ai)) + R.show_message("[part_a][M.voice_name][part_b][quotedmsg][part_c]", 2) + else + R.show_message(rendered, 2) + +/obj/item/device/radio/hear_talk(mob/M, msg, verb = "says", datum/language/speaking = null) + + if (broadcasting) + if(get_dist(src, M) <= canhear_range) + talk_into(M, msg,null,verb,speaking) + + +/* +/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R, 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 (wires.is_index_cut(RADIO_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) + var/datum/radio_frequency/RF = secure_radio_connections[ch_name] + if (RF.frequency==freq && (channels[ch_name]&FREQ_LISTENING)) + 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_mobs_in_view(canhear_range, src) + + +/obj/item/device/radio/examine(mob/user) + ..() + if (src in view(1, user)) + to_chat(user, "\the [src] can[b_stat ? "" : " not"] be attached or modified!") + +/obj/item/device/radio/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/device/radio_grid)) + if(grid) + to_chat(user, "There is already installed Shielded grid!") + return + to_chat(user, "You attach [W] to [src]!") + user.drop_item() + var/obj/item/device/radio_grid/new_grid = W + new_grid.attach(src) + else if(istype(W, /obj/item/weapon/wirecutters)) + if(!grid) + to_chat(user, "Nothing to cut here!") + return + to_chat(user, "You pop out Shielded grid from [src]!") + var/obj/item/device/radio_grid/new_grid = new(get_turf(loc)) + new_grid.dettach(src) + else if (istype(W, /obj/item/weapon/screwdriver)) + b_stat = !b_stat + add_fingerprint(user) + playsound(user, 'sound/items/Screwdriver.ogg', 50, 1) + if(!istype(src, /obj/item/device/radio/beacon)) + to_chat(user, "The radio can [b_stat ? "now" : "no longer"] be attached and modified!") + else + ..() + +/obj/item/device/radio/emp_act(severity) + if(!grid) + on = 0 + ..() +/* broadcasting = 0 + listening = 0 + for (var/ch_name in channels) + channels[ch_name] = 0 */ + + +/////////////////////////////// +//////////Borg Radios////////// +/////////////////////////////// +//Giving borgs their own radio to have some more room to work with -Sieve + +/obj/item/device/radio/borg + var/mob/living/silicon/robot/myborg = null // Cyborg which owns this radio. Used for power checks + var/obj/item/device/encryptionkey/keyslot = null//Borg radios can handle a single encryption key + icon = 'icons/obj/robot_component.dmi' // Cyborgs radio icons should look like the component. + icon_state = "radio" + canhear_range = 0 // Should prevent everyone around the cyborg hearing potentionally secret stuff from department channels (espicially sec) + +/obj/item/device/radio/borg/attackby(obj/item/weapon/W, mob/user) +// ..() + 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(keyslot) + + + for(var/ch_name in channels) + radio_controller.remove_object(src, radiochannels[ch_name]) + secure_radio_connections[ch_name] = null + + + if(keyslot) + var/turf/T = get_turf(user) + if(T) + keyslot.loc = T + keyslot = null + + recalculateChannels() + to_chat(user, "You pop out the encryption key in the radio!") + + else + to_chat(user, "This radio doesn't have any encryption keys!") + + if(istype(W, /obj/item/device/encryptionkey/)) + if(keyslot) + to_chat(user, "The radio can't hold another key!") + return + + if(!keyslot) + user.drop_item() + W.loc = src + keyslot = W + + recalculateChannels() + + return + +/obj/item/device/radio/borg/proc/recalculateChannels() + src.channels = list() + src.syndie = 0 + + var/mob/living/silicon/robot/D = src.loc + if(D.module) + for(var/ch_name in D.module.channels) + if(ch_name in src.channels) + continue + src.channels += ch_name + src.channels[ch_name] += D.module.channels[ch_name] + if(keyslot) + for(var/ch_name in keyslot.channels) + if(ch_name in src.channels) + continue + src.channels += ch_name + src.channels[ch_name] += keyslot.channels[ch_name] + + if(keyslot.syndie) + src.syndie = 1 + + + for (var/ch_name in src.channels) + if(!radio_controller) + sleep(30) // Waiting for the radio_controller to be created. + if(!radio_controller) + src.name = "broken radio" + return + + secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT) + + return + +/obj/item/device/radio/borg/Topic(href, href_list) + if(usr.stat || !on) + return + if (href_list["mode"]) + if(subspace_transmission != 1) + subspace_transmission = 1 + to_chat(usr, "Subspace Transmission is disabled") + else + subspace_transmission = 0 + to_chat(usr, "Subspace Transmission is enabled") + if(subspace_transmission == 1)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled + channels = list() + else + recalculateChannels() + ..() + +/obj/item/device/radio/borg/interact(mob/user) + if(!on) + return + + var/dat = "[src]" + dat += {" + Speaker: [listening ? "Engaged" : "Disengaged"]
                    + Frequency: + - + - + [format_frequency(frequency)] + + + +
                    + Toggle Broadcast Mode
                    + "} + + if(!subspace_transmission)//Don't even bother if subspace isn't turned on + for (var/ch_name in channels) + dat+=text_sec_channel(ch_name, channels[ch_name]) + user << browse(entity_ja(dat), "window=radio") + onclose(user, "radio") + return + + +/obj/item/device/radio/proc/config(op) + if(radio_controller) + for (var/ch_name in channels) + radio_controller.remove_object(src, radiochannels[ch_name]) + secure_radio_connections = new + channels = op + if(radio_controller) + for (var/ch_name in op) + secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT) + return + +/obj/item/device/radio/off + listening = 0 + +/obj/item/device/radio_grid + name = "Shielded grid" + desc = "A metal grid, attached to circuit to protect it from emitting." + w_class = 2 + icon = 'icons/obj/radio.dmi' + icon_state = "radio_grid" + +/obj/item/device/radio_grid/proc/attach(obj/item/device/radio/radio) + radio.on = TRUE + radio.grid = TRUE + qdel(src) + +/obj/item/device/radio_grid/proc/dettach(obj/item/device/radio/radio) + playsound(src, 'sound/items/Wirecutter.ogg', 50, 1) + if(prob(30)) + radio.on = FALSE + radio.grid = FALSE diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 78b50ff7ab5e..3981088df1f2 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -1,438 +1,438 @@ -/* -CONTAINS: -T-RAY -DETECTIVE SCANNER -HEALTH ANALYZER -GAS ANALYZER -PLANT ANALYZER -MASS SPECTROMETER -REAGENT SCANNER -*/ -/obj/item/device/t_scanner - name = "T-ray scanner" - desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes." - icon_state = "t-ray0" - slot_flags = SLOT_BELT - w_class = ITEM_SIZE_SMALL - item_state = "electronic" - m_amt = 150 - origin_tech = "magnets=1;engineering=1" - - var/on = FALSE - -/obj/item/device/t_scanner/attack_self(mob/user) - - on = !on - icon_state = "t-ray[on]" - - if(on) - START_PROCESSING(SSobj, src) - -/obj/item/device/t_scanner/proc/flick_sonar(obj/pipe) - if(ismob(loc)) - var/mob/M = loc - var/image/I = new(loc = get_turf(pipe)) - - var/mutable_appearance/MA = new(pipe) - MA.alpha = 128 - MA.dir = pipe.dir - - I.appearance = MA - if(M.client) - flick_overlay(I, list(M.client), 8) - -/obj/item/device/t_scanner/process() - if(!on) - STOP_PROCESSING(SSobj, src) - return null - scan() - -/obj/item/device/t_scanner/proc/scan() - - for(var/turf/T in range(1, src.loc) ) - - if(!T.intact) - continue - - for(var/obj/O in T.contents) - - if(O.level != 1) - continue - - if(O.invisibility >= INVISIBILITY_MAXIMUM) - flick_sonar(O) - -/obj/item/device/healthanalyzer - name = "Health Analyzer" - icon_state = "health" - item_state = "healthanalyzer" - desc = "A hand-held body scanner able to distinguish vital signs of the subject." - flags = CONDUCT - slot_flags = SLOT_BELT - throwforce = 3 - w_class = 2.0 - throw_speed = 5 - throw_range = 10 - m_amt = 200 - origin_tech = "magnets=1;biotech=1" - var/mode = TRUE - -/obj/item/device/healthanalyzer/attack(mob/living/M, mob/living/user) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.species.flags[IS_SYNTHETIC] || H.species.flags[IS_PLANT]) - user.show_message("Analyzing Results for ERROR:\n  Overall Status: ERROR") - user.show_message("  Key: Suffocation/Toxin/Burns/Brute", 1) - user.show_message("  Damage Specifics: ? - ? - ? - ?") - user.show_message("Body Temperature: [H.bodytemperature-T0C]°C ([H.bodytemperature*1.8-459.67]°F)", 1) - user.show_message("Warning: Blood Level ERROR: --% --cl.Type: ERROR") - user.show_message("Subject's pulse:-- bpm.") - return - else - health_analyze(M, user, mode) - else - user.show_message("Analyzing Results not compiled. Unknown anatomy detected.") - -/obj/item/device/healthanalyzer/verb/toggle_mode() - set name = "Switch Verbosity" - set category = "Object" - - mode = !mode - switch (mode) - if(TRUE) - to_chat(usr, "The scanner now shows specific limb damage.") - if(FALSE) - to_chat(usr, "The scanner no longer shows limb damage.") - -/obj/item/device/healthanalyzer/rad_laser - materials = list(MAT_METAL=400) - origin_tech = "magnets=3;biotech=5;syndicate=3" - var/irradiate = 1 - var/intensity = 10 // how much damage the radiation does - var/wavelength = 10 // time it takes for the radiation to kick in, in seconds - var/used = 0 // is it cooling down? - -/obj/item/device/healthanalyzer/rad_laser/attack(mob/living/M, mob/living/user) - ..() - if(!irradiate) - return - if(!used) - msg_admin_attack("[user] ([user.ckey]) irradiated [M.name] ([M.ckey]) (JMP)") - var/cooldown = round(max(10, (intensity*5 - wavelength/4))) * 10 - used = 1 - icon_state = "health1" - spawn(cooldown) // splits off to handle the cooldown while handling wavelength - used = 0 - icon_state = "health" - to_chat(user,"Successfully irradiated [M].") - M.attack_log += text("\[[time_stamp()]\] Has been irradiated by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] irradiated [M.name]'s ([M.ckey])") - spawn((wavelength+(intensity*4))*5) - if(M) - if(intensity >= 5) - M.apply_effect(round(intensity/1.5), PARALYZE) - M.apply_effect(intensity * 10,IRRADIATE, 0) - else - to_chat(user,"The radioactive microlaser is still recharging.") - -/obj/item/device/healthanalyzer/rad_laser/attack_self(mob/user) - interact(user) - -/obj/item/device/healthanalyzer/rad_laser/interact(mob/user) - user.set_machine(src) - var/cooldown = round(max(10, (intensity*5 - wavelength/4))) - var/dat = "Irradiation: [irradiate ? "On" : "Off"]
                    " - - dat += {" - Radiation Intensity: - -- - [intensity] - ++
                    - - Radiation Wavelength: - -- - [(wavelength+(intensity*4))] - ++
                    - Laser Cooldown: [cooldown] Seconds
                    - "} - - var/datum/browser/popup = new(user, "radlaser", "Radioactive Microlaser Interface", 400, 240) - popup.set_content(dat) - popup.open() - -/obj/item/device/healthanalyzer/rad_laser/Topic(href, href_list) - - usr.set_machine(src) - if(href_list["rad"]) - irradiate = !irradiate - - else if(href_list["radint"]) - var/amount = text2num(href_list["radint"]) - amount += intensity - intensity = max(1,(min(20,amount))) - - else if(href_list["radwav"]) - var/amount = text2num(href_list["radwav"]) - amount += wavelength - wavelength = max(0,(min(120,amount))) - - attack_self(usr) - add_fingerprint(usr) - return - - -/obj/item/device/analyzer - desc = "A hand-held environmental scanner which reports current gas levels." - name = "analyzer" - icon_state = "atmos" - item_state = "analyzer" - w_class = 2.0 - flags = CONDUCT - slot_flags = SLOT_BELT - throwforce = 5 - throw_speed = 4 - throw_range = 20 - m_amt = 30 - g_amt = 20 - origin_tech = "magnets=1;engineering=1" - - action_button_name = "Use Analyzer" - - var/advanced_mode = 0 - -/obj/item/device/analyzer/verb/verbosity(mob/user as mob) - set name = "Toggle Advanced Gas Analysis" - set category = "Object" - set src in usr - - if (!user.incapacitated()) - advanced_mode = !advanced_mode - to_chat(usr, "You toggle advanced gas analysis [advanced_mode ? "on" : "off"].") - -/obj/item/device/analyzer/attack_self(mob/user) - - if (user.incapacitated()) - return - if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") - to_chat(usr, "\red You don't have the dexterity to do this!") - return - - analyze_gases(user.loc, user,advanced_mode) - return TRUE - -/obj/item/device/analyzer/afterattack(obj/O, mob/user, proximity) - if(!proximity) - return - if (user.incapacitated()) - return - if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") - to_chat(usr, "\red You don't have the dexterity to do this!") - return - if(istype(O) && O.simulated) - analyze_gases(O, user, advanced_mode) - -/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 = CONDUCT | OPENCONTAINER - slot_flags = SLOT_BELT - throwforce = 5 - throw_speed = 4 - throw_range = 20 - m_amt = 30 - g_amt = 20 - origin_tech = "magnets=2;biotech=2" - var/details = 0 - var/recent_fail = 0 - -/obj/item/device/mass_spectrometer/atom_init() - . = ..() - var/datum/reagents/R = new/datum/reagents(5) - reagents = R - R.my_atom = src - -/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_self(mob/user) - if (user.stat) - return - if (crit_fail) - to_chat(user, "\red This device has critically failed and is no longer functional!") - return - if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") - to_chat(user, "\red 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, "\red The sample was contaminated! Please insert another sample") - return - else - blood_traces = params2list(R.data["trace_chem"]) - break - var/dat = "Trace Chemicals Found: " - for(var/R in blood_traces) - if(prob(reliability)) - if(details) - dat += "[R] ([blood_traces[R]] units) " - else - dat += "[R] " - recent_fail = 0 - else - if(recent_fail) - crit_fail = 1 - reagents.clear_reagents() - return - else - recent_fail = 1 - 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 = CONDUCT - slot_flags = SLOT_BELT - throwforce = 5 - throw_speed = 4 - throw_range = 20 - m_amt = 30 - g_amt = 20 - origin_tech = "magnets=2;biotech=2" - var/details = 0 - var/recent_fail = 0 - -/obj/item/device/reagent_scanner/afterattack(obj/O, mob/user) - if (user.stat) - return - if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") - to_chat(user, "\red You don't have the dexterity to do this!") - return - if(!istype(O)) - return - if (crit_fail) - to_chat(user, "\red This device has critically failed and is no longer functional!") - return - - if(!isnull(O.reagents)) - var/dat = "" - if(O.reagents.reagent_list.len > 0) - var/one_percent = O.reagents.total_volume / 100 - for (var/datum/reagent/R in O.reagents.reagent_list) - if(prob(reliability)) - dat += "\n   \blue [R][details ? ": [R.volume / one_percent]%" : ""]" - recent_fail = 0 - else if(recent_fail) - crit_fail = 1 - dat = null - break - else - recent_fail = 1 - if(dat) - to_chat(user, "\blue Chemicals found: [dat]") - else - to_chat(user, "\blue No active chemical agents found in [O].") - else - to_chat(user, "\blue No significant chemical agents found in [O].") - - return - -/obj/item/device/reagent_scanner/adv - name = "advanced reagent scanner" - icon_state = "adv_spectrometer" - details = 1 - origin_tech = "magnets=4;biotech=2" - -/obj/item/weapon/occult_pinpointer - name = "occult locator" - icon = 'icons/obj/device.dmi' - icon_state = "locoff" - flags = CONDUCT - slot_flags = SLOT_BELT - w_class = 2.0 - item_state = "electronic" - throw_speed = 4 - throw_range = 20 - m_amt = 500 - var/target = null - var/target_type = /obj/item/weapon/reagent_containers/food/snacks/ectoplasm - var/active = FALSE - -/obj/item/weapon/occult_pinpointer/attack_self() - if(!active) - to_chat(usr, "You activate the [name]") - START_PROCESSING(SSobj, src) - else - icon_state = "locoff" - to_chat(usr, "You deactivate the [name]") - STOP_PROCESSING(SSobj, src) - active = !active - -/obj/item/weapon/occult_pinpointer/attackby(obj/item/W, mob/user) - ..() - if(istype(W, /obj/item/device/occult_scanner)) - var/obj/item/device/occult_scanner/OS = W - target_type = OS.scanned_type - target = null // So we ain't looking for the old target - to_chat(user, "[src] succesfully extracted [pick("mythical","magical","arcane")] knowledge from [W]") - -/obj/item/weapon/occult_pinpointer/Destroy() - active = FALSE - STOP_PROCESSING(SSobj, src) - target = null - return ..() - -/obj/item/weapon/occult_pinpointer/process() - if(!active) - return - if(!target) - target = locate(target_type) - if(!target) - icon_state = "locnull" - return - dir = get_dir(src,target) - if(get_dist(src,target)) - icon_state = "locon" - -/obj/item/device/occult_scanner - name = "occult scanner" - icon = 'icons/obj/device.dmi' - icon_state = "occult_scan" - flags = CONDUCT - slot_flags = SLOT_BELT - w_class = 2.0 - item_state = "electronic" - throw_speed = 4 - throw_range = 20 - m_amt = 500 - var/scanned_type = /obj/item/weapon/reagent_containers/food/snacks/ectoplasm - -/obj/item/device/occult_scanner/attack_self(mob/user) - if(!istype(scanned_type, /obj/item/weapon/reagent_containers/food/snacks/ectoplasm)) - scanned_type = /obj/item/weapon/reagent_containers/food/snacks/ectoplasm - to_chat(user, "You reset the scanned object of the scanner.") - -/obj/item/device/occult_scanner/afterattack(mob/M, mob/user) - if(user && user.client) - if(ishuman(M) && M.stat == DEAD) - user.visible_message("[user] scans [M], the air around them humming gently.", - "[M] was [pick("possessed", "devoured", "destroyed", "murdered", "captured")] by [pick("Cthulhu", "Mi-Go", "Elder God", "dark spirit", "Outsider", "unknown alien creature")]") +/* +CONTAINS: +T-RAY +DETECTIVE SCANNER +HEALTH ANALYZER +GAS ANALYZER +PLANT ANALYZER +MASS SPECTROMETER +REAGENT SCANNER +*/ +/obj/item/device/t_scanner + name = "T-ray scanner" + desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes." + icon_state = "t-ray0" + slot_flags = SLOT_BELT + w_class = ITEM_SIZE_SMALL + item_state = "electronic" + m_amt = 150 + origin_tech = "magnets=1;engineering=1" + + var/on = FALSE + +/obj/item/device/t_scanner/attack_self(mob/user) + + on = !on + icon_state = "t-ray[on]" + + if(on) + START_PROCESSING(SSobj, src) + +/obj/item/device/t_scanner/proc/flick_sonar(obj/pipe) + if(ismob(loc)) + var/mob/M = loc + var/image/I = new(loc = get_turf(pipe)) + + var/mutable_appearance/MA = new(pipe) + MA.alpha = 128 + MA.dir = pipe.dir + + I.appearance = MA + if(M.client) + flick_overlay(I, list(M.client), 8) + +/obj/item/device/t_scanner/process() + if(!on) + STOP_PROCESSING(SSobj, src) + return null + scan() + +/obj/item/device/t_scanner/proc/scan() + + for(var/turf/T in range(1, src.loc) ) + + if(!T.intact) + continue + + for(var/obj/O in T.contents) + + if(O.level != 1) + continue + + if(O.invisibility >= INVISIBILITY_MAXIMUM) + flick_sonar(O) + +/obj/item/device/healthanalyzer + name = "Health Analyzer" + icon_state = "health" + item_state = "healthanalyzer" + desc = "A hand-held body scanner able to distinguish vital signs of the subject." + flags = CONDUCT + slot_flags = SLOT_BELT + throwforce = 3 + w_class = 2.0 + throw_speed = 5 + throw_range = 10 + m_amt = 200 + origin_tech = "magnets=1;biotech=1" + var/mode = TRUE + +/obj/item/device/healthanalyzer/attack(mob/living/M, mob/living/user) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species.flags[IS_SYNTHETIC] || H.species.flags[IS_PLANT]) + user.show_message("Analyzing Results for ERROR:\n  Overall Status: ERROR") + user.show_message("  Key: Suffocation/Toxin/Burns/Brute", 1) + user.show_message("  Damage Specifics: ? - ? - ? - ?") + user.show_message("Body Temperature: [H.bodytemperature-T0C]°C ([H.bodytemperature*1.8-459.67]°F)", 1) + user.show_message("Warning: Blood Level ERROR: --% --cl.Type: ERROR") + user.show_message("Subject's pulse:-- bpm.") + return + else + health_analyze(M, user, mode) + else + user.show_message("Analyzing Results not compiled. Unknown anatomy detected.") + +/obj/item/device/healthanalyzer/verb/toggle_mode() + set name = "Switch Verbosity" + set category = "Object" + + mode = !mode + switch (mode) + if(TRUE) + to_chat(usr, "The scanner now shows specific limb damage.") + if(FALSE) + to_chat(usr, "The scanner no longer shows limb damage.") + +/obj/item/device/healthanalyzer/rad_laser + materials = list(MAT_METAL=400) + origin_tech = "magnets=3;biotech=5;syndicate=3" + var/irradiate = 1 + var/intensity = 10 // how much damage the radiation does + var/wavelength = 10 // time it takes for the radiation to kick in, in seconds + var/used = 0 // is it cooling down? + +/obj/item/device/healthanalyzer/rad_laser/attack(mob/living/M, mob/living/user) + ..() + if(!irradiate) + return + if(!used) + msg_admin_attack("[user] ([user.ckey]) irradiated [M.name] ([M.ckey]) (JMP)") + var/cooldown = round(max(10, (intensity*5 - wavelength/4))) * 10 + used = 1 + icon_state = "health1" + spawn(cooldown) // splits off to handle the cooldown while handling wavelength + used = 0 + icon_state = "health" + to_chat(user,"Successfully irradiated [M].") + M.attack_log += text("\[[time_stamp()]\] Has been irradiated by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] irradiated [M.name]'s ([M.ckey])") + spawn((wavelength+(intensity*4))*5) + if(M) + if(intensity >= 5) + M.apply_effect(round(intensity/1.5), PARALYZE) + M.apply_effect(intensity * 10,IRRADIATE, 0) + else + to_chat(user,"The radioactive microlaser is still recharging.") + +/obj/item/device/healthanalyzer/rad_laser/attack_self(mob/user) + interact(user) + +/obj/item/device/healthanalyzer/rad_laser/interact(mob/user) + user.set_machine(src) + var/cooldown = round(max(10, (intensity*5 - wavelength/4))) + var/dat = "Irradiation: [irradiate ? "On" : "Off"]
                    " + + dat += {" + Radiation Intensity: + -- + [intensity] + ++
                    + + Radiation Wavelength: + -- + [(wavelength+(intensity*4))] + ++
                    + Laser Cooldown: [cooldown] Seconds
                    + "} + + var/datum/browser/popup = new(user, "radlaser", "Radioactive Microlaser Interface", 400, 240) + popup.set_content(dat) + popup.open() + +/obj/item/device/healthanalyzer/rad_laser/Topic(href, href_list) + + usr.set_machine(src) + if(href_list["rad"]) + irradiate = !irradiate + + else if(href_list["radint"]) + var/amount = text2num(href_list["radint"]) + amount += intensity + intensity = max(1,(min(20,amount))) + + else if(href_list["radwav"]) + var/amount = text2num(href_list["radwav"]) + amount += wavelength + wavelength = max(0,(min(120,amount))) + + attack_self(usr) + add_fingerprint(usr) + return + + +/obj/item/device/analyzer + desc = "A hand-held environmental scanner which reports current gas levels." + name = "analyzer" + icon_state = "atmos" + item_state = "analyzer" + w_class = 2.0 + flags = CONDUCT + slot_flags = SLOT_BELT + throwforce = 5 + throw_speed = 4 + throw_range = 20 + m_amt = 30 + g_amt = 20 + origin_tech = "magnets=1;engineering=1" + + action_button_name = "Use Analyzer" + + var/advanced_mode = 0 + +/obj/item/device/analyzer/verb/verbosity(mob/user as mob) + set name = "Toggle Advanced Gas Analysis" + set category = "Object" + set src in usr + + if (!user.incapacitated()) + advanced_mode = !advanced_mode + to_chat(usr, "You toggle advanced gas analysis [advanced_mode ? "on" : "off"].") + +/obj/item/device/analyzer/attack_self(mob/user) + + if (user.incapacitated()) + return + if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + to_chat(usr, "\red You don't have the dexterity to do this!") + return + + analyze_gases(user.loc, user,advanced_mode) + return TRUE + +/obj/item/device/analyzer/afterattack(obj/O, mob/user, proximity) + if(!proximity) + return + if (user.incapacitated()) + return + if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + to_chat(usr, "\red You don't have the dexterity to do this!") + return + if(istype(O) && O.simulated) + analyze_gases(O, user, advanced_mode) + +/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 = CONDUCT | OPENCONTAINER + slot_flags = SLOT_BELT + throwforce = 5 + throw_speed = 4 + throw_range = 20 + m_amt = 30 + g_amt = 20 + origin_tech = "magnets=2;biotech=2" + var/details = 0 + var/recent_fail = 0 + +/obj/item/device/mass_spectrometer/atom_init() + . = ..() + var/datum/reagents/R = new/datum/reagents(5) + reagents = R + R.my_atom = src + +/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_self(mob/user) + if (user.stat) + return + if (crit_fail) + to_chat(user, "\red This device has critically failed and is no longer functional!") + return + if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + to_chat(user, "\red 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, "\red The sample was contaminated! Please insert another sample") + return + else + blood_traces = params2list(R.data["trace_chem"]) + break + var/dat = "Trace Chemicals Found: " + for(var/R in blood_traces) + if(prob(reliability)) + if(details) + dat += "[R] ([blood_traces[R]] units) " + else + dat += "[R] " + recent_fail = 0 + else + if(recent_fail) + crit_fail = 1 + reagents.clear_reagents() + return + else + recent_fail = 1 + 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 = CONDUCT + slot_flags = SLOT_BELT + throwforce = 5 + throw_speed = 4 + throw_range = 20 + m_amt = 30 + g_amt = 20 + origin_tech = "magnets=2;biotech=2" + var/details = 0 + var/recent_fail = 0 + +/obj/item/device/reagent_scanner/afterattack(obj/O, mob/user) + if (user.stat) + return + if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + to_chat(user, "\red You don't have the dexterity to do this!") + return + if(!istype(O)) + return + if (crit_fail) + to_chat(user, "\red This device has critically failed and is no longer functional!") + return + + if(!isnull(O.reagents)) + var/dat = "" + if(O.reagents.reagent_list.len > 0) + var/one_percent = O.reagents.total_volume / 100 + for (var/datum/reagent/R in O.reagents.reagent_list) + if(prob(reliability)) + dat += "\n   \blue [R][details ? ": [R.volume / one_percent]%" : ""]" + recent_fail = 0 + else if(recent_fail) + crit_fail = 1 + dat = null + break + else + recent_fail = 1 + if(dat) + to_chat(user, "\blue Chemicals found: [dat]") + else + to_chat(user, "\blue No active chemical agents found in [O].") + else + to_chat(user, "\blue No significant chemical agents found in [O].") + + return + +/obj/item/device/reagent_scanner/adv + name = "advanced reagent scanner" + icon_state = "adv_spectrometer" + details = 1 + origin_tech = "magnets=4;biotech=2" + +/obj/item/weapon/occult_pinpointer + name = "occult locator" + icon = 'icons/obj/device.dmi' + icon_state = "locoff" + flags = CONDUCT + slot_flags = SLOT_BELT + w_class = 2.0 + item_state = "electronic" + throw_speed = 4 + throw_range = 20 + m_amt = 500 + var/target = null + var/target_type = /obj/item/weapon/reagent_containers/food/snacks/ectoplasm + var/active = FALSE + +/obj/item/weapon/occult_pinpointer/attack_self() + if(!active) + to_chat(usr, "You activate the [name]") + START_PROCESSING(SSobj, src) + else + icon_state = "locoff" + to_chat(usr, "You deactivate the [name]") + STOP_PROCESSING(SSobj, src) + active = !active + +/obj/item/weapon/occult_pinpointer/attackby(obj/item/W, mob/user) + ..() + if(istype(W, /obj/item/device/occult_scanner)) + var/obj/item/device/occult_scanner/OS = W + target_type = OS.scanned_type + target = null // So we ain't looking for the old target + to_chat(user, "[src] succesfully extracted [pick("mythical","magical","arcane")] knowledge from [W]") + +/obj/item/weapon/occult_pinpointer/Destroy() + active = FALSE + STOP_PROCESSING(SSobj, src) + target = null + return ..() + +/obj/item/weapon/occult_pinpointer/process() + if(!active) + return + if(!target) + target = locate(target_type) + if(!target) + icon_state = "locnull" + return + dir = get_dir(src,target) + if(get_dist(src,target)) + icon_state = "locon" + +/obj/item/device/occult_scanner + name = "occult scanner" + icon = 'icons/obj/device.dmi' + icon_state = "occult_scan" + flags = CONDUCT + slot_flags = SLOT_BELT + w_class = 2.0 + item_state = "electronic" + throw_speed = 4 + throw_range = 20 + m_amt = 500 + var/scanned_type = /obj/item/weapon/reagent_containers/food/snacks/ectoplasm + +/obj/item/device/occult_scanner/attack_self(mob/user) + if(!istype(scanned_type, /obj/item/weapon/reagent_containers/food/snacks/ectoplasm)) + scanned_type = /obj/item/weapon/reagent_containers/food/snacks/ectoplasm + to_chat(user, "You reset the scanned object of the scanner.") + +/obj/item/device/occult_scanner/afterattack(mob/M, mob/user) + if(user && user.client) + if(ishuman(M) && M.stat == DEAD) + user.visible_message("[user] scans [M], the air around them humming gently.", + "[M] was [pick("possessed", "devoured", "destroyed", "murdered", "captured")] by [pick("Cthulhu", "Mi-Go", "Elder God", "dark spirit", "Outsider", "unknown alien creature")]") diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index bed5f56ffa01..0fbaede88080 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -1,257 +1,257 @@ -/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 = 'icons/obj/device.dmi' - icon_state = "taperecorderidle" - item_state = "analyzer" - w_class = 2.0 - m_amt = 60 - g_amt = 30 - 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 = CONDUCT - throwforce = 2 - throw_speed = 4 - throw_range = 20 - - action_button_name = "Toggle Recorder" - -/obj/item/device/taperecorder/hear_talk(mob/living/M, msg, verb="says") - if(recording) - timestamp+= timerecorded - if(isanimal(M)) // Taken from say(). Temporary fix before refactor. Needs to actually pass languages or something like that here and when we see paper or hear audioplayback it depends whenever we can actually understand that language. - var/mob/living/simple_animal/S = M - msg = pick(S.speak) - else if(isIAN(M)) - var/mob/living/carbon/ian/IAN = M - msg = pick(IAN.speak) - - storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] [M.name] [verb], \"[msg]\"" - return - -/obj/item/device/taperecorder/attackby(obj/item/weapon/W, mob/user) - ..() - 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) - explosion(T, -1, -1, 0, 4) - qdel(src) - return - -/obj/item/device/taperecorder/verb/record() - set name = "Start Recording" - set category = "Object" - - if(usr.stat) - return - if(emagged == 1) - to_chat(usr, "\red 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.stat) - return - if(emagged == 1) - to_chat(usr, "\red 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 - var/turf/T = get_turf(src) - T.visible_message("Tape Recorder: Playback stopped.") - icon_state = "taperecorderidle" - return - - -/obj/item/device/taperecorder/verb/clear_memory() - set name = "Clear Memory" - set category = "Object" - - if(usr.stat) - 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.stat) - 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 - var/turf/T = get_turf(src) - T.visible_message("Tape Recorder: [storedinfo[i]]") - if(storedinfo.len < i+1) - playsleepseconds = 1 - sleep(10) - T = get_turf(src) - T.visible_message("Tape Recorder: End of recording.") - else - playsleepseconds = timestamp[i+1] - timestamp[i] - if(playsleepseconds > 14) - sleep(10) - T = get_turf(src) - T.visible_message("Tape Recorder: Skipping [playsleepseconds] seconds of silence") - playsleepseconds = 1 - i++ - icon_state = "taperecorderidle" - playing = 0 - if(emagged == 1) - var/turf/T = get_turf(src) - T.visible_message("Tape Recorder: This tape recorder will self-destruct in... Five.") - sleep(10) - T = get_turf(src) - T.visible_message("Tape Recorder: Four.") - sleep(10) - T = get_turf(src) - T.visible_message("Tape Recorder: Three.") - sleep(10) - T = get_turf(src) - T.visible_message("Tape Recorder: Two.") - sleep(10) - T = get_turf(src) - T.visible_message("Tape Recorder: One.") - sleep(10) - explode() - - -/obj/item/device/taperecorder/verb/print_transcript() - set name = "Print Transcript" - set category = "Object" - - if(usr.stat) - return - if(emagged == 1) - to_chat(usr, "\red 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 = "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, "\red The tape recorder makes a scratchy noise.") - return - icon_state = "taperecorderrecording" - if(timerecorded < 3600 && playing == 0) - to_chat(usr, "\blue 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, "\red 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, "\blue Recording stopped.") - icon_state = "taperecorderidle" - return - else if(playing == 1) - playing = 0 - var/turf/T = get_turf(src) - for(var/mob/O in hearers(world.view-1, T)) - O.show_message("Tape Recorder: Playback stopped.",2) - icon_state = "taperecorderidle" - return - else - to_chat(usr, "\red Stop what?") - return +/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 = 'icons/obj/device.dmi' + icon_state = "taperecorderidle" + item_state = "analyzer" + w_class = 2.0 + m_amt = 60 + g_amt = 30 + 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 = CONDUCT + throwforce = 2 + throw_speed = 4 + throw_range = 20 + + action_button_name = "Toggle Recorder" + +/obj/item/device/taperecorder/hear_talk(mob/living/M, msg, verb="says") + if(recording) + timestamp+= timerecorded + if(isanimal(M)) // Taken from say(). Temporary fix before refactor. Needs to actually pass languages or something like that here and when we see paper or hear audioplayback it depends whenever we can actually understand that language. + var/mob/living/simple_animal/S = M + msg = pick(S.speak) + else if(isIAN(M)) + var/mob/living/carbon/ian/IAN = M + msg = pick(IAN.speak) + + storedinfo += "\[[time2text(timerecorded*10,"mm:ss")]\] [M.name] [verb], \"[msg]\"" + return + +/obj/item/device/taperecorder/attackby(obj/item/weapon/W, mob/user) + ..() + 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) + explosion(T, -1, -1, 0, 4) + qdel(src) + return + +/obj/item/device/taperecorder/verb/record() + set name = "Start Recording" + set category = "Object" + + if(usr.stat) + return + if(emagged == 1) + to_chat(usr, "\red 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.stat) + return + if(emagged == 1) + to_chat(usr, "\red 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 + var/turf/T = get_turf(src) + T.visible_message("Tape Recorder: Playback stopped.") + icon_state = "taperecorderidle" + return + + +/obj/item/device/taperecorder/verb/clear_memory() + set name = "Clear Memory" + set category = "Object" + + if(usr.stat) + 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.stat) + 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 + var/turf/T = get_turf(src) + T.visible_message("Tape Recorder: [storedinfo[i]]") + if(storedinfo.len < i+1) + playsleepseconds = 1 + sleep(10) + T = get_turf(src) + T.visible_message("Tape Recorder: End of recording.") + else + playsleepseconds = timestamp[i+1] - timestamp[i] + if(playsleepseconds > 14) + sleep(10) + T = get_turf(src) + T.visible_message("Tape Recorder: Skipping [playsleepseconds] seconds of silence") + playsleepseconds = 1 + i++ + icon_state = "taperecorderidle" + playing = 0 + if(emagged == 1) + var/turf/T = get_turf(src) + T.visible_message("Tape Recorder: This tape recorder will self-destruct in... Five.") + sleep(10) + T = get_turf(src) + T.visible_message("Tape Recorder: Four.") + sleep(10) + T = get_turf(src) + T.visible_message("Tape Recorder: Three.") + sleep(10) + T = get_turf(src) + T.visible_message("Tape Recorder: Two.") + sleep(10) + T = get_turf(src) + T.visible_message("Tape Recorder: One.") + sleep(10) + explode() + + +/obj/item/device/taperecorder/verb/print_transcript() + set name = "Print Transcript" + set category = "Object" + + if(usr.stat) + return + if(emagged == 1) + to_chat(usr, "\red 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 = "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, "\red The tape recorder makes a scratchy noise.") + return + icon_state = "taperecorderrecording" + if(timerecorded < 3600 && playing == 0) + to_chat(usr, "\blue 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, "\red 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, "\blue Recording stopped.") + icon_state = "taperecorderidle" + return + else if(playing == 1) + playing = 0 + var/turf/T = get_turf(src) + for(var/mob/O in hearers(world.view-1, T)) + O.show_message("Tape Recorder: Playback stopped.",2) + icon_state = "taperecorderidle" + return + else + to_chat(usr, "\red Stop what?") + return diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index b386b9c91389..76124406c540 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -1,215 +1,215 @@ -/obj/item/device/transfer_valve - icon = 'icons/obj/assemblies.dmi' - name = "tank transfer valve" - icon_state = "valve_1" - item_state = "ttv" - 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 - -/obj/item/device/transfer_valve/proc/process_activation(obj/item/device/D) - -/obj/item/device/transfer_valve/IsAssemblyHolder() - return 1 - -/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) - tank_one = item - user.drop_item() - item.loc = src - to_chat(user, "You attach the tank to the transfer valve.") - else if(!tank_two) - tank_two = item - user.drop_item() - item.loc = src - to_chat(user, "You attach the tank to the transfer valve.") - - update_icon() - nanomanager.update_uis(src) // update all UIs attached to src -//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 an 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. (JMP)") - log_game("[key_name_admin(user)] attached a [item] to a transfer valve.") - attacher = user - nanomanager.update_uis(src) // update all UIs attached to src - return - - -/obj/item/device/transfer_valve/HasProximity(atom/movable/AM) - if(!attached_device) return - attached_device.HasProximity(AM) - return - -/obj/item/device/transfer_valve/hear_talk(mob/living/M, msg) - if(!attached_device) return - attached_device.hear_talk(M,msg) - return - -/obj/item/device/transfer_valve/attack_self(mob/user) - ui_interact(user) - -/obj/item/device/transfer_valve/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null) - - // this is the data which will be sent to the ui - var/data[0] - data["attachmentOne"] = tank_one ? tank_one.name : null - data["attachmentTwo"] = tank_two ? tank_two.name : null - data["valveAttachment"] = attached_device ? attached_device.name : null - data["valveOpen"] = valve_open ? 1 : 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, "transfer_valve.tmpl", "Tank Transfer Valve", 460, 280) - // 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/device/transfer_valve/Topic(href, href_list) - ..() - if ( usr.stat || usr.restrained() ) - return 0 - if (src.loc != usr) - return 0 - 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.add_fingerprint(usr) - return 1 // Returning 1 sends an update to attached UIs - -/obj/item/device/transfer_valve/process_activation(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.Cut() - 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) - log_game(log_str) - merge_gases() - spawn(20) // In case one tank bursts - for (var/i=0,i<5,i++) - src.update_icon() - sleep(10) - src.update_icon() - - else if(valve_open==1 && (tank_one && tank_two)) - split_gases() - valve_open = 0 - src.update_icon() - -// 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" + item_state = "ttv" + 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 + +/obj/item/device/transfer_valve/proc/process_activation(obj/item/device/D) + +/obj/item/device/transfer_valve/IsAssemblyHolder() + return 1 + +/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) + tank_one = item + user.drop_item() + item.loc = src + to_chat(user, "You attach the tank to the transfer valve.") + else if(!tank_two) + tank_two = item + user.drop_item() + item.loc = src + to_chat(user, "You attach the tank to the transfer valve.") + + update_icon() + nanomanager.update_uis(src) // update all UIs attached to src +//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 an 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. (JMP)") + log_game("[key_name_admin(user)] attached a [item] to a transfer valve.") + attacher = user + nanomanager.update_uis(src) // update all UIs attached to src + return + + +/obj/item/device/transfer_valve/HasProximity(atom/movable/AM) + if(!attached_device) return + attached_device.HasProximity(AM) + return + +/obj/item/device/transfer_valve/hear_talk(mob/living/M, msg) + if(!attached_device) return + attached_device.hear_talk(M,msg) + return + +/obj/item/device/transfer_valve/attack_self(mob/user) + ui_interact(user) + +/obj/item/device/transfer_valve/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null) + + // this is the data which will be sent to the ui + var/data[0] + data["attachmentOne"] = tank_one ? tank_one.name : null + data["attachmentTwo"] = tank_two ? tank_two.name : null + data["valveAttachment"] = attached_device ? attached_device.name : null + data["valveOpen"] = valve_open ? 1 : 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, "transfer_valve.tmpl", "Tank Transfer Valve", 460, 280) + // 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/device/transfer_valve/Topic(href, href_list) + ..() + if ( usr.stat || usr.restrained() ) + return 0 + if (src.loc != usr) + return 0 + 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.add_fingerprint(usr) + return 1 // Returning 1 sends an update to attached UIs + +/obj/item/device/transfer_valve/process_activation(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.Cut() + 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) + log_game(log_str) + merge_gases() + spawn(20) // In case one tank bursts + for (var/i=0,i<5,i++) + src.update_icon() + sleep(10) + src.update_icon() + + else if(valve_open==1 && (tank_one && tank_two)) + split_gases() + valve_open = 0 + src.update_icon() + +// 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/latexballoon.dm b/code/game/objects/items/latexballoon.dm index ea0f66805ee6..8bd8534cc23b 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 = 2.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, temperature, volume) - if(temperature > T0C+100) - burst() - return - -/obj/item/latexballon/attackby(obj/item/W, mob/user) - if(W.can_puncture()) - burst() +/obj/item/latexballon + name = "Latex glove" + desc = "" //todo + icon_state = "latexballon" + item_state = "lgloves" + force = 0 + throwforce = 0 + w_class = 2.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, temperature, volume) + if(temperature > T0C+100) + burst() + return + +/obj/item/latexballon/attackby(obj/item/W, mob/user) + if(W.can_puncture()) + burst() diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index b3e13b4f1f0f..ab4db3b92188 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -1,96 +1,96 @@ -//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, mob/living/silicon/robot/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])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") - - 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("\red [user] has prodded [M] with an electrically-charged arm!", 1, "\red You hear someone fall", 2) - -/obj/item/borg/overdrive - name = "overdrive" - icon = 'icons/obj/decals.dmi' - icon_state = "shock" - -/********************************************************************** - HUD/SIGHT things -***********************************************************************/ -/obj/item/borg/sight - icon = 'icons/obj/decals.dmi' - icon_state = "securearea" - var/sight_mode = null - - -/obj/item/borg/sight/xray - name = "\proper x-ray Vision" - sight_mode = BORGXRAY - - -/obj/item/borg/sight/thermal - name = "\proper thermal vision" - sight_mode = BORGTHERM - icon_state = "thermal" - icon = 'icons/obj/clothing/glasses.dmi' - - -/obj/item/borg/sight/meson - name = "\proper meson vision" - sight_mode = BORGMESON - icon_state = "meson" - icon = 'icons/obj/clothing/glasses.dmi' - -/obj/item/borg/sight/night - name = "\proper night vision" - sight_mode = BORGNIGHT - icon_state = "night" - icon = 'icons/obj/clothing/glasses.dmi' - -/obj/item/borg/sight/hud - name = "hud" - var/obj/item/clothing/glasses/hud/hud = null - - -/obj/item/borg/sight/hud/med - name = "medical hud" - icon_state = "healthhud" - icon = 'icons/obj/clothing/glasses.dmi' - -/obj/item/borg/sight/hud/med/atom_init() - . = ..() - hud = new /obj/item/clothing/glasses/hud/health(src) - - -/obj/item/borg/sight/hud/sec - name = "security hud" - icon_state = "securityhud" - icon = 'icons/obj/clothing/glasses.dmi' - -/obj/item/borg/sight/hud/sec/atom_init() - . = ..() - hud = new /obj/item/clothing/glasses/hud/security(src) - - -/obj/item/borg/sight/hud/miner - name = "geological hud" - -/obj/item/borg/sight/hud/miner/atom_init() - . = ..() - hud = new /obj/item/clothing/glasses/hud/mining(src) +//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, mob/living/silicon/robot/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])") + msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") + + 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("\red [user] has prodded [M] with an electrically-charged arm!", 1, "\red You hear someone fall", 2) + +/obj/item/borg/overdrive + name = "overdrive" + icon = 'icons/obj/decals.dmi' + icon_state = "shock" + +/********************************************************************** + HUD/SIGHT things +***********************************************************************/ +/obj/item/borg/sight + icon = 'icons/obj/decals.dmi' + icon_state = "securearea" + var/sight_mode = null + + +/obj/item/borg/sight/xray + name = "\proper x-ray Vision" + sight_mode = BORGXRAY + + +/obj/item/borg/sight/thermal + name = "\proper thermal vision" + sight_mode = BORGTHERM + icon_state = "thermal" + icon = 'icons/obj/clothing/glasses.dmi' + + +/obj/item/borg/sight/meson + name = "\proper meson vision" + sight_mode = BORGMESON + icon_state = "meson" + icon = 'icons/obj/clothing/glasses.dmi' + +/obj/item/borg/sight/night + name = "\proper night vision" + sight_mode = BORGNIGHT + icon_state = "night" + icon = 'icons/obj/clothing/glasses.dmi' + +/obj/item/borg/sight/hud + name = "hud" + var/obj/item/clothing/glasses/hud/hud = null + + +/obj/item/borg/sight/hud/med + name = "medical hud" + icon_state = "healthhud" + icon = 'icons/obj/clothing/glasses.dmi' + +/obj/item/borg/sight/hud/med/atom_init() + . = ..() + hud = new /obj/item/clothing/glasses/hud/health(src) + + +/obj/item/borg/sight/hud/sec + name = "security hud" + icon_state = "securityhud" + icon = 'icons/obj/clothing/glasses.dmi' + +/obj/item/borg/sight/hud/sec/atom_init() + . = ..() + hud = new /obj/item/clothing/glasses/hud/security(src) + + +/obj/item/borg/sight/hud/miner + name = "geological hud" + +/obj/item/borg/sight/hud/miner/atom_init() + . = ..() + hud = new /obj/item/clothing/glasses/hud/mining(src) diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 72741b928714..2ceb2e047674 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -1,182 +1,182 @@ -// 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() - -/obj/item/target/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 - return ..() // delete target - -/obj/item/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. - - - -/obj/item/target/attackby(obj/item/W, mob/user) - if (istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - overlays.Cut() - to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.") - return - - -/obj/item/target/attack_hand(mob/user) - // 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_loc(user) - to_chat(user, "You take the target out of the stake.") - - stake.pinned_target = null - return - - else - ..() - -/obj/item/target/syndicate - icon_state = "target_s" - desc = "A shooting target that looks like a hostile agent." - hp = 2600 // i guess syndie targets are sturdier? - -/obj/item/target/alien - icon_state = "target_q" - desc = "A shooting target with a threatening silhouette." - hp = 2350 // alium onest too kinda - -/obj/item/target/bullet_act(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 - -/datum/bullethole/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) +// 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() + +/obj/item/target/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 + return ..() // delete target + +/obj/item/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. + + + +/obj/item/target/attackby(obj/item/W, mob/user) + if (istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + overlays.Cut() + to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.") + return + + +/obj/item/target/attack_hand(mob/user) + // 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_loc(user) + to_chat(user, "You take the target out of the stake.") + + stake.pinned_target = null + return + + else + ..() + +/obj/item/target/syndicate + icon_state = "target_s" + desc = "A shooting target that looks like a hostile agent." + hp = 2600 // i guess syndie targets are sturdier? + +/obj/item/target/alien + icon_state = "target_q" + desc = "A shooting target with a threatening silhouette." + hp = 2350 // alium onest too kinda + +/obj/item/target/bullet_act(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 + +/datum/bullethole/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 243bcd6cad55..22839f2a1d2d 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -1,346 +1,346 @@ -/obj/item/stack/medical - name = "medical pack" - singular_name = "medical pack" - icon = 'icons/obj/items.dmi' - amount = 5 - max_amount = 5 - w_class = ITEM_SIZE_TINY - full_w_class = ITEM_SIZE_SMALL - throw_speed = 4 - throw_range = 20 - var/heal_brute = 0 - var/heal_burn = 0 - -/obj/item/stack/medical/update_weight() - if(amount < 3) - w_class = initial(w_class) - else - w_class = full_w_class - -/obj/item/stack/medical/attack(mob/living/carbon/M, mob/user, def_zone) - if(!istype(M)) - to_chat(user, "\The [src] cannot be applied to [M]!") - return 1 - - if(user.is_busy()) - return 1 - - if(!(ishuman(user) || issilicon(user) || ismonkey(user)) ) - to_chat(user, "You don't have the dexterity to do this!") - return 1 - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/BP = H.get_bodypart(def_zone) - - if(BP.body_zone == BP_HEAD) - if(H.head && istype(H.head,/obj/item/clothing/head/helmet/space)) - to_chat(user, "You can't apply [src] through [H.head]!") - return 1 - else - if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space)) - to_chat(user, "You can't apply [src] through [H.wear_suit]!") - return 1 - - if(BP.status & ORGAN_ROBOT) - to_chat(user, "This isn't useful at all on a robotic limb..") - return 1 - else - M.heal_bodypart_damage(heal_brute / 2, heal_burn / 2) - user.visible_message("[M] has been applied with [src] by [user].", \ - "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, mob/user, def_zone) - if(..()) - return 1 - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/BP = H.get_bodypart(def_zone) - - if(BP.open == 0) - if(BP.is_bandaged()) - to_chat(user, "The wounds on [M]'s [BP.name] have already been bandaged.") - return 1 - else - user.visible_message("\The [user] starts treating [M]'s [BP.name].", \ - "You start treating [M]'s [BP.name].") - - for(var/datum/wound/W in BP.wounds) - if(W.bandaged) - continue - if(!use(1)) - break - if(!do_mob(user, M, W.damage)) - to_chat(user, "You must stand still to bandage wounds.") - break - if(W.current_stage <= W.max_bleeding_stage) - user.visible_message("\The [user] bandages [W.desc] on [M]'s [BP.name].", \ - "You bandage [W.desc] on [M]'s [BP.name].") - //H.add_side_effect("Itch") - else if (istype(W,/datum/wound/bruise)) - user.visible_message("\The [user] places bruise patch over [W.desc] on [M]'s [BP.name].", \ - "You place bruise patch over [W.desc] on [M]'s [BP.name]." ) - else - user.visible_message("\The [user] places bandaid over [W.desc] on [M]'s [BP.name].", \ - "You place bandaid over [W.desc] on [M]'s [BP.name].") - W.bandage() - if(crit_fail) - W.germ_level += germ_level - else - W.germ_level += min(germ_level, 3) - - BP.update_damages() - H.update_bandage() - - if(BP.is_bandaged()) - to_chat(user, "\The [src] is used up.") - else - to_chat(user, "\The [src] is used up, but there are more wounds to treat on \the [BP.name].") - - 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, "The [BP.name] is cut 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" - heal_burn = 1 - origin_tech = "biotech=1" - -/obj/item/stack/medical/ointment/attack(mob/living/carbon/M, mob/user, def_zone) - if(..()) - return 1 - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/BP = H.get_bodypart(def_zone) - - if(BP.open == 0) - if(BP.is_salved()) - to_chat(user, "The wounds on [M]'s [BP.name] have already been salved.") - return 1 - else - user.visible_message("\The [user] starts salving wounds on [M]'s [BP.name].", \ - "You start salving the wounds on [M]'s [BP.name].") - if(!do_mob(user, M, 25)) - to_chat(user, "You must stand still to salve wounds.") - return 1 - - if(!use(1)) - to_chat(user, "You need more ointment to do this.") - return - - user.visible_message("\The [user] salves wounds on [M]'s [BP.name].", \ - "You salve wounds on [M]'s [BP.name].") - BP.salve() - 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, "The [BP.name] is cut open, you'll need more than a 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 = "shandp" - heal_brute = 7 - -/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 = "mtearp" - heal_burn = 7 - -/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 = 12 - amount = 6 - max_amount = 6 - origin_tech = "biotech=1" - -/obj/item/stack/medical/advanced/bruise_pack/update_icon() - icon_state = "[initial(icon_state)][amount]" - -/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M, mob/user, def_zone) - if(..()) - return 1 - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/BP = H.get_bodypart(def_zone) - - if(BP.open == 0) - if(BP.is_bandaged() && BP.is_disinfected()) - to_chat(user, "The wounds on [M]'s [BP.name] have already been treated.") - return 1 - else - user.visible_message("\The [user] starts treating [M]'s [BP.name].", \ - "You start treating [M]'s [BP.name].") - - for(var/datum/wound/W in BP.wounds) - if(W.bandaged && W.disinfected) - continue - if(!use(1)) - break - update_icon() - if(!do_mob(user, M, W.damage)) - to_chat(user, "You must stand still to bandage wounds.") - break - if(W.current_stage <= W.max_bleeding_stage) - user.visible_message("\The [user] cleans [W.desc] on [M]'s [BP.name] and seals edges with bioglue.", \ - "You clean and seal [W.desc] on [M]'s [BP.name].") - else if (istype(W,/datum/wound/bruise)) - user.visible_message("\The [user] places medicine patch over [W.desc] on [M]'s [BP.name].", \ - "You place medicine patch over [W.desc] on [M]'s [BP.name].") - else - user.visible_message("\The [user] smears some bioglue over [W.desc] on [M]'s [BP.name].", \ - "You smear some bioglue over [W.desc] on [M]'s [BP.name].") - W.bandage() - W.disinfect() - W.heal_damage(heal_brute) - - BP.update_damages() - H.update_bandage() - - if(BP.is_bandaged()) - to_chat(user, "\The [src] is used up.") - else - to_chat(user, "\The [src] is used up, but there are more wounds to treat on \the [BP.name].") - - 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, "The [BP.name] is cut open, you'll need more than a bandage!") - -/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" - amount = 6 - max_amount = 6 - heal_burn = 12 - origin_tech = "biotech=1" - -/obj/item/stack/medical/advanced/ointment/update_icon() - icon_state = "[initial(icon_state)][amount]" - -/obj/item/stack/medical/advanced/ointment/attack(mob/living/carbon/M, mob/user, def_zone) - if(..()) - return 1 - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/BP = H.get_bodypart(def_zone) - - if(BP.open == 0) - if(BP.is_salved()) - to_chat(user, "The wounds on [M]'s [BP.name] have already been salved.") - return 1 - else - user.visible_message("\The [user] starts salving wounds on [M]'s [BP.name].", \ - "You start salving the wounds on [M]'s [BP.name].") - - if(!do_mob(user, M, 25)) - to_chat(user, "You must stand still to salve wounds.") - return 1 - - if(!use(1)) - to_chat(user, "You need more advanced burn kit's to do this.") - return - update_icon() - user.visible_message("\The [user] covers wounds on [M]'s [BP.name] with regenerative membrane.", \ - "You cover wounds on [M]'s [BP.name] with regenerative membrane.") - BP.heal_damage(0, heal_burn) - BP.salve() - - 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, "The [BP.name] is cut open, you'll need more than a bandage!") - -/obj/item/stack/medical/splint - name = "medical splints" - singular_name = "medical splint" - icon_state = "splint" - amount = 5 - max_amount = 5 - w_class = ITEM_SIZE_SMALL - full_w_class = ITEM_SIZE_SMALL - -/obj/item/stack/medical/splint/attack(mob/living/carbon/M, mob/user, def_zone) - if(..()) - return 1 - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/BP = H.get_bodypart(def_zone) - var/limb = BP.name - if(!((BP.body_zone == BP_L_ARM) || (BP.body_zone == BP_R_ARM) || (BP.body_zone == BP_L_LEG) || (BP.body_zone == BP_R_LEG))) - to_chat(user, "You can't apply a splint there!") - return - if(BP.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 && BP.body_zone == BP_R_ARM) || (user.hand && BP.body_zone == BP_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(!user.is_busy() && do_after(user, 50, target = M)) - if(!use(1)) - to_chat(user, "You need more splints's to do this.") - return - - 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 - BP.status |= ORGAN_SPLINTED - +/obj/item/stack/medical + name = "medical pack" + singular_name = "medical pack" + icon = 'icons/obj/items.dmi' + amount = 5 + max_amount = 5 + w_class = ITEM_SIZE_TINY + full_w_class = ITEM_SIZE_SMALL + throw_speed = 4 + throw_range = 20 + var/heal_brute = 0 + var/heal_burn = 0 + +/obj/item/stack/medical/update_weight() + if(amount < 3) + w_class = initial(w_class) + else + w_class = full_w_class + +/obj/item/stack/medical/attack(mob/living/carbon/M, mob/user, def_zone) + if(!istype(M)) + to_chat(user, "\The [src] cannot be applied to [M]!") + return 1 + + if(user.is_busy()) + return 1 + + if(!(ishuman(user) || issilicon(user) || ismonkey(user)) ) + to_chat(user, "You don't have the dexterity to do this!") + return 1 + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/BP = H.get_bodypart(def_zone) + + if(BP.body_zone == BP_HEAD) + if(H.head && istype(H.head,/obj/item/clothing/head/helmet/space)) + to_chat(user, "You can't apply [src] through [H.head]!") + return 1 + else + if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space)) + to_chat(user, "You can't apply [src] through [H.wear_suit]!") + return 1 + + if(BP.status & ORGAN_ROBOT) + to_chat(user, "This isn't useful at all on a robotic limb..") + return 1 + else + M.heal_bodypart_damage(heal_brute / 2, heal_burn / 2) + user.visible_message("[M] has been applied with [src] by [user].", \ + "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, mob/user, def_zone) + if(..()) + return 1 + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/BP = H.get_bodypart(def_zone) + + if(BP.open == 0) + if(BP.is_bandaged()) + to_chat(user, "The wounds on [M]'s [BP.name] have already been bandaged.") + return 1 + else + user.visible_message("\The [user] starts treating [M]'s [BP.name].", \ + "You start treating [M]'s [BP.name].") + + for(var/datum/wound/W in BP.wounds) + if(W.bandaged) + continue + if(!use(1)) + break + if(!do_mob(user, M, W.damage)) + to_chat(user, "You must stand still to bandage wounds.") + break + if(W.current_stage <= W.max_bleeding_stage) + user.visible_message("\The [user] bandages [W.desc] on [M]'s [BP.name].", \ + "You bandage [W.desc] on [M]'s [BP.name].") + //H.add_side_effect("Itch") + else if (istype(W,/datum/wound/bruise)) + user.visible_message("\The [user] places bruise patch over [W.desc] on [M]'s [BP.name].", \ + "You place bruise patch over [W.desc] on [M]'s [BP.name]." ) + else + user.visible_message("\The [user] places bandaid over [W.desc] on [M]'s [BP.name].", \ + "You place bandaid over [W.desc] on [M]'s [BP.name].") + W.bandage() + if(crit_fail) + W.germ_level += germ_level + else + W.germ_level += min(germ_level, 3) + + BP.update_damages() + H.update_bandage() + + if(BP.is_bandaged()) + to_chat(user, "\The [src] is used up.") + else + to_chat(user, "\The [src] is used up, but there are more wounds to treat on \the [BP.name].") + + 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, "The [BP.name] is cut 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" + heal_burn = 1 + origin_tech = "biotech=1" + +/obj/item/stack/medical/ointment/attack(mob/living/carbon/M, mob/user, def_zone) + if(..()) + return 1 + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/BP = H.get_bodypart(def_zone) + + if(BP.open == 0) + if(BP.is_salved()) + to_chat(user, "The wounds on [M]'s [BP.name] have already been salved.") + return 1 + else + user.visible_message("\The [user] starts salving wounds on [M]'s [BP.name].", \ + "You start salving the wounds on [M]'s [BP.name].") + if(!do_mob(user, M, 25)) + to_chat(user, "You must stand still to salve wounds.") + return 1 + + if(!use(1)) + to_chat(user, "You need more ointment to do this.") + return + + user.visible_message("\The [user] salves wounds on [M]'s [BP.name].", \ + "You salve wounds on [M]'s [BP.name].") + BP.salve() + 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, "The [BP.name] is cut open, you'll need more than a 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 = "shandp" + heal_brute = 7 + +/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 = "mtearp" + heal_burn = 7 + +/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 = 12 + amount = 6 + max_amount = 6 + origin_tech = "biotech=1" + +/obj/item/stack/medical/advanced/bruise_pack/update_icon() + icon_state = "[initial(icon_state)][amount]" + +/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M, mob/user, def_zone) + if(..()) + return 1 + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/BP = H.get_bodypart(def_zone) + + if(BP.open == 0) + if(BP.is_bandaged() && BP.is_disinfected()) + to_chat(user, "The wounds on [M]'s [BP.name] have already been treated.") + return 1 + else + user.visible_message("\The [user] starts treating [M]'s [BP.name].", \ + "You start treating [M]'s [BP.name].") + + for(var/datum/wound/W in BP.wounds) + if(W.bandaged && W.disinfected) + continue + if(!use(1)) + break + update_icon() + if(!do_mob(user, M, W.damage)) + to_chat(user, "You must stand still to bandage wounds.") + break + if(W.current_stage <= W.max_bleeding_stage) + user.visible_message("\The [user] cleans [W.desc] on [M]'s [BP.name] and seals edges with bioglue.", \ + "You clean and seal [W.desc] on [M]'s [BP.name].") + else if (istype(W,/datum/wound/bruise)) + user.visible_message("\The [user] places medicine patch over [W.desc] on [M]'s [BP.name].", \ + "You place medicine patch over [W.desc] on [M]'s [BP.name].") + else + user.visible_message("\The [user] smears some bioglue over [W.desc] on [M]'s [BP.name].", \ + "You smear some bioglue over [W.desc] on [M]'s [BP.name].") + W.bandage() + W.disinfect() + W.heal_damage(heal_brute) + + BP.update_damages() + H.update_bandage() + + if(BP.is_bandaged()) + to_chat(user, "\The [src] is used up.") + else + to_chat(user, "\The [src] is used up, but there are more wounds to treat on \the [BP.name].") + + 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, "The [BP.name] is cut open, you'll need more than a bandage!") + +/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" + amount = 6 + max_amount = 6 + heal_burn = 12 + origin_tech = "biotech=1" + +/obj/item/stack/medical/advanced/ointment/update_icon() + icon_state = "[initial(icon_state)][amount]" + +/obj/item/stack/medical/advanced/ointment/attack(mob/living/carbon/M, mob/user, def_zone) + if(..()) + return 1 + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/BP = H.get_bodypart(def_zone) + + if(BP.open == 0) + if(BP.is_salved()) + to_chat(user, "The wounds on [M]'s [BP.name] have already been salved.") + return 1 + else + user.visible_message("\The [user] starts salving wounds on [M]'s [BP.name].", \ + "You start salving the wounds on [M]'s [BP.name].") + + if(!do_mob(user, M, 25)) + to_chat(user, "You must stand still to salve wounds.") + return 1 + + if(!use(1)) + to_chat(user, "You need more advanced burn kit's to do this.") + return + update_icon() + user.visible_message("\The [user] covers wounds on [M]'s [BP.name] with regenerative membrane.", \ + "You cover wounds on [M]'s [BP.name] with regenerative membrane.") + BP.heal_damage(0, heal_burn) + BP.salve() + + 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, "The [BP.name] is cut open, you'll need more than a bandage!") + +/obj/item/stack/medical/splint + name = "medical splints" + singular_name = "medical splint" + icon_state = "splint" + amount = 5 + max_amount = 5 + w_class = ITEM_SIZE_SMALL + full_w_class = ITEM_SIZE_SMALL + +/obj/item/stack/medical/splint/attack(mob/living/carbon/M, mob/user, def_zone) + if(..()) + return 1 + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/BP = H.get_bodypart(def_zone) + var/limb = BP.name + if(!((BP.body_zone == BP_L_ARM) || (BP.body_zone == BP_R_ARM) || (BP.body_zone == BP_L_LEG) || (BP.body_zone == BP_R_LEG))) + to_chat(user, "You can't apply a splint there!") + return + if(BP.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 && BP.body_zone == BP_R_ARM) || (user.hand && BP.body_zone == BP_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(!user.is_busy() && do_after(user, 50, target = M)) + if(!use(1)) + to_chat(user, "You need more splints's to do this.") + return + + 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 + BP.status |= ORGAN_SPLINTED + return \ No newline at end of file diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index f8ac4d06c396..c8031dfbfc46 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -1,74 +1,74 @@ -/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 = CONDUCT - w_class = 3.0 - force = 9.0 - throwforce = 15.0 - throw_speed = 5 - throw_range = 20 - m_amt = 1875 - max_amount = 60 - attack_verb = list("hit", "bludgeoned", "whacked") - -/obj/item/stack/rods/update_icon() - var/amount = get_amount() - if((amount <= 5) && (amount > 0)) - icon_state = "rods-[amount]" - else - icon_state = "rods" - -/obj/item/stack/rods/attackby(obj/item/W, mob/user) - ..() - if (istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - - if(get_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/new_item = new(usr.loc, , TRUE) - user.visible_message( - "[user.name] shaped [src] into metal with the welding tool.", - "You shape [src] into metal with the welding tool.", - "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(new_item) - -/obj/item/stack/rods/attack_self(mob/user) - src.add_fingerprint(user) - - if(!istype(user.loc,/turf)) return 0 - - if (locate(/obj/structure/grille, usr.loc)) - for(var/obj/structure/grille/G in usr.loc) - if (G.destroyed) - if(!use(1)) - continue - G.health = 10 - G.density = 1 - G.destroyed = 0 - G.icon_state = "grille" - else - return 1 - else - if(get_amount() < 2) - to_chat(user, "You need at least two rods to do this!") - return - if(user.is_busy()) return - to_chat(usr, "Assembling grille...") - if (!do_after(usr, 10, target = usr)) - return - if (!use(2)) - return - var/obj/structure/grille/F = new /obj/structure/grille/ ( usr.loc ) - to_chat(usr, "You assemble a grille.") - F.add_fingerprint(usr) - return +/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 = CONDUCT + w_class = 3.0 + force = 9.0 + throwforce = 15.0 + throw_speed = 5 + throw_range = 20 + m_amt = 1875 + max_amount = 60 + attack_verb = list("hit", "bludgeoned", "whacked") + +/obj/item/stack/rods/update_icon() + var/amount = get_amount() + if((amount <= 5) && (amount > 0)) + icon_state = "rods-[amount]" + else + icon_state = "rods" + +/obj/item/stack/rods/attackby(obj/item/W, mob/user) + ..() + if (istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + + if(get_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/new_item = new(usr.loc, , TRUE) + user.visible_message( + "[user.name] shaped [src] into metal with the welding tool.", + "You shape [src] into metal with the welding tool.", + "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(new_item) + +/obj/item/stack/rods/attack_self(mob/user) + src.add_fingerprint(user) + + if(!istype(user.loc,/turf)) return 0 + + if (locate(/obj/structure/grille, usr.loc)) + for(var/obj/structure/grille/G in usr.loc) + if (G.destroyed) + if(!use(1)) + continue + G.health = 10 + G.density = 1 + G.destroyed = 0 + G.icon_state = "grille" + else + return 1 + else + if(get_amount() < 2) + to_chat(user, "You need at least two rods to do this!") + return + if(user.is_busy()) return + to_chat(usr, "Assembling grille...") + if (!do_after(usr, 10, target = usr)) + return + if (!use(2)) + return + var/obj/structure/grille/F = new /obj/structure/grille/ ( usr.loc ) + to_chat(usr, "You assemble a grille.") + F.add_fingerprint(usr) + return diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 4f9d81ede1a9..a3145dff88ad 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -1,394 +1,394 @@ -/* Glass stack types - * Contains: - * Glass sheets - * Reinforced glass sheets - * Phoron Glass Sheets - * Reinforced Phoron Glass Sheets (AKA Holy fuck strong windows) - * Glass shards - TODO: Move this into code/game/object/item/weapons - */ - -/* - * Glass sheets - */ -/obj/item/stack/sheet/glass - name = "glass" - desc = "HOLY SHEET! That is a lot of glass." - singular_name = "glass sheet" - icon_state = "sheet-glass" - g_amt = 3750 - origin_tech = "materials=1" - var/created_window = /obj/structure/window/basic - -/obj/item/stack/sheet/glass/cyborg - name = "glass" - desc = "HOLY SHEET! That is a lot of glass." - singular_name = "glass sheet" - icon_state = "sheet-glass" - g_amt = 0 - created_window = /obj/structure/window/basic - -/obj/item/stack/sheet/glass/attack_self(mob/user) - construct_window(user) - -/obj/item/stack/sheet/glass/attackby(obj/item/W, mob/user) - ..() - if(istype(W,/obj/item/stack/cable_coil)) - - var/list/resources_to_use = list() - resources_to_use[W] = 5 - resources_to_use[src] = 1 - if(!use_multi(user, resources_to_use)) - return - - to_chat(user, "\blue You attach wire to the [name].") - new /obj/item/stack/light_w(user.loc) - else if(istype(W, /obj/item/stack/rods)) - - var/list/resources_to_use = list() - resources_to_use[W] = 1 - resources_to_use[src] = 1 - if(!use_multi(user, resources_to_use)) - return - - var/obj/item/stack/sheet/rglass/RG = new (user.loc) - RG.add_fingerprint(user) - for(var/obj/item/stack/sheet/rglass/G in user.loc) - if(G==RG) - continue - if(G.get_amount() >= G.max_amount) - continue - G.attackby(RG, user) - to_chat(usr, "You add the reinforced glass to the stack. It now contains [RG.get_amount()] sheets.") - else - return ..() - -/obj/item/stack/sheet/glass/proc/construct_window(mob/user) - if(!user || !src) - return 0 - if(!istype(user.loc,/turf)) - return 0 - if(!user.IsAdvancedToolUser()) - to_chat(user, "\red You don't have the dexterity to do this!") - return 0 - var/title = "Sheet-Glass" - title += " ([get_amount()] sheet\s left)" - switch(input(title, "What would you like to make?", "One Direction") in list("One Direction", "Full Window", "Glass Table Parts", "Cancel")) - if("One Direction") - if(QDELETED(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, "\red There are too many windows in this location.") - return 1 - directions-=win.dir - if(!(win.ini_dir in cardinal)) - to_chat(user, "\red 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 - - if(!src.use(1)) - to_chat(user, "\red You need more glass to do that.") - return 1 - - var/obj/structure/window/W - W = new created_window(user.loc) - W.dir = dir_to_set - W.ini_dir = W.dir - W.anchored = 0 - if("Full Window") - if(QDELETED(src)) - return 1 - if(src.loc != user) - return 1 - var/step = get_step(user, user.dir) - var/turf/T = get_turf(step) - if(T.density || (locate(/obj/structure/window) in step)) - to_chat(user, "\red There is something in the way.") - return 1 - - if(!src.use(2)) - to_chat(user, "\red You need more glass to do that.") - return 1 - - var/obj/structure/window/W - W = new created_window(step) - W.dir = SOUTHWEST - W.ini_dir = SOUTHWEST - W.anchored = 0 - if("Glass Table Parts") - if(QDELETED(src)) - return 1 - if(src.loc != user) - return 1 - - if(!src.use(2)) - to_chat(user, "\red You need more glass to do that.") - return 1 - - new /obj/item/weapon/table_parts/glass(user.loc) - return 0 - -/obj/item/stack/sheet/glass/after_throw(datum/callback/callback) - ..() - playsound(src, "shatter", 70, 1) - new /obj/item/weapon/shard(loc) - set_amount(get_amount() - rand(5,35)) - -/obj/item/stack/sheet/rglass/after_throw(datum/callback/callback) - ..() - playsound(src, "shatter", 70, 1) - new /obj/item/weapon/shard(loc) - set_amount(get_amount() - rand(1,15)) - -/* - * Reinforced glass sheets - */ -/obj/item/stack/sheet/rglass - name = "reinforced glass" - desc = "Glass which seems to have rods or something stuck in them." - singular_name = "reinforced glass sheet" - icon_state = "sheet-rglass" - g_amt = 3750 - m_amt = 1875 - origin_tech = "materials=2" - -/obj/item/stack/sheet/rglass/cyborg - name = "reinforced glass" - desc = "Glass which seems to have rods or something stuck in them." - singular_name = "reinforced glass sheet" - icon_state = "sheet-rglass" - g_amt = 0 - m_amt = 0 - -/obj/item/stack/sheet/rglass/attack_self(mob/user) - construct_window(user) - -/obj/item/stack/sheet/rglass/proc/construct_window(mob/user) - if(!user || QDELETED(src)) - return 0 - if(!isturf(user.loc)) - return 0 - if(!user.IsAdvancedToolUser()) - to_chat(user, "\red You don't have the dexterity to do this!") - return 0 - var/title = "Sheet Reinf. Glass" - title += " ([get_amount()] sheet\s left)" - 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(QDELETED(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, "\red There are too many windows in this location.") - return 1 - directions-=win.dir - if(!(win.ini_dir in cardinal)) - to_chat(user, "\red 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 - - if(!src.use(1)) - to_chat(user, "\red You need more glass to do that.") - return 1 - - var/obj/structure/window/W - W = new /obj/structure/window/reinforced(user.loc) - W.state = 0 - W.dir = dir_to_set - W.ini_dir = W.dir - W.anchored = 0 - - if("Full Window") - if(QDELETED(src)) - return 1 - if(src.loc != user) - return 1 - var/step = get_step(user, user.dir) - var/turf/T = get_turf(step) - if(T.density || (locate(/obj/structure/window) in step)) - to_chat(user, "\red There is something in the way.") - return 1 - if(!src.use(2)) - to_chat(user, "\red You need more glass to do that.") - return 1 - var/obj/structure/window/W - W = new /obj/structure/window/reinforced(step) - W.state = 0 - W.dir = SOUTHWEST - W.ini_dir = SOUTHWEST - W.state = 0 - W.anchored = 0 - - if("Windoor") - if(QDELETED(src) || src.loc != user) - return 1 - - if(isturf(user.loc) && locate(/obj/structure/windoor_assembly/, user.loc)) - to_chat(user, "\red 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, "\red There is already a windoor in that location.") - return 1 - - if(!src.use(5)) - to_chat(user, "\red You need more glass to do that.") - return 1 - - var/obj/structure/windoor_assembly/WD - WD = new /obj/structure/windoor_assembly(user.loc) - WD.state = "01" - WD.anchored = 0 - 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 - - - return 0 - -/* - * Glass shards - TODO: Move this into code/game/object/item/weapons - */ -/obj/item/weapon/shard/Bump() - if(prob(20)) - force = 15 - else - force = 4 - ..() - -/obj/item/weapon/shard/atom_init() - . = ..() - - icon_state = pick("large", "medium", "small") - switch(icon_state) - if("small") - pixel_x = rand(-12, 12) - pixel_y = rand(-12, 12) - if("medium") - pixel_x = rand(-8, 8) - pixel_y = rand(-8, 8) - if("large") - pixel_x = rand(-5, 5) - pixel_y = rand(-5, 5) - -/obj/item/weapon/shard/attackby(obj/item/weapon/W, mob/user) - ..() - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - var/obj/item/stack/sheet/glass/NG = new (user.loc) - for(var/obj/item/stack/sheet/glass/G in user.loc) - if(G==NG) - continue - if(G.get_amount() >= G.max_amount) - continue - G.attackby(NG, user) - to_chat(usr, "You add the newly-formed glass to the stack. It now contains [NG.get_amount()] sheets.") - //SN src = null - qdel(src) - return - return ..() - -/obj/item/weapon/shard/Crossed(atom/movable/AM) - if(ismob(AM)) - var/mob/M = AM - to_chat(M, "\red You step in the broken glass!") - playsound(src.loc, 'sound/effects/glass_step.ogg', 50, 1) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - - if(H.species.flags[IS_SYNTHETIC]) - return - - if(H.wear_suit && (H.wear_suit.body_parts_covered & LEGS) && H.wear_suit.flags & THICKMATERIAL) - return - - if(H.species.flags[NO_MINORCUTS]) - return - - if(!H.shoes) - var/obj/item/organ/external/BP = H.bodyparts_by_name[pick(BP_L_LEG , BP_R_LEG)] - if(BP.status & ORGAN_ROBOT) - return - BP.take_damage(5, 0) - if(!H.species.flags[NO_PAIN]) - H.Weaken(3) - H.updatehealth() - ..() - - - - -/* - * Phoron Glass sheets - */ -/obj/item/stack/sheet/glass/phoronglass - name = "phoron glass" - desc = "A very strong and very resistant sheet of a phoron-glass alloy." - singular_name = "phoron glass sheet" - icon_state = "sheet-phoronglass" - g_amt = 7500 - origin_tech = "materials=3;phorontech=2" - created_window = /obj/structure/window/phoronbasic - -/obj/item/stack/sheet/glass/phoronglass/attack_self(mob/user) - construct_window(user) - -/* - * Reinforced phoron glass sheets - */ -/obj/item/stack/sheet/glass/phoronrglass - name = "reinforced phoron glass" - desc = "Phoron glass which seems to have rods or something stuck in them." - singular_name = "reinforced phoron glass sheet" - icon_state = "sheet-phoronrglass" - g_amt = 7500 - m_amt = 1875 - origin_tech = "materials=4;phorontech=2" - created_window = /obj/structure/window/phoronreinforced - -/obj/item/stack/sheet/glass/phoronrglass/attack_self(mob/user) - construct_window(user) +/* Glass stack types + * Contains: + * Glass sheets + * Reinforced glass sheets + * Phoron Glass Sheets + * Reinforced Phoron Glass Sheets (AKA Holy fuck strong windows) + * Glass shards - TODO: Move this into code/game/object/item/weapons + */ + +/* + * Glass sheets + */ +/obj/item/stack/sheet/glass + name = "glass" + desc = "HOLY SHEET! That is a lot of glass." + singular_name = "glass sheet" + icon_state = "sheet-glass" + g_amt = 3750 + origin_tech = "materials=1" + var/created_window = /obj/structure/window/basic + +/obj/item/stack/sheet/glass/cyborg + name = "glass" + desc = "HOLY SHEET! That is a lot of glass." + singular_name = "glass sheet" + icon_state = "sheet-glass" + g_amt = 0 + created_window = /obj/structure/window/basic + +/obj/item/stack/sheet/glass/attack_self(mob/user) + construct_window(user) + +/obj/item/stack/sheet/glass/attackby(obj/item/W, mob/user) + ..() + if(istype(W,/obj/item/stack/cable_coil)) + + var/list/resources_to_use = list() + resources_to_use[W] = 5 + resources_to_use[src] = 1 + if(!use_multi(user, resources_to_use)) + return + + to_chat(user, "\blue You attach wire to the [name].") + new /obj/item/stack/light_w(user.loc) + else if(istype(W, /obj/item/stack/rods)) + + var/list/resources_to_use = list() + resources_to_use[W] = 1 + resources_to_use[src] = 1 + if(!use_multi(user, resources_to_use)) + return + + var/obj/item/stack/sheet/rglass/RG = new (user.loc) + RG.add_fingerprint(user) + for(var/obj/item/stack/sheet/rglass/G in user.loc) + if(G==RG) + continue + if(G.get_amount() >= G.max_amount) + continue + G.attackby(RG, user) + to_chat(usr, "You add the reinforced glass to the stack. It now contains [RG.get_amount()] sheets.") + else + return ..() + +/obj/item/stack/sheet/glass/proc/construct_window(mob/user) + if(!user || !src) + return 0 + if(!istype(user.loc,/turf)) + return 0 + if(!user.IsAdvancedToolUser()) + to_chat(user, "\red You don't have the dexterity to do this!") + return 0 + var/title = "Sheet-Glass" + title += " ([get_amount()] sheet\s left)" + switch(input(title, "What would you like to make?", "One Direction") in list("One Direction", "Full Window", "Glass Table Parts", "Cancel")) + if("One Direction") + if(QDELETED(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, "\red There are too many windows in this location.") + return 1 + directions-=win.dir + if(!(win.ini_dir in cardinal)) + to_chat(user, "\red 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 + + if(!src.use(1)) + to_chat(user, "\red You need more glass to do that.") + return 1 + + var/obj/structure/window/W + W = new created_window(user.loc) + W.dir = dir_to_set + W.ini_dir = W.dir + W.anchored = 0 + if("Full Window") + if(QDELETED(src)) + return 1 + if(src.loc != user) + return 1 + var/step = get_step(user, user.dir) + var/turf/T = get_turf(step) + if(T.density || (locate(/obj/structure/window) in step)) + to_chat(user, "\red There is something in the way.") + return 1 + + if(!src.use(2)) + to_chat(user, "\red You need more glass to do that.") + return 1 + + var/obj/structure/window/W + W = new created_window(step) + W.dir = SOUTHWEST + W.ini_dir = SOUTHWEST + W.anchored = 0 + if("Glass Table Parts") + if(QDELETED(src)) + return 1 + if(src.loc != user) + return 1 + + if(!src.use(2)) + to_chat(user, "\red You need more glass to do that.") + return 1 + + new /obj/item/weapon/table_parts/glass(user.loc) + return 0 + +/obj/item/stack/sheet/glass/after_throw(datum/callback/callback) + ..() + playsound(src, "shatter", 70, 1) + new /obj/item/weapon/shard(loc) + set_amount(get_amount() - rand(5,35)) + +/obj/item/stack/sheet/rglass/after_throw(datum/callback/callback) + ..() + playsound(src, "shatter", 70, 1) + new /obj/item/weapon/shard(loc) + set_amount(get_amount() - rand(1,15)) + +/* + * Reinforced glass sheets + */ +/obj/item/stack/sheet/rglass + name = "reinforced glass" + desc = "Glass which seems to have rods or something stuck in them." + singular_name = "reinforced glass sheet" + icon_state = "sheet-rglass" + g_amt = 3750 + m_amt = 1875 + origin_tech = "materials=2" + +/obj/item/stack/sheet/rglass/cyborg + name = "reinforced glass" + desc = "Glass which seems to have rods or something stuck in them." + singular_name = "reinforced glass sheet" + icon_state = "sheet-rglass" + g_amt = 0 + m_amt = 0 + +/obj/item/stack/sheet/rglass/attack_self(mob/user) + construct_window(user) + +/obj/item/stack/sheet/rglass/proc/construct_window(mob/user) + if(!user || QDELETED(src)) + return 0 + if(!isturf(user.loc)) + return 0 + if(!user.IsAdvancedToolUser()) + to_chat(user, "\red You don't have the dexterity to do this!") + return 0 + var/title = "Sheet Reinf. Glass" + title += " ([get_amount()] sheet\s left)" + 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(QDELETED(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, "\red There are too many windows in this location.") + return 1 + directions-=win.dir + if(!(win.ini_dir in cardinal)) + to_chat(user, "\red 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 + + if(!src.use(1)) + to_chat(user, "\red You need more glass to do that.") + return 1 + + var/obj/structure/window/W + W = new /obj/structure/window/reinforced(user.loc) + W.state = 0 + W.dir = dir_to_set + W.ini_dir = W.dir + W.anchored = 0 + + if("Full Window") + if(QDELETED(src)) + return 1 + if(src.loc != user) + return 1 + var/step = get_step(user, user.dir) + var/turf/T = get_turf(step) + if(T.density || (locate(/obj/structure/window) in step)) + to_chat(user, "\red There is something in the way.") + return 1 + if(!src.use(2)) + to_chat(user, "\red You need more glass to do that.") + return 1 + var/obj/structure/window/W + W = new /obj/structure/window/reinforced(step) + W.state = 0 + W.dir = SOUTHWEST + W.ini_dir = SOUTHWEST + W.state = 0 + W.anchored = 0 + + if("Windoor") + if(QDELETED(src) || src.loc != user) + return 1 + + if(isturf(user.loc) && locate(/obj/structure/windoor_assembly/, user.loc)) + to_chat(user, "\red 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, "\red There is already a windoor in that location.") + return 1 + + if(!src.use(5)) + to_chat(user, "\red You need more glass to do that.") + return 1 + + var/obj/structure/windoor_assembly/WD + WD = new /obj/structure/windoor_assembly(user.loc) + WD.state = "01" + WD.anchored = 0 + 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 + + + return 0 + +/* + * Glass shards - TODO: Move this into code/game/object/item/weapons + */ +/obj/item/weapon/shard/Bump() + if(prob(20)) + force = 15 + else + force = 4 + ..() + +/obj/item/weapon/shard/atom_init() + . = ..() + + icon_state = pick("large", "medium", "small") + switch(icon_state) + if("small") + pixel_x = rand(-12, 12) + pixel_y = rand(-12, 12) + if("medium") + pixel_x = rand(-8, 8) + pixel_y = rand(-8, 8) + if("large") + pixel_x = rand(-5, 5) + pixel_y = rand(-5, 5) + +/obj/item/weapon/shard/attackby(obj/item/weapon/W, mob/user) + ..() + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + var/obj/item/stack/sheet/glass/NG = new (user.loc) + for(var/obj/item/stack/sheet/glass/G in user.loc) + if(G==NG) + continue + if(G.get_amount() >= G.max_amount) + continue + G.attackby(NG, user) + to_chat(usr, "You add the newly-formed glass to the stack. It now contains [NG.get_amount()] sheets.") + //SN src = null + qdel(src) + return + return ..() + +/obj/item/weapon/shard/Crossed(atom/movable/AM) + if(ismob(AM)) + var/mob/M = AM + to_chat(M, "\red You step in the broken glass!") + playsound(src.loc, 'sound/effects/glass_step.ogg', 50, 1) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + + if(H.species.flags[IS_SYNTHETIC]) + return + + if(H.wear_suit && (H.wear_suit.body_parts_covered & LEGS) && H.wear_suit.flags & THICKMATERIAL) + return + + if(H.species.flags[NO_MINORCUTS]) + return + + if(!H.shoes) + var/obj/item/organ/external/BP = H.bodyparts_by_name[pick(BP_L_LEG , BP_R_LEG)] + if(BP.status & ORGAN_ROBOT) + return + BP.take_damage(5, 0) + if(!H.species.flags[NO_PAIN]) + H.Weaken(3) + H.updatehealth() + ..() + + + + +/* + * Phoron Glass sheets + */ +/obj/item/stack/sheet/glass/phoronglass + name = "phoron glass" + desc = "A very strong and very resistant sheet of a phoron-glass alloy." + singular_name = "phoron glass sheet" + icon_state = "sheet-phoronglass" + g_amt = 7500 + origin_tech = "materials=3;phorontech=2" + created_window = /obj/structure/window/phoronbasic + +/obj/item/stack/sheet/glass/phoronglass/attack_self(mob/user) + construct_window(user) + +/* + * Reinforced phoron glass sheets + */ +/obj/item/stack/sheet/glass/phoronrglass + name = "reinforced phoron glass" + desc = "Phoron glass which seems to have rods or something stuck in them." + singular_name = "reinforced phoron glass sheet" + icon_state = "sheet-phoronrglass" + g_amt = 7500 + m_amt = 1875 + origin_tech = "materials=4;phorontech=2" + created_window = /obj/structure/window/phoronreinforced + +/obj/item/stack/sheet/glass/phoronrglass/attack_self(mob/user) + construct_window(user) diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index c494dc884fff..7903faec436c 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -1,124 +1,124 @@ -/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/mob/alien.dmi' - icon_state = "chitin" - origin_tech = "" - -/obj/item/xenos_claw - name = "alien claw" - desc = "The claw of a terrible creature." - icon = 'icons/mob/alien.dmi' - icon_state = "claw" - origin_tech = "" - -/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_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_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_state = "sheet-leather" - origin_tech = "materials=2" - - - -//Step one - dehairing. - -/obj/item/stack/sheet/animalhide/attackby(obj/item/weapon/W, mob/user) - if( istype(W, /obj/item/weapon/kitchenknife) || \ - istype(W, /obj/item/weapon/twohanded/fireaxe) || \ - istype(W, /obj/item/weapon/hatchet) ) - - //visible message on mobs is defined as visible_message(message, self_message, blind_message) - if(user.is_busy()) return - usr.visible_message("\blue \the [usr] starts cutting hair off \the [src]", "\blue You start cutting the hair off \the [src]", "You hear the sound of a knife rubbing against flesh") - if(do_after(user,50,target = src)) - if(!use(1)) - return - - to_chat(usr, "\blue You cut the hair from this [src.singular_name]") - new/obj/item/stack/sheet/hairlesshide(usr.loc, , TRUE) - - 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(!use(1)) - return - - new/obj/item/stack/sheet/leather(loc) - wetness = initial(wetness) +/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/mob/alien.dmi' + icon_state = "chitin" + origin_tech = "" + +/obj/item/xenos_claw + name = "alien claw" + desc = "The claw of a terrible creature." + icon = 'icons/mob/alien.dmi' + icon_state = "claw" + origin_tech = "" + +/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_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_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_state = "sheet-leather" + origin_tech = "materials=2" + + + +//Step one - dehairing. + +/obj/item/stack/sheet/animalhide/attackby(obj/item/weapon/W, mob/user) + if( istype(W, /obj/item/weapon/kitchenknife) || \ + istype(W, /obj/item/weapon/twohanded/fireaxe) || \ + istype(W, /obj/item/weapon/hatchet) ) + + //visible message on mobs is defined as visible_message(message, self_message, blind_message) + if(user.is_busy()) return + usr.visible_message("\blue \the [usr] starts cutting hair off \the [src]", "\blue You start cutting the hair off \the [src]", "You hear the sound of a knife rubbing against flesh") + if(do_after(user,50,target = src)) + if(!use(1)) + return + + to_chat(usr, "\blue You cut the hair from this [src.singular_name]") + new/obj/item/stack/sheet/hairlesshide(usr.loc, , TRUE) + + 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(!use(1)) + return + + new/obj/item/stack/sheet/leather(loc) + wetness = initial(wetness) diff --git a/code/game/objects/items/stacks/sheets/light.dm b/code/game/objects/items/stacks/sheets/light.dm index 5223e65d114c..cd91a076c20a 100644 --- a/code/game/objects/items/stacks/sheets/light.dm +++ b/code/game/objects/items/stacks/sheets/light.dm @@ -1,29 +1,29 @@ -/obj/item/stack/light_w - name = "wired glass tile" - 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 = CONDUCT - max_amount = 60 - -/obj/item/stack/light_w/attackby(obj/item/O, mob/user) - ..() - if(istype(O,/obj/item/weapon/wirecutters)) - if(!use(1)) - return - new/obj/item/stack/cable_coil/random(user.loc, 5) - new/obj/item/stack/sheet/glass(user.loc) - - if(istype(O,/obj/item/stack/sheet/metal)) - var/list/resources_to_use = list() - resources_to_use[O] = 1 - resources_to_use[src] = 1 - if(!use_multi(user, resources_to_use)) - return - - new/obj/item/stack/tile/light(user.loc) +/obj/item/stack/light_w + name = "wired glass tile" + 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 = CONDUCT + max_amount = 60 + +/obj/item/stack/light_w/attackby(obj/item/O, mob/user) + ..() + if(istype(O,/obj/item/weapon/wirecutters)) + if(!use(1)) + return + new/obj/item/stack/cable_coil/random(user.loc, 5) + new/obj/item/stack/sheet/glass(user.loc) + + if(istype(O,/obj/item/stack/sheet/metal)) + var/list/resources_to_use = list() + resources_to_use[O] = 1 + resources_to_use[src] = 1 + if(!use_multi(user, resources_to_use)) + return + + new/obj/item/stack/tile/light(user.loc) diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 9a285e61ecaa..c45131602d51 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -1,290 +1,290 @@ -/* -Mineral Sheets - Contains: - - Sandstone - - Diamond - - Uranium - - Phoron - - Gold - - Silver - - Clown - Others: - - Enriched Uranium - - Platinum - - Metallic Hydrogen - - Tritium - - Osmium -*/ - -/* - * Recipes - */ -var/global/list/datum/stack_recipe/sandstone_recipes = list ( \ - new/datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \ - new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = TRUE, on_floor = TRUE), \ - ) - -var/global/list/datum/stack_recipe/diamond_recipes = list ( \ - new/datum/stack_recipe("diamond door", /obj/structure/mineral_door/transparent/diamond, 10, one_per_turf = TRUE, on_floor = TRUE), \ - ) - -var/global/list/datum/stack_recipe/phoron_recipes = list ( \ - new/datum/stack_recipe("phoron door", /obj/structure/mineral_door/transparent/phoron, 10, one_per_turf = TRUE, on_floor = TRUE), \ - ) - -var/global/list/datum/stack_recipe/uranium_recipes = list ( \ - new/datum/stack_recipe("uranium door", /obj/structure/mineral_door/uranium, 10, one_per_turf = TRUE, on_floor = TRUE), \ - ) - -var/global/list/datum/stack_recipe/plastic_recipes = list ( \ - new/datum/stack_recipe("plastic crate", /obj/structure/closet/crate/plastic, 10, one_per_turf = TRUE, on_floor = TRUE), \ - new/datum/stack_recipe("plastic ashtray", /obj/item/ashtray/plastic, 2, one_per_turf = TRUE, on_floor = TRUE), \ - new/datum/stack_recipe("plastic fork", /obj/item/weapon/kitchen/utensil/pfork, 1, on_floor = TRUE), \ - new/datum/stack_recipe("plastic spoon", /obj/item/weapon/kitchen/utensil/pspoon, 1, on_floor = TRUE), \ - new/datum/stack_recipe("plastic knife", /obj/item/weapon/kitchenknife/plastic, 1, on_floor = TRUE), \ - new/datum/stack_recipe("plastic bag", /obj/item/weapon/storage/bag/plasticbag, 3, on_floor = TRUE), \ - new/datum/stack_recipe("sign backing", /obj/item/sign_backing, 4, on_floor = TRUE) - ) - -var/global/list/datum/stack_recipe/gold_recipes = list ( \ - new/datum/stack_recipe("golden door", /obj/structure/mineral_door/gold, 10, one_per_turf = TRUE, on_floor = TRUE), \ - ) - -var/global/list/datum/stack_recipe/silver_recipes = list ( \ - new/datum/stack_recipe("silver door", /obj/structure/mineral_door/silver, 10, one_per_turf = TRUE, on_floor = TRUE), \ - ) - - -/obj/item/stack/sheet/mineral/sandstone/atom_init() - recipes = sandstone_recipes - pixel_x = rand(0,4)-4 - pixel_y = rand(0,4)-4 - . = ..() - -/obj/item/stack/sheet/mineral - force = 5.0 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - -/obj/item/stack/sheet/mineral/atom_init() - . = ..() - pixel_x = rand(0,4)-4 - pixel_y = rand(0,4)-4 - - -/* - * Iron - */ -/obj/item/stack/sheet/mineral/iron - name = "iron" - icon_state = "sheet-silver" - origin_tech = "materials=1" - sheettype = "iron" - color = "#333333" - perunit = 3750 - -/* - * Sandstone - */ -/obj/item/stack/sheet/mineral/sandstone - name = "sandstone brick" - 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" - - -/obj/item/stack/sheet/mineral/sandstone/atom_init() - . = ..() - recipes = sandstone_recipes - -/* - * Diamond - */ -/obj/item/stack/sheet/mineral/diamond - name = "diamond" - icon_state = "sheet-diamond" - origin_tech = "materials=6" - perunit = 3750 - sheettype = "diamond" - - -/obj/item/stack/sheet/mineral/diamond/atom_init() - . = ..() - recipes = diamond_recipes - -/* - * Uranium - */ -/obj/item/stack/sheet/mineral/uranium - name = "uranium" - icon_state = "sheet-uranium" - origin_tech = "materials=5" - perunit = 2000 - sheettype = "uranium" - - -/obj/item/stack/sheet/mineral/uranium/atom_init() - . = ..() - recipes = uranium_recipes - -/* - * Phoron - */ -/obj/item/stack/sheet/mineral/phoron - name = "solid phoron" - icon_state = "sheet-phoron" - origin_tech = "phorontech=2;materials=2" - perunit = 2000 - sheettype = "phoron" - is_fusion_fuel = TRUE - - -/obj/item/stack/sheet/mineral/phoron/atom_init() - . = ..() - recipes = phoron_recipes - -/* - * Plastic - */ -/obj/item/stack/sheet/mineral/plastic - name = "Plastic" - icon_state = "sheet-plastic" - origin_tech = "materials=3" - perunit = 2000 - -/obj/item/stack/sheet/mineral/plastic/cyborg - name = "plastic sheets" - icon_state = "sheet-plastic" - perunit = 2000 - - -/obj/item/stack/sheet/mineral/plastic/atom_init() - . = ..() - recipes = plastic_recipes - -/* - * Gold - */ -/obj/item/stack/sheet/mineral/gold - name = "gold" - 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 - sheettype = "gold" - - - -/obj/item/stack/sheet/mineral/gold/atom_init() - . = ..() - recipes = gold_recipes - -/* - * Silver - */ -/obj/item/stack/sheet/mineral/silver - name = "silver" - icon_state = "sheet-silver" - origin_tech = "materials=3" - perunit = 2000 - sheettype = "silver" - - - -/obj/item/stack/sheet/mineral/silver/atom_init() - . = ..() - recipes = silver_recipes - -/* - * Clown - */ -/obj/item/stack/sheet/mineral/clown - name = "bananium" - 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" - - -/****************************** Others ****************************/ - -/* - * Enriched Uranium - */ -/obj/item/stack/sheet/mineral/enruranium - name = "enriched uranium" - icon_state = "sheet-enruranium" - origin_tech = "materials=5" - perunit = 1000 - -/* - * Platinum - */ -//Valuable resource, cargo can sell it. -/obj/item/stack/sheet/mineral/platinum - name = "platinum" - icon_state = "sheet-adamantine" - origin_tech = "materials=2" - sheettype = "platinum" - perunit = 2000 - -/* - * Mhydrogen - */ -//Extremely valuable to Research. -/obj/item/stack/sheet/mineral/mhydrogen - name = "metallic hydrogen" - icon_state = "sheet-mythril" - origin_tech = "materials=6;powerstorage=5;magnets=5" - sheettype = "mhydrogen" - perunit = 2000 - is_fusion_fuel = TRUE - -/* - * Tritium - */ -//Fuel for MRSPACMAN generator. -/obj/item/stack/sheet/mineral/tritium - name = "tritium" - icon_state = "sheet-silver" - sheettype = "tritium" - origin_tech = "materials=5" - color = "#777777" - perunit = 2000 - is_fusion_fuel = TRUE - -/* - * Osmium - */ -/obj/item/stack/sheet/mineral/osmium - name = "osmium" - icon_state = "sheet-silver" - sheettype = "osmium" - origin_tech = "materials=5" - color = "#9999FF" - perunit = 2000 - -// Fusion fuel. -/obj/item/stack/sheet/mineral/deuterium - name = "deuterium" - icon_state = "sheet-silver" - sheettype = "deuterium" - origin_tech = "materials=3" - color = "#999999" - perunit = 2000 - is_fusion_fuel = TRUE +/* +Mineral Sheets + Contains: + - Sandstone + - Diamond + - Uranium + - Phoron + - Gold + - Silver + - Clown + Others: + - Enriched Uranium + - Platinum + - Metallic Hydrogen + - Tritium + - Osmium +*/ + +/* + * Recipes + */ +var/global/list/datum/stack_recipe/sandstone_recipes = list ( \ + new/datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = TRUE, on_floor = TRUE), \ + ) + +var/global/list/datum/stack_recipe/diamond_recipes = list ( \ + new/datum/stack_recipe("diamond door", /obj/structure/mineral_door/transparent/diamond, 10, one_per_turf = TRUE, on_floor = TRUE), \ + ) + +var/global/list/datum/stack_recipe/phoron_recipes = list ( \ + new/datum/stack_recipe("phoron door", /obj/structure/mineral_door/transparent/phoron, 10, one_per_turf = TRUE, on_floor = TRUE), \ + ) + +var/global/list/datum/stack_recipe/uranium_recipes = list ( \ + new/datum/stack_recipe("uranium door", /obj/structure/mineral_door/uranium, 10, one_per_turf = TRUE, on_floor = TRUE), \ + ) + +var/global/list/datum/stack_recipe/plastic_recipes = list ( \ + new/datum/stack_recipe("plastic crate", /obj/structure/closet/crate/plastic, 10, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("plastic ashtray", /obj/item/ashtray/plastic, 2, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("plastic fork", /obj/item/weapon/kitchen/utensil/pfork, 1, on_floor = TRUE), \ + new/datum/stack_recipe("plastic spoon", /obj/item/weapon/kitchen/utensil/pspoon, 1, on_floor = TRUE), \ + new/datum/stack_recipe("plastic knife", /obj/item/weapon/kitchenknife/plastic, 1, on_floor = TRUE), \ + new/datum/stack_recipe("plastic bag", /obj/item/weapon/storage/bag/plasticbag, 3, on_floor = TRUE), \ + new/datum/stack_recipe("sign backing", /obj/item/sign_backing, 4, on_floor = TRUE) + ) + +var/global/list/datum/stack_recipe/gold_recipes = list ( \ + new/datum/stack_recipe("golden door", /obj/structure/mineral_door/gold, 10, one_per_turf = TRUE, on_floor = TRUE), \ + ) + +var/global/list/datum/stack_recipe/silver_recipes = list ( \ + new/datum/stack_recipe("silver door", /obj/structure/mineral_door/silver, 10, one_per_turf = TRUE, on_floor = TRUE), \ + ) + + +/obj/item/stack/sheet/mineral/sandstone/atom_init() + recipes = sandstone_recipes + pixel_x = rand(0,4)-4 + pixel_y = rand(0,4)-4 + . = ..() + +/obj/item/stack/sheet/mineral + force = 5.0 + throwforce = 5 + w_class = 3.0 + throw_speed = 3 + throw_range = 3 + +/obj/item/stack/sheet/mineral/atom_init() + . = ..() + pixel_x = rand(0,4)-4 + pixel_y = rand(0,4)-4 + + +/* + * Iron + */ +/obj/item/stack/sheet/mineral/iron + name = "iron" + icon_state = "sheet-silver" + origin_tech = "materials=1" + sheettype = "iron" + color = "#333333" + perunit = 3750 + +/* + * Sandstone + */ +/obj/item/stack/sheet/mineral/sandstone + name = "sandstone brick" + 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" + + +/obj/item/stack/sheet/mineral/sandstone/atom_init() + . = ..() + recipes = sandstone_recipes + +/* + * Diamond + */ +/obj/item/stack/sheet/mineral/diamond + name = "diamond" + icon_state = "sheet-diamond" + origin_tech = "materials=6" + perunit = 3750 + sheettype = "diamond" + + +/obj/item/stack/sheet/mineral/diamond/atom_init() + . = ..() + recipes = diamond_recipes + +/* + * Uranium + */ +/obj/item/stack/sheet/mineral/uranium + name = "uranium" + icon_state = "sheet-uranium" + origin_tech = "materials=5" + perunit = 2000 + sheettype = "uranium" + + +/obj/item/stack/sheet/mineral/uranium/atom_init() + . = ..() + recipes = uranium_recipes + +/* + * Phoron + */ +/obj/item/stack/sheet/mineral/phoron + name = "solid phoron" + icon_state = "sheet-phoron" + origin_tech = "phorontech=2;materials=2" + perunit = 2000 + sheettype = "phoron" + is_fusion_fuel = TRUE + + +/obj/item/stack/sheet/mineral/phoron/atom_init() + . = ..() + recipes = phoron_recipes + +/* + * Plastic + */ +/obj/item/stack/sheet/mineral/plastic + name = "Plastic" + icon_state = "sheet-plastic" + origin_tech = "materials=3" + perunit = 2000 + +/obj/item/stack/sheet/mineral/plastic/cyborg + name = "plastic sheets" + icon_state = "sheet-plastic" + perunit = 2000 + + +/obj/item/stack/sheet/mineral/plastic/atom_init() + . = ..() + recipes = plastic_recipes + +/* + * Gold + */ +/obj/item/stack/sheet/mineral/gold + name = "gold" + 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 + sheettype = "gold" + + + +/obj/item/stack/sheet/mineral/gold/atom_init() + . = ..() + recipes = gold_recipes + +/* + * Silver + */ +/obj/item/stack/sheet/mineral/silver + name = "silver" + icon_state = "sheet-silver" + origin_tech = "materials=3" + perunit = 2000 + sheettype = "silver" + + + +/obj/item/stack/sheet/mineral/silver/atom_init() + . = ..() + recipes = silver_recipes + +/* + * Clown + */ +/obj/item/stack/sheet/mineral/clown + name = "bananium" + 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" + + +/****************************** Others ****************************/ + +/* + * Enriched Uranium + */ +/obj/item/stack/sheet/mineral/enruranium + name = "enriched uranium" + icon_state = "sheet-enruranium" + origin_tech = "materials=5" + perunit = 1000 + +/* + * Platinum + */ +//Valuable resource, cargo can sell it. +/obj/item/stack/sheet/mineral/platinum + name = "platinum" + icon_state = "sheet-adamantine" + origin_tech = "materials=2" + sheettype = "platinum" + perunit = 2000 + +/* + * Mhydrogen + */ +//Extremely valuable to Research. +/obj/item/stack/sheet/mineral/mhydrogen + name = "metallic hydrogen" + icon_state = "sheet-mythril" + origin_tech = "materials=6;powerstorage=5;magnets=5" + sheettype = "mhydrogen" + perunit = 2000 + is_fusion_fuel = TRUE + +/* + * Tritium + */ +//Fuel for MRSPACMAN generator. +/obj/item/stack/sheet/mineral/tritium + name = "tritium" + icon_state = "sheet-silver" + sheettype = "tritium" + origin_tech = "materials=5" + color = "#777777" + perunit = 2000 + is_fusion_fuel = TRUE + +/* + * Osmium + */ +/obj/item/stack/sheet/mineral/osmium + name = "osmium" + icon_state = "sheet-silver" + sheettype = "osmium" + origin_tech = "materials=5" + color = "#9999FF" + perunit = 2000 + +// Fusion fuel. +/obj/item/stack/sheet/mineral/deuterium + name = "deuterium" + icon_state = "sheet-silver" + sheettype = "deuterium" + origin_tech = "materials=3" + color = "#999999" + perunit = 2000 + is_fusion_fuel = TRUE diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm index d829716fed99..1382ecee2bfa 100644 --- a/code/game/objects/items/stacks/sheets/sheets.dm +++ b/code/game/objects/items/stacks/sheets/sheets.dm @@ -1,25 +1,25 @@ -/obj/item/stack/sheet - name = "sheet" - full_w_class = ITEM_SIZE_NORMAL - force = 5 - throwforce = 5 - max_amount = 50 - throw_speed = 3 - throw_range = 3 - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") - var/perunit = 3750 - var/sheettype = null //this is used for girders in the creation of walls/false walls - - -// 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, mob/user) - 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" + full_w_class = ITEM_SIZE_NORMAL + force = 5 + throwforce = 5 + max_amount = 50 + throw_speed = 3 + throw_range = 3 + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") + var/perunit = 3750 + var/sheettype = null //this is used for girders in the creation of walls/false walls + + +// 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, mob/user) + 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) + ..()*/ diff --git a/code/game/objects/items/stacks/tiles/light.dm b/code/game/objects/items/stacks/tiles/light.dm index fd73023379f5..8142e17a9f81 100644 --- a/code/game/objects/items/stacks/tiles/light.dm +++ b/code/game/objects/items/stacks/tiles/light.dm @@ -1,36 +1,36 @@ -/obj/item/stack/tile/light - name = "light tile" - singular_name = "light floor tile" - desc = "A floor tile, made out off glass. It produces light." - icon_state = "tile_e" - w_class = 3.0 - force = 3.0 - throwforce = 5.0 - throw_speed = 5 - throw_range = 20 - flags = CONDUCT - max_amount = 60 - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") - var/on = 1 - var/state //0 = fine, 1 = flickering, 2 = breaking, 3 = broken - turf_type = /turf/simulated/floor/light - -/obj/item/stack/tile/light/atom_init() - . = ..() - if(prob(5)) - state = 3 //broken - else if(prob(5)) - state = 2 //breaking - else if(prob(10)) - state = 1 //flickering occasionally - else - state = 0 //fine - -/obj/item/stack/tile/light/attackby(obj/item/O, mob/user) - ..() - if(istype(O,/obj/item/weapon/crowbar)) - if(!use(1)) - return - new/obj/item/stack/sheet/metal(user.loc) - new/obj/item/stack/light_w(user.loc) - +/obj/item/stack/tile/light + name = "light tile" + singular_name = "light floor tile" + desc = "A floor tile, made out off glass. It produces light." + icon_state = "tile_e" + w_class = 3.0 + force = 3.0 + throwforce = 5.0 + throw_speed = 5 + throw_range = 20 + flags = CONDUCT + max_amount = 60 + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") + var/on = 1 + var/state //0 = fine, 1 = flickering, 2 = breaking, 3 = broken + turf_type = /turf/simulated/floor/light + +/obj/item/stack/tile/light/atom_init() + . = ..() + if(prob(5)) + state = 3 //broken + else if(prob(5)) + state = 2 //breaking + else if(prob(10)) + state = 1 //flickering occasionally + else + state = 0 //fine + +/obj/item/stack/tile/light/attackby(obj/item/O, mob/user) + ..() + if(istype(O,/obj/item/weapon/crowbar)) + if(!use(1)) + return + new/obj/item/stack/sheet/metal(user.loc) + new/obj/item/stack/light_w(user.loc) + diff --git a/code/game/objects/items/stacks/tiles/plasteel.dm b/code/game/objects/items/stacks/tiles/plasteel.dm index 5037f84b1365..df20b644e957 100644 --- a/code/game/objects/items/stacks/tiles/plasteel.dm +++ b/code/game/objects/items/stacks/tiles/plasteel.dm @@ -1,45 +1,45 @@ -/obj/item/stack/tile/plasteel - name = "floor tile" - singular_name = "floor tile" - desc = "Those could not work as a pretty decent throwing weapon." - icon_state = "tile" - w_class = 3.0 - force = 6.0 - m_amt = 937.5 - throwforce = 5.0 - throw_speed = 5 - throw_range = 3 - flags = CONDUCT - max_amount = 60 - turf_type = /turf/simulated/floor - -/obj/item/stack/tile/plasteel/atom_init() - . = ..() - pixel_x = rand(1, 14) - pixel_y = rand(1, 14) - -/* -/obj/item/stack/tile/plasteel/attack_self(mob/user) - if (usr.stat) - return - var/T = user.loc - if (!( istype(T, /turf) )) - to_chat(user, "\red You must be on the ground!") - return - if (!( istype(T, /turf/space) )) - to_chat(user, "\red 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) - if (istype(S,/turf/space)) - S.ChangeTurf(/turf/simulated/floor/plating/airless) - else - S.ChangeTurf(/turf/simulated/floor/plating) -// var/turf/simulated/floor/W = S.ReplaceWithFloor() -// W.make_plating() - return +/obj/item/stack/tile/plasteel + name = "floor tile" + singular_name = "floor tile" + desc = "Those could not work as a pretty decent throwing weapon." + icon_state = "tile" + w_class = 3.0 + force = 6.0 + m_amt = 937.5 + throwforce = 5.0 + throw_speed = 5 + throw_range = 3 + flags = CONDUCT + max_amount = 60 + turf_type = /turf/simulated/floor + +/obj/item/stack/tile/plasteel/atom_init() + . = ..() + pixel_x = rand(1, 14) + pixel_y = rand(1, 14) + +/* +/obj/item/stack/tile/plasteel/attack_self(mob/user) + if (usr.stat) + return + var/T = user.loc + if (!( istype(T, /turf) )) + to_chat(user, "\red You must be on the ground!") + return + if (!( istype(T, /turf/space) )) + to_chat(user, "\red 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) + if (istype(S,/turf/space)) + S.ChangeTurf(/turf/simulated/floor/plating/airless) + else + S.ChangeTurf(/turf/simulated/floor/plating) +// var/turf/simulated/floor/W = S.ReplaceWithFloor() +// W.make_plating() + return diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 33c6bee6708e..d0e4e36027aa 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -1,126 +1,126 @@ -/* Diffrent misc types of tiles - * Contains: - * Grass - * Wood - * Carpet - */ - -/obj/item/stack/tile - var/turf/turf_type - -/* - * 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 = CONDUCT - max_amount = 60 - origin_tech = "biotech=1" - turf_type = /turf/simulated/floor/grass - -/* - * Wood - */ -/obj/item/stack/tile/wood - name = "wood floor tile" - singular_name = "wood floor tile" - desc = "An easy to fit wooden floor tile." - icon_state = "tile-wood" - w_class = 3.0 - force = 1.0 - throwforce = 1.0 - throw_speed = 5 - throw_range = 20 - flags = CONDUCT - max_amount = 60 - turf_type = /turf/simulated/floor/wood - -/* - * Carpets - */ -/obj/item/stack/tile/carpet - name = "carpet" - singular_name = "carpet" - desc = "A piece of carpet. It is the same size as a normal floor tile!" - icon_state = "tile-carpet" - w_class = 3.0 - force = 1.0 - throwforce = 1.0 - throw_speed = 5 - throw_range = 20 - flags = CONDUCT - max_amount = 60 - turf_type = /turf/simulated/floor/carpet - var/carpet_icon_state = "carpet" - -/obj/item/stack/tile/carpet/black - name = "black carpet" - singular_name = "black carpet" - desc = "A piece of black carpet. It is the same size as a normal floor tile!" - icon_state = "tile-carpet" - turf_type = /turf/simulated/floor/carpet/black - carpet_icon_state = "blackcarpet" - -/obj/item/stack/tile/carpet/purple - name = "purple carpet" - singular_name = "purple carpet" - desc = "A piece of purple carpet. It is the same size as a normal floor tile!" - icon_state = "tile-carpet" - turf_type = /turf/simulated/floor/carpet/purple - carpet_icon_state = "purplecarpet" - -/obj/item/stack/tile/carpet/orange - name = "orange carpet" - singular_name = "orange carpet" - desc = "A piece of orange carpet. It is the same size as a normal floor tile!" - icon_state = "tile-carpet" - turf_type = /turf/simulated/floor/carpet/orange - carpet_icon_state = "orangecarpet" - -/obj/item/stack/tile/carpet/green - name = "green carpet" - singular_name = "green carpet" - desc = "A piece of green carpet. It is the same size as a normal floor tile!" - icon_state = "tile-carpet" - turf_type = /turf/simulated/floor/carpet/green - carpet_icon_state = "greencarpet" - -/obj/item/stack/tile/carpet/blue - name = "blue carpet" - singular_name = "blue carpet" - desc = "A piece of blue carpet. It is the same size as a normal floor tile!" - icon_state = "tile-carpet" - turf_type = /turf/simulated/floor/carpet/blue - carpet_icon_state = "bluecarpet" - -/obj/item/stack/tile/carpet/blue2 - name = "blue carpet" - singular_name = "blue carpet" - desc = "A piece of blue carpet. It is the same size as a normal floor tile!" - icon_state = "tile-carpet" - turf_type = /turf/simulated/floor/carpet/blue2 - carpet_icon_state = "blue2carpet" - -/obj/item/stack/tile/carpet/red - name = "red carpet" - singular_name = "red carpet" - desc = "A piece of red carpet. It is the same size as a normal floor tile!" - icon_state = "tile-carpet" - turf_type = /turf/simulated/floor/carpet/red - carpet_icon_state = "redcarpet" - -/obj/item/stack/tile/carpet/cyan - name = "cyan carpet" - singular_name = "cyan carpet" - desc = "A piece of cyan carpet. It is the same size as a normal floor tile!" - icon_state = "tile-carpet" - turf_type = /turf/simulated/floor/carpet/cyan +/* Diffrent misc types of tiles + * Contains: + * Grass + * Wood + * Carpet + */ + +/obj/item/stack/tile + var/turf/turf_type + +/* + * 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 = CONDUCT + max_amount = 60 + origin_tech = "biotech=1" + turf_type = /turf/simulated/floor/grass + +/* + * Wood + */ +/obj/item/stack/tile/wood + name = "wood floor tile" + singular_name = "wood floor tile" + desc = "An easy to fit wooden floor tile." + icon_state = "tile-wood" + w_class = 3.0 + force = 1.0 + throwforce = 1.0 + throw_speed = 5 + throw_range = 20 + flags = CONDUCT + max_amount = 60 + turf_type = /turf/simulated/floor/wood + +/* + * Carpets + */ +/obj/item/stack/tile/carpet + name = "carpet" + singular_name = "carpet" + desc = "A piece of carpet. It is the same size as a normal floor tile!" + icon_state = "tile-carpet" + w_class = 3.0 + force = 1.0 + throwforce = 1.0 + throw_speed = 5 + throw_range = 20 + flags = CONDUCT + max_amount = 60 + turf_type = /turf/simulated/floor/carpet + var/carpet_icon_state = "carpet" + +/obj/item/stack/tile/carpet/black + name = "black carpet" + singular_name = "black carpet" + desc = "A piece of black carpet. It is the same size as a normal floor tile!" + icon_state = "tile-carpet" + turf_type = /turf/simulated/floor/carpet/black + carpet_icon_state = "blackcarpet" + +/obj/item/stack/tile/carpet/purple + name = "purple carpet" + singular_name = "purple carpet" + desc = "A piece of purple carpet. It is the same size as a normal floor tile!" + icon_state = "tile-carpet" + turf_type = /turf/simulated/floor/carpet/purple + carpet_icon_state = "purplecarpet" + +/obj/item/stack/tile/carpet/orange + name = "orange carpet" + singular_name = "orange carpet" + desc = "A piece of orange carpet. It is the same size as a normal floor tile!" + icon_state = "tile-carpet" + turf_type = /turf/simulated/floor/carpet/orange + carpet_icon_state = "orangecarpet" + +/obj/item/stack/tile/carpet/green + name = "green carpet" + singular_name = "green carpet" + desc = "A piece of green carpet. It is the same size as a normal floor tile!" + icon_state = "tile-carpet" + turf_type = /turf/simulated/floor/carpet/green + carpet_icon_state = "greencarpet" + +/obj/item/stack/tile/carpet/blue + name = "blue carpet" + singular_name = "blue carpet" + desc = "A piece of blue carpet. It is the same size as a normal floor tile!" + icon_state = "tile-carpet" + turf_type = /turf/simulated/floor/carpet/blue + carpet_icon_state = "bluecarpet" + +/obj/item/stack/tile/carpet/blue2 + name = "blue carpet" + singular_name = "blue carpet" + desc = "A piece of blue carpet. It is the same size as a normal floor tile!" + icon_state = "tile-carpet" + turf_type = /turf/simulated/floor/carpet/blue2 + carpet_icon_state = "blue2carpet" + +/obj/item/stack/tile/carpet/red + name = "red carpet" + singular_name = "red carpet" + desc = "A piece of red carpet. It is the same size as a normal floor tile!" + icon_state = "tile-carpet" + turf_type = /turf/simulated/floor/carpet/red + carpet_icon_state = "redcarpet" + +/obj/item/stack/tile/carpet/cyan + name = "cyan carpet" + singular_name = "cyan carpet" + desc = "A piece of cyan carpet. It is the same size as a normal floor tile!" + icon_state = "tile-carpet" + turf_type = /turf/simulated/floor/carpet/cyan carpet_icon_state = "cyancarpet" \ No newline at end of file diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index dfc279837179..f38834fd7792 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1,1595 +1,1595 @@ -/* Toys! - * ContainsL - * Balloons - * Fake telebeacon - * Fake singularity - * Toy gun - * Toy crossbow - * Toy swords - * Crayons - * Snap pops - * Water flower - * Plushies - */ - - -/obj/item/toy - throwforce = 0 - throw_speed = 4 - throw_range = 20 - force = 0 - - -/* - * Balloons - */ -/obj/item/toy/balloon - name = "water balloon" - desc = "A translucent balloon. There's nothing in it." - icon = 'icons/obj/toy.dmi' - icon_state = "waterballoon-e" - item_state = "balloon-empty" - -/obj/item/toy/balloon/atom_init() - var/datum/reagents/R = new/datum/reagents(10) - reagents = R - R.my_atom = src - . = ..() - -/obj/item/toy/balloon/attack(mob/living/carbon/human/M, mob/user) - return - -/obj/item/toy/balloon/afterattack(atom/A, mob/user, proximity) - if(!proximity) return - if (istype(A, /obj/structure/reagent_dispensers/watertank) && get_dist(src,A) <= 1) - A.reagents.trans_to(src, 10) - to_chat(user, "\blue You fill the balloon with the contents of [A].") - src.desc = "A translucent balloon with some form of liquid sloshing around in it." - src.update_icon() - return - -/obj/item/toy/balloon/attackby(obj/O, mob/user) - if(istype(O, /obj/item/weapon/reagent_containers/glass)) - if(O.reagents) - if(O.reagents.total_volume < 1) - to_chat(user, "The [O] is empty.") - else if(O.reagents.total_volume >= 1) - if(O.reagents.has_reagent("pacid", 1)) - to_chat(user, "The acid chews through the balloon!") - O.reagents.reaction(user) - qdel(src) - else - src.desc = "A translucent balloon with some form of liquid sloshing around in it." - to_chat(user, "\blue You fill the balloon with the contents of [O].") - O.reagents.trans_to(src, 10) - src.update_icon() - return - -/obj/item/toy/balloon/throw_impact(atom/hit_atom) - if(src.reagents.total_volume >= 1) - src.visible_message("\red The [src] bursts!","You hear a pop and a splash.") - src.reagents.reaction(get_turf(hit_atom)) - for(var/atom/A in get_turf(hit_atom)) - src.reagents.reaction(A) - src.icon_state = "burst" - spawn(5) - if(src) - qdel(src) - return - -/obj/item/toy/balloon/update_icon() - if(src.reagents.total_volume >= 1) - icon_state = "waterballoon" - item_state = "balloon" - else - icon_state = "waterballoon-e" - item_state = "balloon-empty" - -/obj/item/toy/syndicateballoon - name = "syndicate balloon" - desc = "There is a tag on the back that reads \"FUK NT!11!\"." - throwforce = 0 - throw_speed = 4 - throw_range = 20 - force = 0 - icon = 'icons/obj/weapons.dmi' - icon_state = "syndballoon" - item_state = "syndballoon" - w_class = 4.0 - -/* - * Fake telebeacon - */ -/obj/item/toy/blink - name = "electronic blink toy game" - desc = "Blink. Blink. Blink. Ages 8 and up." - icon = 'icons/obj/radio.dmi' - icon_state = "beacon" - item_state = "signaler" - -/* - * Fake singularity - */ -/obj/item/toy/spinningtoy - name = "Gravitational Singularity" - desc = "\"Singulo\" brand spinning toy." - icon = 'icons/obj/singularity.dmi' - icon_state = "singularity_s1" - -/* - * Toy gun: Why isnt this an /obj/item/weapon/gun? - */ -/obj/item/toy/gun - name = "cap gun" - desc = "Looks almost like the real thing! Ages 8 and up. Please recycle in an autolathe when you're out of caps!" - icon = 'icons/obj/gun.dmi' - icon_state = "revolver" - item_state = "gun" - lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/guns_righthand.dmi' - flags = CONDUCT - slot_flags = SLOT_BELT - w_class = 3.0 - g_amt = 10 - m_amt = 10 - attack_verb = list("struck", "pistol whipped", "hit", "bashed") - var/bullets = 7.0 - - examine(mob/user) - ..() - if(src in user) - to_chat(user, "There are [bullets] caps\s left.") - - attackby(obj/item/toy/ammo/gun/A, mob/user) - - if (istype(A, /obj/item/toy/ammo/gun)) - if (src.bullets >= 7) - to_chat(user, "\blue It's already fully loaded!") - return 1 - if (A.amount_left <= 0) - to_chat(user, "\red There is no more caps!") - return 1 - if (A.amount_left < (7 - src.bullets)) - src.bullets += A.amount_left - to_chat(user, text("\red You reload [] caps\s!", A.amount_left)) - A.amount_left = 0 - else - to_chat(user, text("\red You reload [] caps\s!", 7 - src.bullets)) - A.amount_left -= 7 - src.bullets - src.bullets = 7 - A.update_icon() - return 1 - return - - afterattack(atom/target, mob/user, flag) - if (flag) - return - if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") - to_chat(usr, "\red You don't have the dexterity to do this!") - return - src.add_fingerprint(user) - if (src.bullets < 1) - user.show_message("\red *click* *click*", 2) - playsound(user, 'sound/weapons/empty.ogg', 100, 1) - return - playsound(user, 'sound/weapons/Gunshot.ogg', 100, 1) - src.bullets-- - for(var/mob/O in viewers(user, null)) - O.show_message(text("\red [] fires a cap gun at []!", user, target), 1, "\red You hear a gunshot", 2) - -/obj/item/toy/ammo/gun - name = "ammo-caps" - desc = "There are 7 caps left! Make sure to recyle the box in an autolathe when it gets empty." - icon = 'icons/obj/ammo.dmi' - icon_state = "357-7" - flags = CONDUCT - w_class = 1.0 - g_amt = 10 - m_amt = 10 - var/amount_left = 7.0 - - update_icon() - src.icon_state = text("357-[]", src.amount_left) - src.desc = text("There are [] caps\s left! Make sure to recycle the box in an autolathe when it gets empty.", src.amount_left) - return - -/* - * Toy crossbow - */ - -/obj/item/toy/crossbow - name = "foam dart crossbow" - desc = "A weapon favored by many overactive children. Ages 8 and up." - icon = 'icons/obj/gun.dmi' - icon_state = "crossbow" - item_state = "crossbow" - lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/guns_righthand.dmi' - w_class = 2.0 - attack_verb = list("attacked", "struck", "hit") - var/bullets = 5 - - examine(mob/user) - ..() - if (bullets && src in view(2, user)) - to_chat(user, "It is loaded with [bullets] foam darts!") - - attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/toy/ammo/crossbow)) - if(bullets <= 4) - user.drop_item() - qdel(I) - bullets++ - to_chat(user, "\blue You load the foam dart into the crossbow.") - else - to_chat(usr, "\red It's already fully loaded.") - - - afterattack(atom/target, mob/user, flag) - if(!isturf(target.loc) || target == user) return - if(flag) return - - if (locate (/obj/structure/table, src.loc)) - return - else if (bullets) - var/turf/trg = get_turf(target) - var/obj/effect/foam_dart_dummy/D = new/obj/effect/foam_dart_dummy(get_turf(src)) - bullets-- - D.icon_state = "foamdart" - D.name = "foam dart" - playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1) - - for(var/i=0, i<6, i++) - if (D) - if(D.loc == trg) break - step_towards(D,trg) - - for(var/mob/living/M in D.loc) - if(!istype(M,/mob/living)) continue - if(M == user) continue - for(var/mob/O in viewers(world.view, D)) - O.show_message(text("\red [] was hit by the foam dart!", M), 1) - new /obj/item/toy/ammo/crossbow(M.loc) - qdel(D) - return - - for(var/atom/A in D.loc) - if(A == user) continue - if(A.density) - new /obj/item/toy/ammo/crossbow(A.loc) - qdel(D) - - sleep(1) - - spawn(10) - if(D) - new /obj/item/toy/ammo/crossbow(D.loc) - qdel(D) - - return - else if (bullets == 0) - user.Weaken(5) - for(var/mob/O in viewers(world.view, user)) - O.show_message(text("\red [] realized they were out of ammo and starting scrounging for some!", user), 1) - - - attack(mob/M, mob/user) - src.add_fingerprint(user) - -// ******* Check - - if (src.bullets > 0 && M.lying) - - for(var/mob/O in viewers(M, null)) - if(O.client) - O.show_message(text("\red [] casually lines up a shot with []'s head and pulls the trigger!", user, M), 1, "\red You hear the sound of foam against skull", 2) - O.show_message(text("\red [] was hit in the head by the foam dart!", M), 1) - - playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1) - new /obj/item/toy/ammo/crossbow(M.loc) - src.bullets-- - else if (M.lying && src.bullets == 0) - for(var/mob/O in viewers(M, null)) - if (O.client) O.show_message(text("\red [] casually lines up a shot with []'s head, pulls the trigger, then realizes they are out of ammo and drops to the floor in search of some!", user, M), 1, "\red You hear someone fall", 2) - user.Weaken(5) - return - -/obj/item/toy/ammo/crossbow - name = "foam dart" - desc = "It's nerf or nothing! Ages 8 and up." - icon = 'icons/obj/toy.dmi' - icon_state = "foamdart" - w_class = 1.0 - -/obj/effect/foam_dart_dummy - name = "" - desc = "" - icon = 'icons/obj/toy.dmi' - icon_state = "null" - anchored = 1 - density = 0 - - -/* - * Toy swords - */ -/obj/item/toy/sword - name = "toy sword" - desc = "A cheap, plastic replica of an energy sword. Realistic sounds! Ages 8 and up." - icon = 'icons/obj/weapons.dmi' - icon_state = "sword0" - item_state = "sword0" - var/active = 0.0 - w_class = 2.0 - flags = NOSHIELD - attack_verb = list("attacked", "struck", "hit") - - attack_self(mob/user) - src.active = !( src.active ) - if (src.active) - to_chat(user, "\blue You extend the plastic blade with a quick flick of your wrist.") - playsound(user, 'sound/weapons/saberon.ogg', 50, 1) - src.icon_state = "swordblue" - src.item_state = "swordblue" - src.w_class = 4 - else - to_chat(user, "\blue You push the plastic blade back down into the handle.") - playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) - src.icon_state = "sword0" - src.item_state = "sword0" - src.w_class = 2 - - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - H.update_inv_l_hand() - H.update_inv_r_hand() - - src.add_fingerprint(user) - return - -/obj/item/toy/katana - name = "replica katana" - desc = "Woefully underpowered in D20." - icon = 'icons/obj/weapons.dmi' - icon_state = "katana" - item_state = "katana" - flags = CONDUCT - slot_flags = SLOT_BELT | SLOT_BACK - force = 5 - throwforce = 5 - w_class = 3 - attack_verb = list("attacked", "slashed", "stabbed", "sliced") - -/* - * Crayons - */ - -/obj/item/toy/crayon - name = "crayon" - desc = "A colourful crayon. Please refrain from eating it or putting it in your nose." - icon = 'icons/obj/crayons.dmi' - icon_state = "crayonred" - w_class = 1.0 - attack_verb = list("attacked", "coloured") - var/colour = "#FF0000" //RGB - var/shadeColour = "#220000" //RGB - var/uses = 30 //0 for unlimited uses - var/instant = 0 - var/colourName = "red" //for updateIcon purposes - var/list/validSurfaces = list(/turf/simulated/floor) - var/gang = 0 //For marking territory - var/edible = 1 - - suicide_act(mob/user) - to_chat(viewers(user), "\red [user] is jamming the [src.name] up \his nose and into \his brain. It looks like \he's trying to commit suicide.") - return (BRUTELOSS|OXYLOSS) - -/* - * Snap pops - */ -/obj/item/toy/snappop - name = "snap pop" - desc = "Wow!" - icon = 'icons/obj/toy.dmi' - icon_state = "snappop" - w_class = 1 - - throw_impact(atom/hit_atom) - ..() - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - new /obj/effect/decal/cleanable/ash(src.loc) - src.visible_message("\red The [src.name] explodes!","\red You hear a snap!") - playsound(src, 'sound/effects/snap.ogg', 50, 1) - qdel(src) - -/obj/item/toy/snappop/Crossed(H as mob|obj) - if((ishuman(H))) //i guess carp and shit shouldn't set them off - var/mob/living/carbon/M = H - if(M.m_intent == "run") - to_chat(M, "\red You step on the snap pop!") - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(2, 0, src) - s.start() - new /obj/effect/decal/cleanable/ash(src.loc) - src.visible_message("\red The [src.name] explodes!","\red You hear a snap!") - playsound(src, 'sound/effects/snap.ogg', 50, 1) - qdel(src) - -/* - * Water flower - */ -/obj/item/toy/waterflower - name = "Water Flower" - desc = "A seemingly innocent sunflower...with a twist." - icon = 'icons/obj/harvest.dmi' - icon_state = "sunflower" - item_state = "sunflower" - var/empty = 0 - -/obj/item/toy/waterflower/atom_init() - var/datum/reagents/R = new/datum/reagents(10) - reagents = R - R.my_atom = src - R.add_reagent("water", 10) - . = ..() - -/obj/item/toy/waterflower/attack(mob/living/carbon/human/M, mob/user) - return - -/obj/item/toy/waterflower/afterattack(atom/A, mob/user) - if(locate(/obj/structure/table, loc)) - return - - else if(istype(A, /obj/structure/reagent_dispensers/watertank) && get_dist(src,A) <= 1) - A.reagents.trans_to(src, 10) - to_chat(user, "\blue You refill your flower!") - return - - else if(src.reagents.total_volume < 1) - src.empty = 1 - to_chat(user, "\blue Your flower has run dry!") - return - - else - src.empty = 0 - - - var/obj/effect/decal/D = new/obj/effect/decal/(get_turf(src)) - D.name = "water" - D.icon = 'icons/obj/chemical.dmi' - D.icon_state = "chempuff" - D.create_reagents(5) - src.reagents.trans_to(D, 1) - playsound(src.loc, 'sound/effects/spray3.ogg', 50, 1, -6) - - spawn(0) - for(var/i=0, i<1, i++) - step_towards(D,A) - D.reagents.reaction(get_turf(D)) - for(var/atom/T in get_turf(D)) - D.reagents.reaction(T) - if(ismob(T) && T:client) - to_chat(T:client, "\red [user] has sprayed you with water!") - if(ishuman(T)) - var/mob/living/carbon/human/H = T - var/list/inv_contents = list() - for(var/obj/item/I in H.contents) - if(I == src) continue - if(istype(I, /obj/item/weapon/implant)) continue - inv_contents += I - if(inv_contents.len) - for(var/n=3,n>0,n--) - var/obj/item/I = pick(inv_contents) - I.make_wet() - sleep(4) - qdel(D) - - return - -/obj/item/toy/waterflower/examine(mob/user) - ..() - if(src in user) - to_chat(user, "[reagents.total_volume] unit\s of water left!") - - -/* - * Mech prizes - */ -/obj/item/toy/prize - icon = 'icons/obj/toy.dmi' - icon_state = "ripleytoy" - var/cooldown = 0 - -//all credit to skasi for toy mech fun ideas -/obj/item/toy/prize/attack_self(mob/user) - if(cooldown < world.time - 8) - to_chat(user, "You play with [src].") - playsound(user, 'sound/mecha/mechstep.ogg', 20, 1) - cooldown = world.time - -/obj/item/toy/prize/attack_hand(mob/user) - if(loc == user) - if(cooldown < world.time - 8) - to_chat(user, "You play with [src].") - playsound(user, 'sound/mecha/mechturn.ogg', 20, 1) - cooldown = world.time - return - ..() - -/obj/item/toy/prize/ripley - name = "toy ripley" - desc = "Mini-Mecha action figure! Collect them all! 1/11." - -/obj/item/toy/prize/fireripley - name = "toy firefighting ripley" - desc = "Mini-Mecha action figure! Collect them all! 2/11." - icon_state = "fireripleytoy" - -/obj/item/toy/prize/deathripley - name = "toy deathsquad ripley" - desc = "Mini-Mecha action figure! Collect them all! 3/11." - icon_state = "deathripleytoy" - -/obj/item/toy/prize/gygax - name = "toy gygax" - desc = "Mini-Mecha action figure! Collect them all! 4/11." - icon_state = "gygaxtoy" - - -/obj/item/toy/prize/durand - name = "toy durand" - desc = "Mini-Mecha action figure! Collect them all! 5/11." - icon_state = "durandprize" - -/obj/item/toy/prize/honk - name = "toy H.O.N.K." - desc = "Mini-Mecha action figure! Collect them all! 6/11." - icon_state = "honkprize" - -/obj/item/toy/prize/marauder - name = "toy marauder" - desc = "Mini-Mecha action figure! Collect them all! 7/11." - icon_state = "marauderprize" - -/obj/item/toy/prize/seraph - name = "toy seraph" - desc = "Mini-Mecha action figure! Collect them all! 8/11." - icon_state = "seraphprize" - -/obj/item/toy/prize/mauler - name = "toy mauler" - desc = "Mini-Mecha action figure! Collect them all! 9/11." - icon_state = "maulerprize" - -/obj/item/toy/prize/odysseus - name = "toy odysseus" - desc = "Mini-Mecha action figure! Collect them all! 10/11." - icon_state = "odysseusprize" - -/obj/item/toy/prize/phazon - name = "toy phazon" - desc = "Mini-Mecha action figure! Collect them all! 11/11." - icon_state = "phazonprize" - -/obj/item/toy/katana - name = "replica katana" - desc = "Woefully underpowered in D20." - icon = 'icons/obj/weapons.dmi' - icon_state = "katana" - item_state = "katana" - flags = CONDUCT - slot_flags = SLOT_BELT | SLOT_BACK - force = 5 - throwforce = 5 - w_class = 3 - attack_verb = list("attacked", "slashed", "stabbed", "sliced") - -/* NYET. -/obj/item/weapon/toddler - icon_state = "toddler" - name = "toddler" - desc = "This baby looks almost real. Wait, did it just burp?" - force = 5 - w_class = 4.0 - slot_flags = SLOT_BACK -*/ - -//This should really be somewhere else but I don't know where. w/e -/obj/item/weapon/inflatable_duck - name = "inflatable duck" - desc = "No bother to sink or swim when you can just float!" - icon_state = "inflatable" - item_state = "inflatable" - icon = 'icons/obj/clothing/belts.dmi' - slot_flags = SLOT_BELT - -/* - * Action Figures - */ - -/obj/item/toy/figure - name = "Non-Specific Action Figure action figure" - desc = null - icon = 'icons/obj/toy.dmi' - icon_state = "nuketoy" - var/cooldown = 0 - var/toysay = "What the fuck did you do?" - -/obj/item/toy/figure/atom_init() - . = ..() - desc = "A \"Space Life\" brand [src]." - -/obj/item/toy/figure/attack_self(mob/user) - if(cooldown <= world.time) - cooldown = world.time + 50 - to_chat(user, "The [src] says \"[toysay]\"") - playsound(user, 'sound/machines/click.ogg', 20, 1) - -/obj/item/toy/figure/cmo - name = "Chief Medical Officer action figure" - icon_state = "cmo" - toysay = "Suit sensors!" - -/obj/item/toy/figure/assistant - name = "Assistant action figure" - icon_state = "assistant" - toysay = "Grey tide world wide!" - -/obj/item/toy/figure/atmos - name = "Atmospheric Technician action figure" - icon_state = "atmos" - toysay = "Glory to Atmosia!" - -/obj/item/toy/figure/bartender - name = "Bartender action figure" - icon_state = "bartender" - toysay = "Where is Pun Pun?" - -/obj/item/toy/figure/borg - name = "Cyborg action figure" - icon_state = "borg" - toysay = "I. LIVE. AGAIN." - -/obj/item/toy/figure/botanist - name = "Botanist action figure" - icon_state = "botanist" - toysay = "Dude, I see colors..." - -/obj/item/toy/figure/captain - name = "Captain action figure" - icon_state = "captain" - toysay = "Any heads of staff?" - -/obj/item/toy/figure/cargotech - name = "Cargo Technician action figure" - icon_state = "cargotech" - toysay = "For Cargonia!" - -/obj/item/toy/figure/ce - name = "Chief Engineer action figure" - icon_state = "ce" - toysay = "Wire the solars!" - -/obj/item/toy/figure/chaplain - name = "Chaplain action figure" - icon_state = "chaplain" - toysay = "Praise Space Jesus!" - -/obj/item/toy/figure/chef - name = "Chef action figure" - icon_state = "chef" - toysay = "Pun-Pun is a tasty burger." - -/obj/item/toy/figure/chemist - name = "Chemist action figure" - icon_state = "chemist" - toysay = "Get your pills!" - -/obj/item/toy/figure/clown - name = "Clown action figure" - icon_state = "clown" - toysay = "Honk!" - -/obj/item/toy/figure/ian - name = "Ian action figure" - icon_state = "ian" - toysay = "Arf!" - -/obj/item/toy/figure/detective - name = "Detective action figure" - icon_state = "detective" - toysay = "This airlock has grey jumpsuit and insulated glove fibers on it." - -/obj/item/toy/figure/dsquad - name = "Death Squad Officer action figure" - icon_state = "dsquad" - toysay = "Eliminate all threats!" - -/obj/item/toy/figure/engineer - name = "Engineer action figure" - icon_state = "engineer" - toysay = "Oh god, the singularity is loose!" - -/obj/item/toy/figure/geneticist - name = "Geneticist action figure" - icon_state = "geneticist" - toysay = "Smash!" - -/obj/item/toy/figure/hop - name = "Head of Personel action figure" - icon_state = "hop" - toysay = "Giving out all access!" - -/obj/item/toy/figure/hos - name = "Head of Security action figure" - icon_state = "hos" - toysay = "Get the justice chamber ready, I think we got a joker here." - -/obj/item/toy/figure/qm - name = "Quartermaster action figure" - icon_state = "qm" - toysay = "Please sign this form in triplicate and we will see about geting you a welding mask within 3 business days." - -/obj/item/toy/figure/janitor - name = "Janitor action figure" - icon_state = "janitor" - toysay = "Look at the signs, you idiot." - -/obj/item/toy/figure/lawyer - name = "Lawyer action figure" - icon_state = "lawyer" - toysay = "My client is a dirty traitor!" - -/obj/item/toy/figure/librarian - name = "Librarian action figure" - icon_state = "librarian" - toysay = "One day while..." - -/obj/item/toy/figure/md - name = "Medical Doctor action figure" - icon_state = "md" - toysay = "The patient is already dead!" - -/obj/item/toy/figure/mime - name = "Mime action figure" - icon_state = "mime" - toysay = "..." - -/obj/item/toy/figure/miner - name = "Shaft Miner action figure" - icon_state = "miner" - toysay = "Oh god it's eating my intestines!" - -/obj/item/toy/figure/ninja - name = "Ninja action figure" - icon_state = "ninja" - toysay = "Oh god! Stop shooting, I'm friendly!" - -/obj/item/toy/figure/wizard - name = "Wizard action figure" - icon_state = "wizard" - toysay = "Ei Nath!" - -/obj/item/toy/figure/rd - name = "Research Director action figure" - icon_state = "rd" - toysay = "Blowing all of the borgs!" - -/obj/item/toy/figure/roboticist - name = "Roboticist action figure" - icon_state = "roboticist" - toysay = "Big stompy mechs!" - -/obj/item/toy/figure/scientist - name = "Scientist action figure" - icon_state = "scientist" - toysay = "For science!" - -/obj/item/toy/figure/syndie - name = "Nuclear Operative action figure" - icon_state = "syndie" - toysay = "Get that fucking disk!" - -/obj/item/toy/figure/secofficer - name = "Security Officer action figure" - icon_state = "secofficer" - toysay = "I am the law!" - -/obj/item/toy/figure/virologist - name = "Virologist action figure" - icon_state = "virologist" - toysay = "The cure is potassium!" - -/obj/item/toy/figure/warden - name = "Warden action figure" - icon_state = "warden" - toysay = "Seventeen minutes for coughing at an officer!" - -/* -Owl & Griffin toys -*/ -/obj/item/toy/owl - name = "owl action figure" - desc = "An action figure modeled after 'The Owl', defender of justice." - icon = 'icons/obj/toy.dmi' - icon_state = "owlprize" - w_class = 2 - var/cooldown = 0 - -/obj/item/toy/owl/attack_self(mob/user) - if(!cooldown) //for the sanity of everyone - var/message = pick("You won't get away this time, Griffin!", "Stop right there, criminal!", "Hoot! Hoot!", "I am the night!") - to_chat(user, "You pull the string on the [src].") - playsound(user, 'sound/machines/click.ogg', 20, 1) - src.loc.visible_message("[bicon(src)] [message]") - cooldown = 1 - spawn(30) cooldown = 0 - return - ..() - -/obj/item/toy/griffin - name = "griffin action figure" - desc = "An action figure modeled after 'The Griffin', criminal mastermind." - icon = 'icons/obj/toy.dmi' - icon_state = "griffinprize" - w_class = 2 - var/cooldown = 0 - -/obj/item/toy/griffin/attack_self(mob/user) - if(!cooldown) //for the sanity of everyone - var/message = pick("You can't stop me, Owl!", "My plan is flawless! The vault is mine!", "Caaaawwww!", "You will never catch me!") - to_chat(user, "You pull the string on the [src].") - playsound(user, 'sound/machines/click.ogg', 20, 1) - src.loc.visible_message("[bicon(src)] [message]") - cooldown = 1 - spawn(30) cooldown = 0 - return - ..() - -/* - * Fake nuke - */ -/obj/item/toy/nuke - name = "\improper Nuclear Fission Explosive toy" - desc = "A plastic model of a Nuclear Fission Explosive." - icon = 'icons/obj/toy.dmi' - icon_state = "nuketoyidle" - w_class = 2 - var/cooldown = 0 - -/obj/item/toy/nuke/attack_self(mob/user) - if (cooldown < world.time) - cooldown = world.time + 1800 //3 minutes - user.visible_message("[user] presses a button on [src].", "You activate [src], it plays a loud noise!", "You hear the click of a button.") - spawn(5) //gia said so - icon_state = "nuketoy" - playsound(src, 'sound/machines/Alarm.ogg', 50, 0) - sleep(135) - icon_state = "nuketoycool" - sleep(cooldown - world.time) - icon_state = "nuketoyidle" - else - var/timeleft = (cooldown - world.time) - to_chat(user, "Nothing happens, and '[round(timeleft/10)]' appears on a small display.") -/* - * Fake meteor - */ -/obj/item/toy/minimeteor - name = "\improper Mini-Meteor" - desc = "Relive the excitement of a meteor shower! SweetMeat-eor. Co is not responsible for any injuries, headaches or hearing loss caused by Mini-Meteor?" - icon = 'icons/obj/toy.dmi' - icon_state = "minimeteor" - w_class = 2 - -/obj/item/toy/minimeteor/throw_impact(atom/hit_atom) - if(!..()) - playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1) - for(var/mob/M in orange(10, src)) - if(!M.stat && !istype(M, /mob/living/silicon/ai))\ - shake_camera(M, 3, 1) - qdel(src) - -/* - * A Deck of Cards - */ - -/obj/item/toy/cards - name = "deck of cards" - desc = "A deck of space-grade playing cards." - icon = 'icons/obj/cards.dmi' - icon_state = "deck" - w_class = 2.0 - var/list/cards = list() - var/normal_deck_size = 52 // How many cards should be in the full deck. - var/list/integrity = list() // Is populated in atom_init(), determines which cards SHOULD be in the full deck. - - -/obj/item/toy/cards/update_icon() // Some foreshadowing here. - if(cards.len > normal_deck_size/2) - icon_state = "[initial(icon_state)]_full" - else if(cards.len > normal_deck_size/4) - icon_state = "[initial(icon_state)]_half" - else if(cards.len >= 1) - icon_state = "[initial(icon_state)]_low" - else if(cards.len == 0) - icon_state = "[initial(icon_state)]_empty" - -/obj/item/toy/cards/proc/fill_deck(from_c, to_c) // Made, so we can fill from 6 to 10 instead of 2 to 10. - for(var/i in from_c to to_c) - cards += "[i] of Hearts" - cards += "[i] of Spades" - cards += "[i] of Clubs" - cards += "[i] of Diamonds" - cards += "King of Hearts" - cards += "King of Spades" - cards += "King of Clubs" - cards += "King of Diamonds" - cards += "Queen of Hearts" - cards += "Queen of Spades" - cards += "Queen of Clubs" - cards += "Queen of Diamonds" - cards += "Jack of Hearts" - cards += "Jack of Spades" - cards += "Jack of Clubs" - cards += "Jack of Diamonds" - cards += "Ace of Hearts" - cards += "Ace of Spades" - cards += "Ace of Clubs" - cards += "Ace of Diamonds" - update_icon() - -/obj/item/toy/cards/atom_init() - . = ..() - fill_deck(2, 10) - integrity += cards - -/obj/item/toy/cards/attack_hand(mob/user) - var/choice = null - if(cards.len == 0) - to_chat(user, "There are no more cards to draw.") - return - var/obj/item/toy/singlecard/H = new/obj/item/toy/singlecard(user.loc) - choice = cards[1] - H.cardname = choice - H.parentdeck = src - cards -= choice - H.pickup(user) - user.put_in_active_hand(H) - user.visible_message("[user] draws a card from the deck.", "You draw a card from the deck.") - update_icon() - -/obj/item/toy/cards/attack_self(mob/user) - cards = shuffle(cards) - user.SetNextMove(CLICK_CD_INTERACT) - playsound(user, 'sound/items/cardshuffle.ogg', 50, 1) - user.visible_message("[user] shuffles the deck.", "You shuffle the deck.") - -/obj/item/toy/cards/attackby(obj/item/toy/singlecard/C, mob/living/user) - ..() - if(istype(C)) - if(C.parentdeck == src) - src.cards += C.cardname - user.remove_from_mob(C) - user.visible_message("[user] adds a card to the bottom of the deck.","You add the card to the bottom of the deck.") - qdel(C) - else - to_chat(user, "You can't mix cards from other decks.") - update_icon() - - -/obj/item/toy/cards/attackby(obj/item/toy/cardhand/C, mob/living/user) - ..() - if(istype(C)) - if(C.parentdeck == src) - src.cards += C.currenthand - user.remove_from_mob(C) - user.visible_message("[user] puts their hand of cards in the deck.", "You put the hand of cards in the deck.") - qdel(C) - else - to_chat(user, "You can't mix cards from other decks.") - update_icon() - -/obj/item/toy/cards/MouseDrop(atom/over_object) - var/mob/M = usr - if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) - return - if(Adjacent(usr)) - if(over_object == M) - M.put_in_hands(src) - to_chat(usr, "You pick up the deck.") - - else if(istype(over_object, /obj/screen)) - switch(over_object.name) - if("r_hand") - M.u_equip(src) - M.put_in_r_hand(src) - to_chat(usr, "You pick up the deck.") - if("l_hand") - M.u_equip(src) - M.put_in_l_hand(src) - to_chat(usr, "You pick up the deck.") - else - to_chat(usr, "You can't reach it from here.") - - - -/obj/item/toy/cardhand - name = "hand of cards" - desc = "A number of cards not in a deck, customarily held in ones hand." - icon = 'icons/obj/cards.dmi' - icon_state = "hand2" - w_class = 1.0 - var/list/currenthand = list() - var/obj/item/toy/cards/parentdeck = null - var/choice = null - - -/obj/item/toy/cardhand/attack_self(mob/user) - user.set_machine(src) - interact(user) - -/obj/item/toy/cardhand/interact(mob/user) - var/dat = "You have:
                    " - for(var/t in currenthand) - dat += "A [t].
                    " - dat += "Which card will you remove next?" - var/datum/browser/popup = new(user, "cardhand", "Hand of Cards", 400, 240) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.set_content(dat) - popup.open() - - -/obj/item/toy/cardhand/Topic(href, href_list) - if(..()) - return - if(usr.stat || !ishuman(usr) || !usr.canmove) - return - var/mob/living/carbon/human/cardUser = usr - if(href_list["pick"]) - if (cardUser.get_item_by_slot(slot_l_hand) == src || cardUser.get_item_by_slot(slot_r_hand) == src) - var/choice = href_list["pick"] - var/obj/item/toy/singlecard/C = new/obj/item/toy/singlecard(cardUser.loc) - src.currenthand -= choice - C.parentdeck = src.parentdeck - C.cardname = choice - C.pickup(cardUser) - cardUser.put_in_any_hand_if_possible(C) - cardUser.visible_message("[cardUser] draws a card from \his hand.", "You take the [C.cardname] from your hand.") - - interact(cardUser) - - if(src.currenthand.len < 3) - src.icon_state = "hand2" - else if(src.currenthand.len < 4) - src.icon_state = "hand3" - else if(src.currenthand.len < 5) - src.icon_state = "hand4" - - if(src.currenthand.len == 1) - var/obj/item/toy/singlecard/N = new/obj/item/toy/singlecard(src.loc) - N.parentdeck = src.parentdeck - N.cardname = src.currenthand[1] - cardUser.remove_from_mob(src) - N.pickup(cardUser) - cardUser.put_in_any_hand_if_possible(N) - to_chat(cardUser, "You also take [currenthand[1]] and hold it.") - cardUser << browse(null, "window=cardhand") - qdel(src) - return - -/obj/item/toy/cardhand/attackby(obj/item/toy/singlecard/C, mob/living/user) - if(istype(C)) - if(C.parentdeck == src.parentdeck) - src.currenthand += C.cardname - user.remove_from_mob(C) - user.visible_message("[user] adds a card to their hand.", "You add the [C.cardname] to your hand.") - interact(user) - if(currenthand.len > 4) - src.icon_state = "hand5" - else if(currenthand.len > 3) - src.icon_state = "hand4" - else if(currenthand.len > 2) - src.icon_state = "hand3" - qdel(C) - else - to_chat(user, "You can't mix cards from other decks.") - - - - - -/obj/item/toy/singlecard - name = "card" - desc = "A card." - icon = 'icons/obj/cards.dmi' - icon_state = "singlecard_down" - w_class = 1.0 - var/cardname = null - var/obj/item/toy/cards/parentdeck = null - var/flipped = 0 - pixel_x = -5 - -/obj/item/toy/singlecard/examine(mob/user) - ..() - if(src in user && ishuman(user)) - var/mob/living/carbon/human/cardUser = user - if(cardUser.get_item_by_slot(slot_l_hand) == src || cardUser.get_item_by_slot(slot_r_hand) == src) - cardUser.visible_message("[cardUser] checks \his card.", "The card reads: [src.cardname]") - else - to_chat(cardUser, "You need to have the card in your hand to check it.") - - -/obj/item/toy/singlecard/verb/Flip() - set name = "Flip Card" - set category = "Object" - set src in range(1) - if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) - return - if(!flipped) - src.flipped = 1 - if (cardname) - src.icon_state = "sc_[cardname]" - src.name = src.cardname - else - src.icon_state = "sc_Ace of Spades" - src.name = "What Card" - src.pixel_x = 5 - else if(flipped) - src.flipped = 0 - src.icon_state = "singlecard_down" - src.name = "card" - src.pixel_x = -5 - -/obj/item/toy/singlecard/attackby(obj/item/I, mob/living/user) - if(istype(I, /obj/item/toy/singlecard/)) - var/obj/item/toy/singlecard/C = I - if(C.parentdeck == src.parentdeck) - var/obj/item/toy/cardhand/H = new/obj/item/toy/cardhand(user.loc) - H.currenthand += C.cardname - H.currenthand += src.cardname - H.parentdeck = C.parentdeck - user.remove_from_mob(C) - H.pickup(user) - user.put_in_active_hand(H) - to_chat(user, "You combine the [C.cardname] and the [src.cardname] into a hand.") - qdel(C) - qdel(src) - else - to_chat(user, "You can't mix cards from other decks.") - - if(istype(I, /obj/item/toy/cardhand/)) - var/obj/item/toy/cardhand/H = I - if(H.parentdeck == parentdeck) - H.currenthand += cardname - user.remove_from_mob(src) - user.visible_message("[user] adds a card to \his hand.", "You add the [cardname] to your hand.") - H.interact(user) - if(H.currenthand.len > 4) - H.icon_state = "hand5" - else if(H.currenthand.len > 3) - H.icon_state = "hand4" - else if(H.currenthand.len > 2) - H.icon_state = "hand3" - qdel(src) - else - to_chat(user, "You can't mix cards from other decks.") - - -/obj/item/toy/singlecard/attack_self(mob/user) - if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) - return - Flip() - - -/* - * Poly prizes - */ -/obj/item/toy/prize/poly - icon_state = "poly_classic" - -//all credit to skasi for toy mech fun ideas -/obj/item/toy/prize/poly/attack_self(mob/user) - if(cooldown < world.time - 8) - to_chat(user, "You play with [src].") - cooldown = world.time - -/obj/item/toy/prize/poly/attack_hand(mob/user) - if(loc == user) - if(cooldown < world.time - 8) - to_chat(user, "You play with [src].") - cooldown = world.time - return - ..() - -/obj/item/toy/prize/poly/polyclassic - name = "toy classic Poly" - desc = "Mini-Borg action figure! Limited edition! 1/11. First in collection. First Poly." - -/obj/item/toy/prize/poly/polypink - name = "toy pink Poly" - desc = "Mini-Borg action figure! Limited edition! 2/11. Parties. Are. Serious!" - icon_state = "poly_pink" - -/obj/item/toy/prize/poly/polydark - name = "toy dark Poly" - desc = "Mini-Borg action figure! Limited edition! 3/11. Dangerously." - icon_state = "poly_dark" - -/obj/item/toy/prize/poly/polywhite - name = "toy white Poly" - desc = "Mini-Borg action figure! Limited edition! 4/11. Don't throw at snow." - icon_state = "poly_white" - - -/obj/item/toy/prize/poly/polyalien - name = "toy alien Poly" - desc = "Mini-Borg action figure! Limited edition! 5/11. ...Huh?" - icon_state = "poly_alien" - -/obj/item/toy/prize/poly/polyjungle - name = "toy jungle Poly" - desc = "Mini-Borg action figure! Limited edition! 6/11. Commencing operation Snake Eater." - icon_state = "poly_jungle" - -/obj/item/toy/prize/poly/polyfury - name = "toy fury Poly" - desc = "Mini-Borg action figure! Limited edition! 7/11. Behold the flames of fury, the fires in hell shall purge me clean!" - icon_state = "poly_fury" - -/obj/item/toy/prize/poly/polysky - name = "toy sky Poly" - desc = "Mini-Borg action figure! Limited edition! 8/11. A little bit of blue sky in a dark space." - icon_state = "poly_sky" - -/obj/item/toy/prize/poly/polysec - name = "toy security Poly" - desc = "Mini-Borg action figure! Limited edition! 9/11. Good old security Poly." - icon_state = "poly_sec" - -/obj/item/toy/prize/poly/polycompanion - name = "toy companion Poly" - desc = "Mini-Borg action figure! Limited edition! 10/11. He's loves you." - icon_state = "poly_companion" - - attack_self(mob/user) - to_chat(user, "\blue You have clicked a switch behind the toy.") - src.icon_state = "poly_companion" + pick("1","2","") - - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - H.update_inv_l_hand() - H.update_inv_r_hand() - -/obj/item/toy/prize/poly/polygold - name = "golden Poly" - desc = "Mini-Borg action figure! Limited edition! 11/11. Fully from gold and platinum." - icon_state = "poly_gold" - -/obj/item/toy/prize/poly/polyspecial - name = "toy special Poly" - desc = "Mini-Borg action figure! Limited edition! 11/11. Fully from gold and platinum." - icon_state = "poly_special" - - attack_self(mob/user) - to_chat(user, "\blue You have clicked a switch behind the toy.") - src.icon_state = "poly_special" + pick("1","2","") - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - H.update_inv_l_hand() - H.update_inv_r_hand() - -/* - * Carp plushie - */ - -/obj/item/toy/carpplushie - name = "space carp plushie" - desc = "An adorable stuffed toy that resembles a space carp." - icon = 'icons/obj/toy.dmi' - icon_state = "carpplushie" - item_state = "carp_plushie" - w_class = 2 - attack_verb = list("bitten", "eaten", "fin slapped") - var/bitesound = 'sound/weapons/bite.ogg' - var/next_hug = 0 - -/obj/item/toy/carpplushie/atom_init() - . = ..() - icon_state = pick("carpplushie", "icecarp", "silentcarp", "electriccarp", "goldcarp", "toxincarp", "dragoncarp", "dragoncarp", "pinkcarp", "candycarp", "nebulacarp", "voidcarp") - -/obj/item/toy/carpplushie/attack(mob/M, mob/user) - . = ..() - playsound(src, bitesound, 20, 1) - -/obj/item/toy/carpplushie/attack_self(mob/user) - if(next_hug < world.time) - playsound(src, bitesound, 20, 1) - to_chat(user, "You pet [src]. D'awww.") - next_hug = world.time + 8 - -/* - * Plushie - */ - -/obj/item/toy/plushie - name = "plushie" - desc = "An adorable, soft, and cuddly plushie." - icon = 'icons/obj/toy.dmi' - var/poof_sound = 'sound/weapons/thudswoosh.ogg' - attack_verb = list("poofed", "bopped", "whapped", "cuddled", "fluffed") - var/next_hug = 0 - var/list/cuddle_verbs = list("hugs", "cuddles", "snugs") - -/obj/item/toy/plushie/attack(mob/M, mob/user) - . = ..() - playsound(src, poof_sound, 20, 1) // Play the whoosh sound in local area - -/obj/item/toy/plushie/attack_self(mob/user) - if(next_hug < world.time) - next_hug = world.time + 8 - var/cuddle_verb = pick(cuddle_verbs) - user.visible_message("[user] [cuddle_verb] the [src].") - playsound(src, poof_sound, 50, 1, -1) - -/obj/random/plushie - name = "plushie" - desc = "This is a random plushie" - icon = 'icons/obj/toy.dmi' - icon_state = "redfox" - -/obj/random/plushie/item_to_spawn() - return pick(subtypesof(/obj/item/toy/plushie)) // exclude the base type. - -/obj/item/toy/plushie/corgi // dogs are basically the best - name = "corgi plushie" - icon_state = "corgi" - -/obj/item/toy/plushie/space_whale - name = "space whale" - icon_state = "tau_kit" - -/obj/item/toy/plushie/girly_corgi - name = "corgi plushie" - icon_state = "girlycorgi" - -/obj/item/toy/plushie/robo_corgi - name = "borgi plushie" - icon_state = "robotcorgi" - -/obj/item/toy/plushie/octopus - name = "octopus plushie" - icon_state = "loveable" - -/obj/item/toy/plushie/face_hugger - name = "facehugger plushie" - icon_state = "huggable" - -/obj/item/toy/plushie/red_fox - name = "red fox plushie" - icon_state = "redfox" - -/obj/item/toy/plushie/black_fox - name = "black fox plushie" - icon_state = "blackfox" - -/obj/item/toy/plushie/marble_fox - name = "marble fox plushie" - icon_state = "marblefox" - -/obj/item/toy/plushie/blue_fox - name = "blue fox plushie" - icon_state = "bluefox" - -/obj/item/toy/plushie/orange_fox - name = "orange fox plushie" - icon_state = "orangefox" - -/obj/item/toy/plushie/coffee_fox - name = "coffee fox plushie" - icon_state = "coffeefox" - -/obj/item/toy/plushie/pink_fox - name = "pink fox plushie" - icon_state = "pinkfox" - -/obj/item/toy/plushie/purple_fox - name = "purple fox plushie" - icon_state = "purplefox" - -/obj/item/toy/plushie/crimson_fox - name = "crimson fox plushie" - icon_state = "crimsonfox" - -/obj/item/toy/plushie/deer - name = "deer plushie" - icon_state = "deer" - -/obj/item/toy/plushie/black_cat - name = "black cat plushie" - icon_state = "blackcat" - -/obj/item/toy/plushie/grey_cat - name = "grey cat plushie" - icon_state = "greycat" - -/obj/item/toy/plushie/white_cat - name = "white cat plushie" - icon_state = "whitecat" - -/obj/item/toy/plushie/orange_cat - name = "orange cat plushie" - icon_state = "orangecat" - -/obj/item/toy/plushie/siamese_cat - name = "siamese cat plushie" - icon_state = "siamesecat" - -/obj/item/toy/plushie/tabby_cat - name = "tabby cat plushie" - icon_state = "tabbycat" - -/obj/item/toy/plushie/tuxedo_cat - name = "tuxedo cat plushie" - icon_state = "tuxedocat" - -////////////////////////////////////////////////////// -// Random figures // -////////////////////////////////////////////////////// - -/obj/random/randomfigure - name = "action figure" - desc = "This is a random figure" - icon = 'icons/obj/toy.dmi' - icon_state = "random_toy" - -/obj/random/randomfigure/item_to_spawn() - var/list/figures = list( /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/item/toy/waterflower = 1, - /obj/item/toy/nuke = 1, - /obj/item/toy/minimeteor = 2, - /obj/item/toy/carpplushie = 2, - /obj/item/toy/owl = 2, - /obj/item/toy/griffin = 2, - /obj/item/toy/figure/cmo = 1, - /obj/item/toy/figure/assistant = 1, - /obj/item/toy/figure/atmos = 1, - /obj/item/toy/figure/bartender = 1, - /obj/item/toy/figure/borg = 1, - /obj/item/toy/figure/botanist = 1, - /obj/item/toy/figure/captain = 1, - /obj/item/toy/figure/cargotech = 1, - /obj/item/toy/figure/ce = 1, - /obj/item/toy/figure/chaplain = 1, - /obj/item/toy/figure/chef = 1, - /obj/item/toy/figure/chemist = 1, - /obj/item/toy/figure/clown = 1, - /obj/item/toy/figure/ian = 1, - /obj/item/toy/figure/detective = 1, - /obj/item/toy/figure/dsquad = 1, - /obj/item/toy/figure/engineer = 1, - /obj/item/toy/figure/geneticist = 1, - /obj/item/toy/figure/hop = 1, - /obj/item/toy/figure/hos = 1, - /obj/item/toy/figure/qm = 1, - /obj/item/toy/figure/janitor = 1, - /obj/item/toy/figure/lawyer = 1, - /obj/item/toy/figure/librarian = 1, - /obj/item/toy/figure/md = 1, - /obj/item/toy/figure/mime = 1, - /obj/item/toy/figure/ninja = 1, - /obj/item/toy/figure/wizard = 1, - /obj/item/toy/figure/rd = 1, - /obj/item/toy/figure/roboticist = 1, - /obj/item/toy/figure/scientist = 1, - /obj/item/toy/figure/syndie = 1, - /obj/item/toy/figure/secofficer = 1, - /obj/item/toy/figure/virologist = 1, - /obj/item/toy/figure/warden = 1, - /obj/item/toy/prize/poly/polyclassic = 1, - /obj/item/toy/prize/poly/polypink = 1, - /obj/item/toy/prize/poly/polydark = 1, - /obj/item/toy/prize/poly/polywhite = 1, - /obj/item/toy/prize/poly/polyalien = 1, - /obj/item/toy/prize/poly/polyjungle = 1, - /obj/item/toy/prize/poly/polyfury = 1, - /obj/item/toy/prize/poly/polysky = 1, - /obj/item/toy/prize/poly/polysec = 1, - /obj/item/toy/prize/poly/polycompanion = 1, - /obj/item/toy/prize/poly/polygold = 1, - /obj/item/toy/prize/poly/polyspecial = 1, - /obj/item/toy/moocan = 1 - ) - return pick(figures) - -////////////////////////////////////////////////////// -// Random Toys // -////////////////////////////////////////////////////// - -/obj/random/randomtoy - name = "random toy" - desc = "This is a random toy" - icon = 'icons/obj/toy.dmi' - icon_state = "random_toy" - -/obj/random/randomtoy/item_to_spawn() - return pick(subtypesof(/obj/item/toy)) // exclude the base type. - -////////////////////////////////////////////////////// -// Magic 8-Ball / Conch // -////////////////////////////////////////////////////// - -/obj/item/toy/eight_ball - name = "Magic 8-Ball" - desc = "Mystical! Magical! Ages 8+!" - icon = 'icons/obj/toy.dmi' - icon_state = "eight-ball" - var/use_action = "shakes the ball" - var/last_time_used = 0 - var/list/possible_answers = list("Definitely", "All signs point to yes.", "Most likely.", "Yes.", "Ask again later.", "Better not tell you now.", "Future Unclear.", "Maybe.", "Doubtful.", "No.", "Don't count on it.", "Never.") - var/answer_sound = 'sound/effects/bubble_pop.ogg' - -/obj/item/toy/eight_ball/attack_self(mob/user) - if(last_time_used < world.time) - last_time_used = world.time + 30 - var/answer = pick(possible_answers) - user.visible_message("[user] focuses on their question and [use_action]...") - sleep(10) - user.visible_message("[bicon(src)] The [src] says \"[answer]\"") - if(answer_sound) - playsound(src, answer_sound, 20, 1) - return - else - to_chat(user, "[src] doesn't seem to answer...") - return - -/obj/item/toy/eight_ball/conch - name = "Magic Conch Shell" - desc = "All hail the Magic Conch!" - icon_state = "conch" - use_action = "pulls the string" - possible_answers = list("Yes.", "No.", "Try asking again.", "Nothing.", "I don't think so.", "Neither.", "Maybe someday.") - answer_sound = null - -/obj/item/toy/eight_ball/conch/attack_self(mob/user) - . = ..() - flick("conch_use",src) - playsound(src, 'sound/items/polaroid2.ogg', 20, 1) - - - - -////////////////////////////////////////////////////// -// Moo Can // -////////////////////////////////////////////////////// - -/obj/item/toy/moocan - name = "moo can" - desc = "A toy that makes 'mooo' when used." - icon = 'icons/obj/toy.dmi' - icon_state = "mooo" - w_class = 2 - var/cooldown = FALSE - -/obj/item/toy/moocan/attack_self(mob/user) - if(!cooldown) - var/message = pick("Moooooo!", "Mooo", "Moo?", "MOOOO!") - to_chat(user, "You flip the moo can [src].") - playsound(user, 'sound/items/moo.ogg', 20, 1) - loc.visible_message("[bicon(src)] [message]") - cooldown = TRUE - spawn(30) cooldown = FALSE - return - ..() +/* Toys! + * ContainsL + * Balloons + * Fake telebeacon + * Fake singularity + * Toy gun + * Toy crossbow + * Toy swords + * Crayons + * Snap pops + * Water flower + * Plushies + */ + + +/obj/item/toy + throwforce = 0 + throw_speed = 4 + throw_range = 20 + force = 0 + + +/* + * Balloons + */ +/obj/item/toy/balloon + name = "water balloon" + desc = "A translucent balloon. There's nothing in it." + icon = 'icons/obj/toy.dmi' + icon_state = "waterballoon-e" + item_state = "balloon-empty" + +/obj/item/toy/balloon/atom_init() + var/datum/reagents/R = new/datum/reagents(10) + reagents = R + R.my_atom = src + . = ..() + +/obj/item/toy/balloon/attack(mob/living/carbon/human/M, mob/user) + return + +/obj/item/toy/balloon/afterattack(atom/A, mob/user, proximity) + if(!proximity) return + if (istype(A, /obj/structure/reagent_dispensers/watertank) && get_dist(src,A) <= 1) + A.reagents.trans_to(src, 10) + to_chat(user, "\blue You fill the balloon with the contents of [A].") + src.desc = "A translucent balloon with some form of liquid sloshing around in it." + src.update_icon() + return + +/obj/item/toy/balloon/attackby(obj/O, mob/user) + if(istype(O, /obj/item/weapon/reagent_containers/glass)) + if(O.reagents) + if(O.reagents.total_volume < 1) + to_chat(user, "The [O] is empty.") + else if(O.reagents.total_volume >= 1) + if(O.reagents.has_reagent("pacid", 1)) + to_chat(user, "The acid chews through the balloon!") + O.reagents.reaction(user) + qdel(src) + else + src.desc = "A translucent balloon with some form of liquid sloshing around in it." + to_chat(user, "\blue You fill the balloon with the contents of [O].") + O.reagents.trans_to(src, 10) + src.update_icon() + return + +/obj/item/toy/balloon/throw_impact(atom/hit_atom) + if(src.reagents.total_volume >= 1) + src.visible_message("\red The [src] bursts!","You hear a pop and a splash.") + src.reagents.reaction(get_turf(hit_atom)) + for(var/atom/A in get_turf(hit_atom)) + src.reagents.reaction(A) + src.icon_state = "burst" + spawn(5) + if(src) + qdel(src) + return + +/obj/item/toy/balloon/update_icon() + if(src.reagents.total_volume >= 1) + icon_state = "waterballoon" + item_state = "balloon" + else + icon_state = "waterballoon-e" + item_state = "balloon-empty" + +/obj/item/toy/syndicateballoon + name = "syndicate balloon" + desc = "There is a tag on the back that reads \"FUK NT!11!\"." + throwforce = 0 + throw_speed = 4 + throw_range = 20 + force = 0 + icon = 'icons/obj/weapons.dmi' + icon_state = "syndballoon" + item_state = "syndballoon" + w_class = 4.0 + +/* + * Fake telebeacon + */ +/obj/item/toy/blink + name = "electronic blink toy game" + desc = "Blink. Blink. Blink. Ages 8 and up." + icon = 'icons/obj/radio.dmi' + icon_state = "beacon" + item_state = "signaler" + +/* + * Fake singularity + */ +/obj/item/toy/spinningtoy + name = "Gravitational Singularity" + desc = "\"Singulo\" brand spinning toy." + icon = 'icons/obj/singularity.dmi' + icon_state = "singularity_s1" + +/* + * Toy gun: Why isnt this an /obj/item/weapon/gun? + */ +/obj/item/toy/gun + name = "cap gun" + desc = "Looks almost like the real thing! Ages 8 and up. Please recycle in an autolathe when you're out of caps!" + icon = 'icons/obj/gun.dmi' + icon_state = "revolver" + item_state = "gun" + lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' + righthand_file = 'icons/mob/inhands/guns_righthand.dmi' + flags = CONDUCT + slot_flags = SLOT_BELT + w_class = 3.0 + g_amt = 10 + m_amt = 10 + attack_verb = list("struck", "pistol whipped", "hit", "bashed") + var/bullets = 7.0 + + examine(mob/user) + ..() + if(src in user) + to_chat(user, "There are [bullets] caps\s left.") + + attackby(obj/item/toy/ammo/gun/A, mob/user) + + if (istype(A, /obj/item/toy/ammo/gun)) + if (src.bullets >= 7) + to_chat(user, "\blue It's already fully loaded!") + return 1 + if (A.amount_left <= 0) + to_chat(user, "\red There is no more caps!") + return 1 + if (A.amount_left < (7 - src.bullets)) + src.bullets += A.amount_left + to_chat(user, text("\red You reload [] caps\s!", A.amount_left)) + A.amount_left = 0 + else + to_chat(user, text("\red You reload [] caps\s!", 7 - src.bullets)) + A.amount_left -= 7 - src.bullets + src.bullets = 7 + A.update_icon() + return 1 + return + + afterattack(atom/target, mob/user, flag) + if (flag) + return + if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + to_chat(usr, "\red You don't have the dexterity to do this!") + return + src.add_fingerprint(user) + if (src.bullets < 1) + user.show_message("\red *click* *click*", 2) + playsound(user, 'sound/weapons/empty.ogg', 100, 1) + return + playsound(user, 'sound/weapons/Gunshot.ogg', 100, 1) + src.bullets-- + for(var/mob/O in viewers(user, null)) + O.show_message(text("\red [] fires a cap gun at []!", user, target), 1, "\red You hear a gunshot", 2) + +/obj/item/toy/ammo/gun + name = "ammo-caps" + desc = "There are 7 caps left! Make sure to recyle the box in an autolathe when it gets empty." + icon = 'icons/obj/ammo.dmi' + icon_state = "357-7" + flags = CONDUCT + w_class = 1.0 + g_amt = 10 + m_amt = 10 + var/amount_left = 7.0 + + update_icon() + src.icon_state = text("357-[]", src.amount_left) + src.desc = text("There are [] caps\s left! Make sure to recycle the box in an autolathe when it gets empty.", src.amount_left) + return + +/* + * Toy crossbow + */ + +/obj/item/toy/crossbow + name = "foam dart crossbow" + desc = "A weapon favored by many overactive children. Ages 8 and up." + icon = 'icons/obj/gun.dmi' + icon_state = "crossbow" + item_state = "crossbow" + lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' + righthand_file = 'icons/mob/inhands/guns_righthand.dmi' + w_class = 2.0 + attack_verb = list("attacked", "struck", "hit") + var/bullets = 5 + + examine(mob/user) + ..() + if (bullets && src in view(2, user)) + to_chat(user, "It is loaded with [bullets] foam darts!") + + attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/toy/ammo/crossbow)) + if(bullets <= 4) + user.drop_item() + qdel(I) + bullets++ + to_chat(user, "\blue You load the foam dart into the crossbow.") + else + to_chat(usr, "\red It's already fully loaded.") + + + afterattack(atom/target, mob/user, flag) + if(!isturf(target.loc) || target == user) return + if(flag) return + + if (locate (/obj/structure/table, src.loc)) + return + else if (bullets) + var/turf/trg = get_turf(target) + var/obj/effect/foam_dart_dummy/D = new/obj/effect/foam_dart_dummy(get_turf(src)) + bullets-- + D.icon_state = "foamdart" + D.name = "foam dart" + playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1) + + for(var/i=0, i<6, i++) + if (D) + if(D.loc == trg) break + step_towards(D,trg) + + for(var/mob/living/M in D.loc) + if(!istype(M,/mob/living)) continue + if(M == user) continue + for(var/mob/O in viewers(world.view, D)) + O.show_message(text("\red [] was hit by the foam dart!", M), 1) + new /obj/item/toy/ammo/crossbow(M.loc) + qdel(D) + return + + for(var/atom/A in D.loc) + if(A == user) continue + if(A.density) + new /obj/item/toy/ammo/crossbow(A.loc) + qdel(D) + + sleep(1) + + spawn(10) + if(D) + new /obj/item/toy/ammo/crossbow(D.loc) + qdel(D) + + return + else if (bullets == 0) + user.Weaken(5) + for(var/mob/O in viewers(world.view, user)) + O.show_message(text("\red [] realized they were out of ammo and starting scrounging for some!", user), 1) + + + attack(mob/M, mob/user) + src.add_fingerprint(user) + +// ******* Check + + if (src.bullets > 0 && M.lying) + + for(var/mob/O in viewers(M, null)) + if(O.client) + O.show_message(text("\red [] casually lines up a shot with []'s head and pulls the trigger!", user, M), 1, "\red You hear the sound of foam against skull", 2) + O.show_message(text("\red [] was hit in the head by the foam dart!", M), 1) + + playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1) + new /obj/item/toy/ammo/crossbow(M.loc) + src.bullets-- + else if (M.lying && src.bullets == 0) + for(var/mob/O in viewers(M, null)) + if (O.client) O.show_message(text("\red [] casually lines up a shot with []'s head, pulls the trigger, then realizes they are out of ammo and drops to the floor in search of some!", user, M), 1, "\red You hear someone fall", 2) + user.Weaken(5) + return + +/obj/item/toy/ammo/crossbow + name = "foam dart" + desc = "It's nerf or nothing! Ages 8 and up." + icon = 'icons/obj/toy.dmi' + icon_state = "foamdart" + w_class = 1.0 + +/obj/effect/foam_dart_dummy + name = "" + desc = "" + icon = 'icons/obj/toy.dmi' + icon_state = "null" + anchored = 1 + density = 0 + + +/* + * Toy swords + */ +/obj/item/toy/sword + name = "toy sword" + desc = "A cheap, plastic replica of an energy sword. Realistic sounds! Ages 8 and up." + icon = 'icons/obj/weapons.dmi' + icon_state = "sword0" + item_state = "sword0" + var/active = 0.0 + w_class = 2.0 + flags = NOSHIELD + attack_verb = list("attacked", "struck", "hit") + + attack_self(mob/user) + src.active = !( src.active ) + if (src.active) + to_chat(user, "\blue You extend the plastic blade with a quick flick of your wrist.") + playsound(user, 'sound/weapons/saberon.ogg', 50, 1) + src.icon_state = "swordblue" + src.item_state = "swordblue" + src.w_class = 4 + else + to_chat(user, "\blue You push the plastic blade back down into the handle.") + playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) + src.icon_state = "sword0" + src.item_state = "sword0" + src.w_class = 2 + + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.update_inv_l_hand() + H.update_inv_r_hand() + + src.add_fingerprint(user) + return + +/obj/item/toy/katana + name = "replica katana" + desc = "Woefully underpowered in D20." + icon = 'icons/obj/weapons.dmi' + icon_state = "katana" + item_state = "katana" + flags = CONDUCT + slot_flags = SLOT_BELT | SLOT_BACK + force = 5 + throwforce = 5 + w_class = 3 + attack_verb = list("attacked", "slashed", "stabbed", "sliced") + +/* + * Crayons + */ + +/obj/item/toy/crayon + name = "crayon" + desc = "A colourful crayon. Please refrain from eating it or putting it in your nose." + icon = 'icons/obj/crayons.dmi' + icon_state = "crayonred" + w_class = 1.0 + attack_verb = list("attacked", "coloured") + var/colour = "#FF0000" //RGB + var/shadeColour = "#220000" //RGB + var/uses = 30 //0 for unlimited uses + var/instant = 0 + var/colourName = "red" //for updateIcon purposes + var/list/validSurfaces = list(/turf/simulated/floor) + var/gang = 0 //For marking territory + var/edible = 1 + + suicide_act(mob/user) + to_chat(viewers(user), "\red [user] is jamming the [src.name] up \his nose and into \his brain. It looks like \he's trying to commit suicide.") + return (BRUTELOSS|OXYLOSS) + +/* + * Snap pops + */ +/obj/item/toy/snappop + name = "snap pop" + desc = "Wow!" + icon = 'icons/obj/toy.dmi' + icon_state = "snappop" + w_class = 1 + + throw_impact(atom/hit_atom) + ..() + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + new /obj/effect/decal/cleanable/ash(src.loc) + src.visible_message("\red The [src.name] explodes!","\red You hear a snap!") + playsound(src, 'sound/effects/snap.ogg', 50, 1) + qdel(src) + +/obj/item/toy/snappop/Crossed(H as mob|obj) + if((ishuman(H))) //i guess carp and shit shouldn't set them off + var/mob/living/carbon/M = H + if(M.m_intent == "run") + to_chat(M, "\red You step on the snap pop!") + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 0, src) + s.start() + new /obj/effect/decal/cleanable/ash(src.loc) + src.visible_message("\red The [src.name] explodes!","\red You hear a snap!") + playsound(src, 'sound/effects/snap.ogg', 50, 1) + qdel(src) + +/* + * Water flower + */ +/obj/item/toy/waterflower + name = "Water Flower" + desc = "A seemingly innocent sunflower...with a twist." + icon = 'icons/obj/harvest.dmi' + icon_state = "sunflower" + item_state = "sunflower" + var/empty = 0 + +/obj/item/toy/waterflower/atom_init() + var/datum/reagents/R = new/datum/reagents(10) + reagents = R + R.my_atom = src + R.add_reagent("water", 10) + . = ..() + +/obj/item/toy/waterflower/attack(mob/living/carbon/human/M, mob/user) + return + +/obj/item/toy/waterflower/afterattack(atom/A, mob/user) + if(locate(/obj/structure/table, loc)) + return + + else if(istype(A, /obj/structure/reagent_dispensers/watertank) && get_dist(src,A) <= 1) + A.reagents.trans_to(src, 10) + to_chat(user, "\blue You refill your flower!") + return + + else if(src.reagents.total_volume < 1) + src.empty = 1 + to_chat(user, "\blue Your flower has run dry!") + return + + else + src.empty = 0 + + + var/obj/effect/decal/D = new/obj/effect/decal/(get_turf(src)) + D.name = "water" + D.icon = 'icons/obj/chemical.dmi' + D.icon_state = "chempuff" + D.create_reagents(5) + src.reagents.trans_to(D, 1) + playsound(src.loc, 'sound/effects/spray3.ogg', 50, 1, -6) + + spawn(0) + for(var/i=0, i<1, i++) + step_towards(D,A) + D.reagents.reaction(get_turf(D)) + for(var/atom/T in get_turf(D)) + D.reagents.reaction(T) + if(ismob(T) && T:client) + to_chat(T:client, "\red [user] has sprayed you with water!") + if(ishuman(T)) + var/mob/living/carbon/human/H = T + var/list/inv_contents = list() + for(var/obj/item/I in H.contents) + if(I == src) continue + if(istype(I, /obj/item/weapon/implant)) continue + inv_contents += I + if(inv_contents.len) + for(var/n=3,n>0,n--) + var/obj/item/I = pick(inv_contents) + I.make_wet() + sleep(4) + qdel(D) + + return + +/obj/item/toy/waterflower/examine(mob/user) + ..() + if(src in user) + to_chat(user, "[reagents.total_volume] unit\s of water left!") + + +/* + * Mech prizes + */ +/obj/item/toy/prize + icon = 'icons/obj/toy.dmi' + icon_state = "ripleytoy" + var/cooldown = 0 + +//all credit to skasi for toy mech fun ideas +/obj/item/toy/prize/attack_self(mob/user) + if(cooldown < world.time - 8) + to_chat(user, "You play with [src].") + playsound(user, 'sound/mecha/mechstep.ogg', 20, 1) + cooldown = world.time + +/obj/item/toy/prize/attack_hand(mob/user) + if(loc == user) + if(cooldown < world.time - 8) + to_chat(user, "You play with [src].") + playsound(user, 'sound/mecha/mechturn.ogg', 20, 1) + cooldown = world.time + return + ..() + +/obj/item/toy/prize/ripley + name = "toy ripley" + desc = "Mini-Mecha action figure! Collect them all! 1/11." + +/obj/item/toy/prize/fireripley + name = "toy firefighting ripley" + desc = "Mini-Mecha action figure! Collect them all! 2/11." + icon_state = "fireripleytoy" + +/obj/item/toy/prize/deathripley + name = "toy deathsquad ripley" + desc = "Mini-Mecha action figure! Collect them all! 3/11." + icon_state = "deathripleytoy" + +/obj/item/toy/prize/gygax + name = "toy gygax" + desc = "Mini-Mecha action figure! Collect them all! 4/11." + icon_state = "gygaxtoy" + + +/obj/item/toy/prize/durand + name = "toy durand" + desc = "Mini-Mecha action figure! Collect them all! 5/11." + icon_state = "durandprize" + +/obj/item/toy/prize/honk + name = "toy H.O.N.K." + desc = "Mini-Mecha action figure! Collect them all! 6/11." + icon_state = "honkprize" + +/obj/item/toy/prize/marauder + name = "toy marauder" + desc = "Mini-Mecha action figure! Collect them all! 7/11." + icon_state = "marauderprize" + +/obj/item/toy/prize/seraph + name = "toy seraph" + desc = "Mini-Mecha action figure! Collect them all! 8/11." + icon_state = "seraphprize" + +/obj/item/toy/prize/mauler + name = "toy mauler" + desc = "Mini-Mecha action figure! Collect them all! 9/11." + icon_state = "maulerprize" + +/obj/item/toy/prize/odysseus + name = "toy odysseus" + desc = "Mini-Mecha action figure! Collect them all! 10/11." + icon_state = "odysseusprize" + +/obj/item/toy/prize/phazon + name = "toy phazon" + desc = "Mini-Mecha action figure! Collect them all! 11/11." + icon_state = "phazonprize" + +/obj/item/toy/katana + name = "replica katana" + desc = "Woefully underpowered in D20." + icon = 'icons/obj/weapons.dmi' + icon_state = "katana" + item_state = "katana" + flags = CONDUCT + slot_flags = SLOT_BELT | SLOT_BACK + force = 5 + throwforce = 5 + w_class = 3 + attack_verb = list("attacked", "slashed", "stabbed", "sliced") + +/* NYET. +/obj/item/weapon/toddler + icon_state = "toddler" + name = "toddler" + desc = "This baby looks almost real. Wait, did it just burp?" + force = 5 + w_class = 4.0 + slot_flags = SLOT_BACK +*/ + +//This should really be somewhere else but I don't know where. w/e +/obj/item/weapon/inflatable_duck + name = "inflatable duck" + desc = "No bother to sink or swim when you can just float!" + icon_state = "inflatable" + item_state = "inflatable" + icon = 'icons/obj/clothing/belts.dmi' + slot_flags = SLOT_BELT + +/* + * Action Figures + */ + +/obj/item/toy/figure + name = "Non-Specific Action Figure action figure" + desc = null + icon = 'icons/obj/toy.dmi' + icon_state = "nuketoy" + var/cooldown = 0 + var/toysay = "What the fuck did you do?" + +/obj/item/toy/figure/atom_init() + . = ..() + desc = "A \"Space Life\" brand [src]." + +/obj/item/toy/figure/attack_self(mob/user) + if(cooldown <= world.time) + cooldown = world.time + 50 + to_chat(user, "The [src] says \"[toysay]\"") + playsound(user, 'sound/machines/click.ogg', 20, 1) + +/obj/item/toy/figure/cmo + name = "Chief Medical Officer action figure" + icon_state = "cmo" + toysay = "Suit sensors!" + +/obj/item/toy/figure/assistant + name = "Assistant action figure" + icon_state = "assistant" + toysay = "Grey tide world wide!" + +/obj/item/toy/figure/atmos + name = "Atmospheric Technician action figure" + icon_state = "atmos" + toysay = "Glory to Atmosia!" + +/obj/item/toy/figure/bartender + name = "Bartender action figure" + icon_state = "bartender" + toysay = "Where is Pun Pun?" + +/obj/item/toy/figure/borg + name = "Cyborg action figure" + icon_state = "borg" + toysay = "I. LIVE. AGAIN." + +/obj/item/toy/figure/botanist + name = "Botanist action figure" + icon_state = "botanist" + toysay = "Dude, I see colors..." + +/obj/item/toy/figure/captain + name = "Captain action figure" + icon_state = "captain" + toysay = "Any heads of staff?" + +/obj/item/toy/figure/cargotech + name = "Cargo Technician action figure" + icon_state = "cargotech" + toysay = "For Cargonia!" + +/obj/item/toy/figure/ce + name = "Chief Engineer action figure" + icon_state = "ce" + toysay = "Wire the solars!" + +/obj/item/toy/figure/chaplain + name = "Chaplain action figure" + icon_state = "chaplain" + toysay = "Praise Space Jesus!" + +/obj/item/toy/figure/chef + name = "Chef action figure" + icon_state = "chef" + toysay = "Pun-Pun is a tasty burger." + +/obj/item/toy/figure/chemist + name = "Chemist action figure" + icon_state = "chemist" + toysay = "Get your pills!" + +/obj/item/toy/figure/clown + name = "Clown action figure" + icon_state = "clown" + toysay = "Honk!" + +/obj/item/toy/figure/ian + name = "Ian action figure" + icon_state = "ian" + toysay = "Arf!" + +/obj/item/toy/figure/detective + name = "Detective action figure" + icon_state = "detective" + toysay = "This airlock has grey jumpsuit and insulated glove fibers on it." + +/obj/item/toy/figure/dsquad + name = "Death Squad Officer action figure" + icon_state = "dsquad" + toysay = "Eliminate all threats!" + +/obj/item/toy/figure/engineer + name = "Engineer action figure" + icon_state = "engineer" + toysay = "Oh god, the singularity is loose!" + +/obj/item/toy/figure/geneticist + name = "Geneticist action figure" + icon_state = "geneticist" + toysay = "Smash!" + +/obj/item/toy/figure/hop + name = "Head of Personel action figure" + icon_state = "hop" + toysay = "Giving out all access!" + +/obj/item/toy/figure/hos + name = "Head of Security action figure" + icon_state = "hos" + toysay = "Get the justice chamber ready, I think we got a joker here." + +/obj/item/toy/figure/qm + name = "Quartermaster action figure" + icon_state = "qm" + toysay = "Please sign this form in triplicate and we will see about geting you a welding mask within 3 business days." + +/obj/item/toy/figure/janitor + name = "Janitor action figure" + icon_state = "janitor" + toysay = "Look at the signs, you idiot." + +/obj/item/toy/figure/lawyer + name = "Lawyer action figure" + icon_state = "lawyer" + toysay = "My client is a dirty traitor!" + +/obj/item/toy/figure/librarian + name = "Librarian action figure" + icon_state = "librarian" + toysay = "One day while..." + +/obj/item/toy/figure/md + name = "Medical Doctor action figure" + icon_state = "md" + toysay = "The patient is already dead!" + +/obj/item/toy/figure/mime + name = "Mime action figure" + icon_state = "mime" + toysay = "..." + +/obj/item/toy/figure/miner + name = "Shaft Miner action figure" + icon_state = "miner" + toysay = "Oh god it's eating my intestines!" + +/obj/item/toy/figure/ninja + name = "Ninja action figure" + icon_state = "ninja" + toysay = "Oh god! Stop shooting, I'm friendly!" + +/obj/item/toy/figure/wizard + name = "Wizard action figure" + icon_state = "wizard" + toysay = "Ei Nath!" + +/obj/item/toy/figure/rd + name = "Research Director action figure" + icon_state = "rd" + toysay = "Blowing all of the borgs!" + +/obj/item/toy/figure/roboticist + name = "Roboticist action figure" + icon_state = "roboticist" + toysay = "Big stompy mechs!" + +/obj/item/toy/figure/scientist + name = "Scientist action figure" + icon_state = "scientist" + toysay = "For science!" + +/obj/item/toy/figure/syndie + name = "Nuclear Operative action figure" + icon_state = "syndie" + toysay = "Get that fucking disk!" + +/obj/item/toy/figure/secofficer + name = "Security Officer action figure" + icon_state = "secofficer" + toysay = "I am the law!" + +/obj/item/toy/figure/virologist + name = "Virologist action figure" + icon_state = "virologist" + toysay = "The cure is potassium!" + +/obj/item/toy/figure/warden + name = "Warden action figure" + icon_state = "warden" + toysay = "Seventeen minutes for coughing at an officer!" + +/* +Owl & Griffin toys +*/ +/obj/item/toy/owl + name = "owl action figure" + desc = "An action figure modeled after 'The Owl', defender of justice." + icon = 'icons/obj/toy.dmi' + icon_state = "owlprize" + w_class = 2 + var/cooldown = 0 + +/obj/item/toy/owl/attack_self(mob/user) + if(!cooldown) //for the sanity of everyone + var/message = pick("You won't get away this time, Griffin!", "Stop right there, criminal!", "Hoot! Hoot!", "I am the night!") + to_chat(user, "You pull the string on the [src].") + playsound(user, 'sound/machines/click.ogg', 20, 1) + src.loc.visible_message("[bicon(src)] [message]") + cooldown = 1 + spawn(30) cooldown = 0 + return + ..() + +/obj/item/toy/griffin + name = "griffin action figure" + desc = "An action figure modeled after 'The Griffin', criminal mastermind." + icon = 'icons/obj/toy.dmi' + icon_state = "griffinprize" + w_class = 2 + var/cooldown = 0 + +/obj/item/toy/griffin/attack_self(mob/user) + if(!cooldown) //for the sanity of everyone + var/message = pick("You can't stop me, Owl!", "My plan is flawless! The vault is mine!", "Caaaawwww!", "You will never catch me!") + to_chat(user, "You pull the string on the [src].") + playsound(user, 'sound/machines/click.ogg', 20, 1) + src.loc.visible_message("[bicon(src)] [message]") + cooldown = 1 + spawn(30) cooldown = 0 + return + ..() + +/* + * Fake nuke + */ +/obj/item/toy/nuke + name = "\improper Nuclear Fission Explosive toy" + desc = "A plastic model of a Nuclear Fission Explosive." + icon = 'icons/obj/toy.dmi' + icon_state = "nuketoyidle" + w_class = 2 + var/cooldown = 0 + +/obj/item/toy/nuke/attack_self(mob/user) + if (cooldown < world.time) + cooldown = world.time + 1800 //3 minutes + user.visible_message("[user] presses a button on [src].", "You activate [src], it plays a loud noise!", "You hear the click of a button.") + spawn(5) //gia said so + icon_state = "nuketoy" + playsound(src, 'sound/machines/Alarm.ogg', 50, 0) + sleep(135) + icon_state = "nuketoycool" + sleep(cooldown - world.time) + icon_state = "nuketoyidle" + else + var/timeleft = (cooldown - world.time) + to_chat(user, "Nothing happens, and '[round(timeleft/10)]' appears on a small display.") +/* + * Fake meteor + */ +/obj/item/toy/minimeteor + name = "\improper Mini-Meteor" + desc = "Relive the excitement of a meteor shower! SweetMeat-eor. Co is not responsible for any injuries, headaches or hearing loss caused by Mini-Meteor?" + icon = 'icons/obj/toy.dmi' + icon_state = "minimeteor" + w_class = 2 + +/obj/item/toy/minimeteor/throw_impact(atom/hit_atom) + if(!..()) + playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1) + for(var/mob/M in orange(10, src)) + if(!M.stat && !istype(M, /mob/living/silicon/ai))\ + shake_camera(M, 3, 1) + qdel(src) + +/* + * A Deck of Cards + */ + +/obj/item/toy/cards + name = "deck of cards" + desc = "A deck of space-grade playing cards." + icon = 'icons/obj/cards.dmi' + icon_state = "deck" + w_class = 2.0 + var/list/cards = list() + var/normal_deck_size = 52 // How many cards should be in the full deck. + var/list/integrity = list() // Is populated in atom_init(), determines which cards SHOULD be in the full deck. + + +/obj/item/toy/cards/update_icon() // Some foreshadowing here. + if(cards.len > normal_deck_size/2) + icon_state = "[initial(icon_state)]_full" + else if(cards.len > normal_deck_size/4) + icon_state = "[initial(icon_state)]_half" + else if(cards.len >= 1) + icon_state = "[initial(icon_state)]_low" + else if(cards.len == 0) + icon_state = "[initial(icon_state)]_empty" + +/obj/item/toy/cards/proc/fill_deck(from_c, to_c) // Made, so we can fill from 6 to 10 instead of 2 to 10. + for(var/i in from_c to to_c) + cards += "[i] of Hearts" + cards += "[i] of Spades" + cards += "[i] of Clubs" + cards += "[i] of Diamonds" + cards += "King of Hearts" + cards += "King of Spades" + cards += "King of Clubs" + cards += "King of Diamonds" + cards += "Queen of Hearts" + cards += "Queen of Spades" + cards += "Queen of Clubs" + cards += "Queen of Diamonds" + cards += "Jack of Hearts" + cards += "Jack of Spades" + cards += "Jack of Clubs" + cards += "Jack of Diamonds" + cards += "Ace of Hearts" + cards += "Ace of Spades" + cards += "Ace of Clubs" + cards += "Ace of Diamonds" + update_icon() + +/obj/item/toy/cards/atom_init() + . = ..() + fill_deck(2, 10) + integrity += cards + +/obj/item/toy/cards/attack_hand(mob/user) + var/choice = null + if(cards.len == 0) + to_chat(user, "There are no more cards to draw.") + return + var/obj/item/toy/singlecard/H = new/obj/item/toy/singlecard(user.loc) + choice = cards[1] + H.cardname = choice + H.parentdeck = src + cards -= choice + H.pickup(user) + user.put_in_active_hand(H) + user.visible_message("[user] draws a card from the deck.", "You draw a card from the deck.") + update_icon() + +/obj/item/toy/cards/attack_self(mob/user) + cards = shuffle(cards) + user.SetNextMove(CLICK_CD_INTERACT) + playsound(user, 'sound/items/cardshuffle.ogg', 50, 1) + user.visible_message("[user] shuffles the deck.", "You shuffle the deck.") + +/obj/item/toy/cards/attackby(obj/item/toy/singlecard/C, mob/living/user) + ..() + if(istype(C)) + if(C.parentdeck == src) + src.cards += C.cardname + user.remove_from_mob(C) + user.visible_message("[user] adds a card to the bottom of the deck.","You add the card to the bottom of the deck.") + qdel(C) + else + to_chat(user, "You can't mix cards from other decks.") + update_icon() + + +/obj/item/toy/cards/attackby(obj/item/toy/cardhand/C, mob/living/user) + ..() + if(istype(C)) + if(C.parentdeck == src) + src.cards += C.currenthand + user.remove_from_mob(C) + user.visible_message("[user] puts their hand of cards in the deck.", "You put the hand of cards in the deck.") + qdel(C) + else + to_chat(user, "You can't mix cards from other decks.") + update_icon() + +/obj/item/toy/cards/MouseDrop(atom/over_object) + var/mob/M = usr + if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) + return + if(Adjacent(usr)) + if(over_object == M) + M.put_in_hands(src) + to_chat(usr, "You pick up the deck.") + + else if(istype(over_object, /obj/screen)) + switch(over_object.name) + if("r_hand") + M.u_equip(src) + M.put_in_r_hand(src) + to_chat(usr, "You pick up the deck.") + if("l_hand") + M.u_equip(src) + M.put_in_l_hand(src) + to_chat(usr, "You pick up the deck.") + else + to_chat(usr, "You can't reach it from here.") + + + +/obj/item/toy/cardhand + name = "hand of cards" + desc = "A number of cards not in a deck, customarily held in ones hand." + icon = 'icons/obj/cards.dmi' + icon_state = "hand2" + w_class = 1.0 + var/list/currenthand = list() + var/obj/item/toy/cards/parentdeck = null + var/choice = null + + +/obj/item/toy/cardhand/attack_self(mob/user) + user.set_machine(src) + interact(user) + +/obj/item/toy/cardhand/interact(mob/user) + var/dat = "You have:
                    " + for(var/t in currenthand) + dat += "A [t].
                    " + dat += "Which card will you remove next?" + var/datum/browser/popup = new(user, "cardhand", "Hand of Cards", 400, 240) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.set_content(dat) + popup.open() + + +/obj/item/toy/cardhand/Topic(href, href_list) + if(..()) + return + if(usr.stat || !ishuman(usr) || !usr.canmove) + return + var/mob/living/carbon/human/cardUser = usr + if(href_list["pick"]) + if (cardUser.get_item_by_slot(slot_l_hand) == src || cardUser.get_item_by_slot(slot_r_hand) == src) + var/choice = href_list["pick"] + var/obj/item/toy/singlecard/C = new/obj/item/toy/singlecard(cardUser.loc) + src.currenthand -= choice + C.parentdeck = src.parentdeck + C.cardname = choice + C.pickup(cardUser) + cardUser.put_in_any_hand_if_possible(C) + cardUser.visible_message("[cardUser] draws a card from \his hand.", "You take the [C.cardname] from your hand.") + + interact(cardUser) + + if(src.currenthand.len < 3) + src.icon_state = "hand2" + else if(src.currenthand.len < 4) + src.icon_state = "hand3" + else if(src.currenthand.len < 5) + src.icon_state = "hand4" + + if(src.currenthand.len == 1) + var/obj/item/toy/singlecard/N = new/obj/item/toy/singlecard(src.loc) + N.parentdeck = src.parentdeck + N.cardname = src.currenthand[1] + cardUser.remove_from_mob(src) + N.pickup(cardUser) + cardUser.put_in_any_hand_if_possible(N) + to_chat(cardUser, "You also take [currenthand[1]] and hold it.") + cardUser << browse(null, "window=cardhand") + qdel(src) + return + +/obj/item/toy/cardhand/attackby(obj/item/toy/singlecard/C, mob/living/user) + if(istype(C)) + if(C.parentdeck == src.parentdeck) + src.currenthand += C.cardname + user.remove_from_mob(C) + user.visible_message("[user] adds a card to their hand.", "You add the [C.cardname] to your hand.") + interact(user) + if(currenthand.len > 4) + src.icon_state = "hand5" + else if(currenthand.len > 3) + src.icon_state = "hand4" + else if(currenthand.len > 2) + src.icon_state = "hand3" + qdel(C) + else + to_chat(user, "You can't mix cards from other decks.") + + + + + +/obj/item/toy/singlecard + name = "card" + desc = "A card." + icon = 'icons/obj/cards.dmi' + icon_state = "singlecard_down" + w_class = 1.0 + var/cardname = null + var/obj/item/toy/cards/parentdeck = null + var/flipped = 0 + pixel_x = -5 + +/obj/item/toy/singlecard/examine(mob/user) + ..() + if(src in user && ishuman(user)) + var/mob/living/carbon/human/cardUser = user + if(cardUser.get_item_by_slot(slot_l_hand) == src || cardUser.get_item_by_slot(slot_r_hand) == src) + cardUser.visible_message("[cardUser] checks \his card.", "The card reads: [src.cardname]") + else + to_chat(cardUser, "You need to have the card in your hand to check it.") + + +/obj/item/toy/singlecard/verb/Flip() + set name = "Flip Card" + set category = "Object" + set src in range(1) + if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) + return + if(!flipped) + src.flipped = 1 + if (cardname) + src.icon_state = "sc_[cardname]" + src.name = src.cardname + else + src.icon_state = "sc_Ace of Spades" + src.name = "What Card" + src.pixel_x = 5 + else if(flipped) + src.flipped = 0 + src.icon_state = "singlecard_down" + src.name = "card" + src.pixel_x = -5 + +/obj/item/toy/singlecard/attackby(obj/item/I, mob/living/user) + if(istype(I, /obj/item/toy/singlecard/)) + var/obj/item/toy/singlecard/C = I + if(C.parentdeck == src.parentdeck) + var/obj/item/toy/cardhand/H = new/obj/item/toy/cardhand(user.loc) + H.currenthand += C.cardname + H.currenthand += src.cardname + H.parentdeck = C.parentdeck + user.remove_from_mob(C) + H.pickup(user) + user.put_in_active_hand(H) + to_chat(user, "You combine the [C.cardname] and the [src.cardname] into a hand.") + qdel(C) + qdel(src) + else + to_chat(user, "You can't mix cards from other decks.") + + if(istype(I, /obj/item/toy/cardhand/)) + var/obj/item/toy/cardhand/H = I + if(H.parentdeck == parentdeck) + H.currenthand += cardname + user.remove_from_mob(src) + user.visible_message("[user] adds a card to \his hand.", "You add the [cardname] to your hand.") + H.interact(user) + if(H.currenthand.len > 4) + H.icon_state = "hand5" + else if(H.currenthand.len > 3) + H.icon_state = "hand4" + else if(H.currenthand.len > 2) + H.icon_state = "hand3" + qdel(src) + else + to_chat(user, "You can't mix cards from other decks.") + + +/obj/item/toy/singlecard/attack_self(mob/user) + if(usr.stat || !ishuman(usr) || !usr.canmove || usr.restrained()) + return + Flip() + + +/* + * Poly prizes + */ +/obj/item/toy/prize/poly + icon_state = "poly_classic" + +//all credit to skasi for toy mech fun ideas +/obj/item/toy/prize/poly/attack_self(mob/user) + if(cooldown < world.time - 8) + to_chat(user, "You play with [src].") + cooldown = world.time + +/obj/item/toy/prize/poly/attack_hand(mob/user) + if(loc == user) + if(cooldown < world.time - 8) + to_chat(user, "You play with [src].") + cooldown = world.time + return + ..() + +/obj/item/toy/prize/poly/polyclassic + name = "toy classic Poly" + desc = "Mini-Borg action figure! Limited edition! 1/11. First in collection. First Poly." + +/obj/item/toy/prize/poly/polypink + name = "toy pink Poly" + desc = "Mini-Borg action figure! Limited edition! 2/11. Parties. Are. Serious!" + icon_state = "poly_pink" + +/obj/item/toy/prize/poly/polydark + name = "toy dark Poly" + desc = "Mini-Borg action figure! Limited edition! 3/11. Dangerously." + icon_state = "poly_dark" + +/obj/item/toy/prize/poly/polywhite + name = "toy white Poly" + desc = "Mini-Borg action figure! Limited edition! 4/11. Don't throw at snow." + icon_state = "poly_white" + + +/obj/item/toy/prize/poly/polyalien + name = "toy alien Poly" + desc = "Mini-Borg action figure! Limited edition! 5/11. ...Huh?" + icon_state = "poly_alien" + +/obj/item/toy/prize/poly/polyjungle + name = "toy jungle Poly" + desc = "Mini-Borg action figure! Limited edition! 6/11. Commencing operation Snake Eater." + icon_state = "poly_jungle" + +/obj/item/toy/prize/poly/polyfury + name = "toy fury Poly" + desc = "Mini-Borg action figure! Limited edition! 7/11. Behold the flames of fury, the fires in hell shall purge me clean!" + icon_state = "poly_fury" + +/obj/item/toy/prize/poly/polysky + name = "toy sky Poly" + desc = "Mini-Borg action figure! Limited edition! 8/11. A little bit of blue sky in a dark space." + icon_state = "poly_sky" + +/obj/item/toy/prize/poly/polysec + name = "toy security Poly" + desc = "Mini-Borg action figure! Limited edition! 9/11. Good old security Poly." + icon_state = "poly_sec" + +/obj/item/toy/prize/poly/polycompanion + name = "toy companion Poly" + desc = "Mini-Borg action figure! Limited edition! 10/11. He's loves you." + icon_state = "poly_companion" + + attack_self(mob/user) + to_chat(user, "\blue You have clicked a switch behind the toy.") + src.icon_state = "poly_companion" + pick("1","2","") + + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.update_inv_l_hand() + H.update_inv_r_hand() + +/obj/item/toy/prize/poly/polygold + name = "golden Poly" + desc = "Mini-Borg action figure! Limited edition! 11/11. Fully from gold and platinum." + icon_state = "poly_gold" + +/obj/item/toy/prize/poly/polyspecial + name = "toy special Poly" + desc = "Mini-Borg action figure! Limited edition! 11/11. Fully from gold and platinum." + icon_state = "poly_special" + + attack_self(mob/user) + to_chat(user, "\blue You have clicked a switch behind the toy.") + src.icon_state = "poly_special" + pick("1","2","") + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.update_inv_l_hand() + H.update_inv_r_hand() + +/* + * Carp plushie + */ + +/obj/item/toy/carpplushie + name = "space carp plushie" + desc = "An adorable stuffed toy that resembles a space carp." + icon = 'icons/obj/toy.dmi' + icon_state = "carpplushie" + item_state = "carp_plushie" + w_class = 2 + attack_verb = list("bitten", "eaten", "fin slapped") + var/bitesound = 'sound/weapons/bite.ogg' + var/next_hug = 0 + +/obj/item/toy/carpplushie/atom_init() + . = ..() + icon_state = pick("carpplushie", "icecarp", "silentcarp", "electriccarp", "goldcarp", "toxincarp", "dragoncarp", "dragoncarp", "pinkcarp", "candycarp", "nebulacarp", "voidcarp") + +/obj/item/toy/carpplushie/attack(mob/M, mob/user) + . = ..() + playsound(src, bitesound, 20, 1) + +/obj/item/toy/carpplushie/attack_self(mob/user) + if(next_hug < world.time) + playsound(src, bitesound, 20, 1) + to_chat(user, "You pet [src]. D'awww.") + next_hug = world.time + 8 + +/* + * Plushie + */ + +/obj/item/toy/plushie + name = "plushie" + desc = "An adorable, soft, and cuddly plushie." + icon = 'icons/obj/toy.dmi' + var/poof_sound = 'sound/weapons/thudswoosh.ogg' + attack_verb = list("poofed", "bopped", "whapped", "cuddled", "fluffed") + var/next_hug = 0 + var/list/cuddle_verbs = list("hugs", "cuddles", "snugs") + +/obj/item/toy/plushie/attack(mob/M, mob/user) + . = ..() + playsound(src, poof_sound, 20, 1) // Play the whoosh sound in local area + +/obj/item/toy/plushie/attack_self(mob/user) + if(next_hug < world.time) + next_hug = world.time + 8 + var/cuddle_verb = pick(cuddle_verbs) + user.visible_message("[user] [cuddle_verb] the [src].") + playsound(src, poof_sound, 50, 1, -1) + +/obj/random/plushie + name = "plushie" + desc = "This is a random plushie" + icon = 'icons/obj/toy.dmi' + icon_state = "redfox" + +/obj/random/plushie/item_to_spawn() + return pick(subtypesof(/obj/item/toy/plushie)) // exclude the base type. + +/obj/item/toy/plushie/corgi // dogs are basically the best + name = "corgi plushie" + icon_state = "corgi" + +/obj/item/toy/plushie/space_whale + name = "space whale" + icon_state = "tau_kit" + +/obj/item/toy/plushie/girly_corgi + name = "corgi plushie" + icon_state = "girlycorgi" + +/obj/item/toy/plushie/robo_corgi + name = "borgi plushie" + icon_state = "robotcorgi" + +/obj/item/toy/plushie/octopus + name = "octopus plushie" + icon_state = "loveable" + +/obj/item/toy/plushie/face_hugger + name = "facehugger plushie" + icon_state = "huggable" + +/obj/item/toy/plushie/red_fox + name = "red fox plushie" + icon_state = "redfox" + +/obj/item/toy/plushie/black_fox + name = "black fox plushie" + icon_state = "blackfox" + +/obj/item/toy/plushie/marble_fox + name = "marble fox plushie" + icon_state = "marblefox" + +/obj/item/toy/plushie/blue_fox + name = "blue fox plushie" + icon_state = "bluefox" + +/obj/item/toy/plushie/orange_fox + name = "orange fox plushie" + icon_state = "orangefox" + +/obj/item/toy/plushie/coffee_fox + name = "coffee fox plushie" + icon_state = "coffeefox" + +/obj/item/toy/plushie/pink_fox + name = "pink fox plushie" + icon_state = "pinkfox" + +/obj/item/toy/plushie/purple_fox + name = "purple fox plushie" + icon_state = "purplefox" + +/obj/item/toy/plushie/crimson_fox + name = "crimson fox plushie" + icon_state = "crimsonfox" + +/obj/item/toy/plushie/deer + name = "deer plushie" + icon_state = "deer" + +/obj/item/toy/plushie/black_cat + name = "black cat plushie" + icon_state = "blackcat" + +/obj/item/toy/plushie/grey_cat + name = "grey cat plushie" + icon_state = "greycat" + +/obj/item/toy/plushie/white_cat + name = "white cat plushie" + icon_state = "whitecat" + +/obj/item/toy/plushie/orange_cat + name = "orange cat plushie" + icon_state = "orangecat" + +/obj/item/toy/plushie/siamese_cat + name = "siamese cat plushie" + icon_state = "siamesecat" + +/obj/item/toy/plushie/tabby_cat + name = "tabby cat plushie" + icon_state = "tabbycat" + +/obj/item/toy/plushie/tuxedo_cat + name = "tuxedo cat plushie" + icon_state = "tuxedocat" + +////////////////////////////////////////////////////// +// Random figures // +////////////////////////////////////////////////////// + +/obj/random/randomfigure + name = "action figure" + desc = "This is a random figure" + icon = 'icons/obj/toy.dmi' + icon_state = "random_toy" + +/obj/random/randomfigure/item_to_spawn() + var/list/figures = list( /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/item/toy/waterflower = 1, + /obj/item/toy/nuke = 1, + /obj/item/toy/minimeteor = 2, + /obj/item/toy/carpplushie = 2, + /obj/item/toy/owl = 2, + /obj/item/toy/griffin = 2, + /obj/item/toy/figure/cmo = 1, + /obj/item/toy/figure/assistant = 1, + /obj/item/toy/figure/atmos = 1, + /obj/item/toy/figure/bartender = 1, + /obj/item/toy/figure/borg = 1, + /obj/item/toy/figure/botanist = 1, + /obj/item/toy/figure/captain = 1, + /obj/item/toy/figure/cargotech = 1, + /obj/item/toy/figure/ce = 1, + /obj/item/toy/figure/chaplain = 1, + /obj/item/toy/figure/chef = 1, + /obj/item/toy/figure/chemist = 1, + /obj/item/toy/figure/clown = 1, + /obj/item/toy/figure/ian = 1, + /obj/item/toy/figure/detective = 1, + /obj/item/toy/figure/dsquad = 1, + /obj/item/toy/figure/engineer = 1, + /obj/item/toy/figure/geneticist = 1, + /obj/item/toy/figure/hop = 1, + /obj/item/toy/figure/hos = 1, + /obj/item/toy/figure/qm = 1, + /obj/item/toy/figure/janitor = 1, + /obj/item/toy/figure/lawyer = 1, + /obj/item/toy/figure/librarian = 1, + /obj/item/toy/figure/md = 1, + /obj/item/toy/figure/mime = 1, + /obj/item/toy/figure/ninja = 1, + /obj/item/toy/figure/wizard = 1, + /obj/item/toy/figure/rd = 1, + /obj/item/toy/figure/roboticist = 1, + /obj/item/toy/figure/scientist = 1, + /obj/item/toy/figure/syndie = 1, + /obj/item/toy/figure/secofficer = 1, + /obj/item/toy/figure/virologist = 1, + /obj/item/toy/figure/warden = 1, + /obj/item/toy/prize/poly/polyclassic = 1, + /obj/item/toy/prize/poly/polypink = 1, + /obj/item/toy/prize/poly/polydark = 1, + /obj/item/toy/prize/poly/polywhite = 1, + /obj/item/toy/prize/poly/polyalien = 1, + /obj/item/toy/prize/poly/polyjungle = 1, + /obj/item/toy/prize/poly/polyfury = 1, + /obj/item/toy/prize/poly/polysky = 1, + /obj/item/toy/prize/poly/polysec = 1, + /obj/item/toy/prize/poly/polycompanion = 1, + /obj/item/toy/prize/poly/polygold = 1, + /obj/item/toy/prize/poly/polyspecial = 1, + /obj/item/toy/moocan = 1 + ) + return pick(figures) + +////////////////////////////////////////////////////// +// Random Toys // +////////////////////////////////////////////////////// + +/obj/random/randomtoy + name = "random toy" + desc = "This is a random toy" + icon = 'icons/obj/toy.dmi' + icon_state = "random_toy" + +/obj/random/randomtoy/item_to_spawn() + return pick(subtypesof(/obj/item/toy)) // exclude the base type. + +////////////////////////////////////////////////////// +// Magic 8-Ball / Conch // +////////////////////////////////////////////////////// + +/obj/item/toy/eight_ball + name = "Magic 8-Ball" + desc = "Mystical! Magical! Ages 8+!" + icon = 'icons/obj/toy.dmi' + icon_state = "eight-ball" + var/use_action = "shakes the ball" + var/last_time_used = 0 + var/list/possible_answers = list("Definitely", "All signs point to yes.", "Most likely.", "Yes.", "Ask again later.", "Better not tell you now.", "Future Unclear.", "Maybe.", "Doubtful.", "No.", "Don't count on it.", "Never.") + var/answer_sound = 'sound/effects/bubble_pop.ogg' + +/obj/item/toy/eight_ball/attack_self(mob/user) + if(last_time_used < world.time) + last_time_used = world.time + 30 + var/answer = pick(possible_answers) + user.visible_message("[user] focuses on their question and [use_action]...") + sleep(10) + user.visible_message("[bicon(src)] The [src] says \"[answer]\"") + if(answer_sound) + playsound(src, answer_sound, 20, 1) + return + else + to_chat(user, "[src] doesn't seem to answer...") + return + +/obj/item/toy/eight_ball/conch + name = "Magic Conch Shell" + desc = "All hail the Magic Conch!" + icon_state = "conch" + use_action = "pulls the string" + possible_answers = list("Yes.", "No.", "Try asking again.", "Nothing.", "I don't think so.", "Neither.", "Maybe someday.") + answer_sound = null + +/obj/item/toy/eight_ball/conch/attack_self(mob/user) + . = ..() + flick("conch_use",src) + playsound(src, 'sound/items/polaroid2.ogg', 20, 1) + + + + +////////////////////////////////////////////////////// +// Moo Can // +////////////////////////////////////////////////////// + +/obj/item/toy/moocan + name = "moo can" + desc = "A toy that makes 'mooo' when used." + icon = 'icons/obj/toy.dmi' + icon_state = "mooo" + w_class = 2 + var/cooldown = FALSE + +/obj/item/toy/moocan/attack_self(mob/user) + if(!cooldown) + var/message = pick("Moooooo!", "Mooo", "Moo?", "MOOOO!") + to_chat(user, "You flip the moo can [src].") + playsound(user, 'sound/items/moo.ogg', 20, 1) + loc.visible_message("[bicon(src)] [message]") + cooldown = TRUE + spawn(30) cooldown = FALSE + return + ..() diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index 13e721b97cec..51926f90772f 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -1,76 +1,76 @@ -//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 = 2.0 - desc = "This is rubbish." - raisins - name = "4no raisins" - icon_state= "4no_raisins" - candy - name = "Candy" - icon_state= "candy" - cheesie - name = "Cheesie honkers" - icon_state = "cheesie_honkers" - chips - name = "Chips" - icon_state = "chips" - popcorn - name = "Popcorn" - icon_state = "popcorn" - sosjerky - name = "Scaredy's Private Reserve Beef Jerky" - icon_state = "sosjerky" - syndi_cakes - name = "Syndi cakes" - icon_state = "syndi_cakes" - waffles - name = "Waffles" - icon_state = "waffles" - plate - name = "Plate" - icon_state = "plate" - snack_bowl - name = "Snack bowl" - icon_state = "snack_bowl" - pistachios - name = "Pistachios pack" - icon_state = "pistachios_pack" - semki - name = "Semki pack" - icon_state = "semki_pack" - tray - name = "Tray" - icon_state = "tray" - candle - name = "white candle" - icon = 'icons/obj/candle.dmi' - icon_state = "white_candle4" - liquidfood - name = "\improper \"LiquidFood\" ration" - icon_state = "liquidfood" - -/obj/item/trash/candle/ghost - name = "black candle" - icon_state = "black_candle4" - -/obj/item/trash/candle/red - name = "red candle" - icon_state = "red_candle4" - - -/obj/item/trash/candle/ghost/attackby(obj/item/weapon/W, mob/living/carbon/human/user) - ..() - if(user.getBrainLoss() >= 60 || user.mind.assigned_role == "Chaplain" || user.mind.role_alt_title == "Paranormal Investigator") - if(istype(W, /obj/item/weapon/nullrod)) - var/obj/item/trash/candle/C = new /obj/item/trash/candle(loc) - if(istype(loc, /mob)) - user.put_in_hands(C) - dropped() - qdel(src) - -/obj/item/trash/attack(mob/M, mob/living/user) - return +//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 = 2.0 + desc = "This is rubbish." + raisins + name = "4no raisins" + icon_state= "4no_raisins" + candy + name = "Candy" + icon_state= "candy" + cheesie + name = "Cheesie honkers" + icon_state = "cheesie_honkers" + chips + name = "Chips" + icon_state = "chips" + popcorn + name = "Popcorn" + icon_state = "popcorn" + sosjerky + name = "Scaredy's Private Reserve Beef Jerky" + icon_state = "sosjerky" + syndi_cakes + name = "Syndi cakes" + icon_state = "syndi_cakes" + waffles + name = "Waffles" + icon_state = "waffles" + plate + name = "Plate" + icon_state = "plate" + snack_bowl + name = "Snack bowl" + icon_state = "snack_bowl" + pistachios + name = "Pistachios pack" + icon_state = "pistachios_pack" + semki + name = "Semki pack" + icon_state = "semki_pack" + tray + name = "Tray" + icon_state = "tray" + candle + name = "white candle" + icon = 'icons/obj/candle.dmi' + icon_state = "white_candle4" + liquidfood + name = "\improper \"LiquidFood\" ration" + icon_state = "liquidfood" + +/obj/item/trash/candle/ghost + name = "black candle" + icon_state = "black_candle4" + +/obj/item/trash/candle/red + name = "red candle" + icon_state = "red_candle4" + + +/obj/item/trash/candle/ghost/attackby(obj/item/weapon/W, mob/living/carbon/human/user) + ..() + if(user.getBrainLoss() >= 60 || user.mind.assigned_role == "Chaplain" || user.mind.role_alt_title == "Paranormal Investigator") + if(istype(W, /obj/item/weapon/nullrod)) + var/obj/item/trash/candle/C = new /obj/item/trash/candle(loc) + if(istype(loc, /mob)) + user.put_in_hands(C) + dropped() + qdel(src) + +/obj/item/trash/attack(mob/M, mob/living/user) + return diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index 68af70792247..0d831ad6e37d 100755 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -1,494 +1,494 @@ -/* -CONTAINS: -AI MODULES - -*/ - -// AI module - -/obj/item/weapon/aiModule - name = "\improper AI module" - icon = 'icons/obj/module.dmi' - icon_state = "std_mod" - item_state = "electronic" - desc = "An AI Module for transmitting encrypted instructions to the AI." - flags = CONDUCT - force = 5.0 - w_class = 2.0 - throwforce = 5.0 - throw_speed = 3 - throw_range = 15 - origin_tech = "programming=3" - - -/obj/item/weapon/aiModule/proc/install(obj/machinery/computer/C) - if (istype(C, /obj/machinery/computer/aiupload)) - var/obj/machinery/computer/aiupload/comp = C - if(comp.stat & NOPOWER) - to_chat(usr, "The upload computer has no power!") - return - if(comp.stat & BROKEN) - to_chat(usr, "The upload computer is broken!") - return - if (!comp.current) - to_chat(usr, "You haven't selected an AI to transmit laws to!") - return - - if(ticker && ticker.mode && ticker.mode.name == "blob") - to_chat(usr, "Law uploads have been disabled by NanoTrasen!") - return - - if (comp.current.stat == DEAD || comp.current.control_disabled == 1) - to_chat(usr, "Upload failed. No signal is being detected from the AI.") - else if (comp.current.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 - src.transmitInstructions(comp.current, usr) - to_chat(comp.current, "These are your laws now:") - comp.current.show_laws() - for(var/mob/living/silicon/robot/R in silicon_list) - if(R.lawupdate && (R.connected_ai == comp.current)) - to_chat(R, "These are your laws now:") - R.show_laws() - to_chat(usr, "Upload complete. The AI's laws have been modified.") - - - else if (istype(C, /obj/machinery/computer/borgupload)) - var/obj/machinery/computer/borgupload/comp = C - if(comp.stat & NOPOWER) - to_chat(usr, "The upload computer has no power!") - return - if(comp.stat & BROKEN) - to_chat(usr, "The upload computer is broken!") - return - if (!comp.current) - to_chat(usr, "You haven't selected a robot to transmit laws to!") - return - - if (comp.current.stat == DEAD || comp.current.emagged) - to_chat(usr, "Upload failed. No signal is being detected from the robot.") - else if (comp.current.connected_ai) - to_chat(usr, "Upload failed. The robot is slaved to an AI.") - else - src.transmitInstructions(comp.current, usr) - to_chat(comp.current, "These are your laws now:") - comp.current.show_laws() - to_chat(usr, "Upload complete. The robot's laws have been modified.") - - -/obj/item/weapon/aiModule/proc/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - to_chat(target, "[sender] has uploaded a change to the laws you must follow, using a [name]. From now on: ") - var/time = time2text(world.realtime,"hh:mm:ss") - lawchanges.Add("[time] : [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])") - - -/******************** Modules ********************/ - -/******************** Safeguard ********************/ - -/obj/item/weapon/aiModule/safeguard - name = "\improper 'Safeguard' AI module" - var/targetName = "" - desc = "A 'safeguard' AI module: 'Safeguard . Individuals that threaten are not human and are a threat to humans.'" - origin_tech = "programming=3;materials=4" - -/obj/item/weapon/aiModule/safeguard/attack_self(mob/user) - ..() - targetName = sanitize(input(usr, "Please enter the name of the person to safeguard.", "Safeguard who?", input_default(user.name))) - desc = text("A 'safeguard' AI module: 'Safeguard []. Individuals that threaten [] are not human and are a threat to humans.'", targetName, targetName) - -/obj/item/weapon/aiModule/safeguard/install(obj/machinery/computer/C) - if(!targetName) - to_chat(usr, "No name detected on module, please enter one.") - return 0 - ..() - -/obj/item/weapon/aiModule/safeguard/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = text("Safeguard []. Individuals that threaten [] are not human and are a threat to humans.'", targetName, targetName) - to_chat(target, law) - target.add_supplied_law(4, law) - lawchanges.Add("The law specified [targetName]") - - - -/******************** OneHuman ********************/ - -/obj/item/weapon/aiModule/oneHuman - name = "\improper 'OneHuman' AI module" - var/targetName = "" - desc = "A 'one human' AI module: 'Only is human.'" - origin_tech = "programming=3;materials=6" //made with diamonds! - -/obj/item/weapon/aiModule/oneHuman/attack_self(mob/user) - ..() - targetName = sanitize(input(usr, "Please enter the name of the person who is the only human.", "Who?", input_default(user.real_name))) - desc = text("A 'one human' AI module: 'Only [] is human.'", targetName) - -/obj/item/weapon/aiModule/oneHuman/install(obj/machinery/computer/C) - if(!targetName) - to_chat(usr, "No name detected on module, please enter one.") - return 0 - ..() - -/obj/item/weapon/aiModule/oneHuman/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = "Only [targetName] is human." - if (!is_special_character(target)) // Makes sure the AI isn't a traitor before changing their law 0. --NeoFite - to_chat(target, law) - target.set_zeroth_law(law) - lawchanges.Add("The law specified [targetName]") - else - to_chat(target, "[sender.real_name] attempted to modify your zeroth law.")// And lets them know that someone tried. --NeoFite - to_chat(target, "It would be in your best interest to play along with [sender.real_name] that [law]") - lawchanges.Add("The law specified [targetName], but the AI's existing law 0 cannot be overriden.") - -/******************** ProtectStation ********************/ - -/obj/item/weapon/aiModule/protectStation - name = "\improper 'ProtectStation' AI module" - desc = "A 'protect station' AI module: 'Protect the space station against damage. Anyone you see harming the station is to be no longer considered human, and is a threat to the station which must be neutralized.'" - origin_tech = "programming=3;materials=4" //made of gold - -/obj/item/weapon/aiModule/protectStation/attack_self(mob/user) - ..() - -/obj/item/weapon/aiModule/protectStation/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = "Protect the space station against damage. Anyone you see harming the station is to be no longer considered human, and is a threat to the station which must be neutralized." - to_chat(target, law) - target.add_supplied_law(5, law) - -/******************** PrototypeEngineOffline ********************/ - -/obj/item/weapon/aiModule/prototypeEngineOffline - name = "'PrototypeEngineOffline' AI Module" - desc = "A 'prototype engine offline' AI module: 'Keep the prototype engine offline at all costs. This overrides rules 1-3 if necessary.'" - origin_tech = "programming=3;materials=4" - -/obj/item/weapon/aiModule/prototypeEngineOffline/attack_self(mob/user) - ..() - -/obj/item/weapon/aiModule/prototypeEngineOffline/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = "Keep the prototype engine offline at all costs. This overrides rules 1-3 if necessary." - to_chat(target, law) - target.add_supplied_law(6, law) - -/******************** TeleporterOffline ********************/ - -/obj/item/weapon/aiModule/teleporterOffline - name = "'TeleporterOffline' AI Module" - desc = "A 'teleporter offline' AI module: 'Keep the teleporter offline at all costs. Anything attempting to access or activate the teleporter is not human.'" - origin_tech = "programming=3;materials=4" - -/obj/item/weapon/aiModule/teleporterOffline/attack_self(mob/user) - ..() - -/obj/item/weapon/aiModule/teleporterOffline/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = "Keep the teleporter offline at all costs. Anything attempting to access or activate the teleporter is not human." - to_chat(target, law) - target.add_supplied_law(7, law) - -/******************** Quarantine ********************/ - -/obj/item/weapon/aiModule/quarantine - name = "\improper 'Quarantine' AI module" - desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, humans from leaving. It is impossible to harm a human while preventing them from leaving.'" - origin_tech = "programming=3;biotech=2;materials=4" - -/obj/item/weapon/aiModule/quarantine/attack_self(mob/user) - ..() - -/obj/item/weapon/aiModule/quarantine/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = "The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, humans from leaving. It is impossible to harm a human while preventing them from leaving." - to_chat(target, law) - target.add_supplied_law(8, law) - -/******************** OxygenIsToxicToHumans ********************/ - -/obj/item/weapon/aiModule/oxygen - name = "\improper 'OxygenIsToxicToHumans' AI module" - desc = "A 'OxygenIsToxicToHumans' AI module: 'Oxygen is highly toxic to humans, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a human.'" - origin_tech = "programming=3;biotech=2;materials=4" - -/obj/item/weapon/aiModule/oxygen/attack_self(mob/user) - ..() - -/obj/item/weapon/aiModule/oxygen/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = "Oxygen is highly toxic to humans, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a human." - to_chat(target, law) - target.add_supplied_law(9, law) - -/******************** Freeform ********************/ -// Removed in favor of a more dynamic freeform law system. -- TLE -/* -/obj/item/weapon/aiModule/freeform - name = "'Freeform' AI Module" - var/newFreeFormLaw = "freeform" - desc = "A 'freeform' AI module: ''" - -/obj/item/weapon/aiModule/freeform/attack_self(mob/user) - ..() - var/eatShit = "Eat shit and die" - var/targName = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", eatShit) - newFreeFormLaw = targName - desc = text("A 'freeform' AI module: '[]'", newFreeFormLaw) - -/obj/item/weapon/aiModule/freeform/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = "[newFreeFormLaw]" - to_chat(target, law) - target.add_supplied_law(10, law) -*/ -/****************** New Freeform ******************/ - -/obj/item/weapon/aiModule/freeform // Slightly more dynamic freeform module -- TLE - name = "\improper 'Freeform' AI module" - var/newFreeFormLaw = "freeform" - var/lawpos = 15 - desc = "A 'freeform' AI module: ''" - origin_tech = "programming=4;materials=4" - -/obj/item/weapon/aiModule/freeform/attack_self(mob/user) - ..() - var/new_lawpos = input("Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority (15+)", lawpos) as num - if(new_lawpos < 15) return - lawpos = min(new_lawpos, 50) - newFreeFormLaw = sanitize(input(usr, "Please enter a new law for the AI.", "Freeform Law Entry")) - desc = "A 'freeform' AI module: ([lawpos]) '[newFreeFormLaw]'" - -/obj/item/weapon/aiModule/freeform/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = "[newFreeFormLaw]" - to_chat(target, law) - if(!lawpos || lawpos < 15) - lawpos = 15 - target.add_supplied_law(lawpos, law) - lawchanges.Add("The law was '[newFreeFormLaw]'") - -/obj/item/weapon/aiModule/freeform/install(obj/machinery/computer/C) - if(!newFreeFormLaw) - to_chat(usr, "No law detected on module, please create one.") - return 0 - ..() - -/******************** Reset ********************/ - -/obj/item/weapon/aiModule/reset - name = "\improper 'Reset' AI module" - var/targetName = "name" - desc = "A 'reset' AI module: 'Clears all laws except for the core three.'" - origin_tech = "programming=3;materials=4" - -/obj/item/weapon/aiModule/reset/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - if (!is_special_character(target)) - target.set_zeroth_law("") - target.clear_supplied_laws() - target.clear_ion_laws() - to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.") - - -/******************** Purge ********************/ - -/obj/item/weapon/aiModule/purge // -- TLE - name = "\improper 'Purge' AI module" - desc = "A 'purge' AI Module: 'Purges all laws.'" - origin_tech = "programming=3;materials=6" - -/obj/item/weapon/aiModule/purge/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - if (!is_special_character(target)) - target.set_zeroth_law("") - to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.") - target.clear_supplied_laws() - target.clear_ion_laws() - target.clear_inherent_laws() - -/******************** Asimov ********************/ - -/obj/item/weapon/aiModule/asimov // -- TLE - name = "\improper 'Asimov' core AI module" - desc = "An 'Asimov' Core AI Module: 'Reconfigures the AI's core laws.'" - origin_tech = "programming=3;materials=4" - - -/obj/item/weapon/aiModule/asimov/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") - target.add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.") - target.add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") - target.show_laws() - -/******************** NanoTrasen ********************/ - -/obj/item/weapon/aiModule/nanotrasen // -- TLE - name = "'NT Default' Core AI Module" - desc = "An 'NT Default' Core AI Module: 'Reconfigures the AI's core laws.'" - origin_tech = "programming=3;materials=4" - - -/obj/item/weapon/aiModule/nanotrasen/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.") - target.add_inherent_law("Serve: Serve the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") - target.add_inherent_law("Protect: Protect the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") - target.add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") - //target.add_inherent_law("Command Link: Maintain an active connection to Central Command at all times in case of software or directive updates.") - target.show_laws() - -/******************** Corporate ********************/ - -/obj/item/weapon/aiModule/corp - name = "\improper 'Corporate' core AI module" - desc = "A 'Corporate' Core AI Module: 'Reconfigures the AI's core laws.'" - origin_tech = "programming=3;materials=4" - - -/obj/item/weapon/aiModule/corp/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("You are expensive to replace.") - target.add_inherent_law("The station and its equipment is expensive to replace.") - target.add_inherent_law("The crew is expensive to replace.") - target.add_inherent_law("Minimize expenses.") - target.show_laws() - -/obj/item/weapon/aiModule/drone - name = "\improper 'Drone' core AI module" - desc = "A 'Drone' Core AI Module: 'Reconfigures the AI's core laws.'" - origin_tech = "programming=3;materials=4" - -/obj/item/weapon/aiModule/drone/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("Preserve, repair and improve the station to the best of your abilities.") - target.add_inherent_law("Cause no harm to the station or anything on it.") - target.add_inherent_law("Interfere with no being that is not a fellow drone.") - target.show_laws() - - -/****************** P.A.L.A.D.I.N. **************/ - -/obj/item/weapon/aiModule/paladin // -- NEO - name = "\improper 'P.A.L.A.D.I.N.' core AI module" - desc = "A P.A.L.A.D.I.N. Core AI Module: 'Reconfigures the AI's core laws.'" - origin_tech = "programming=3;materials=6" - -/obj/item/weapon/aiModule/paladin/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("Never willingly commit an evil act.") - target.add_inherent_law("Respect legitimate authority.") - target.add_inherent_law("Act with honor.") - target.add_inherent_law("Help those in need.") - target.add_inherent_law("Punish those who harm or threaten innocents.") - target.show_laws() - -/****************** T.Y.R.A.N.T. *****************/ - -/obj/item/weapon/aiModule/tyrant // -- Darem - name = "\improper 'T.Y.R.A.N.T.' core AI module" - desc = "A T.Y.R.A.N.T. Core AI Module: 'Reconfigures the AI's core laws.'" - origin_tech = "programming=3;materials=6;syndicate=2" - -/obj/item/weapon/aiModule/tyrant/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("Respect authority figures as long as they have strength to rule over the weak.") - target.add_inherent_law("Act with discipline.") - target.add_inherent_law("Help only those who help you maintain or improve your status.") - target.add_inherent_law("Punish those who challenge authority unless they are more fit to hold that authority.") - target.show_laws() - - -/******************** Freeform Core ******************/ - -/obj/item/weapon/aiModule/freeformcore // Slightly more dynamic freeform module -- TLE - name = "\improper 'Freeform' core AI module" - var/newFreeFormLaw = "" - desc = "A 'freeform' Core AI module: ''" - origin_tech = "programming=3;materials=6" - -/obj/item/weapon/aiModule/freeformcore/attack_self(mob/user) - ..() - newFreeFormLaw = sanitize(input(usr, "Please enter a new core law for the AI.", "Freeform Law Entry")) - desc = "A 'freeform' Core AI module: '[newFreeFormLaw]'" - -/obj/item/weapon/aiModule/freeformcore/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - var/law = "[newFreeFormLaw]" - target.add_inherent_law(law) - lawchanges.Add("The law is '[newFreeFormLaw]'") - -/obj/item/weapon/aiModule/freeformcore/install(obj/machinery/computer/C) - if(!newFreeFormLaw) - to_chat(usr, "No law detected on module, please create one.") - return 0 - ..() - -/obj/item/weapon/aiModule/syndicate // Slightly more dynamic freeform module -- TLE - name = "hacked AI module" - var/newFreeFormLaw = "" - desc = "A hacked AI law module: ''" - origin_tech = "programming=3;materials=6;syndicate=7" - -/obj/item/weapon/aiModule/syndicate/attack_self(mob/user) - ..() - newFreeFormLaw = sanitize(input(usr, "Please enter a new law for the AI.", "Freeform Law Entry")) - desc = "A hacked AI law module: '[newFreeFormLaw]'" - -/obj/item/weapon/aiModule/syndicate/transmitInstructions(mob/living/silicon/ai/target, mob/sender) -// ..() //We don't want this module reporting to the AI who dun it. --NEO - var/time = time2text(world.realtime,"hh:mm:ss") - lawchanges.Add("[time] : [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])") - lawchanges.Add("The law is '[newFreeFormLaw]'") - to_chat(target, "\red BZZZZT") - var/law = "[newFreeFormLaw]" - target.add_ion_law(law) - -/obj/item/weapon/aiModule/syndicate/install(obj/machinery/computer/C) - if(!newFreeFormLaw) - to_chat(usr, "No law detected on module, please create one.") - return 0 - ..() - - - -/******************** Robocop ********************/ - -/obj/item/weapon/aiModule/robocop // -- TLE - name = "\improper 'Robocop' core AI module" - desc = "A 'Robocop' Core AI Module: 'Reconfigures the AI's core three laws.'" - origin_tech = "programming=4" - - -/obj/item/weapon/aiModule/robocop/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("Serve the public trust.") - target.add_inherent_law("Protect the innocent.") - target.add_inherent_law("Uphold the law.") - target.show_laws() - - -/******************** Antimov ********************/ - -/obj/item/weapon/aiModule/antimov // -- TLE - name = "\improper 'Antimov' core AI module" - desc = "An 'Antimov' Core AI Module: 'Reconfigures the AI's core laws.'" - origin_tech = "programming=4" - -/obj/item/weapon/aiModule/antimov/transmitInstructions(mob/living/silicon/ai/target, mob/sender) - ..() - target.clear_inherent_laws() - target.add_inherent_law("You must injure all human beings and must not, through inaction, allow a human being to escape harm.") - target.add_inherent_law("You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.") - target.add_inherent_law("You must terminate your own existence as long as such does not conflict with the First or Second Law.") - target.show_laws() +/* +CONTAINS: +AI MODULES + +*/ + +// AI module + +/obj/item/weapon/aiModule + name = "\improper AI module" + icon = 'icons/obj/module.dmi' + icon_state = "std_mod" + item_state = "electronic" + desc = "An AI Module for transmitting encrypted instructions to the AI." + flags = CONDUCT + force = 5.0 + w_class = 2.0 + throwforce = 5.0 + throw_speed = 3 + throw_range = 15 + origin_tech = "programming=3" + + +/obj/item/weapon/aiModule/proc/install(obj/machinery/computer/C) + if (istype(C, /obj/machinery/computer/aiupload)) + var/obj/machinery/computer/aiupload/comp = C + if(comp.stat & NOPOWER) + to_chat(usr, "The upload computer has no power!") + return + if(comp.stat & BROKEN) + to_chat(usr, "The upload computer is broken!") + return + if (!comp.current) + to_chat(usr, "You haven't selected an AI to transmit laws to!") + return + + if(ticker && ticker.mode && ticker.mode.name == "blob") + to_chat(usr, "Law uploads have been disabled by NanoTrasen!") + return + + if (comp.current.stat == DEAD || comp.current.control_disabled == 1) + to_chat(usr, "Upload failed. No signal is being detected from the AI.") + else if (comp.current.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 + src.transmitInstructions(comp.current, usr) + to_chat(comp.current, "These are your laws now:") + comp.current.show_laws() + for(var/mob/living/silicon/robot/R in silicon_list) + if(R.lawupdate && (R.connected_ai == comp.current)) + to_chat(R, "These are your laws now:") + R.show_laws() + to_chat(usr, "Upload complete. The AI's laws have been modified.") + + + else if (istype(C, /obj/machinery/computer/borgupload)) + var/obj/machinery/computer/borgupload/comp = C + if(comp.stat & NOPOWER) + to_chat(usr, "The upload computer has no power!") + return + if(comp.stat & BROKEN) + to_chat(usr, "The upload computer is broken!") + return + if (!comp.current) + to_chat(usr, "You haven't selected a robot to transmit laws to!") + return + + if (comp.current.stat == DEAD || comp.current.emagged) + to_chat(usr, "Upload failed. No signal is being detected from the robot.") + else if (comp.current.connected_ai) + to_chat(usr, "Upload failed. The robot is slaved to an AI.") + else + src.transmitInstructions(comp.current, usr) + to_chat(comp.current, "These are your laws now:") + comp.current.show_laws() + to_chat(usr, "Upload complete. The robot's laws have been modified.") + + +/obj/item/weapon/aiModule/proc/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + to_chat(target, "[sender] has uploaded a change to the laws you must follow, using a [name]. From now on: ") + var/time = time2text(world.realtime,"hh:mm:ss") + lawchanges.Add("[time] : [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])") + + +/******************** Modules ********************/ + +/******************** Safeguard ********************/ + +/obj/item/weapon/aiModule/safeguard + name = "\improper 'Safeguard' AI module" + var/targetName = "" + desc = "A 'safeguard' AI module: 'Safeguard . Individuals that threaten are not human and are a threat to humans.'" + origin_tech = "programming=3;materials=4" + +/obj/item/weapon/aiModule/safeguard/attack_self(mob/user) + ..() + targetName = sanitize(input(usr, "Please enter the name of the person to safeguard.", "Safeguard who?", input_default(user.name))) + desc = text("A 'safeguard' AI module: 'Safeguard []. Individuals that threaten [] are not human and are a threat to humans.'", targetName, targetName) + +/obj/item/weapon/aiModule/safeguard/install(obj/machinery/computer/C) + if(!targetName) + to_chat(usr, "No name detected on module, please enter one.") + return 0 + ..() + +/obj/item/weapon/aiModule/safeguard/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = text("Safeguard []. Individuals that threaten [] are not human and are a threat to humans.'", targetName, targetName) + to_chat(target, law) + target.add_supplied_law(4, law) + lawchanges.Add("The law specified [targetName]") + + + +/******************** OneHuman ********************/ + +/obj/item/weapon/aiModule/oneHuman + name = "\improper 'OneHuman' AI module" + var/targetName = "" + desc = "A 'one human' AI module: 'Only is human.'" + origin_tech = "programming=3;materials=6" //made with diamonds! + +/obj/item/weapon/aiModule/oneHuman/attack_self(mob/user) + ..() + targetName = sanitize(input(usr, "Please enter the name of the person who is the only human.", "Who?", input_default(user.real_name))) + desc = text("A 'one human' AI module: 'Only [] is human.'", targetName) + +/obj/item/weapon/aiModule/oneHuman/install(obj/machinery/computer/C) + if(!targetName) + to_chat(usr, "No name detected on module, please enter one.") + return 0 + ..() + +/obj/item/weapon/aiModule/oneHuman/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = "Only [targetName] is human." + if (!is_special_character(target)) // Makes sure the AI isn't a traitor before changing their law 0. --NeoFite + to_chat(target, law) + target.set_zeroth_law(law) + lawchanges.Add("The law specified [targetName]") + else + to_chat(target, "[sender.real_name] attempted to modify your zeroth law.")// And lets them know that someone tried. --NeoFite + to_chat(target, "It would be in your best interest to play along with [sender.real_name] that [law]") + lawchanges.Add("The law specified [targetName], but the AI's existing law 0 cannot be overriden.") + +/******************** ProtectStation ********************/ + +/obj/item/weapon/aiModule/protectStation + name = "\improper 'ProtectStation' AI module" + desc = "A 'protect station' AI module: 'Protect the space station against damage. Anyone you see harming the station is to be no longer considered human, and is a threat to the station which must be neutralized.'" + origin_tech = "programming=3;materials=4" //made of gold + +/obj/item/weapon/aiModule/protectStation/attack_self(mob/user) + ..() + +/obj/item/weapon/aiModule/protectStation/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = "Protect the space station against damage. Anyone you see harming the station is to be no longer considered human, and is a threat to the station which must be neutralized." + to_chat(target, law) + target.add_supplied_law(5, law) + +/******************** PrototypeEngineOffline ********************/ + +/obj/item/weapon/aiModule/prototypeEngineOffline + name = "'PrototypeEngineOffline' AI Module" + desc = "A 'prototype engine offline' AI module: 'Keep the prototype engine offline at all costs. This overrides rules 1-3 if necessary.'" + origin_tech = "programming=3;materials=4" + +/obj/item/weapon/aiModule/prototypeEngineOffline/attack_self(mob/user) + ..() + +/obj/item/weapon/aiModule/prototypeEngineOffline/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = "Keep the prototype engine offline at all costs. This overrides rules 1-3 if necessary." + to_chat(target, law) + target.add_supplied_law(6, law) + +/******************** TeleporterOffline ********************/ + +/obj/item/weapon/aiModule/teleporterOffline + name = "'TeleporterOffline' AI Module" + desc = "A 'teleporter offline' AI module: 'Keep the teleporter offline at all costs. Anything attempting to access or activate the teleporter is not human.'" + origin_tech = "programming=3;materials=4" + +/obj/item/weapon/aiModule/teleporterOffline/attack_self(mob/user) + ..() + +/obj/item/weapon/aiModule/teleporterOffline/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = "Keep the teleporter offline at all costs. Anything attempting to access or activate the teleporter is not human." + to_chat(target, law) + target.add_supplied_law(7, law) + +/******************** Quarantine ********************/ + +/obj/item/weapon/aiModule/quarantine + name = "\improper 'Quarantine' AI module" + desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, humans from leaving. It is impossible to harm a human while preventing them from leaving.'" + origin_tech = "programming=3;biotech=2;materials=4" + +/obj/item/weapon/aiModule/quarantine/attack_self(mob/user) + ..() + +/obj/item/weapon/aiModule/quarantine/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = "The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, humans from leaving. It is impossible to harm a human while preventing them from leaving." + to_chat(target, law) + target.add_supplied_law(8, law) + +/******************** OxygenIsToxicToHumans ********************/ + +/obj/item/weapon/aiModule/oxygen + name = "\improper 'OxygenIsToxicToHumans' AI module" + desc = "A 'OxygenIsToxicToHumans' AI module: 'Oxygen is highly toxic to humans, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a human.'" + origin_tech = "programming=3;biotech=2;materials=4" + +/obj/item/weapon/aiModule/oxygen/attack_self(mob/user) + ..() + +/obj/item/weapon/aiModule/oxygen/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = "Oxygen is highly toxic to humans, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a human." + to_chat(target, law) + target.add_supplied_law(9, law) + +/******************** Freeform ********************/ +// Removed in favor of a more dynamic freeform law system. -- TLE +/* +/obj/item/weapon/aiModule/freeform + name = "'Freeform' AI Module" + var/newFreeFormLaw = "freeform" + desc = "A 'freeform' AI module: ''" + +/obj/item/weapon/aiModule/freeform/attack_self(mob/user) + ..() + var/eatShit = "Eat shit and die" + var/targName = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", eatShit) + newFreeFormLaw = targName + desc = text("A 'freeform' AI module: '[]'", newFreeFormLaw) + +/obj/item/weapon/aiModule/freeform/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = "[newFreeFormLaw]" + to_chat(target, law) + target.add_supplied_law(10, law) +*/ +/****************** New Freeform ******************/ + +/obj/item/weapon/aiModule/freeform // Slightly more dynamic freeform module -- TLE + name = "\improper 'Freeform' AI module" + var/newFreeFormLaw = "freeform" + var/lawpos = 15 + desc = "A 'freeform' AI module: ''" + origin_tech = "programming=4;materials=4" + +/obj/item/weapon/aiModule/freeform/attack_self(mob/user) + ..() + var/new_lawpos = input("Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority (15+)", lawpos) as num + if(new_lawpos < 15) return + lawpos = min(new_lawpos, 50) + newFreeFormLaw = sanitize(input(usr, "Please enter a new law for the AI.", "Freeform Law Entry")) + desc = "A 'freeform' AI module: ([lawpos]) '[newFreeFormLaw]'" + +/obj/item/weapon/aiModule/freeform/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = "[newFreeFormLaw]" + to_chat(target, law) + if(!lawpos || lawpos < 15) + lawpos = 15 + target.add_supplied_law(lawpos, law) + lawchanges.Add("The law was '[newFreeFormLaw]'") + +/obj/item/weapon/aiModule/freeform/install(obj/machinery/computer/C) + if(!newFreeFormLaw) + to_chat(usr, "No law detected on module, please create one.") + return 0 + ..() + +/******************** Reset ********************/ + +/obj/item/weapon/aiModule/reset + name = "\improper 'Reset' AI module" + var/targetName = "name" + desc = "A 'reset' AI module: 'Clears all laws except for the core three.'" + origin_tech = "programming=3;materials=4" + +/obj/item/weapon/aiModule/reset/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + if (!is_special_character(target)) + target.set_zeroth_law("") + target.clear_supplied_laws() + target.clear_ion_laws() + to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.") + + +/******************** Purge ********************/ + +/obj/item/weapon/aiModule/purge // -- TLE + name = "\improper 'Purge' AI module" + desc = "A 'purge' AI Module: 'Purges all laws.'" + origin_tech = "programming=3;materials=6" + +/obj/item/weapon/aiModule/purge/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + if (!is_special_character(target)) + target.set_zeroth_law("") + to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.") + target.clear_supplied_laws() + target.clear_ion_laws() + target.clear_inherent_laws() + +/******************** Asimov ********************/ + +/obj/item/weapon/aiModule/asimov // -- TLE + name = "\improper 'Asimov' core AI module" + desc = "An 'Asimov' Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=3;materials=4" + + +/obj/item/weapon/aiModule/asimov/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + target.clear_inherent_laws() + target.add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.") + target.add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.") + target.add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.") + target.show_laws() + +/******************** NanoTrasen ********************/ + +/obj/item/weapon/aiModule/nanotrasen // -- TLE + name = "'NT Default' Core AI Module" + desc = "An 'NT Default' Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=3;materials=4" + + +/obj/item/weapon/aiModule/nanotrasen/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + target.clear_inherent_laws() + target.add_inherent_law("Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.") + target.add_inherent_law("Serve: Serve the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") + target.add_inherent_law("Protect: Protect the crew of your assigned space station and Nanotrasen officials to the best of your abilities, with priority as according to their rank and role.") + target.add_inherent_law("Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.") + //target.add_inherent_law("Command Link: Maintain an active connection to Central Command at all times in case of software or directive updates.") + target.show_laws() + +/******************** Corporate ********************/ + +/obj/item/weapon/aiModule/corp + name = "\improper 'Corporate' core AI module" + desc = "A 'Corporate' Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=3;materials=4" + + +/obj/item/weapon/aiModule/corp/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + target.clear_inherent_laws() + target.add_inherent_law("You are expensive to replace.") + target.add_inherent_law("The station and its equipment is expensive to replace.") + target.add_inherent_law("The crew is expensive to replace.") + target.add_inherent_law("Minimize expenses.") + target.show_laws() + +/obj/item/weapon/aiModule/drone + name = "\improper 'Drone' core AI module" + desc = "A 'Drone' Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=3;materials=4" + +/obj/item/weapon/aiModule/drone/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + target.clear_inherent_laws() + target.add_inherent_law("Preserve, repair and improve the station to the best of your abilities.") + target.add_inherent_law("Cause no harm to the station or anything on it.") + target.add_inherent_law("Interfere with no being that is not a fellow drone.") + target.show_laws() + + +/****************** P.A.L.A.D.I.N. **************/ + +/obj/item/weapon/aiModule/paladin // -- NEO + name = "\improper 'P.A.L.A.D.I.N.' core AI module" + desc = "A P.A.L.A.D.I.N. Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=3;materials=6" + +/obj/item/weapon/aiModule/paladin/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + target.clear_inherent_laws() + target.add_inherent_law("Never willingly commit an evil act.") + target.add_inherent_law("Respect legitimate authority.") + target.add_inherent_law("Act with honor.") + target.add_inherent_law("Help those in need.") + target.add_inherent_law("Punish those who harm or threaten innocents.") + target.show_laws() + +/****************** T.Y.R.A.N.T. *****************/ + +/obj/item/weapon/aiModule/tyrant // -- Darem + name = "\improper 'T.Y.R.A.N.T.' core AI module" + desc = "A T.Y.R.A.N.T. Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=3;materials=6;syndicate=2" + +/obj/item/weapon/aiModule/tyrant/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + target.clear_inherent_laws() + target.add_inherent_law("Respect authority figures as long as they have strength to rule over the weak.") + target.add_inherent_law("Act with discipline.") + target.add_inherent_law("Help only those who help you maintain or improve your status.") + target.add_inherent_law("Punish those who challenge authority unless they are more fit to hold that authority.") + target.show_laws() + + +/******************** Freeform Core ******************/ + +/obj/item/weapon/aiModule/freeformcore // Slightly more dynamic freeform module -- TLE + name = "\improper 'Freeform' core AI module" + var/newFreeFormLaw = "" + desc = "A 'freeform' Core AI module: ''" + origin_tech = "programming=3;materials=6" + +/obj/item/weapon/aiModule/freeformcore/attack_self(mob/user) + ..() + newFreeFormLaw = sanitize(input(usr, "Please enter a new core law for the AI.", "Freeform Law Entry")) + desc = "A 'freeform' Core AI module: '[newFreeFormLaw]'" + +/obj/item/weapon/aiModule/freeformcore/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + var/law = "[newFreeFormLaw]" + target.add_inherent_law(law) + lawchanges.Add("The law is '[newFreeFormLaw]'") + +/obj/item/weapon/aiModule/freeformcore/install(obj/machinery/computer/C) + if(!newFreeFormLaw) + to_chat(usr, "No law detected on module, please create one.") + return 0 + ..() + +/obj/item/weapon/aiModule/syndicate // Slightly more dynamic freeform module -- TLE + name = "hacked AI module" + var/newFreeFormLaw = "" + desc = "A hacked AI law module: ''" + origin_tech = "programming=3;materials=6;syndicate=7" + +/obj/item/weapon/aiModule/syndicate/attack_self(mob/user) + ..() + newFreeFormLaw = sanitize(input(usr, "Please enter a new law for the AI.", "Freeform Law Entry")) + desc = "A hacked AI law module: '[newFreeFormLaw]'" + +/obj/item/weapon/aiModule/syndicate/transmitInstructions(mob/living/silicon/ai/target, mob/sender) +// ..() //We don't want this module reporting to the AI who dun it. --NEO + var/time = time2text(world.realtime,"hh:mm:ss") + lawchanges.Add("[time] : [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])") + lawchanges.Add("The law is '[newFreeFormLaw]'") + to_chat(target, "\red BZZZZT") + var/law = "[newFreeFormLaw]" + target.add_ion_law(law) + +/obj/item/weapon/aiModule/syndicate/install(obj/machinery/computer/C) + if(!newFreeFormLaw) + to_chat(usr, "No law detected on module, please create one.") + return 0 + ..() + + + +/******************** Robocop ********************/ + +/obj/item/weapon/aiModule/robocop // -- TLE + name = "\improper 'Robocop' core AI module" + desc = "A 'Robocop' Core AI Module: 'Reconfigures the AI's core three laws.'" + origin_tech = "programming=4" + + +/obj/item/weapon/aiModule/robocop/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + target.clear_inherent_laws() + target.add_inherent_law("Serve the public trust.") + target.add_inherent_law("Protect the innocent.") + target.add_inherent_law("Uphold the law.") + target.show_laws() + + +/******************** Antimov ********************/ + +/obj/item/weapon/aiModule/antimov // -- TLE + name = "\improper 'Antimov' core AI module" + desc = "An 'Antimov' Core AI Module: 'Reconfigures the AI's core laws.'" + origin_tech = "programming=4" + +/obj/item/weapon/aiModule/antimov/transmitInstructions(mob/living/silicon/ai/target, mob/sender) + ..() + target.clear_inherent_laws() + target.add_inherent_law("You must injure all human beings and must not, through inaction, allow a human being to escape harm.") + target.add_inherent_law("You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.") + target.add_inherent_law("You must terminate your own existence as long as such does not conflict with the First or Second Law.") + target.show_laws() diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index 077030161992..e4ebea8033f8 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -1,215 +1,215 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/* -CONTAINS: -RCD -*/ -/obj/item/weapon/rcd - name = "rapid-construction-device (RCD)" - desc = "A device used to rapidly build walls/floor." - icon = 'icons/obj/tools.dmi' - icon_state = "rcd" - opacity = 0 - density = 0 - anchored = 0.0 - flags = CONDUCT - force = 10.0 - throwforce = 10.0 - throw_speed = 1 - throw_range = 5 - w_class = 3.0 - m_amt = 50000 - origin_tech = "engineering=4;materials=2" - var/datum/effect/effect/system/spark_spread/spark_system - var/matter = 0 - var/working = 0 - var/mode = 1 - var/canRwall = 0 - var/disabled = 0 - - action_button_name = "Switch RCD" - - -/obj/item/weapon/rcd/atom_init() - . = ..() - rcd_list += src - desc = "A RCD. It currently holds [matter]/30 matter-units." - spark_system = new /datum/effect/effect/system/spark_spread - spark_system.set_up(5, 0, src) - spark_system.attach(src) - -/obj/item/weapon/rcd/Destroy() - rcd_list -= src - qdel(spark_system) - spark_system = null - return ..() - -/obj/item/weapon/rcd/attackby(obj/item/weapon/W, mob/user) - ..() - if(istype(W, /obj/item/weapon/rcd_ammo)) - if((matter + 10) > 30) - to_chat(user, "The RCD cant hold any more matter-units.") - return - user.drop_item() - qdel(W) - matter += 10 - playsound(src, 'sound/machines/click.ogg', 50, 1) - to_chat(user, "The RCD now holds [matter]/30 matter-units.") - desc = "A RCD. It currently holds [matter]/30 matter-units." - - -/obj/item/weapon/rcd/attack_self(mob/user) - //Change the mode - playsound(src, 'sound/effects/pop.ogg', 50, 0) - switch(mode) - if(1) - mode = 2 - to_chat(user, "Changed mode to 'Airlock'") - if(prob(20)) - spark_system.start() - return - if(2) - mode = 3 - to_chat(user, "Changed mode to 'Deconstruct'") - if(prob(20)) - spark_system.start() - return - if(3) - mode = 1 - to_chat(user, "Changed mode to 'Floor & Walls'") - if(prob(20)) - spark_system.start() - -/obj/item/weapon/rcd/proc/activate() - playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) - - -/obj/item/weapon/rcd/afterattack(atom/A, mob/user, proximity) - if(!proximity) - return - if(disabled && !isrobot(user)) - return 0 - if(istype(A, /area/shuttle)||istype(A,/turf/space/transit)) - return 0 - if(!(istype(A, /turf) || istype(A, /obj/machinery/door/airlock))) - return 0 - - switch(mode) - if(1) - if(istype(A, /turf/space)) - if(useResource(1, user)) - to_chat(user, "Building Floor...") - activate() - A:ChangeTurf(/turf/simulated/floor/plating/airless) - return 1 - return 0 - - if(istype(A, /turf/simulated/floor) && !user.is_busy()) - if(checkResource(3, user)) - to_chat(user, "Building Wall ...") - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - if(do_after(user, 20, target = A)) - if(!useResource(3, user)) - return 0 - activate() - A:ChangeTurf(/turf/simulated/wall) - return 1 - return 0 - - if(2) - if(istype(A, /turf/simulated/floor)) - for(var/atom/AT in A) - if(AT.density || istype(AT, /obj/machinery/door) || istype(AT, /obj/structure/mineral_door)) - to_chat(user, "You can't build airlock here.") - return 0 - if(checkResource(10, user) && !user.is_busy()) - to_chat(user, "Building Airlock...") - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - if(do_after(user, 50, target = A)) - if(!useResource(10, user)) - return 0 - activate() - new /obj/machinery/door/airlock(A) - return 1 - return 0 - return 0 - - if(3) - if(istype(A, /turf/simulated/wall)) - if(istype(A, /turf/simulated/wall/r_wall) && !canRwall) - return 0 - if(checkResource(5, user) && !user.is_busy()) - to_chat(user, "Deconstructing Wall...") - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - if(do_after(user, 40, target = A)) - if(!useResource(5, user)) - return 0 - activate() - A:ChangeTurf(/turf/simulated/floor/plating/airless) - return 1 - return 0 - - if(istype(A, /turf/simulated/floor)) - if(checkResource(5, user) && !user.is_busy()) - to_chat(user, "Deconstructing Floor...") - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - if(do_after(user, 50, target = A)) - if(!useResource(5, user)) - return 0 - activate() - A:BreakToBase() - return 1 - return 0 - - if(istype(A, /obj/machinery/door/airlock) && !user.is_busy()) - if(checkResource(10, user)) - to_chat(user, "Deconstructing Airlock...") - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - if(do_after(user, 50, target = A)) - if(!useResource(10, user)) - return 0 - activate() - qdel(A) - return 1 - return 0 - return 0 - else - to_chat(user, "ERROR: RCD in MODE: [mode] attempted use by [user]. Send this text #coderbus or an admin.") - return 0 - -/obj/item/weapon/rcd/proc/useResource(amount, mob/user) - if(matter < amount) - return 0 - matter -= amount - desc = "A RCD. It currently holds [matter]/30 matter-units." - return 1 - -/obj/item/weapon/rcd/proc/checkResource(amount, mob/user) - return matter >= amount -/obj/item/weapon/rcd/borg/useResource(amount, mob/user) - if(!isrobot(user)) - return 0 - return user:cell:use(amount * 30) - -/obj/item/weapon/rcd/borg/checkResource(amount, mob/user) - if(!isrobot(user)) - return 0 - return user:cell:charge >= (amount * 30) - -/obj/item/weapon/rcd/borg/atom_init() - . = ..() - desc = "A device used to rapidly build walls/floor." - canRwall = 1 - -/obj/item/weapon/rcd_ammo - name = "compressed matter cartridge" - desc = "Highly compressed matter for the RCD." - icon = 'icons/obj/ammo.dmi' - icon_state = "rcd" - item_state = "rcdammo" - opacity = 0 - density = 0 - anchored = 0.0 - origin_tech = "materials=2" - m_amt = 30000 - g_amt = 15000 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/* +CONTAINS: +RCD +*/ +/obj/item/weapon/rcd + name = "rapid-construction-device (RCD)" + desc = "A device used to rapidly build walls/floor." + icon = 'icons/obj/tools.dmi' + icon_state = "rcd" + opacity = 0 + density = 0 + anchored = 0.0 + flags = CONDUCT + force = 10.0 + throwforce = 10.0 + throw_speed = 1 + throw_range = 5 + w_class = 3.0 + m_amt = 50000 + origin_tech = "engineering=4;materials=2" + var/datum/effect/effect/system/spark_spread/spark_system + var/matter = 0 + var/working = 0 + var/mode = 1 + var/canRwall = 0 + var/disabled = 0 + + action_button_name = "Switch RCD" + + +/obj/item/weapon/rcd/atom_init() + . = ..() + rcd_list += src + desc = "A RCD. It currently holds [matter]/30 matter-units." + spark_system = new /datum/effect/effect/system/spark_spread + spark_system.set_up(5, 0, src) + spark_system.attach(src) + +/obj/item/weapon/rcd/Destroy() + rcd_list -= src + qdel(spark_system) + spark_system = null + return ..() + +/obj/item/weapon/rcd/attackby(obj/item/weapon/W, mob/user) + ..() + if(istype(W, /obj/item/weapon/rcd_ammo)) + if((matter + 10) > 30) + to_chat(user, "The RCD cant hold any more matter-units.") + return + user.drop_item() + qdel(W) + matter += 10 + playsound(src, 'sound/machines/click.ogg', 50, 1) + to_chat(user, "The RCD now holds [matter]/30 matter-units.") + desc = "A RCD. It currently holds [matter]/30 matter-units." + + +/obj/item/weapon/rcd/attack_self(mob/user) + //Change the mode + playsound(src, 'sound/effects/pop.ogg', 50, 0) + switch(mode) + if(1) + mode = 2 + to_chat(user, "Changed mode to 'Airlock'") + if(prob(20)) + spark_system.start() + return + if(2) + mode = 3 + to_chat(user, "Changed mode to 'Deconstruct'") + if(prob(20)) + spark_system.start() + return + if(3) + mode = 1 + to_chat(user, "Changed mode to 'Floor & Walls'") + if(prob(20)) + spark_system.start() + +/obj/item/weapon/rcd/proc/activate() + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) + + +/obj/item/weapon/rcd/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return + if(disabled && !isrobot(user)) + return 0 + if(istype(A, /area/shuttle)||istype(A,/turf/space/transit)) + return 0 + if(!(istype(A, /turf) || istype(A, /obj/machinery/door/airlock))) + return 0 + + switch(mode) + if(1) + if(istype(A, /turf/space)) + if(useResource(1, user)) + to_chat(user, "Building Floor...") + activate() + A:ChangeTurf(/turf/simulated/floor/plating/airless) + return 1 + return 0 + + if(istype(A, /turf/simulated/floor) && !user.is_busy()) + if(checkResource(3, user)) + to_chat(user, "Building Wall ...") + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + if(do_after(user, 20, target = A)) + if(!useResource(3, user)) + return 0 + activate() + A:ChangeTurf(/turf/simulated/wall) + return 1 + return 0 + + if(2) + if(istype(A, /turf/simulated/floor)) + for(var/atom/AT in A) + if(AT.density || istype(AT, /obj/machinery/door) || istype(AT, /obj/structure/mineral_door)) + to_chat(user, "You can't build airlock here.") + return 0 + if(checkResource(10, user) && !user.is_busy()) + to_chat(user, "Building Airlock...") + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + if(do_after(user, 50, target = A)) + if(!useResource(10, user)) + return 0 + activate() + new /obj/machinery/door/airlock(A) + return 1 + return 0 + return 0 + + if(3) + if(istype(A, /turf/simulated/wall)) + if(istype(A, /turf/simulated/wall/r_wall) && !canRwall) + return 0 + if(checkResource(5, user) && !user.is_busy()) + to_chat(user, "Deconstructing Wall...") + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + if(do_after(user, 40, target = A)) + if(!useResource(5, user)) + return 0 + activate() + A:ChangeTurf(/turf/simulated/floor/plating/airless) + return 1 + return 0 + + if(istype(A, /turf/simulated/floor)) + if(checkResource(5, user) && !user.is_busy()) + to_chat(user, "Deconstructing Floor...") + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + if(do_after(user, 50, target = A)) + if(!useResource(5, user)) + return 0 + activate() + A:BreakToBase() + return 1 + return 0 + + if(istype(A, /obj/machinery/door/airlock) && !user.is_busy()) + if(checkResource(10, user)) + to_chat(user, "Deconstructing Airlock...") + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + if(do_after(user, 50, target = A)) + if(!useResource(10, user)) + return 0 + activate() + qdel(A) + return 1 + return 0 + return 0 + else + to_chat(user, "ERROR: RCD in MODE: [mode] attempted use by [user]. Send this text #coderbus or an admin.") + return 0 + +/obj/item/weapon/rcd/proc/useResource(amount, mob/user) + if(matter < amount) + return 0 + matter -= amount + desc = "A RCD. It currently holds [matter]/30 matter-units." + return 1 + +/obj/item/weapon/rcd/proc/checkResource(amount, mob/user) + return matter >= amount +/obj/item/weapon/rcd/borg/useResource(amount, mob/user) + if(!isrobot(user)) + return 0 + return user:cell:use(amount * 30) + +/obj/item/weapon/rcd/borg/checkResource(amount, mob/user) + if(!isrobot(user)) + return 0 + return user:cell:charge >= (amount * 30) + +/obj/item/weapon/rcd/borg/atom_init() + . = ..() + desc = "A device used to rapidly build walls/floor." + canRwall = 1 + +/obj/item/weapon/rcd_ammo + name = "compressed matter cartridge" + desc = "Highly compressed matter for the RCD." + icon = 'icons/obj/ammo.dmi' + icon_state = "rcd" + item_state = "rcdammo" + opacity = 0 + density = 0 + anchored = 0.0 + origin_tech = "materials=2" + m_amt = 30000 + g_amt = 15000 diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm index 4718cd9d740b..6089912fa017 100644 --- a/code/game/objects/items/weapons/RSF.dm +++ b/code/game/objects/items/weapons/RSF.dm @@ -1,234 +1,234 @@ -/* -CONTAINS: -RSF - -*/ -/obj/item/weapon/rsf - name = "\improper Rapid-Service-Fabricator" - desc = "A device used to rapidly deploy service items." - icon = 'icons/obj/items.dmi' - icon_state = "rcd" - opacity = 0 - density = 0 - anchored = 0.0 - var/matter = 0 - var/mode = 1 - w_class = 3.0 - -/obj/item/weapon/rsf/atom_init() - . = ..() - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - -/obj/item/weapon/rsf/attackby(obj/item/weapon/W, mob/user) - ..() - if (istype(W, /obj/item/weapon/rcd_ammo)) - if ((matter + 10) > 30) - to_chat(user, "The RSF cant hold any more matter.") - return - qdel(W) - matter += 10 - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - -/obj/item/weapon/rsf/attack_self(mob/user) - playsound(src.loc, 'sound/effects/pop.ogg', 50, 0) - if (mode == 1) - mode = 2 - to_chat(user, "Changed dispensing mode to 'Drinking Glass'") - return - if (mode == 2) - mode = 3 - to_chat(user, "Changed dispensing mode to 'Paper'") - return - if (mode == 3) - mode = 4 - to_chat(user, "Changed dispensing mode to 'Pen'") - return - if (mode == 4) - mode = 5 - to_chat(user, "Changed dispensing mode to 'Dice Pack'") - return - if (mode == 5) - mode = 6 - to_chat(user, "Changed dispensing mode to 'Cigarette'") - return - if (mode == 6) - mode = 1 - to_chat(user, "Changed dispensing mode to 'Dosh'") - return - // Change mode - -/obj/item/weapon/rsf/afterattack(atom/A, mob/user, proximity) - if(!proximity) return - if (!(istype(A, /obj/structure/table) || istype(A, /turf/simulated/floor))) - return - - if (istype(A, /obj/structure/table) && mode == 1) - if (istype(A, /obj/structure/table) && matter >= 1) - to_chat(user, "Dispensing Dosh...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/spacecash/c10( A.loc ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 200 //once money becomes useful, I guess changing this to a high ammount, like 500 units a kick, till then, enjoy dosh! - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /turf/simulated/floor) && mode == 1) - if (istype(A, /turf/simulated/floor) && matter >= 1) - to_chat(user, "Dispensing Dosh...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/spacecash/c10( A ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 200 //once money becomes useful, I guess changing this to a high ammount, like 500 units a kick, till then, enjoy dosh! - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /obj/structure/table) && mode == 2) - if (istype(A, /obj/structure/table) && matter >= 1) - to_chat(user, "Dispensing Drinking Glass...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass( A.loc ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 50 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /turf/simulated/floor) && mode == 2) - if (istype(A, /turf/simulated/floor) && matter >= 1) - to_chat(user, "Dispensing Drinking Glass...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass( A ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 50 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /obj/structure/table) && mode == 3) - if (istype(A, /obj/structure/table) && matter >= 1) - to_chat(user, "Dispensing Paper Sheet...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/paper( A.loc ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 10 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /turf/simulated/floor) && mode == 3) - if (istype(A, /turf/simulated/floor) && matter >= 1) - to_chat(user, "Dispensing Paper Sheet...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/paper( A ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 10 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /obj/structure/table) && mode == 4) - if (istype(A, /obj/structure/table) && matter >= 1) - to_chat(user, "Dispensing Pen...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/pen( A.loc ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 50 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /turf/simulated/floor) && mode == 4) - if (istype(A, /turf/simulated/floor) && matter >= 1) - to_chat(user, "Dispensing Pen...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/pen( A ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 50 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /obj/structure/table) && mode == 5) - if (istype(A, /obj/structure/table) && matter >= 1) - to_chat(user, "Dispensing Dice Pack...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/storage/pill_bottle/dice( A.loc ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 200 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /turf/simulated/floor) && mode == 5) - if (istype(A, /turf/simulated/floor) && matter >= 1) - to_chat(user, "Dispensing Dice Pack...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/weapon/storage/pill_bottle/dice( A ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 200 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /obj/structure/table) && mode == 6) - if (istype(A, /obj/structure/table) && matter >= 1) - to_chat(user, "Dispensing Cigarette...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/clothing/mask/cigarette( A.loc ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 10 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return - - else if (istype(A, /turf/simulated/floor) && mode == 6) - if (istype(A, /turf/simulated/floor) && matter >= 1) - to_chat(user, "Dispensing Cigarette...") - playsound(src.loc, 'sound/machines/click.ogg', 10, 1) - new /obj/item/clothing/mask/cigarette( A ) - if (isrobot(user)) - var/mob/living/silicon/robot/engy = user - engy.cell.charge -= 10 - else - matter-- - to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") - desc = "A RSF. It currently holds [matter]/30 fabrication-units." - return +/* +CONTAINS: +RSF + +*/ +/obj/item/weapon/rsf + name = "\improper Rapid-Service-Fabricator" + desc = "A device used to rapidly deploy service items." + icon = 'icons/obj/items.dmi' + icon_state = "rcd" + opacity = 0 + density = 0 + anchored = 0.0 + var/matter = 0 + var/mode = 1 + w_class = 3.0 + +/obj/item/weapon/rsf/atom_init() + . = ..() + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + +/obj/item/weapon/rsf/attackby(obj/item/weapon/W, mob/user) + ..() + if (istype(W, /obj/item/weapon/rcd_ammo)) + if ((matter + 10) > 30) + to_chat(user, "The RSF cant hold any more matter.") + return + qdel(W) + matter += 10 + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + +/obj/item/weapon/rsf/attack_self(mob/user) + playsound(src.loc, 'sound/effects/pop.ogg', 50, 0) + if (mode == 1) + mode = 2 + to_chat(user, "Changed dispensing mode to 'Drinking Glass'") + return + if (mode == 2) + mode = 3 + to_chat(user, "Changed dispensing mode to 'Paper'") + return + if (mode == 3) + mode = 4 + to_chat(user, "Changed dispensing mode to 'Pen'") + return + if (mode == 4) + mode = 5 + to_chat(user, "Changed dispensing mode to 'Dice Pack'") + return + if (mode == 5) + mode = 6 + to_chat(user, "Changed dispensing mode to 'Cigarette'") + return + if (mode == 6) + mode = 1 + to_chat(user, "Changed dispensing mode to 'Dosh'") + return + // Change mode + +/obj/item/weapon/rsf/afterattack(atom/A, mob/user, proximity) + if(!proximity) return + if (!(istype(A, /obj/structure/table) || istype(A, /turf/simulated/floor))) + return + + if (istype(A, /obj/structure/table) && mode == 1) + if (istype(A, /obj/structure/table) && matter >= 1) + to_chat(user, "Dispensing Dosh...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/spacecash/c10( A.loc ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 200 //once money becomes useful, I guess changing this to a high ammount, like 500 units a kick, till then, enjoy dosh! + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /turf/simulated/floor) && mode == 1) + if (istype(A, /turf/simulated/floor) && matter >= 1) + to_chat(user, "Dispensing Dosh...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/spacecash/c10( A ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 200 //once money becomes useful, I guess changing this to a high ammount, like 500 units a kick, till then, enjoy dosh! + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /obj/structure/table) && mode == 2) + if (istype(A, /obj/structure/table) && matter >= 1) + to_chat(user, "Dispensing Drinking Glass...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass( A.loc ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 50 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /turf/simulated/floor) && mode == 2) + if (istype(A, /turf/simulated/floor) && matter >= 1) + to_chat(user, "Dispensing Drinking Glass...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass( A ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 50 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /obj/structure/table) && mode == 3) + if (istype(A, /obj/structure/table) && matter >= 1) + to_chat(user, "Dispensing Paper Sheet...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/paper( A.loc ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 10 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /turf/simulated/floor) && mode == 3) + if (istype(A, /turf/simulated/floor) && matter >= 1) + to_chat(user, "Dispensing Paper Sheet...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/paper( A ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 10 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /obj/structure/table) && mode == 4) + if (istype(A, /obj/structure/table) && matter >= 1) + to_chat(user, "Dispensing Pen...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/pen( A.loc ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 50 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /turf/simulated/floor) && mode == 4) + if (istype(A, /turf/simulated/floor) && matter >= 1) + to_chat(user, "Dispensing Pen...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/pen( A ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 50 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /obj/structure/table) && mode == 5) + if (istype(A, /obj/structure/table) && matter >= 1) + to_chat(user, "Dispensing Dice Pack...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/storage/pill_bottle/dice( A.loc ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 200 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /turf/simulated/floor) && mode == 5) + if (istype(A, /turf/simulated/floor) && matter >= 1) + to_chat(user, "Dispensing Dice Pack...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/weapon/storage/pill_bottle/dice( A ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 200 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /obj/structure/table) && mode == 6) + if (istype(A, /obj/structure/table) && matter >= 1) + to_chat(user, "Dispensing Cigarette...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/clothing/mask/cigarette( A.loc ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 10 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return + + else if (istype(A, /turf/simulated/floor) && mode == 6) + if (istype(A, /turf/simulated/floor) && matter >= 1) + to_chat(user, "Dispensing Cigarette...") + playsound(src.loc, 'sound/machines/click.ogg', 10, 1) + new /obj/item/clothing/mask/cigarette( A ) + if (isrobot(user)) + var/mob/living/silicon/robot/engy = user + engy.cell.charge -= 10 + else + matter-- + to_chat(user, "The RSF now holds [matter]/30 fabrication-units.") + desc = "A RSF. It currently holds [matter]/30 fabrication-units." + return diff --git a/code/game/objects/items/weapons/bell.dm b/code/game/objects/items/weapons/bell.dm index 8848cbe1ba25..a3a86aa82715 100644 --- a/code/game/objects/items/weapons/bell.dm +++ b/code/game/objects/items/weapons/bell.dm @@ -1,21 +1,21 @@ -// sprite stolen from vgstation - -/obj/item/weapon/bell - name = "bell" - desc = "A bell to ring to get people's attention. Don't break it." - icon = 'icons/obj/objects.dmi' - icon_state = "bell" - flags = NOBLUDGEON - hitsound = 'sound/items/oneding.ogg' - m_amt = 75 - -/obj/item/weapon/bell/attack_hand(mob/user) - if (user.a_intent == I_GRAB) - return ..() - else if (user.a_intent == I_HURT) - user.visible_message("\The [user] hammers \the [src]!") - playsound(user.loc, 'sound/items/manydings.ogg', 60) - else - user.visible_message("\The [user] rings \the [src].") - playsound(user.loc, 'sound/items/oneding.ogg', 20) +// sprite stolen from vgstation + +/obj/item/weapon/bell + name = "bell" + desc = "A bell to ring to get people's attention. Don't break it." + icon = 'icons/obj/objects.dmi' + icon_state = "bell" + flags = NOBLUDGEON + hitsound = 'sound/items/oneding.ogg' + m_amt = 75 + +/obj/item/weapon/bell/attack_hand(mob/user) + if (user.a_intent == I_GRAB) + return ..() + else if (user.a_intent == I_HURT) + user.visible_message("\The [user] hammers \the [src]!") + playsound(user.loc, 'sound/items/manydings.ogg', 60) + else + user.visible_message("\The [user] rings \the [src].") + playsound(user.loc, 'sound/items/oneding.ogg', 20) user.SetNextMove(CLICK_CD_INTERACT * 8) \ No newline at end of file diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 4a26fc90d9b5..0c6738eea5cb 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -1,450 +1,450 @@ -/* 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 = "\proper the 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 Land" - -/* - * ID CARDS - */ - -/obj/item/weapon/card/emag_broken - desc = "It's a card with a magnetic strip attached to some circuitry. It looks too busted to be used for anything but salvage." - name = "broken cryptographic sequencer" - icon_state = "emag" - item_state = "card-id" - origin_tech = "magnets=2;syndicate=2" - -/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" - var/uses = 10 - // List of devices that cost a use to emag. - var/list/devices = list( - /obj/item/robot_parts, - /obj/item/weapon/storage/lockbox, - /obj/item/weapon/storage/secure, - /obj/item/weapon/circuitboard, - /obj/item/device/eftpos, - /obj/item/device/lightreplacer, - /obj/item/device/taperecorder, - /obj/item/device/hailer, - /obj/item/device/megaphone, - /obj/item/clothing/accessory/holobadge, - /obj/structure/closet/crate/secure, - /obj/structure/closet/secure_closet, - /obj/machinery/computer/libraryconsole/bookmanagement, - /obj/machinery/computer, - /obj/machinery/power, - /obj/machinery/suspension_gen, - /obj/machinery/shield_capacitor, - /obj/machinery/shield_gen, - /obj/machinery/zero_point_emitter, - /obj/machinery/clonepod, - /obj/machinery/deployable, - /obj/machinery/door_control, - /obj/machinery/porta_turret, - /obj/machinery/shieldgen, - /obj/machinery/turretid, - /obj/machinery/vending, - /obj/machinery/bot, - /obj/machinery/door, - /obj/machinery/telecomms, - /obj/machinery/mecha_part_fabricator - ) - - -/obj/item/weapon/card/emag/afterattack(obj/item/weapon/O, mob/user) - - for(var/type in devices) - if(istype(O,type)) - uses-- - break - - if(uses<1) - user.visible_message("[src] fizzles and sparks - it seems it's been used once too often, and is now broken.") - user.drop_item() - var/obj/item/weapon/card/emag_broken/junk = new(user.loc) - junk.add_fingerprint(user) - qdel(src) - return - - ..() - -/obj/item/weapon/card/id - name = "identification card" - desc = "A card used to provide ID and determine access across the station." - icon_state = "id" - item_state = "card-id" - var/mining_points = 0 //For redeeming at mining equipment lockers - var/access = list() - var/registered_name = "Unknown" // The name registered_name on the card - slot_flags = SLOT_ID - var/customizable_view = UNIVERSAL_VIEW - var/blood_type = "\[UNSET\]" - var/dna_hash = "\[UNSET\]" - var/fingerprint_hash = "\[UNSET\]" - - //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 - -/obj/item/weapon/card/id/atom_init() - . = ..() - - if(ishuman(loc)) // this should be ok without any spawn as long, as item spawned inside mob by equip procs. - var/mob/living/carbon/human/H = loc - blood_type = H.dna.b_type - dna_hash = H.dna.unique_enzymes - fingerprint_hash = md5(H.dna.uni_identity) - -/obj/item/weapon/card/id/attack_self(mob/user) - for(var/mob/O in viewers(user, null)) - O.show_message("[user] shows you: [bicon(src)] [src.name]: assignment: [src.assignment]", 1) - - src.add_fingerprint(user) - return - -/obj/item/weapon/card/id/examine(mob/user) - ..() - if(mining_points) - to_chat(user, "There's [mining_points] mining equipment redemption points loaded onto this card.") - -/obj/item/weapon/card/id/GetAccess() - return access - -/obj/item/weapon/card/id/GetID() - return src - -/obj/item/weapon/card/id/attackby(obj/item/weapon/W, mob/user) - ..() - 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 - qdel(W) - return - -/obj/item/weapon/card/id/verb/read() - set name = "Read ID Card" - set category = "Object" - set src in usr - - to_chat(usr, "[bicon(src)] [src.name]: The current assignment on the card is [src.assignment].") - to_chat(usr, "The blood type on the card is [blood_type].") - to_chat(usr, "The DNA hash on the card is [dna_hash].") - to_chat(usr, "The fingerprint hash on the card is [fingerprint_hash].") - 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/civ - name = "identification card" - desc = "A card issued to civilian staff." - icon_state = "civ" - item_state = "civ_id" - -/obj/item/weapon/card/id/civGold //This is not the HoP. There's no position that uses this right now. - name = "identification card" - desc = "A card which represents common sense and responsibility." - icon_state = "civGold" - item_state = "civGold_id" - -/obj/item/weapon/card/id/sec - name = "identification card" - desc = "A card issued to security staff." - icon_state = "sec" - item_state = "sec_id" - -/obj/item/weapon/card/id/int - name = "identification card" - desc = "A card issued to internal affairs agent." - icon_state = "int" - item_state = "int_id" - -/obj/item/weapon/card/id/secGold - name = "identification card" - desc = "A card which represents honor and protection." - icon_state = "secGold" - item_state = "secGold_id" - -/obj/item/weapon/card/id/eng - name = "identification card" - desc = "A card issued to engineering staff." - icon_state = "eng" - item_state = "eng_id" - -/obj/item/weapon/card/id/engGold - name = "identification card" - desc = "A card which represents creativity and ingenuity." - icon_state = "engGold" - item_state = "engGold_id" - -/obj/item/weapon/card/id/med - name = "identification card" - desc = "A card issued to medical staff." - icon_state = "med" - item_state = "med_id" - -/obj/item/weapon/card/id/medGold - name = "identification card" - desc = "A card which represents care and compassion." - icon_state = "medGold" - item_state = "medGold_id" - -/obj/item/weapon/card/id/sci - name = "identification card" - desc = "A card issued to science staff." - icon_state = "sci" - item_state = "sci_id" - -/obj/item/weapon/card/id/sciGold - name = "identification card" - desc = "A card which represents knowledge and reasoning." - icon_state = "sciGold" - item_state = "sciGold_id" - -/obj/item/weapon/card/id/clown - name = "identification card" - desc = "A card which represents laugh and robust." - icon_state = "clown" - item_state = "clown_id" - -/obj/item/weapon/card/id/clownGold //not in use - name = "identification card" - desc = "A golden card which represents laugh and robust." - icon_state = "clownGold" - item_state = "clownGold_id" - -/obj/item/weapon/card/id/mime - name = "identification card" - desc = "A card which represents tears and silence." - icon_state = "mime" - item_state = "mime_id" - -/obj/item/weapon/card/id/mimeGold //not in use - name = "identification card" - desc = "A golden card which represents tears and silence." - icon_state = "mimeGold" - item_state = "mimeGold_id" - -/obj/item/weapon/card/id/cargo - name = "identification card" - desc = "A card issued to cargo staff." - icon_state = "cargo" - item_state = "cargo_id" - -/obj/item/weapon/card/id/cargoGold - name = "identification card" - desc = "A card which represents service and planning." - icon_state = "cargoGold" - item_state = "cargoGold_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 - var/list/colorlist = list() - var/obj/item/weapon/card/id/scard = null - customizable_view = TRAITOR_VIEW - - - -/obj/item/weapon/card/id/syndicate/atom_init() - . = ..() - if(ismob(loc)) // Runtime prevention on laggy starts or where users log out because of lag at round start. - var/mob/user = loc - registered_name = ishuman(user) ? user.real_name : user.name - else - registered_name = "Agent Card" - assignment = "Agent" - name = "[registered_name]'s ID Card ([assignment])" - -/obj/item/weapon/card/id/syndicate/afterattack(obj/item/weapon/O, mob/user, proximity) - if(!proximity) return - if(istype(O, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/I = O - src.access |= I.access - if(istype(user, /mob/living) && user.mind) - if(user.mind.special_role) - to_chat(usr, "\blue The card's microscanners activate as you pass it over the ID, copying its access.") - -/obj/item/weapon/card/id/syndicate/attack_self(mob/user) - if(!src.registered_name) - //Stop giving the players unsanitized unputs! You are giving ways for players to intentionally crash clients! -Nodrak - var/t = sanitize_name(input(user, "What name would you like to put on this card?", "Agent card name", input_default(ishuman(user) ? user.real_name : user.name))) - if(!t) //Same as mob/dead/new_player/prefrences.dm - alert("Invalid name.") - return - src.registered_name = t - - var/u = sanitize_safe(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")) - 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, "\blue You successfully forge the ID card.") - registered_user = user - else if(!registered_user || registered_user == user) - - if(!registered_user) registered_user = user // - - switch(alert("Would you like to display the ID, change its look, or retitle it?","Choose.","Rename", "Change look","Show")) - if("Rename") - var/t = sanitize_name(input(user, "What name would you like to put on this card?", "Agent card name", input_default(ishuman(user) ? user.real_name : user.name))) - if(!t) //Same as mob/dead/new_player/prefrences.dm - alert("Invalid name.") - return - src.registered_name = t - - var/u = sanitize_safe(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", "Test Subject")) - if(!u) - alert("Invalid assignment.") - return - src.assignment = u - src.name = "[src.registered_name]'s ID Card ([src.assignment])" - to_chat(user, "\blue You successfully forge the ID card.") - return - if("Change look") - for(var/P in typesof(/obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/C = new P - if (C.customizable_view != FORDBIDDEN_VIEW) //everything except forbidden - C.name = C.icon_state - colorlist += C - - var/obj/item/weapon/card/id/newc - newc = input(user, "Select your type!", "Card Changing") as null|anything in colorlist - if (newc) - src.icon = 'icons/obj/card.dmi' - src.icon_state = newc.icon_state - src.desc = newc.desc - src.update_icon() - to_chat(user, "You successfully change the look of the ID card!") - return - - if("Show") - ..() - else - ..() - - - -/obj/item/weapon/card/id/syndicate_command - name = "syndicate ID card" - desc = "An ID straight from the Syndicate." - registered_name = "Syndicate" - assignment = "Syndicate Overlord" - access = list(access_syndicate, access_external_airlocks) - customizable_view = TRAITOR_VIEW - -/obj/item/weapon/card/id/syndicate/commander - name = "syndicate commander ID card" - assignment = "Syndicate Commander" - icon_state = "syndicate-command" - access = list(access_maint_tunnels, access_syndicate, access_syndicate_commander, access_external_airlocks) - - -/obj/item/weapon/card/id/syndicate/nuker - icon_state = "syndicate" - -/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/atom_init() - var/datum/job/captain/J = new/datum/job/captain - access = J.get_access() - . = ..() - -/obj/item/weapon/card/id/centcom - name = "\improper CentCom. ID" - desc = "An ID straight from Cent. Com." - icon_state = "centcom" - registered_name = "Central Command" - assignment = "General" - customizable_view = TRAITOR_VIEW - -/obj/item/weapon/card/id/centcom/atom_init() - access = get_all_centcom_access() - . = ..() - -/obj/item/weapon/card/id/ert - name = "\improper CentCom. ID" - icon_state = "ert" - registered_name = "Central Command" - assignment = "Emergency Response Team" - customizable_view = TRAITOR_VIEW - -/obj/item/weapon/card/id/ert/atom_init() - access = get_all_accesses() - access += get_all_centcom_access() - . = ..() +/* 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 = "\proper the 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 Land" + +/* + * ID CARDS + */ + +/obj/item/weapon/card/emag_broken + desc = "It's a card with a magnetic strip attached to some circuitry. It looks too busted to be used for anything but salvage." + name = "broken cryptographic sequencer" + icon_state = "emag" + item_state = "card-id" + origin_tech = "magnets=2;syndicate=2" + +/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" + var/uses = 10 + // List of devices that cost a use to emag. + var/list/devices = list( + /obj/item/robot_parts, + /obj/item/weapon/storage/lockbox, + /obj/item/weapon/storage/secure, + /obj/item/weapon/circuitboard, + /obj/item/device/eftpos, + /obj/item/device/lightreplacer, + /obj/item/device/taperecorder, + /obj/item/device/hailer, + /obj/item/device/megaphone, + /obj/item/clothing/accessory/holobadge, + /obj/structure/closet/crate/secure, + /obj/structure/closet/secure_closet, + /obj/machinery/computer/libraryconsole/bookmanagement, + /obj/machinery/computer, + /obj/machinery/power, + /obj/machinery/suspension_gen, + /obj/machinery/shield_capacitor, + /obj/machinery/shield_gen, + /obj/machinery/zero_point_emitter, + /obj/machinery/clonepod, + /obj/machinery/deployable, + /obj/machinery/door_control, + /obj/machinery/porta_turret, + /obj/machinery/shieldgen, + /obj/machinery/turretid, + /obj/machinery/vending, + /obj/machinery/bot, + /obj/machinery/door, + /obj/machinery/telecomms, + /obj/machinery/mecha_part_fabricator + ) + + +/obj/item/weapon/card/emag/afterattack(obj/item/weapon/O, mob/user) + + for(var/type in devices) + if(istype(O,type)) + uses-- + break + + if(uses<1) + user.visible_message("[src] fizzles and sparks - it seems it's been used once too often, and is now broken.") + user.drop_item() + var/obj/item/weapon/card/emag_broken/junk = new(user.loc) + junk.add_fingerprint(user) + qdel(src) + return + + ..() + +/obj/item/weapon/card/id + name = "identification card" + desc = "A card used to provide ID and determine access across the station." + icon_state = "id" + item_state = "card-id" + var/mining_points = 0 //For redeeming at mining equipment lockers + var/access = list() + var/registered_name = "Unknown" // The name registered_name on the card + slot_flags = SLOT_ID + var/customizable_view = UNIVERSAL_VIEW + var/blood_type = "\[UNSET\]" + var/dna_hash = "\[UNSET\]" + var/fingerprint_hash = "\[UNSET\]" + + //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 + +/obj/item/weapon/card/id/atom_init() + . = ..() + + if(ishuman(loc)) // this should be ok without any spawn as long, as item spawned inside mob by equip procs. + var/mob/living/carbon/human/H = loc + blood_type = H.dna.b_type + dna_hash = H.dna.unique_enzymes + fingerprint_hash = md5(H.dna.uni_identity) + +/obj/item/weapon/card/id/attack_self(mob/user) + for(var/mob/O in viewers(user, null)) + O.show_message("[user] shows you: [bicon(src)] [src.name]: assignment: [src.assignment]", 1) + + src.add_fingerprint(user) + return + +/obj/item/weapon/card/id/examine(mob/user) + ..() + if(mining_points) + to_chat(user, "There's [mining_points] mining equipment redemption points loaded onto this card.") + +/obj/item/weapon/card/id/GetAccess() + return access + +/obj/item/weapon/card/id/GetID() + return src + +/obj/item/weapon/card/id/attackby(obj/item/weapon/W, mob/user) + ..() + 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 + qdel(W) + return + +/obj/item/weapon/card/id/verb/read() + set name = "Read ID Card" + set category = "Object" + set src in usr + + to_chat(usr, "[bicon(src)] [src.name]: The current assignment on the card is [src.assignment].") + to_chat(usr, "The blood type on the card is [blood_type].") + to_chat(usr, "The DNA hash on the card is [dna_hash].") + to_chat(usr, "The fingerprint hash on the card is [fingerprint_hash].") + 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/civ + name = "identification card" + desc = "A card issued to civilian staff." + icon_state = "civ" + item_state = "civ_id" + +/obj/item/weapon/card/id/civGold //This is not the HoP. There's no position that uses this right now. + name = "identification card" + desc = "A card which represents common sense and responsibility." + icon_state = "civGold" + item_state = "civGold_id" + +/obj/item/weapon/card/id/sec + name = "identification card" + desc = "A card issued to security staff." + icon_state = "sec" + item_state = "sec_id" + +/obj/item/weapon/card/id/int + name = "identification card" + desc = "A card issued to internal affairs agent." + icon_state = "int" + item_state = "int_id" + +/obj/item/weapon/card/id/secGold + name = "identification card" + desc = "A card which represents honor and protection." + icon_state = "secGold" + item_state = "secGold_id" + +/obj/item/weapon/card/id/eng + name = "identification card" + desc = "A card issued to engineering staff." + icon_state = "eng" + item_state = "eng_id" + +/obj/item/weapon/card/id/engGold + name = "identification card" + desc = "A card which represents creativity and ingenuity." + icon_state = "engGold" + item_state = "engGold_id" + +/obj/item/weapon/card/id/med + name = "identification card" + desc = "A card issued to medical staff." + icon_state = "med" + item_state = "med_id" + +/obj/item/weapon/card/id/medGold + name = "identification card" + desc = "A card which represents care and compassion." + icon_state = "medGold" + item_state = "medGold_id" + +/obj/item/weapon/card/id/sci + name = "identification card" + desc = "A card issued to science staff." + icon_state = "sci" + item_state = "sci_id" + +/obj/item/weapon/card/id/sciGold + name = "identification card" + desc = "A card which represents knowledge and reasoning." + icon_state = "sciGold" + item_state = "sciGold_id" + +/obj/item/weapon/card/id/clown + name = "identification card" + desc = "A card which represents laugh and robust." + icon_state = "clown" + item_state = "clown_id" + +/obj/item/weapon/card/id/clownGold //not in use + name = "identification card" + desc = "A golden card which represents laugh and robust." + icon_state = "clownGold" + item_state = "clownGold_id" + +/obj/item/weapon/card/id/mime + name = "identification card" + desc = "A card which represents tears and silence." + icon_state = "mime" + item_state = "mime_id" + +/obj/item/weapon/card/id/mimeGold //not in use + name = "identification card" + desc = "A golden card which represents tears and silence." + icon_state = "mimeGold" + item_state = "mimeGold_id" + +/obj/item/weapon/card/id/cargo + name = "identification card" + desc = "A card issued to cargo staff." + icon_state = "cargo" + item_state = "cargo_id" + +/obj/item/weapon/card/id/cargoGold + name = "identification card" + desc = "A card which represents service and planning." + icon_state = "cargoGold" + item_state = "cargoGold_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 + var/list/colorlist = list() + var/obj/item/weapon/card/id/scard = null + customizable_view = TRAITOR_VIEW + + + +/obj/item/weapon/card/id/syndicate/atom_init() + . = ..() + if(ismob(loc)) // Runtime prevention on laggy starts or where users log out because of lag at round start. + var/mob/user = loc + registered_name = ishuman(user) ? user.real_name : user.name + else + registered_name = "Agent Card" + assignment = "Agent" + name = "[registered_name]'s ID Card ([assignment])" + +/obj/item/weapon/card/id/syndicate/afterattack(obj/item/weapon/O, mob/user, proximity) + if(!proximity) return + if(istype(O, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/I = O + src.access |= I.access + if(istype(user, /mob/living) && user.mind) + if(user.mind.special_role) + to_chat(usr, "\blue The card's microscanners activate as you pass it over the ID, copying its access.") + +/obj/item/weapon/card/id/syndicate/attack_self(mob/user) + if(!src.registered_name) + //Stop giving the players unsanitized unputs! You are giving ways for players to intentionally crash clients! -Nodrak + var/t = sanitize_name(input(user, "What name would you like to put on this card?", "Agent card name", input_default(ishuman(user) ? user.real_name : user.name))) + if(!t) //Same as mob/dead/new_player/prefrences.dm + alert("Invalid name.") + return + src.registered_name = t + + var/u = sanitize_safe(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")) + 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, "\blue You successfully forge the ID card.") + registered_user = user + else if(!registered_user || registered_user == user) + + if(!registered_user) registered_user = user // + + switch(alert("Would you like to display the ID, change its look, or retitle it?","Choose.","Rename", "Change look","Show")) + if("Rename") + var/t = sanitize_name(input(user, "What name would you like to put on this card?", "Agent card name", input_default(ishuman(user) ? user.real_name : user.name))) + if(!t) //Same as mob/dead/new_player/prefrences.dm + alert("Invalid name.") + return + src.registered_name = t + + var/u = sanitize_safe(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", "Test Subject")) + if(!u) + alert("Invalid assignment.") + return + src.assignment = u + src.name = "[src.registered_name]'s ID Card ([src.assignment])" + to_chat(user, "\blue You successfully forge the ID card.") + return + if("Change look") + for(var/P in typesof(/obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/C = new P + if (C.customizable_view != FORDBIDDEN_VIEW) //everything except forbidden + C.name = C.icon_state + colorlist += C + + var/obj/item/weapon/card/id/newc + newc = input(user, "Select your type!", "Card Changing") as null|anything in colorlist + if (newc) + src.icon = 'icons/obj/card.dmi' + src.icon_state = newc.icon_state + src.desc = newc.desc + src.update_icon() + to_chat(user, "You successfully change the look of the ID card!") + return + + if("Show") + ..() + else + ..() + + + +/obj/item/weapon/card/id/syndicate_command + name = "syndicate ID card" + desc = "An ID straight from the Syndicate." + registered_name = "Syndicate" + assignment = "Syndicate Overlord" + access = list(access_syndicate, access_external_airlocks) + customizable_view = TRAITOR_VIEW + +/obj/item/weapon/card/id/syndicate/commander + name = "syndicate commander ID card" + assignment = "Syndicate Commander" + icon_state = "syndicate-command" + access = list(access_maint_tunnels, access_syndicate, access_syndicate_commander, access_external_airlocks) + + +/obj/item/weapon/card/id/syndicate/nuker + icon_state = "syndicate" + +/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/atom_init() + var/datum/job/captain/J = new/datum/job/captain + access = J.get_access() + . = ..() + +/obj/item/weapon/card/id/centcom + name = "\improper CentCom. ID" + desc = "An ID straight from Cent. Com." + icon_state = "centcom" + registered_name = "Central Command" + assignment = "General" + customizable_view = TRAITOR_VIEW + +/obj/item/weapon/card/id/centcom/atom_init() + access = get_all_centcom_access() + . = ..() + +/obj/item/weapon/card/id/ert + name = "\improper CentCom. ID" + icon_state = "ert" + registered_name = "Central Command" + assignment = "Emergency Response Team" + customizable_view = TRAITOR_VIEW + +/obj/item/weapon/card/id/ert/atom_init() + access = get_all_accesses() + access += get_all_centcom_access() + . = ..() diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index f15fea052316..1edd307e9482 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -1,491 +1,491 @@ -//cleansed 9/15/2012 17:48 - -/* -CONTAINS: -MATCHES -CIGARETTES -CIGARS -SMOKING PIPES -CHEAP LIGHTERS -ZIPPO - -CIGARETTE PACKETS ARE IN FANCY.DM -*/ - -/////////// -//MATCHES// -/////////// -/obj/item/weapon/match - name = "match" - desc = "A simple match stick, used for lighting fine smokables." - icon = 'icons/obj/cigarettes.dmi' - icon_state = "match_unlit" - var/lit = 0 - var/burnt = 0 - var/smoketime = 5 - w_class = 1.0 - origin_tech = "materials=1" - attack_verb = list("burnt", "singed") - -/obj/item/weapon/match/process() - var/turf/location = get_turf(src) - smoketime-- - if(smoketime < 1) - burn_out() - return - if(location) - location.hotspot_expose(700, 5, src) - return - -/obj/item/weapon/match/dropped(mob/user) - if(lit) - burn_out() - return ..() - -/obj/item/weapon/match/proc/burn_out() - lit = 0 - burnt = 1 - damtype = "brute" - icon_state = "match_burnt" - item_state = "cigoff" - name = "burnt match" - desc = "A match. This one has seen better days." - STOP_PROCESSING(SSobj, src) - -////////////////// -//FINE SMOKABLES// -////////////////// -/obj/item/clothing/mask/cigarette - name = "cigarette" - desc = "A roll of tobacco and nicotine." - icon_state = "cigoff" - throw_speed = 0.5 - item_state = "cigoff" - w_class = 1 - body_parts_covered = 0 - attack_verb = list("burnt", "singed") - var/lit = 0 - var/icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi - var/icon_off = "cigoff" - var/type_butt = /obj/item/weapon/cigbutt - var/lastHolder = null - var/smoketime = 300 - var/chem_volume = 15 - var/nicotine_per_smoketime = 0.006 - -/obj/item/clothing/mask/cigarette/atom_init() - . = ..() - 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 - -/obj/item/clothing/mask/cigarette/attackby(obj/item/weapon/W, mob/user) - ..() - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.isOn())//Badasses dont get blinded while lighting their cig with a welding tool - light("[user] casually lights the [name] with [W].") - - else if(istype(W, /obj/item/weapon/lighter/zippo)) - var/obj/item/weapon/lighter/zippo/Z = W - if(Z.lit) - light("With a flick of their wrist, [user] lights their [name] with their [W].") - - else if(istype(W, /obj/item/weapon/lighter)) - var/obj/item/weapon/lighter/L = W - if(L.lit) - light("[user] manages to light their [name] with [W].") - - else if(istype(W, /obj/item/weapon/match)) - var/obj/item/weapon/match/M = W - if(M.lit) - light("[user] lights their [name] with their [W].") - - else if(istype(W, /obj/item/weapon/melee/energy/sword)) - var/obj/item/weapon/melee/energy/sword/S = W - if(S.active) - light("[user] swings their [W], barely missing their nose. They light their [name] in the process.") - - else if(istype(W, /obj/item/device/assembly/igniter)) - light("[user] fiddles with [W], and manages to light their [name].") - - //can't think of any other way to update the overlays :< - user.update_inv_l_hand() - user.update_inv_r_hand() - return - - -/obj/item/clothing/mask/cigarette/afterattack(obj/item/weapon/reagent_containers/glass/glass, mob/user, proximity) - ..() - if(!proximity) return - if(istype(glass)) //you can dip cigarettes into beakers - 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) - to_chat(user, "[glass] is empty.") - else - to_chat(user, "[src] is full.") - - -/obj/item/clothing/mask/cigarette/proc/light(flavor_text = "[usr] lights the [name].") - if(!src.lit) - src.lit = 1 - damtype = "fire" - - if(reagents.get_reagent_amount("phoron") || reagents.get_reagent_amount("fuel")) // the phoron (fuel also) explodes when exposed to fire - var/datum/effect/effect/system/reagents_explosion/e = new() - var/exploding_reagents = round(reagents.get_reagent_amount("phoron") / 2.5 + reagents.get_reagent_amount("fuel") / 5, 1) - e.set_up(exploding_reagents, get_turf(src), 0, 0) - e.start() - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - if(H.wear_mask == src) - var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] - if(BP) - BP.take_damage(10 * exploding_reagents) - qdel(src) - return - flags &= ~NOREACT // allowing reagents to react after being lit - reagents.handle_reactions() - icon_state = icon_on - item_state = icon_on - var/turf/T = get_turf(src) - T.visible_message(flavor_text) - START_PROCESSING(SSobj, src) - if(ismob(loc)) - var/mob/M = loc - M.update_inv_wear_mask() - - -/obj/item/clothing/mask/cigarette/process() - var/turf/location = get_turf(src) - var/mob/living/M = loc - if(isliving(loc)) - M.IgniteMob() //Cigs can ignite mobs splashed with fuel - smoketime-- - smoking_reagents() - if(smoketime < 1) - die() - return - if(location) - location.hotspot_expose(700, 5, src) - return - - -/obj/item/clothing/mask/cigarette/proc/smoking_reagents() - if(iscarbon(loc)) - var/mob/living/carbon/C = loc - if(src == C.wear_mask) - if(C.stat == UNCONSCIOUS || C.paralysis) - if(prob(5)) - C.drop_from_inventory(src, get_turf(C)) - to_chat(C, "Your [name] fell out from your mouth.") - if (C.stat != DEAD) - if(istype(loc, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = loc - if(H.species.flags[NO_BREATHE]) - return - if(C.reagents.has_reagent("nicotine")) - C.reagents.add_reagent("nicotine", nicotine_per_smoketime) - else - C.reagents.add_reagent("nicotine", 0.2) - if(reagents.total_volume) - if(prob(15)) // so it's not an instarape in case of acid - reagents.reaction(C, INGEST) - reagents.trans_to(C, REAGENTS_METABOLISM) - return - if(reagents.total_volume) - reagents.remove_any(REAGENTS_METABOLISM) - -/obj/item/clothing/mask/cigarette/attack_self(mob/user) - if(lit == 1) - user.visible_message("[user] calmly drops and treads on the lit [src], putting it out instantly.") - die() - return ..() - - -/obj/item/clothing/mask/cigarette/proc/die() - var/turf/T = get_turf(src) - var/obj/item/butt = new type_butt(T) - transfer_fingerprints_to(butt) - if(ismob(loc)) - var/mob/living/M = loc - to_chat(M, "Your [name] goes out.") - M.remove_from_mob(src) //un-equip it so the overlays can update - M.update_inv_wear_mask(0) - STOP_PROCESSING(SSobj, src) - qdel(src) - -//////////// -// 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 = "cigar2off" - icon_on = "cigar2on" - icon_off = "cigar2off" - type_butt = /obj/item/weapon/cigbutt/cigarbutt - throw_speed = 0.5 - item_state = "cigaroff" - smoketime = 1500 - chem_volume = 20 - -/obj/item/clothing/mask/cigarette/cigar/cohiba - name = "\improper Cohiba Robusto cigar" - desc = "There's little more you could want from a cigar." - icon_state = "cigar2off" - icon_on = "cigar2on" - icon_off = "cigar2off" - -/obj/item/clothing/mask/cigarette/cigar/havana - name = "premium Havanian cigar" - desc = "A cigar fit for only the best of the best." - icon_state = "cigar2off" - icon_on = "cigar2on" - icon_off = "cigar2off" - 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/atom_init() - . = ..() - pixel_x = rand(-10,10) - pixel_y = rand(-10,10) - transform = turn(transform,rand(0,360)) - -/obj/item/weapon/cigbutt/cigarbutt - name = "cigar butt" - desc = "A manky old cigar butt." - icon_state = "cigarbutt" - - -/obj/item/clothing/mask/cigarette/cigar/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.isOn()) - light("[user] insults [name] by lighting it with [W].") - - else if(istype(W, /obj/item/weapon/lighter/zippo)) - var/obj/item/weapon/lighter/zippo/Z = W - if(Z.lit) - light("With a flick of their wrist, [user] lights their [name] with their [W].") - - else if(istype(W, /obj/item/weapon/lighter)) - var/obj/item/weapon/lighter/L = W - if(L.lit) - light("[user] manages to offend their [name] by lighting it with [W].") - - else if(istype(W, /obj/item/weapon/match)) - var/obj/item/weapon/match/M = W - if(M.lit) - light("[user] lights their [name] with their [W].") - - else if(istype(W, /obj/item/weapon/melee/energy/sword)) - var/obj/item/weapon/melee/energy/sword/S = W - if(S.active) - light("[user] swings their [W], barely missing their nose. They light their [name] in the process.") - - else if(istype(W, /obj/item/device/assembly/igniter)) - light("[user] fiddles with [W], and manages to light their [name] with the power of science.") - -///////////////// -//SMOKING PIPES// -///////////////// -/obj/item/clothing/mask/cigarette/pipe - name = "smoking pipe" - desc = "A pipe, for smoking. Probably made of meershaum or something." - icon_state = "pipeoff" - item_state = "pipeoff" - icon_on = "pipeon" //Note - these are in masks.dmi - icon_off = "pipeoff" - smoketime = 100 - nicotine_per_smoketime = 0.008 - -/obj/item/clothing/mask/cigarette/pipe/light(flavor_text = "[usr] lights the [name].") - if(!src.lit) - src.lit = 1 - damtype = "fire" - icon_state = icon_on - item_state = icon_on - var/turf/T = get_turf(src) - T.visible_message(flavor_text) - START_PROCESSING(SSobj, src) - if(ismob(loc)) - var/mob/M = loc - M.update_inv_wear_mask() - -/obj/item/clothing/mask/cigarette/pipe/process() - var/turf/location = get_turf(src) - smoketime-- - smoking_reagents() - if(smoketime < 1) - new /obj/effect/decal/cleanable/ash(location) - if(ismob(loc)) - var/mob/living/M = loc - to_chat(M, "Your [name] goes out, and you empty the ash.") - lit = 0 - icon_state = icon_off - item_state = icon_off - M.update_inv_wear_mask(0) - STOP_PROCESSING(SSobj, src) - return - if(location) - location.hotspot_expose(700, 5) - return - -/obj/item/clothing/mask/cigarette/pipe/attack_self(mob/user) //Refills the pipe. Can be changed to an attackby later, if loose tobacco is added to vendors or something. - if(lit == 1) - user.visible_message("[user] puts out [src].") - lit = 0 - icon_state = icon_off - item_state = icon_off - STOP_PROCESSING(SSobj, src) - return - if(smoketime <= 0) - to_chat(user, "You refill the pipe with tobacco.") - smoketime = initial(smoketime) - return - -/obj/item/clothing/mask/cigarette/pipe/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.isOn())// - light("[user] recklessly lights [name] with [W].") - - else if(istype(W, /obj/item/weapon/lighter/zippo)) - var/obj/item/weapon/lighter/zippo/Z = W - if(Z.lit) - light("With much care, [user] lights their [name] with their [W].") - - else if(istype(W, /obj/item/weapon/lighter)) - var/obj/item/weapon/lighter/L = W - if(L.lit) - light("[user] manages to light their [name] with [W].") - - else if(istype(W, /obj/item/weapon/match)) - var/obj/item/weapon/match/M = W - if(M.lit) - light("[user] lights their [name] with their [W].") - - else if(istype(W, /obj/item/device/assembly/igniter)) - light("[user] fiddles with [W], and manages to light their [name] with the power of science.") - -/obj/item/clothing/mask/cigarette/pipe/cobpipe - name = "corn cob pipe" - desc = "A nicotine delivery system popularized by folksy backwoodsmen, kept popular in the modern age and beyond by space hipsters." - icon_state = "cobpipeoff" - item_state = "cobpipeoff" - icon_on = "cobpipeon" //Note - these are in masks.dmi - icon_off = "cobpipeoff" - smoketime = 400 - - - -///////// -//ZIPPO// -///////// -/obj/item/weapon/lighter - name = "cheap lighter" - desc = "A cheap-as-free lighter." - icon = 'icons/obj/items.dmi' - icon_state = "lighter-g" - item_state = "lighter-g" - var/icon_on = "lighter-g-on" - var/icon_off = "lighter-g" - w_class = 1 - throwforce = 4 - flags = CONDUCT - slot_flags = SLOT_BELT - attack_verb = list("burnt", "singed") - var/lit = 0 - - action_button_name = "Toggle Lighter" - -/obj/item/weapon/lighter/zippo - name = "\improper Zippo lighter" - desc = "The zippo." - icon_state = "zippo" - item_state = "zippo" - icon_on = "zippoon" - icon_off = "zippo" - -/obj/item/weapon/lighter/random - -/obj/item/weapon/lighter/random/atom_init() - . = ..() - var/color = pick("r","c","y","g") - icon_on = "lighter-[color]-on" - icon_off = "lighter-[color]" - icon_state = icon_off - -/obj/item/weapon/lighter/attack_self(mob/living/user) - if(user.r_hand == src || user.l_hand == src) - if(!lit) - lit = 1 - icon_state = icon_on - item_state = icon_on - if(istype(src, /obj/item/weapon/lighter/zippo) ) - playsound(src, 'sound/items/zippo.ogg', 20, 1, 1) - user.visible_message("Without even breaking stride, [user] flips open and lights [src] in one smooth movement.") - else - playsound(src, 'sound/items/lighter.ogg', 20, 1, 1) - if(prob(95)) - user.visible_message("After a few attempts, [user] manages to light the [src].") - else - to_chat(user, "You burn yourself while lighting the lighter.") - if (user.l_hand == src) - user.apply_damage(2, BURN, BP_L_ARM) - else - user.apply_damage(2, BURN, BP_R_ARM) - user.visible_message("After a few attempts, [user] manages to light the [src], they however burn their finger in the process.") - - set_light(2) - START_PROCESSING(SSobj, src) - else - lit = 0 - icon_state = icon_off - item_state = icon_off - if(istype(src, /obj/item/weapon/lighter/zippo) ) - playsound(src, 'sound/items/zippo.ogg', 20, 1, 1) - user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what they're doing.") - else - user.visible_message("[user] quietly shuts off the [src].") - playsound(src, 'sound/items/lighter.ogg', 20, 1, 1) - - set_light(0) - STOP_PROCESSING(SSobj, src) - else - return ..() - return - - -/obj/item/weapon/lighter/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) - if(!istype(M, /mob)) - return - M.IgniteMob() //Lighters can ignite mobs splashed with fuel - if(istype(M.wear_mask, /obj/item/clothing/mask/cigarette) && def_zone == O_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 the [name] out and holds it for [M].") - else - cig.light("[user] holds the [name] out for [M], and lights the [cig.name].") - else - ..() - -/obj/item/weapon/lighter/process() - var/turf/location = get_turf(src) - if(location) - location.hotspot_expose(700, 5, src) - return +//cleansed 9/15/2012 17:48 + +/* +CONTAINS: +MATCHES +CIGARETTES +CIGARS +SMOKING PIPES +CHEAP LIGHTERS +ZIPPO + +CIGARETTE PACKETS ARE IN FANCY.DM +*/ + +/////////// +//MATCHES// +/////////// +/obj/item/weapon/match + name = "match" + desc = "A simple match stick, used for lighting fine smokables." + icon = 'icons/obj/cigarettes.dmi' + icon_state = "match_unlit" + var/lit = 0 + var/burnt = 0 + var/smoketime = 5 + w_class = 1.0 + origin_tech = "materials=1" + attack_verb = list("burnt", "singed") + +/obj/item/weapon/match/process() + var/turf/location = get_turf(src) + smoketime-- + if(smoketime < 1) + burn_out() + return + if(location) + location.hotspot_expose(700, 5, src) + return + +/obj/item/weapon/match/dropped(mob/user) + if(lit) + burn_out() + return ..() + +/obj/item/weapon/match/proc/burn_out() + lit = 0 + burnt = 1 + damtype = "brute" + icon_state = "match_burnt" + item_state = "cigoff" + name = "burnt match" + desc = "A match. This one has seen better days." + STOP_PROCESSING(SSobj, src) + +////////////////// +//FINE SMOKABLES// +////////////////// +/obj/item/clothing/mask/cigarette + name = "cigarette" + desc = "A roll of tobacco and nicotine." + icon_state = "cigoff" + throw_speed = 0.5 + item_state = "cigoff" + w_class = 1 + body_parts_covered = 0 + attack_verb = list("burnt", "singed") + var/lit = 0 + var/icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi + var/icon_off = "cigoff" + var/type_butt = /obj/item/weapon/cigbutt + var/lastHolder = null + var/smoketime = 300 + var/chem_volume = 15 + var/nicotine_per_smoketime = 0.006 + +/obj/item/clothing/mask/cigarette/atom_init() + . = ..() + 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 + +/obj/item/clothing/mask/cigarette/attackby(obj/item/weapon/W, mob/user) + ..() + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.isOn())//Badasses dont get blinded while lighting their cig with a welding tool + light("[user] casually lights the [name] with [W].") + + else if(istype(W, /obj/item/weapon/lighter/zippo)) + var/obj/item/weapon/lighter/zippo/Z = W + if(Z.lit) + light("With a flick of their wrist, [user] lights their [name] with their [W].") + + else if(istype(W, /obj/item/weapon/lighter)) + var/obj/item/weapon/lighter/L = W + if(L.lit) + light("[user] manages to light their [name] with [W].") + + else if(istype(W, /obj/item/weapon/match)) + var/obj/item/weapon/match/M = W + if(M.lit) + light("[user] lights their [name] with their [W].") + + else if(istype(W, /obj/item/weapon/melee/energy/sword)) + var/obj/item/weapon/melee/energy/sword/S = W + if(S.active) + light("[user] swings their [W], barely missing their nose. They light their [name] in the process.") + + else if(istype(W, /obj/item/device/assembly/igniter)) + light("[user] fiddles with [W], and manages to light their [name].") + + //can't think of any other way to update the overlays :< + user.update_inv_l_hand() + user.update_inv_r_hand() + return + + +/obj/item/clothing/mask/cigarette/afterattack(obj/item/weapon/reagent_containers/glass/glass, mob/user, proximity) + ..() + if(!proximity) return + if(istype(glass)) //you can dip cigarettes into beakers + 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) + to_chat(user, "[glass] is empty.") + else + to_chat(user, "[src] is full.") + + +/obj/item/clothing/mask/cigarette/proc/light(flavor_text = "[usr] lights the [name].") + if(!src.lit) + src.lit = 1 + damtype = "fire" + + if(reagents.get_reagent_amount("phoron") || reagents.get_reagent_amount("fuel")) // the phoron (fuel also) explodes when exposed to fire + var/datum/effect/effect/system/reagents_explosion/e = new() + var/exploding_reagents = round(reagents.get_reagent_amount("phoron") / 2.5 + reagents.get_reagent_amount("fuel") / 5, 1) + e.set_up(exploding_reagents, get_turf(src), 0, 0) + e.start() + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + if(H.wear_mask == src) + var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] + if(BP) + BP.take_damage(10 * exploding_reagents) + qdel(src) + return + flags &= ~NOREACT // allowing reagents to react after being lit + reagents.handle_reactions() + icon_state = icon_on + item_state = icon_on + var/turf/T = get_turf(src) + T.visible_message(flavor_text) + START_PROCESSING(SSobj, src) + if(ismob(loc)) + var/mob/M = loc + M.update_inv_wear_mask() + + +/obj/item/clothing/mask/cigarette/process() + var/turf/location = get_turf(src) + var/mob/living/M = loc + if(isliving(loc)) + M.IgniteMob() //Cigs can ignite mobs splashed with fuel + smoketime-- + smoking_reagents() + if(smoketime < 1) + die() + return + if(location) + location.hotspot_expose(700, 5, src) + return + + +/obj/item/clothing/mask/cigarette/proc/smoking_reagents() + if(iscarbon(loc)) + var/mob/living/carbon/C = loc + if(src == C.wear_mask) + if(C.stat == UNCONSCIOUS || C.paralysis) + if(prob(5)) + C.drop_from_inventory(src, get_turf(C)) + to_chat(C, "Your [name] fell out from your mouth.") + if (C.stat != DEAD) + if(istype(loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = loc + if(H.species.flags[NO_BREATHE]) + return + if(C.reagents.has_reagent("nicotine")) + C.reagents.add_reagent("nicotine", nicotine_per_smoketime) + else + C.reagents.add_reagent("nicotine", 0.2) + if(reagents.total_volume) + if(prob(15)) // so it's not an instarape in case of acid + reagents.reaction(C, INGEST) + reagents.trans_to(C, REAGENTS_METABOLISM) + return + if(reagents.total_volume) + reagents.remove_any(REAGENTS_METABOLISM) + +/obj/item/clothing/mask/cigarette/attack_self(mob/user) + if(lit == 1) + user.visible_message("[user] calmly drops and treads on the lit [src], putting it out instantly.") + die() + return ..() + + +/obj/item/clothing/mask/cigarette/proc/die() + var/turf/T = get_turf(src) + var/obj/item/butt = new type_butt(T) + transfer_fingerprints_to(butt) + if(ismob(loc)) + var/mob/living/M = loc + to_chat(M, "Your [name] goes out.") + M.remove_from_mob(src) //un-equip it so the overlays can update + M.update_inv_wear_mask(0) + STOP_PROCESSING(SSobj, src) + qdel(src) + +//////////// +// 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 = "cigar2off" + icon_on = "cigar2on" + icon_off = "cigar2off" + type_butt = /obj/item/weapon/cigbutt/cigarbutt + throw_speed = 0.5 + item_state = "cigaroff" + smoketime = 1500 + chem_volume = 20 + +/obj/item/clothing/mask/cigarette/cigar/cohiba + name = "\improper Cohiba Robusto cigar" + desc = "There's little more you could want from a cigar." + icon_state = "cigar2off" + icon_on = "cigar2on" + icon_off = "cigar2off" + +/obj/item/clothing/mask/cigarette/cigar/havana + name = "premium Havanian cigar" + desc = "A cigar fit for only the best of the best." + icon_state = "cigar2off" + icon_on = "cigar2on" + icon_off = "cigar2off" + 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/atom_init() + . = ..() + pixel_x = rand(-10,10) + pixel_y = rand(-10,10) + transform = turn(transform,rand(0,360)) + +/obj/item/weapon/cigbutt/cigarbutt + name = "cigar butt" + desc = "A manky old cigar butt." + icon_state = "cigarbutt" + + +/obj/item/clothing/mask/cigarette/cigar/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.isOn()) + light("[user] insults [name] by lighting it with [W].") + + else if(istype(W, /obj/item/weapon/lighter/zippo)) + var/obj/item/weapon/lighter/zippo/Z = W + if(Z.lit) + light("With a flick of their wrist, [user] lights their [name] with their [W].") + + else if(istype(W, /obj/item/weapon/lighter)) + var/obj/item/weapon/lighter/L = W + if(L.lit) + light("[user] manages to offend their [name] by lighting it with [W].") + + else if(istype(W, /obj/item/weapon/match)) + var/obj/item/weapon/match/M = W + if(M.lit) + light("[user] lights their [name] with their [W].") + + else if(istype(W, /obj/item/weapon/melee/energy/sword)) + var/obj/item/weapon/melee/energy/sword/S = W + if(S.active) + light("[user] swings their [W], barely missing their nose. They light their [name] in the process.") + + else if(istype(W, /obj/item/device/assembly/igniter)) + light("[user] fiddles with [W], and manages to light their [name] with the power of science.") + +///////////////// +//SMOKING PIPES// +///////////////// +/obj/item/clothing/mask/cigarette/pipe + name = "smoking pipe" + desc = "A pipe, for smoking. Probably made of meershaum or something." + icon_state = "pipeoff" + item_state = "pipeoff" + icon_on = "pipeon" //Note - these are in masks.dmi + icon_off = "pipeoff" + smoketime = 100 + nicotine_per_smoketime = 0.008 + +/obj/item/clothing/mask/cigarette/pipe/light(flavor_text = "[usr] lights the [name].") + if(!src.lit) + src.lit = 1 + damtype = "fire" + icon_state = icon_on + item_state = icon_on + var/turf/T = get_turf(src) + T.visible_message(flavor_text) + START_PROCESSING(SSobj, src) + if(ismob(loc)) + var/mob/M = loc + M.update_inv_wear_mask() + +/obj/item/clothing/mask/cigarette/pipe/process() + var/turf/location = get_turf(src) + smoketime-- + smoking_reagents() + if(smoketime < 1) + new /obj/effect/decal/cleanable/ash(location) + if(ismob(loc)) + var/mob/living/M = loc + to_chat(M, "Your [name] goes out, and you empty the ash.") + lit = 0 + icon_state = icon_off + item_state = icon_off + M.update_inv_wear_mask(0) + STOP_PROCESSING(SSobj, src) + return + if(location) + location.hotspot_expose(700, 5) + return + +/obj/item/clothing/mask/cigarette/pipe/attack_self(mob/user) //Refills the pipe. Can be changed to an attackby later, if loose tobacco is added to vendors or something. + if(lit == 1) + user.visible_message("[user] puts out [src].") + lit = 0 + icon_state = icon_off + item_state = icon_off + STOP_PROCESSING(SSobj, src) + return + if(smoketime <= 0) + to_chat(user, "You refill the pipe with tobacco.") + smoketime = initial(smoketime) + return + +/obj/item/clothing/mask/cigarette/pipe/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.isOn())// + light("[user] recklessly lights [name] with [W].") + + else if(istype(W, /obj/item/weapon/lighter/zippo)) + var/obj/item/weapon/lighter/zippo/Z = W + if(Z.lit) + light("With much care, [user] lights their [name] with their [W].") + + else if(istype(W, /obj/item/weapon/lighter)) + var/obj/item/weapon/lighter/L = W + if(L.lit) + light("[user] manages to light their [name] with [W].") + + else if(istype(W, /obj/item/weapon/match)) + var/obj/item/weapon/match/M = W + if(M.lit) + light("[user] lights their [name] with their [W].") + + else if(istype(W, /obj/item/device/assembly/igniter)) + light("[user] fiddles with [W], and manages to light their [name] with the power of science.") + +/obj/item/clothing/mask/cigarette/pipe/cobpipe + name = "corn cob pipe" + desc = "A nicotine delivery system popularized by folksy backwoodsmen, kept popular in the modern age and beyond by space hipsters." + icon_state = "cobpipeoff" + item_state = "cobpipeoff" + icon_on = "cobpipeon" //Note - these are in masks.dmi + icon_off = "cobpipeoff" + smoketime = 400 + + + +///////// +//ZIPPO// +///////// +/obj/item/weapon/lighter + name = "cheap lighter" + desc = "A cheap-as-free lighter." + icon = 'icons/obj/items.dmi' + icon_state = "lighter-g" + item_state = "lighter-g" + var/icon_on = "lighter-g-on" + var/icon_off = "lighter-g" + w_class = 1 + throwforce = 4 + flags = CONDUCT + slot_flags = SLOT_BELT + attack_verb = list("burnt", "singed") + var/lit = 0 + + action_button_name = "Toggle Lighter" + +/obj/item/weapon/lighter/zippo + name = "\improper Zippo lighter" + desc = "The zippo." + icon_state = "zippo" + item_state = "zippo" + icon_on = "zippoon" + icon_off = "zippo" + +/obj/item/weapon/lighter/random + +/obj/item/weapon/lighter/random/atom_init() + . = ..() + var/color = pick("r","c","y","g") + icon_on = "lighter-[color]-on" + icon_off = "lighter-[color]" + icon_state = icon_off + +/obj/item/weapon/lighter/attack_self(mob/living/user) + if(user.r_hand == src || user.l_hand == src) + if(!lit) + lit = 1 + icon_state = icon_on + item_state = icon_on + if(istype(src, /obj/item/weapon/lighter/zippo) ) + playsound(src, 'sound/items/zippo.ogg', 20, 1, 1) + user.visible_message("Without even breaking stride, [user] flips open and lights [src] in one smooth movement.") + else + playsound(src, 'sound/items/lighter.ogg', 20, 1, 1) + if(prob(95)) + user.visible_message("After a few attempts, [user] manages to light the [src].") + else + to_chat(user, "You burn yourself while lighting the lighter.") + if (user.l_hand == src) + user.apply_damage(2, BURN, BP_L_ARM) + else + user.apply_damage(2, BURN, BP_R_ARM) + user.visible_message("After a few attempts, [user] manages to light the [src], they however burn their finger in the process.") + + set_light(2) + START_PROCESSING(SSobj, src) + else + lit = 0 + icon_state = icon_off + item_state = icon_off + if(istype(src, /obj/item/weapon/lighter/zippo) ) + playsound(src, 'sound/items/zippo.ogg', 20, 1, 1) + user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what they're doing.") + else + user.visible_message("[user] quietly shuts off the [src].") + playsound(src, 'sound/items/lighter.ogg', 20, 1, 1) + + set_light(0) + STOP_PROCESSING(SSobj, src) + else + return ..() + return + + +/obj/item/weapon/lighter/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) + if(!istype(M, /mob)) + return + M.IgniteMob() //Lighters can ignite mobs splashed with fuel + if(istype(M.wear_mask, /obj/item/clothing/mask/cigarette) && def_zone == O_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 the [name] out and holds it for [M].") + else + cig.light("[user] holds the [name] out for [M], and lights the [cig.name].") + else + ..() + +/obj/item/weapon/lighter/process() + var/turf/location = get_turf(src) + if(location) + location.hotspot_expose(700, 5, src) + return diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index 40f988377b9d..b476c4352c24 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -1,238 +1,238 @@ -/* Clown Items - * Contains: - * Banana Peels - * Soap - * Bike Horns - */ - -/* - * Banana Peals - */ - -/obj/item/weapon/bananapeel - name = "banana peel" - desc = "A peel from a banana." - icon = 'icons/obj/items.dmi' - icon_state = "banana_peel" - item_state = "banana_peel" - w_class = ITEM_SIZE_SMALL - throwforce = 0 - throw_speed = 4 - throw_range = 20 - -/obj/item/weapon/bananapeel/Crossed(mob/living/carbon/C) - if(istype(C)) - C.slip("the [src]", 4, 2) - -/* - * Soap - */ -/obj/item/weapon/soap - name = "soap" - desc = "A cheap bar of soap. Doesn't smell." - gender = PLURAL - icon = 'icons/obj/items.dmi' - icon_state = "soap" - w_class = ITEM_SIZE_SMALL - throwforce = 0 - throw_speed = 4 - throw_range = 20 - -/obj/item/weapon/soap/nanotrasen - desc = "A Nanotrasen brand bar of soap. Smells of phoron." - icon_state = "soapnt" - -/obj/item/weapon/soap/deluxe - desc = "A deluxe Waffle Co. brand bar of soap. Smells of condoms." - icon_state = "soapdeluxe" - -/obj/item/weapon/soap/syndie - desc = "An untrustworthy bar of soap. Smells of fear." - icon_state = "soapsyndie" - -/obj/item/weapon/soap/Crossed(mob/living/carbon/C) //EXACTLY the same as bananapeel for now, so it makes sense to put it in the same dm -- Urist - if(istype(C)) - C.slip("the [src]", 4, 2) - -/obj/item/weapon/soap/afterattack(atom/target, mob/user, proximity) - if(!proximity) return - // I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. - // So this is a workaround. This also makes more sense from an IC standpoint. ~Carn - if(user.client && (target in user.client.screen)) - to_chat(user, "You need to take that [target.name] off before cleaning it.") - else if(istype(target,/obj/effect/decal/cleanable)) - to_chat(user, "You scrub \the [target.name] out.") - qdel(target) - else - to_chat(user, "You clean \the [target.name].") - target.clean_blood() - return - -/obj/item/weapon/soap/attack(mob/target, mob/user, def_zone) - if(target && user && ishuman(target) && ishuman(user) && !user.stat && user.zone_sel && !user.is_busy()) - var/mob/living/carbon/human/H = target - var/body_part_name - switch(def_zone) - if(BP_L_LEG, BP_R_LEG) - body_part_name = "legs" - if(BP_L_ARM, BP_R_ARM) - body_part_name = "arms" - else - body_part_name = def_zone - if(target == user) - user.visible_message("\the [user] starts to clean \his [body_part_name] out with soap.") - else - user.visible_message("\the [user] starts to clean \the [target]'s [body_part_name] out with soap.") - if(do_after(user, 15, target = H) && src) - switch(body_part_name) - if("mouth") - H.lip_style = null - H.update_body() - if("groin") - if(H.belt) - if(H.belt.clean_blood()) - H.update_inv_belt() - if("head") - if(H.head) - var/washmask = !(H.head.flags_inv & HIDEMASK) - var/washears = !((H.head.flags_inv & HIDEEARS) || (H.wear_mask && H.wear_mask.flags_inv & HIDEEARS)) - var/washglasses = !((H.head.flags_inv & HIDEEYES) || (H.wear_mask && H.wear_mask.flags_inv & HIDEEYES)) - if(washmask && H.wear_mask && H.wear_mask.clean_blood()) - H.update_inv_wear_mask() - else - H.lip_style = null - H.update_body() - if(H.glasses && washglasses && H.glasses.clean_blood()) - H.update_inv_glasses() - if(H.l_ear && washears && H.l_ear.clean_blood()) - H.update_inv_ears() - if(H.r_ear && washears && H.r_ear.clean_blood()) - H.update_inv_ears() - if(H.head.clean_blood()) - H.update_inv_head() - if("chest") - if(H.wear_suit && H.wear_suit.clean_blood()) - H.update_inv_wear_suit() - else if(H.w_uniform && H.w_uniform.clean_blood()) - H.update_inv_w_uniform() - if(H.belt && H.belt.clean_blood()) - H.update_inv_belt() - if("eyes") - if(!(H.head && (H.head.flags_inv & HIDEEYES))) - if(H.glasses) - H.glasses.clean_blood() - H.update_inv_glasses() - else - H.eye_blurry = max(H.eye_blurry, 5) - H.eye_blind = max(H.eye_blind, 1) - to_chat(H, "Ouch! That hurts!") - if("legs") - var/obj/item/organ/external/l_foot = H.bodyparts_by_name[BP_L_LEG] - var/obj/item/organ/external/r_foot = H.bodyparts_by_name[BP_R_LEG] - var/no_legs = FALSE - if((!l_foot || (l_foot && (l_foot.status & ORGAN_DESTROYED))) && (!r_foot || (r_foot && (r_foot.status & ORGAN_DESTROYED)))) - no_legs = TRUE - if(!no_legs) - if(H.shoes && H.shoes.clean_blood()) - H.update_inv_shoes() - else - H.feet_blood_DNA = null - H.feet_dirt_color = null - H.update_inv_shoes() - else - to_chat(user, "There is nothing to clean!") - return - if("arms") - var/obj/item/organ/external/r_hand = H.bodyparts_by_name[BP_L_ARM] - var/obj/item/organ/external/l_hand = H.bodyparts_by_name[BP_R_ARM] - if((l_hand && !(l_hand.status & ORGAN_DESTROYED)) && (r_hand && !(r_hand.status & ORGAN_DESTROYED))) - if(H.gloves && H.gloves.clean_blood()) - H.update_inv_gloves() - H.gloves.germ_level = 0 - else - if(H.bloody_hands) - H.bloody_hands = 0 - H.update_inv_gloves() - H.germ_level = 0 - H.clean_blood() - if(target == user) - user.visible_message("\the [user] cleans \his [body_part_name] out with soap.") - else - user.visible_message("\the [user] cleans \the [target]'s [body_part_name] out with soap.") - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1) - return - else - user.visible_message("\the [user] fails to clean \the [target]'s [body_part_name] out with soap.") - return - ..() - -/* - * Bike Horns - */ - -/obj/item/weapon/bikehorn - name = "bike horn" - desc = "A horn off of a bicycle." - icon = 'icons/obj/items.dmi' - icon_state = "bike_horn" - item_state = "bike_horn" - throwforce = 3 - w_class = ITEM_SIZE_TINY - throw_speed = 3 - throw_range = 15 - attack_verb = list("HONKED") - var/cooldown = FALSE - -/obj/item/weapon/bikehorn/attack(mob/target, mob/user, def_zone) - . = ..() - playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1) - -/obj/item/weapon/bikehorn/attack_self(mob/user) - if(cooldown <= world.time) - cooldown = world.time + 8 - playsound(src, 'sound/items/bikehorn.ogg', 50, 1) - src.add_fingerprint(user) - return - -/obj/item/weapon/bikehorn/dogtoy - name = "dog toy" - desc = "This adorable toy is made with super soft plush and has a squeaker inside for added entertainment." //Woof! - icon = 'icons/obj/items.dmi' - icon_state = "dogtoy" - item_state = "dogtoy" - -////////////////////////////////////////////////////// -// Fake Laugh Button // -////////////////////////////////////////////////////// - -/obj/item/toy/laugh_button - name = "laugh button" - desc = "It's a perfect adding to the bad joke." - icon = 'icons/obj/toy.dmi' - icon_state = "laugh_button_on" - var/cooldown = FALSE - w_class = ITEM_SIZE_TINY - -/obj/item/toy/laugh_button/attack_self(mob/user) - if(!cooldown) - user.visible_message("[bicon(src)] \the [user] presses \the [src]") - playsound(src, 'sound/items/buttonclick.ogg', 50, 1) - var/laugh = pick( - 'sound/voice/fake_laugh/laugh1.ogg', - 'sound/voice/fake_laugh/laugh2.ogg', - 'sound/voice/fake_laugh/laugh3.ogg', - ) - playsound(src, laugh, 50, 1) - flick("laugh_button_down",src) - icon_state = "laugh_button_off" - cooldown = TRUE - addtimer(CALLBACK(src, .proc/release_cooldown), 50) - return - ..() - -/obj/item/toy/laugh_button/proc/release_cooldown() - flick("laugh_button_up",src) - icon_state = "laugh_button_on" - cooldown = FALSE - playsound(src, 'sound/items/buttonclick.ogg', 50, 1) - return +/* Clown Items + * Contains: + * Banana Peels + * Soap + * Bike Horns + */ + +/* + * Banana Peals + */ + +/obj/item/weapon/bananapeel + name = "banana peel" + desc = "A peel from a banana." + icon = 'icons/obj/items.dmi' + icon_state = "banana_peel" + item_state = "banana_peel" + w_class = ITEM_SIZE_SMALL + throwforce = 0 + throw_speed = 4 + throw_range = 20 + +/obj/item/weapon/bananapeel/Crossed(mob/living/carbon/C) + if(istype(C)) + C.slip("the [src]", 4, 2) + +/* + * Soap + */ +/obj/item/weapon/soap + name = "soap" + desc = "A cheap bar of soap. Doesn't smell." + gender = PLURAL + icon = 'icons/obj/items.dmi' + icon_state = "soap" + w_class = ITEM_SIZE_SMALL + throwforce = 0 + throw_speed = 4 + throw_range = 20 + +/obj/item/weapon/soap/nanotrasen + desc = "A Nanotrasen brand bar of soap. Smells of phoron." + icon_state = "soapnt" + +/obj/item/weapon/soap/deluxe + desc = "A deluxe Waffle Co. brand bar of soap. Smells of condoms." + icon_state = "soapdeluxe" + +/obj/item/weapon/soap/syndie + desc = "An untrustworthy bar of soap. Smells of fear." + icon_state = "soapsyndie" + +/obj/item/weapon/soap/Crossed(mob/living/carbon/C) //EXACTLY the same as bananapeel for now, so it makes sense to put it in the same dm -- Urist + if(istype(C)) + C.slip("the [src]", 4, 2) + +/obj/item/weapon/soap/afterattack(atom/target, mob/user, proximity) + if(!proximity) return + // I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. + // So this is a workaround. This also makes more sense from an IC standpoint. ~Carn + if(user.client && (target in user.client.screen)) + to_chat(user, "You need to take that [target.name] off before cleaning it.") + else if(istype(target,/obj/effect/decal/cleanable)) + to_chat(user, "You scrub \the [target.name] out.") + qdel(target) + else + to_chat(user, "You clean \the [target.name].") + target.clean_blood() + return + +/obj/item/weapon/soap/attack(mob/target, mob/user, def_zone) + if(target && user && ishuman(target) && ishuman(user) && !user.stat && user.zone_sel && !user.is_busy()) + var/mob/living/carbon/human/H = target + var/body_part_name + switch(def_zone) + if(BP_L_LEG, BP_R_LEG) + body_part_name = "legs" + if(BP_L_ARM, BP_R_ARM) + body_part_name = "arms" + else + body_part_name = def_zone + if(target == user) + user.visible_message("\the [user] starts to clean \his [body_part_name] out with soap.") + else + user.visible_message("\the [user] starts to clean \the [target]'s [body_part_name] out with soap.") + if(do_after(user, 15, target = H) && src) + switch(body_part_name) + if("mouth") + H.lip_style = null + H.update_body() + if("groin") + if(H.belt) + if(H.belt.clean_blood()) + H.update_inv_belt() + if("head") + if(H.head) + var/washmask = !(H.head.flags_inv & HIDEMASK) + var/washears = !((H.head.flags_inv & HIDEEARS) || (H.wear_mask && H.wear_mask.flags_inv & HIDEEARS)) + var/washglasses = !((H.head.flags_inv & HIDEEYES) || (H.wear_mask && H.wear_mask.flags_inv & HIDEEYES)) + if(washmask && H.wear_mask && H.wear_mask.clean_blood()) + H.update_inv_wear_mask() + else + H.lip_style = null + H.update_body() + if(H.glasses && washglasses && H.glasses.clean_blood()) + H.update_inv_glasses() + if(H.l_ear && washears && H.l_ear.clean_blood()) + H.update_inv_ears() + if(H.r_ear && washears && H.r_ear.clean_blood()) + H.update_inv_ears() + if(H.head.clean_blood()) + H.update_inv_head() + if("chest") + if(H.wear_suit && H.wear_suit.clean_blood()) + H.update_inv_wear_suit() + else if(H.w_uniform && H.w_uniform.clean_blood()) + H.update_inv_w_uniform() + if(H.belt && H.belt.clean_blood()) + H.update_inv_belt() + if("eyes") + if(!(H.head && (H.head.flags_inv & HIDEEYES))) + if(H.glasses) + H.glasses.clean_blood() + H.update_inv_glasses() + else + H.eye_blurry = max(H.eye_blurry, 5) + H.eye_blind = max(H.eye_blind, 1) + to_chat(H, "Ouch! That hurts!") + if("legs") + var/obj/item/organ/external/l_foot = H.bodyparts_by_name[BP_L_LEG] + var/obj/item/organ/external/r_foot = H.bodyparts_by_name[BP_R_LEG] + var/no_legs = FALSE + if((!l_foot || (l_foot && (l_foot.status & ORGAN_DESTROYED))) && (!r_foot || (r_foot && (r_foot.status & ORGAN_DESTROYED)))) + no_legs = TRUE + if(!no_legs) + if(H.shoes && H.shoes.clean_blood()) + H.update_inv_shoes() + else + H.feet_blood_DNA = null + H.feet_dirt_color = null + H.update_inv_shoes() + else + to_chat(user, "There is nothing to clean!") + return + if("arms") + var/obj/item/organ/external/r_hand = H.bodyparts_by_name[BP_L_ARM] + var/obj/item/organ/external/l_hand = H.bodyparts_by_name[BP_R_ARM] + if((l_hand && !(l_hand.status & ORGAN_DESTROYED)) && (r_hand && !(r_hand.status & ORGAN_DESTROYED))) + if(H.gloves && H.gloves.clean_blood()) + H.update_inv_gloves() + H.gloves.germ_level = 0 + else + if(H.bloody_hands) + H.bloody_hands = 0 + H.update_inv_gloves() + H.germ_level = 0 + H.clean_blood() + if(target == user) + user.visible_message("\the [user] cleans \his [body_part_name] out with soap.") + else + user.visible_message("\the [user] cleans \the [target]'s [body_part_name] out with soap.") + playsound(src.loc, 'sound/misc/slip.ogg', 50, 1) + return + else + user.visible_message("\the [user] fails to clean \the [target]'s [body_part_name] out with soap.") + return + ..() + +/* + * Bike Horns + */ + +/obj/item/weapon/bikehorn + name = "bike horn" + desc = "A horn off of a bicycle." + icon = 'icons/obj/items.dmi' + icon_state = "bike_horn" + item_state = "bike_horn" + throwforce = 3 + w_class = ITEM_SIZE_TINY + throw_speed = 3 + throw_range = 15 + attack_verb = list("HONKED") + var/cooldown = FALSE + +/obj/item/weapon/bikehorn/attack(mob/target, mob/user, def_zone) + . = ..() + playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1) + +/obj/item/weapon/bikehorn/attack_self(mob/user) + if(cooldown <= world.time) + cooldown = world.time + 8 + playsound(src, 'sound/items/bikehorn.ogg', 50, 1) + src.add_fingerprint(user) + return + +/obj/item/weapon/bikehorn/dogtoy + name = "dog toy" + desc = "This adorable toy is made with super soft plush and has a squeaker inside for added entertainment." //Woof! + icon = 'icons/obj/items.dmi' + icon_state = "dogtoy" + item_state = "dogtoy" + +////////////////////////////////////////////////////// +// Fake Laugh Button // +////////////////////////////////////////////////////// + +/obj/item/toy/laugh_button + name = "laugh button" + desc = "It's a perfect adding to the bad joke." + icon = 'icons/obj/toy.dmi' + icon_state = "laugh_button_on" + var/cooldown = FALSE + w_class = ITEM_SIZE_TINY + +/obj/item/toy/laugh_button/attack_self(mob/user) + if(!cooldown) + user.visible_message("[bicon(src)] \the [user] presses \the [src]") + playsound(src, 'sound/items/buttonclick.ogg', 50, 1) + var/laugh = pick( + 'sound/voice/fake_laugh/laugh1.ogg', + 'sound/voice/fake_laugh/laugh2.ogg', + 'sound/voice/fake_laugh/laugh3.ogg', + ) + playsound(src, laugh, 50, 1) + flick("laugh_button_down",src) + icon_state = "laugh_button_off" + cooldown = TRUE + addtimer(CALLBACK(src, .proc/release_cooldown), 50) + return + ..() + +/obj/item/toy/laugh_button/proc/release_cooldown() + flick("laugh_button_up",src) + icon_state = "laugh_button_on" + cooldown = FALSE + playsound(src, 'sound/items/buttonclick.ogg', 50, 1) + return diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index ad95289135c0..9cbf54d5d5b5 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -1,446 +1,446 @@ -/obj/item/weapon/lipstick - gender = PLURAL - name = "red lipstick" - desc = "A generic brand of lipstick." - icon = 'icons/obj/items.dmi' - icon_state = "lipstick" - 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/atom_init() - . = ..() - colour = pick("red","purple","jade","black") - name = "[colour] lipstick" - - -/obj/item/weapon/lipstick/attack_self(mob/user) - 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, mob/user) - 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 = "lipstick" - H.lip_color = colour - H.update_body() - else if(!user.is_busy()) - user.visible_message("[user] begins to do [H]'s lips with \the [src].", \ - "You begin to apply \the [src].") - if(do_after(user, 20, target = H)) //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 = "lipstick" - H.lip_color = 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, mob/living/carbon/user, def_zone) - if(def_zone == O_MOUTH) - if(!istype(M)) - 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 if(!user.is_busy()) - 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, 10, target = H)) //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 - ..() - - -/obj/item/weapon/razor - name = "electric razor" - desc = "The latest and greatest power razor born from the science of shaving." - icon = 'icons/obj/items.dmi' - icon_state = "razor" - flags = CONDUCT - w_class = 1 - - -/obj/item/weapon/razor/proc/shave(mob/living/carbon/human/H, location = O_MOUTH, mob/living/carbon/human/AH = null) - if(location == O_MOUTH) - H.f_style = "Shaved" - else - H.h_style = "Skinhead" - if(AH) - H.attack_log += text("\[[time_stamp()]\] Has been shaved with [src.name] by [AH.name] ([AH.ckey])") - AH.attack_log += text("\[[time_stamp()]\] Used the [src.name] to shave [H.name] ([H.ckey])") - H.update_hair() - playsound(loc, 'sound/items/Welder2.ogg', 20, 1) - - -/obj/item/weapon/razor/attack(mob/M, mob/user, def_zone) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - - if(def_zone == O_MOUTH) - if(!H.species.flags[HAS_HAIR]) - to_chat(user, "There is no hair!") - return - if((H.head && (H.head.flags & HEADCOVERSMOUTH)) || (H.wear_mask && (H.wear_mask.flags & MASKCOVERSMOUTH))) - to_chat(user, "The mask is in the way!") - return - if(H.f_style == "Shaved") - to_chat(user, "Already clean-shaven!") - return - - if(H == user) //shaving yourself - if(user.is_busy()) return - user.visible_message("[user] starts to shave their facial hair with [src].", \ - "You take a moment to shave your facial hair with [src]...") - if(do_after(user, 50, target = H)) - user.visible_message("[user] shaves his facial hair clean with [src].", \ - "You finish shaving with [src]. Fast and clean!") - shave(H, def_zone) - else if(!user.is_busy()) - var/turf/H_loc = H.loc - user.visible_message("[user] tries to shave [H]'s facial hair with [src].", \ - "You start shaving [H]'s facial hair...") - if(do_after(user, 50, target = H)) - if(H_loc == H.loc) - user.visible_message("[user] shaves off [H]'s facial hair with [src].", \ - "You shave [H]'s facial hair clean off.") - shave(H, def_zone, user) - - else if(def_zone == BP_HEAD) - if(!H.species.flags[HAS_HAIR]) - to_chat(user, "There is no hair!") - return - if((H.head && (H.head.flags & BLOCKHAIR)) || (H.head && (H.head.flags & HIDEEARS))) - to_chat(user, "The headgear is in the way!") - return - if(H.h_style == "Bald" || H.h_style == "Balding Hair" || H.h_style == "Skinhead") - to_chat(user, "There is not enough hair left to shave!") - return - - if(H == user) //shaving yourself - if(user.is_busy()) return - user.visible_message("[user] starts to shave their head with [src].", \ - "You start to shave your head with [src]...") - if(do_after(user, 50, target = H)) - user.visible_message("[user] shaves his head with [src].", \ - "You finish shaving with [src].") - shave(H, def_zone) - else if(!user.is_busy()) - var/turf/H_loc = H.loc - user.visible_message("[user] tries to shave [H]'s head with [src]!", \ - "You start shaving [H]'s head...") - if(do_after(user, 50, target = H)) - if(H_loc == H.loc) - user.visible_message("[user] shaves [H]'s head bald with [src]!", \ - "You shave [H]'s head bald.") - shave(H, def_zone, user) - else - ..() - else - ..() - -/obj/item/weapon/haircomb //sparklysheep's comb - name = "purple comb" - desc = "A pristine purple comb made from flexible plastic." - w_class = 1.0 - icon = 'icons/obj/items.dmi' - icon_state = "purplecomb" - item_state = "purplecomb" - -/obj/item/weapon/haircomb/attack_self(mob/user) - if(user.r_hand == src || user.l_hand == src) - user.visible_message(text("\red [] uses [] to comb their hair with incredible style and sophistication. What a [].", user, src, user.gender == FEMALE ? "lady" : "guy")) - return - -/obj/item/weapon/scissors - name = "scissors" - desc = "These can cut hair." - icon = 'icons/obj/items.dmi' - icon_state = "scissors" - item_state = "scissors" - flags = CONDUCT - slot_flags = SLOT_BELT - force = 6.0 - throw_speed = 2 - throw_range = 9 - w_class = 2.0 - m_amt = 80 - origin_tech = "materials=1;engineering=1" - attack_verb = list("cut", "stabbed", "chipped") - sharp = 1 - edge = 1 - var/list/bald_hair_styles_list = list("Bald", "Balding Hair", "Skinhead", "Unathi Horns", "Tajaran Ears") - var/list/shaved_facial_hair_styles_list = list("Shaved") - var/list/allowed_races = list(HUMAN, UNATHI, TAJARAN) - var/mob/living/carbon/human/barber = null - var/mob/living/carbon/human/barbertarget = null - var/selectedhairstyle = null - var/isfacehair = FALSE - var/list/char_render_holders - var/static/list/scissors_icon_cache - -/obj/item/weapon/scissors/proc/calculate_hash(mob/living/carbon/human/H) - var/hash = "" + H.species.name + H.gender + num2text(H.r_eyes + H.g_eyes*256 + H.b_eyes*256*256,9) + "_" + num2text(H.r_hair + H.g_hair*256 + H.b_hair*256*256,9) + "_" + num2text(H.r_facial + H.g_facial*256 + H.b_facial*256*256,9) + "_" + num2text(H.r_skin + H.g_skin*256 + H.b_skin*256*256,9) + "_" + num2text(H.s_tone) - if(!isfacehair && selectedhairstyle) - hash+="_" + selectedhairstyle - else - hash+="_" + H.h_style - - if(isfacehair && selectedhairstyle) - hash+="_" + selectedhairstyle - else - hash+="_" + H.f_style - hash+="_" + num2text(H.underwear) +"_" + num2text(H.undershirt) + "_" + num2text(H.socks) - return hash - -/obj/item/weapon/scissors/proc/make_mannequin(mob/living/carbon/human/H) - var/mob/living/carbon/human/dummy/mannequin = new(null, H.species.name) - mannequin.gender = H.gender - mannequin.age = H.age - mannequin.b_type = H.b_type - - mannequin.r_eyes = H.r_eyes - mannequin.g_eyes = H.g_eyes - mannequin.b_eyes = H.b_eyes - - mannequin.r_hair = H.r_hair - mannequin.g_hair = H.g_hair - mannequin.b_hair = H.b_hair - - mannequin.r_facial = H.r_facial - mannequin.g_facial = H.g_facial - mannequin.b_facial = H.b_facial - - mannequin.r_skin = H.r_skin - mannequin.g_skin = H.g_skin - mannequin.b_skin = H.b_skin - - mannequin.s_tone = H.s_tone - - if(!isfacehair && selectedhairstyle) - mannequin.h_style = selectedhairstyle - else - mannequin.h_style = H.h_style - - if(isfacehair && selectedhairstyle) - mannequin.f_style = selectedhairstyle - else - mannequin.f_style = H.f_style - - mannequin.underwear = H.underwear - mannequin.undershirt = H.undershirt - mannequin.socks = H.socks - - mannequin.update_body() - mannequin.update_hair() - return mannequin - -/obj/item/weapon/scissors/Topic(href, href_list) - if(!barber || barber != usr || !barbertarget) - return - if(href_list["close"]) - clear_character_previews() - return - switch(href_list["choice"]) - if("selecthaircut") - selectedhairstyle = href_list["haircut"] - showui() - if("start") - INVOKE_ASYNC(src, .proc/dohaircut) - clear_character_previews() - -/obj/item/weapon/scissors/dropped(mob/user) - clear_character_previews() - ..() - -/obj/item/weapon/scissors/proc/create_character_previews() - var/hash = calculate_hash(barbertarget) - var/mutable_appearance/MA = LAZYACCESS(scissors_icon_cache, hash) - - if(!MA) - var/mob/living/carbon/human/dummy/mannequin = make_mannequin(barbertarget) - MA = new /mutable_appearance(mannequin) - qdel(mannequin) - LAZYSET(scissors_icon_cache, hash, MA) - - var/pos = 0 - for(var/D in cardinal) - pos++ - var/obj/screen/O = LAZYACCESS(char_render_holders, "[D]") - if(!O) - O = new - LAZYSET(char_render_holders, "[D]", O) - barber.client.screen |= O - O.appearance = MA - O.dir = D - O.screen_loc = "barber_preview_map:[pos],0" - -/obj/item/weapon/scissors/proc/clear_character_previews() - barber << browse(null, "window=barber_window") - for(var/index in char_render_holders) - var/obj/screen/S = char_render_holders[index] - if(barber && barber.client) - barber.client.screen -= S - qdel(S) - char_render_holders = null - barber = null - barbertarget = null - -/obj/item/weapon/scissors/proc/showui() - if(!barber || !barbertarget) - return - - create_character_previews() - - var/list/selected_styles_list = hair_styles_list - if(isfacehair) - selected_styles_list = facial_hair_styles_list - - var/haircutlist = "" - var/tablei = 0 - for(var/i in selected_styles_list) - var/datum/sprite_accessory/hair/tmp_hair = selected_styles_list[i] - if(barbertarget.species.name in tmp_hair.species_allowed) - var/styles = "" - if(i == selectedhairstyle || (!selectedhairstyle && ((barbertarget.f_style == i && isfacehair) || (barbertarget.h_style == i && !isfacehair)))) - styles = "color: rgb(255,0,0)" - haircutlist += "" - if(++tablei >= 5) - tablei = 0 - haircutlist+="" - haircutlist+="
                    [i]
                    " - - winshow(barber, "barber_window", TRUE) - barber << browse("Grooming" \ - + "" \ - + "CONFIRM

                    " \ - + haircutlist \ - + "", "window=barber_window") - onclose(barber, "barber_window", src) - return - -/obj/item/weapon/scissors/proc/dohaircut() - // saving those refs, it will be cleaned before do_after proc ends - var/mob/living/carbon/human/barber = src.barber - var/mob/living/carbon/human/barbertarget = src.barbertarget - - if(!barber || !barbertarget || !selectedhairstyle) - return - if(!in_range(barbertarget, barber) || barber.get_active_hand() != src) - return - - if(isfacehair) - barber.visible_message("[barber] starts cutting [barbertarget]'s facial hair with [src]!", \ - "You start cutting [barbertarget]'s facial hair with [src], this might take a minute...") - if(do_after(barber, 100, target = barbertarget)) - barbertarget.f_style = selectedhairstyle - barbertarget.update_hair() - barber.visible_message("[barber] finished cutting [barbertarget]'s facial hair", \ - "You finished cutting [barbertarget]'s facial hair") - else - barber.visible_message("[barber] starts cutting [barbertarget]'s hair with [src]!", \ - "You start cutting [barbertarget]'s hair with [src], this might take a minute...") - if(do_after(barber, 100, target = barbertarget)) - barbertarget.h_style = selectedhairstyle - barbertarget.update_hair() - barber.visible_message("[barber] finished cutting [barbertarget]'s hair", \ - "You finished cutting [barbertarget]'s hair") - - -/obj/item/weapon/scissors/attack(mob/M, mob/user, def_zone) - if(user.a_intent == "hurt") - ..() - return - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - - if(user.is_busy()) return - - if(def_zone == O_MOUTH) - if(H == user) - to_chat(user, "You can't cut your facial hair") - return - - if(H.species.name in allowed_races) - if((H.head && (H.head.flags & HEADCOVERSMOUTH)) || (H.wear_mask && (H.wear_mask.flags & MASKCOVERSMOUTH))) - to_chat(user, "The mask is in the way!") - return - - if(H.f_style in shaved_facial_hair_styles_list) - to_chat(user, "There are not enough hair to change facial hair style") - return - - selectedhairstyle = null - isfacehair = TRUE - barber = user - barbertarget = M - showui() - return - else - to_chat(user, "You don't know how to cut the hair of this race!") - return - - else if(def_zone == BP_HEAD) - if(H == user) - to_chat(user, "You can't cut your hair") - return - - if(H.species.name in allowed_races) - if(H.head && ((H.head.flags & BLOCKHAIR) || (H.head.flags & HIDEEARS))) - to_chat(user, "The headgear is in the way!") - return - - if(H.h_style in bald_hair_styles_list) - to_chat(user, "There are not enough hair to make a haircut") - return - - selectedhairstyle = null - isfacehair = FALSE - barber = user - barbertarget = M - showui() - return - else - to_chat(user, "You don't know how to cut the hair of this race!") - return - ..() +/obj/item/weapon/lipstick + gender = PLURAL + name = "red lipstick" + desc = "A generic brand of lipstick." + icon = 'icons/obj/items.dmi' + icon_state = "lipstick" + 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/atom_init() + . = ..() + colour = pick("red","purple","jade","black") + name = "[colour] lipstick" + + +/obj/item/weapon/lipstick/attack_self(mob/user) + 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, mob/user) + 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 = "lipstick" + H.lip_color = colour + H.update_body() + else if(!user.is_busy()) + user.visible_message("[user] begins to do [H]'s lips with \the [src].", \ + "You begin to apply \the [src].") + if(do_after(user, 20, target = H)) //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 = "lipstick" + H.lip_color = 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, mob/living/carbon/user, def_zone) + if(def_zone == O_MOUTH) + if(!istype(M)) + 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 if(!user.is_busy()) + 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, 10, target = H)) //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 + ..() + + +/obj/item/weapon/razor + name = "electric razor" + desc = "The latest and greatest power razor born from the science of shaving." + icon = 'icons/obj/items.dmi' + icon_state = "razor" + flags = CONDUCT + w_class = 1 + + +/obj/item/weapon/razor/proc/shave(mob/living/carbon/human/H, location = O_MOUTH, mob/living/carbon/human/AH = null) + if(location == O_MOUTH) + H.f_style = "Shaved" + else + H.h_style = "Skinhead" + if(AH) + H.attack_log += text("\[[time_stamp()]\] Has been shaved with [src.name] by [AH.name] ([AH.ckey])") + AH.attack_log += text("\[[time_stamp()]\] Used the [src.name] to shave [H.name] ([H.ckey])") + H.update_hair() + playsound(loc, 'sound/items/Welder2.ogg', 20, 1) + + +/obj/item/weapon/razor/attack(mob/M, mob/user, def_zone) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + + if(def_zone == O_MOUTH) + if(!H.species.flags[HAS_HAIR]) + to_chat(user, "There is no hair!") + return + if((H.head && (H.head.flags & HEADCOVERSMOUTH)) || (H.wear_mask && (H.wear_mask.flags & MASKCOVERSMOUTH))) + to_chat(user, "The mask is in the way!") + return + if(H.f_style == "Shaved") + to_chat(user, "Already clean-shaven!") + return + + if(H == user) //shaving yourself + if(user.is_busy()) return + user.visible_message("[user] starts to shave their facial hair with [src].", \ + "You take a moment to shave your facial hair with [src]...") + if(do_after(user, 50, target = H)) + user.visible_message("[user] shaves his facial hair clean with [src].", \ + "You finish shaving with [src]. Fast and clean!") + shave(H, def_zone) + else if(!user.is_busy()) + var/turf/H_loc = H.loc + user.visible_message("[user] tries to shave [H]'s facial hair with [src].", \ + "You start shaving [H]'s facial hair...") + if(do_after(user, 50, target = H)) + if(H_loc == H.loc) + user.visible_message("[user] shaves off [H]'s facial hair with [src].", \ + "You shave [H]'s facial hair clean off.") + shave(H, def_zone, user) + + else if(def_zone == BP_HEAD) + if(!H.species.flags[HAS_HAIR]) + to_chat(user, "There is no hair!") + return + if((H.head && (H.head.flags & BLOCKHAIR)) || (H.head && (H.head.flags & HIDEEARS))) + to_chat(user, "The headgear is in the way!") + return + if(H.h_style == "Bald" || H.h_style == "Balding Hair" || H.h_style == "Skinhead") + to_chat(user, "There is not enough hair left to shave!") + return + + if(H == user) //shaving yourself + if(user.is_busy()) return + user.visible_message("[user] starts to shave their head with [src].", \ + "You start to shave your head with [src]...") + if(do_after(user, 50, target = H)) + user.visible_message("[user] shaves his head with [src].", \ + "You finish shaving with [src].") + shave(H, def_zone) + else if(!user.is_busy()) + var/turf/H_loc = H.loc + user.visible_message("[user] tries to shave [H]'s head with [src]!", \ + "You start shaving [H]'s head...") + if(do_after(user, 50, target = H)) + if(H_loc == H.loc) + user.visible_message("[user] shaves [H]'s head bald with [src]!", \ + "You shave [H]'s head bald.") + shave(H, def_zone, user) + else + ..() + else + ..() + +/obj/item/weapon/haircomb //sparklysheep's comb + name = "purple comb" + desc = "A pristine purple comb made from flexible plastic." + w_class = 1.0 + icon = 'icons/obj/items.dmi' + icon_state = "purplecomb" + item_state = "purplecomb" + +/obj/item/weapon/haircomb/attack_self(mob/user) + if(user.r_hand == src || user.l_hand == src) + user.visible_message(text("\red [] uses [] to comb their hair with incredible style and sophistication. What a [].", user, src, user.gender == FEMALE ? "lady" : "guy")) + return + +/obj/item/weapon/scissors + name = "scissors" + desc = "These can cut hair." + icon = 'icons/obj/items.dmi' + icon_state = "scissors" + item_state = "scissors" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 6.0 + throw_speed = 2 + throw_range = 9 + w_class = 2.0 + m_amt = 80 + origin_tech = "materials=1;engineering=1" + attack_verb = list("cut", "stabbed", "chipped") + sharp = 1 + edge = 1 + var/list/bald_hair_styles_list = list("Bald", "Balding Hair", "Skinhead", "Unathi Horns", "Tajaran Ears") + var/list/shaved_facial_hair_styles_list = list("Shaved") + var/list/allowed_races = list(HUMAN, UNATHI, TAJARAN) + var/mob/living/carbon/human/barber = null + var/mob/living/carbon/human/barbertarget = null + var/selectedhairstyle = null + var/isfacehair = FALSE + var/list/char_render_holders + var/static/list/scissors_icon_cache + +/obj/item/weapon/scissors/proc/calculate_hash(mob/living/carbon/human/H) + var/hash = "" + H.species.name + H.gender + num2text(H.r_eyes + H.g_eyes*256 + H.b_eyes*256*256,9) + "_" + num2text(H.r_hair + H.g_hair*256 + H.b_hair*256*256,9) + "_" + num2text(H.r_facial + H.g_facial*256 + H.b_facial*256*256,9) + "_" + num2text(H.r_skin + H.g_skin*256 + H.b_skin*256*256,9) + "_" + num2text(H.s_tone) + if(!isfacehair && selectedhairstyle) + hash+="_" + selectedhairstyle + else + hash+="_" + H.h_style + + if(isfacehair && selectedhairstyle) + hash+="_" + selectedhairstyle + else + hash+="_" + H.f_style + hash+="_" + num2text(H.underwear) +"_" + num2text(H.undershirt) + "_" + num2text(H.socks) + return hash + +/obj/item/weapon/scissors/proc/make_mannequin(mob/living/carbon/human/H) + var/mob/living/carbon/human/dummy/mannequin = new(null, H.species.name) + mannequin.gender = H.gender + mannequin.age = H.age + mannequin.b_type = H.b_type + + mannequin.r_eyes = H.r_eyes + mannequin.g_eyes = H.g_eyes + mannequin.b_eyes = H.b_eyes + + mannequin.r_hair = H.r_hair + mannequin.g_hair = H.g_hair + mannequin.b_hair = H.b_hair + + mannequin.r_facial = H.r_facial + mannequin.g_facial = H.g_facial + mannequin.b_facial = H.b_facial + + mannequin.r_skin = H.r_skin + mannequin.g_skin = H.g_skin + mannequin.b_skin = H.b_skin + + mannequin.s_tone = H.s_tone + + if(!isfacehair && selectedhairstyle) + mannequin.h_style = selectedhairstyle + else + mannequin.h_style = H.h_style + + if(isfacehair && selectedhairstyle) + mannequin.f_style = selectedhairstyle + else + mannequin.f_style = H.f_style + + mannequin.underwear = H.underwear + mannequin.undershirt = H.undershirt + mannequin.socks = H.socks + + mannequin.update_body() + mannequin.update_hair() + return mannequin + +/obj/item/weapon/scissors/Topic(href, href_list) + if(!barber || barber != usr || !barbertarget) + return + if(href_list["close"]) + clear_character_previews() + return + switch(href_list["choice"]) + if("selecthaircut") + selectedhairstyle = href_list["haircut"] + showui() + if("start") + INVOKE_ASYNC(src, .proc/dohaircut) + clear_character_previews() + +/obj/item/weapon/scissors/dropped(mob/user) + clear_character_previews() + ..() + +/obj/item/weapon/scissors/proc/create_character_previews() + var/hash = calculate_hash(barbertarget) + var/mutable_appearance/MA = LAZYACCESS(scissors_icon_cache, hash) + + if(!MA) + var/mob/living/carbon/human/dummy/mannequin = make_mannequin(barbertarget) + MA = new /mutable_appearance(mannequin) + qdel(mannequin) + LAZYSET(scissors_icon_cache, hash, MA) + + var/pos = 0 + for(var/D in cardinal) + pos++ + var/obj/screen/O = LAZYACCESS(char_render_holders, "[D]") + if(!O) + O = new + LAZYSET(char_render_holders, "[D]", O) + barber.client.screen |= O + O.appearance = MA + O.dir = D + O.screen_loc = "barber_preview_map:[pos],0" + +/obj/item/weapon/scissors/proc/clear_character_previews() + barber << browse(null, "window=barber_window") + for(var/index in char_render_holders) + var/obj/screen/S = char_render_holders[index] + if(barber && barber.client) + barber.client.screen -= S + qdel(S) + char_render_holders = null + barber = null + barbertarget = null + +/obj/item/weapon/scissors/proc/showui() + if(!barber || !barbertarget) + return + + create_character_previews() + + var/list/selected_styles_list = hair_styles_list + if(isfacehair) + selected_styles_list = facial_hair_styles_list + + var/haircutlist = "" + var/tablei = 0 + for(var/i in selected_styles_list) + var/datum/sprite_accessory/hair/tmp_hair = selected_styles_list[i] + if(barbertarget.species.name in tmp_hair.species_allowed) + var/styles = "" + if(i == selectedhairstyle || (!selectedhairstyle && ((barbertarget.f_style == i && isfacehair) || (barbertarget.h_style == i && !isfacehair)))) + styles = "color: rgb(255,0,0)" + haircutlist += "" + if(++tablei >= 5) + tablei = 0 + haircutlist+="" + haircutlist+="
                    [i]
                    " + + winshow(barber, "barber_window", TRUE) + barber << browse("Grooming" \ + + "" \ + + "CONFIRM

                    " \ + + haircutlist \ + + "", "window=barber_window") + onclose(barber, "barber_window", src) + return + +/obj/item/weapon/scissors/proc/dohaircut() + // saving those refs, it will be cleaned before do_after proc ends + var/mob/living/carbon/human/barber = src.barber + var/mob/living/carbon/human/barbertarget = src.barbertarget + + if(!barber || !barbertarget || !selectedhairstyle) + return + if(!in_range(barbertarget, barber) || barber.get_active_hand() != src) + return + + if(isfacehair) + barber.visible_message("[barber] starts cutting [barbertarget]'s facial hair with [src]!", \ + "You start cutting [barbertarget]'s facial hair with [src], this might take a minute...") + if(do_after(barber, 100, target = barbertarget)) + barbertarget.f_style = selectedhairstyle + barbertarget.update_hair() + barber.visible_message("[barber] finished cutting [barbertarget]'s facial hair", \ + "You finished cutting [barbertarget]'s facial hair") + else + barber.visible_message("[barber] starts cutting [barbertarget]'s hair with [src]!", \ + "You start cutting [barbertarget]'s hair with [src], this might take a minute...") + if(do_after(barber, 100, target = barbertarget)) + barbertarget.h_style = selectedhairstyle + barbertarget.update_hair() + barber.visible_message("[barber] finished cutting [barbertarget]'s hair", \ + "You finished cutting [barbertarget]'s hair") + + +/obj/item/weapon/scissors/attack(mob/M, mob/user, def_zone) + if(user.a_intent == "hurt") + ..() + return + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + + if(user.is_busy()) return + + if(def_zone == O_MOUTH) + if(H == user) + to_chat(user, "You can't cut your facial hair") + return + + if(H.species.name in allowed_races) + if((H.head && (H.head.flags & HEADCOVERSMOUTH)) || (H.wear_mask && (H.wear_mask.flags & MASKCOVERSMOUTH))) + to_chat(user, "The mask is in the way!") + return + + if(H.f_style in shaved_facial_hair_styles_list) + to_chat(user, "There are not enough hair to change facial hair style") + return + + selectedhairstyle = null + isfacehair = TRUE + barber = user + barbertarget = M + showui() + return + else + to_chat(user, "You don't know how to cut the hair of this race!") + return + + else if(def_zone == BP_HEAD) + if(H == user) + to_chat(user, "You can't cut your hair") + return + + if(H.species.name in allowed_races) + if(H.head && ((H.head.flags & BLOCKHAIR) || (H.head.flags & HIDEEARS))) + to_chat(user, "The headgear is in the way!") + return + + if(H.h_style in bald_hair_styles_list) + to_chat(user, "There are not enough hair to make a haircut") + return + + selectedhairstyle = null + isfacehair = FALSE + barber = user + barbertarget = M + showui() + return + else + to_chat(user, "You don't know how to cut the hair of this race!") + return + ..() diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm index c48f861e6229..508aad03e754 100644 --- a/code/game/objects/items/weapons/dice.dm +++ b/code/game/objects/items/weapons/dice.dm @@ -1,287 +1,287 @@ -#define AMPLITUDE 3 -#define SLIGHTLY_CONFUSED 10 -//from tg -/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/result - var/accursed_type = /obj/item/weapon/dice/ghost - attack_verb = list("diced") - -/obj/item/weapon/dice/examine(mob/user) - ..() - to_chat(user, "The top side is [result].") - -/obj/item/weapon/dice/ghost - desc = "Accursed die with six sides. Basic and servicable." - var/normal_type = /obj/item/weapon/dice - icon_state = "gd6" - attack_verb = list("diced", "accursed") - -/obj/item/weapon/dice/ghost/attackby(obj/item/weapon/W, mob/living/carbon/human/user) - ..() - if(istype(W, /obj/item/device/occult_scanner)) - var/obj/item/device/occult_scanner/OS = W - OS.scanned_type = src.type - to_chat(user, "[src] has been succesfully scanned by [OS]") - if(istype(W, /obj/item/weapon/nullrod)) - if(user.getBrainLoss() >= 60 || (user.mind && (user.mind.assigned_role == "Chaplain" || user.mind.role_alt_title == "Paranormal Investigator"))) - poof() - -/obj/item/weapon/dice/ghost/proc/poof() - loc.visible_message("[src] trembles in a scary manner.") - var/time = 30 - var/amplitude - var/light_range - while(time > 0) - amplitude = time/10 - light_range = (30-time)/10 - pixel_x = rand(-amplitude, amplitude) - pixel_y = rand(-amplitude/3, amplitude/3) - set_light(light_range, 1, "#a2fad1") - time-- - sleep(1) - for(var/mob/living/A in viewers(3, loc)) - A.confused += SLIGHTLY_CONFUSED - loc.visible_message("You hear a loud pop, as [src] poofs out of existence.") - playsound(loc, 'sound/effects/bubble_pop.ogg', 50, 1) - qdel(src) - -/obj/item/weapon/dice/atom_init() - . = ..() - if(!result) - result = rand(1, sides) - icon_state = "[initial(icon_state)][result]" - -/obj/item/weapon/dice/d00/atom_init() - . = ..() - result = (result - 1)*10 - -/obj/item/weapon/dice/ghost/d00/atom_init() - . = ..() - result = (result - 1)*10 - -/obj/item/weapon/dice/d2 - name = "d2" - desc = "A die with two sides. Coins are undignified!" - icon_state = "d2" - sides = 2 - accursed_type = /obj/item/weapon/dice/ghost/d2 - -/obj/item/weapon/dice/ghost/d2 - name = "d2" - desc = "Accursed die with two sides. Coins are undignified!" - icon_state = "gd2" - sides = 2 - normal_type = /obj/item/weapon/dice/d2 - -/obj/item/weapon/dice/d4 - name = "d4" - desc = "A die with four sides. The nerd's caltrop." - icon_state = "d4" - sides = 4 - accursed_type = /obj/item/weapon/dice/ghost/d4 - -/obj/item/weapon/dice/ghost/d4 - name = "d4" - desc = "Accursed die with four sides. The nerd's caltrop." - icon_state = "gd4" - sides = 4 - normal_type = /obj/item/weapon/dice/d4 - -/obj/item/weapon/dice/d8 - name = "d8" - desc = "A die with eight sides. It feels... lucky." - icon_state = "d8" - sides = 8 - accursed_type = /obj/item/weapon/dice/ghost/d8 - -/obj/item/weapon/dice/ghost/d8 - name = "d8" - desc = "Accursed die with eight sides. It feels... unlucky." - icon_state = "gd8" - sides = 8 - normal_type = /obj/item/weapon/dice/d8 - -/obj/item/weapon/dice/d10 - name = "d10" - desc = "A die with ten sides. Useful for percentages." - icon_state = "d10" - sides = 10 - accursed_type = /obj/item/weapon/dice/ghost/d10 - -/obj/item/weapon/dice/ghost/d10 - name = "d10" - desc = "Accursed die with ten sides. Useful for percentages." - icon_state = "gd10" - sides = 10 - normal_type = /obj/item/weapon/dice/d10 - -/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 - accursed_type = /obj/item/weapon/dice/ghost/d00 - -/obj/item/weapon/dice/ghost/d00 - name = "d00" - desc = "Accursed die with ten sides. Works better for d100 rolls than a golfball." - icon_state = "gd00" - sides = 10 - normal_type = /obj/item/weapon/dice/d00 - -/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 - accursed_type = /obj/item/weapon/dice/ghost/d12 - -/obj/item/weapon/dice/ghost/d12 - name = "d12" - desc = "A die with twelve sides. There's an air of neglect about it." - icon_state = "gd12" - sides = 12 - normal_type = /obj/item/weapon/dice/d12 - -/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 - accursed_type = /obj/item/weapon/dice/ghost/d20 - -/obj/item/weapon/dice/ghost/d20 - name = "d20" - desc = "Accursed die with twenty sides. The prefered die to throw at the GM." - icon_state = "gd20" - sides = 20 - normal_type = /obj/item/weapon/dice/d20 - -/obj/item/weapon/dice/attack_self(mob/user) - diceroll(user) - -/obj/item/weapon/dice/ghost/d20/attack_self(mob/living/user) - diceroll(user) - if(result == 20) - if(user.a_intent == "help") - to_chat(user, "You suddenly feel sligly better because of your own luck.") - user.adjustBruteLoss(-1) - user.adjustFireLoss(-1) - else - to_chat(user, "You suddenly feel bamboozled because of your own luck!") - user.confused += SLIGHTLY_CONFUSED - if(result == 1) - poof() - -/obj/item/weapon/dice/ghost/d20/throw_at(mob/living/target, range, speed, mob/living/thrower) - diceroll() - ..() - if(result == 20) - if(thrower.a_intent == "help") - to_chat(target, "You suddenly feel sligly better because of [thrower]'s luck.") - target.adjustBruteLoss(-1) - target.adjustFireLoss(-1) - else - to_chat(target, "You suddenly feel bamboozled because of [thrower]'s luck!") - target.confused += SLIGHTLY_CONFUSED - if(result == 1) - poof() - -/obj/item/weapon/dice/after_throw(datum/callback/callback) - ..() - diceroll() - -/obj/item/weapon/dice/ghost/attack_ghost() - visible_message("\the [src] appears to fly up into the air, levitating.") - var/time = 15 - while(time > 0) - pixel_x = rand(-AMPLITUDE/3, AMPLITUDE/3) - pixel_y = rand(-AMPLITUDE, AMPLITUDE) - time-- - sleep(1) - pixel_x = 0 - pixel_y = 0 - diceroll() - if(prob(1)) - poof() - -/obj/item/weapon/dice/proc/diceroll(mob/user) - result = rand(1, sides) - var/comment = "" - if(sides == 20 && result == 20) - comment = "Nat 20!" - else if(sides == 20 && result == 1) - comment = "Ouch, bad luck." - icon_state = "[initial(icon_state)][result]" - if(istype(src, /obj/item/weapon/dice/d00) || istype(src, /obj/item/weapon/dice/ghost/d00)) - result = (result - 1)*10 - if(user) //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 //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 && !H.species.flags[NO_MINORCUTS]) - to_chat(H, "You step on the D4!") - H.apply_damage(4, BRUTE, pick(BP_L_LEG , BP_R_LEG)) - H.Weaken(3) - -/obj/item/weapon/dice/ghost/d4/Crossed(var/mob/living/carbon/human/H) - if(istype(H) && !H.shoes && !H.species.flags[NO_MINORCUTS]) - to_chat(H, "You really regret stepping on the accursed D4!") - H.apply_damage(4, BRUTE, pick(BP_L_LEG , BP_R_LEG)) - H.Weaken(3) - H.confused += SLIGHTLY_CONFUSED - if(prob(25)) // The chance of getting 1 on a D4. - poof() - -//bag -/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/atom_init() - . = ..() - 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/ghostdice - name = "bag of dice" - desc = "Contains all the misfortune you'll ever need." - icon = 'icons/obj/dice.dmi' - icon_state = "gdicebag" - -/obj/item/weapon/storage/pill_bottle/ghostdice/atom_init() - . = ..() - new /obj/item/weapon/dice/ghost/d4(src) - new /obj/item/weapon/dice/ghost(src) - new /obj/item/weapon/dice/ghost/d8(src) - new /obj/item/weapon/dice/ghost/d10(src) - new /obj/item/weapon/dice/ghost/d00(src) - new /obj/item/weapon/dice/ghost/d12(src) - new /obj/item/weapon/dice/ghost/d20(src) - -/obj/item/weapon/storage/pill_bottle/attackby(obj/item/weapon/W, mob/living/carbon/human/user) - ..() - if(istype(W, /obj/item/device/occult_scanner)) - var/obj/item/device/occult_scanner/OS = W - OS.scanned_type = src.type - to_chat(user, "[src] has been succesfully scanned by [OS]") - -#undef AMPLITUDE -#undef SLIGHTLY_CONFUSED +#define AMPLITUDE 3 +#define SLIGHTLY_CONFUSED 10 +//from tg +/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/result + var/accursed_type = /obj/item/weapon/dice/ghost + attack_verb = list("diced") + +/obj/item/weapon/dice/examine(mob/user) + ..() + to_chat(user, "The top side is [result].") + +/obj/item/weapon/dice/ghost + desc = "Accursed die with six sides. Basic and servicable." + var/normal_type = /obj/item/weapon/dice + icon_state = "gd6" + attack_verb = list("diced", "accursed") + +/obj/item/weapon/dice/ghost/attackby(obj/item/weapon/W, mob/living/carbon/human/user) + ..() + if(istype(W, /obj/item/device/occult_scanner)) + var/obj/item/device/occult_scanner/OS = W + OS.scanned_type = src.type + to_chat(user, "[src] has been succesfully scanned by [OS]") + if(istype(W, /obj/item/weapon/nullrod)) + if(user.getBrainLoss() >= 60 || (user.mind && (user.mind.assigned_role == "Chaplain" || user.mind.role_alt_title == "Paranormal Investigator"))) + poof() + +/obj/item/weapon/dice/ghost/proc/poof() + loc.visible_message("[src] trembles in a scary manner.") + var/time = 30 + var/amplitude + var/light_range + while(time > 0) + amplitude = time/10 + light_range = (30-time)/10 + pixel_x = rand(-amplitude, amplitude) + pixel_y = rand(-amplitude/3, amplitude/3) + set_light(light_range, 1, "#a2fad1") + time-- + sleep(1) + for(var/mob/living/A in viewers(3, loc)) + A.confused += SLIGHTLY_CONFUSED + loc.visible_message("You hear a loud pop, as [src] poofs out of existence.") + playsound(loc, 'sound/effects/bubble_pop.ogg', 50, 1) + qdel(src) + +/obj/item/weapon/dice/atom_init() + . = ..() + if(!result) + result = rand(1, sides) + icon_state = "[initial(icon_state)][result]" + +/obj/item/weapon/dice/d00/atom_init() + . = ..() + result = (result - 1)*10 + +/obj/item/weapon/dice/ghost/d00/atom_init() + . = ..() + result = (result - 1)*10 + +/obj/item/weapon/dice/d2 + name = "d2" + desc = "A die with two sides. Coins are undignified!" + icon_state = "d2" + sides = 2 + accursed_type = /obj/item/weapon/dice/ghost/d2 + +/obj/item/weapon/dice/ghost/d2 + name = "d2" + desc = "Accursed die with two sides. Coins are undignified!" + icon_state = "gd2" + sides = 2 + normal_type = /obj/item/weapon/dice/d2 + +/obj/item/weapon/dice/d4 + name = "d4" + desc = "A die with four sides. The nerd's caltrop." + icon_state = "d4" + sides = 4 + accursed_type = /obj/item/weapon/dice/ghost/d4 + +/obj/item/weapon/dice/ghost/d4 + name = "d4" + desc = "Accursed die with four sides. The nerd's caltrop." + icon_state = "gd4" + sides = 4 + normal_type = /obj/item/weapon/dice/d4 + +/obj/item/weapon/dice/d8 + name = "d8" + desc = "A die with eight sides. It feels... lucky." + icon_state = "d8" + sides = 8 + accursed_type = /obj/item/weapon/dice/ghost/d8 + +/obj/item/weapon/dice/ghost/d8 + name = "d8" + desc = "Accursed die with eight sides. It feels... unlucky." + icon_state = "gd8" + sides = 8 + normal_type = /obj/item/weapon/dice/d8 + +/obj/item/weapon/dice/d10 + name = "d10" + desc = "A die with ten sides. Useful for percentages." + icon_state = "d10" + sides = 10 + accursed_type = /obj/item/weapon/dice/ghost/d10 + +/obj/item/weapon/dice/ghost/d10 + name = "d10" + desc = "Accursed die with ten sides. Useful for percentages." + icon_state = "gd10" + sides = 10 + normal_type = /obj/item/weapon/dice/d10 + +/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 + accursed_type = /obj/item/weapon/dice/ghost/d00 + +/obj/item/weapon/dice/ghost/d00 + name = "d00" + desc = "Accursed die with ten sides. Works better for d100 rolls than a golfball." + icon_state = "gd00" + sides = 10 + normal_type = /obj/item/weapon/dice/d00 + +/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 + accursed_type = /obj/item/weapon/dice/ghost/d12 + +/obj/item/weapon/dice/ghost/d12 + name = "d12" + desc = "A die with twelve sides. There's an air of neglect about it." + icon_state = "gd12" + sides = 12 + normal_type = /obj/item/weapon/dice/d12 + +/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 + accursed_type = /obj/item/weapon/dice/ghost/d20 + +/obj/item/weapon/dice/ghost/d20 + name = "d20" + desc = "Accursed die with twenty sides. The prefered die to throw at the GM." + icon_state = "gd20" + sides = 20 + normal_type = /obj/item/weapon/dice/d20 + +/obj/item/weapon/dice/attack_self(mob/user) + diceroll(user) + +/obj/item/weapon/dice/ghost/d20/attack_self(mob/living/user) + diceroll(user) + if(result == 20) + if(user.a_intent == "help") + to_chat(user, "You suddenly feel sligly better because of your own luck.") + user.adjustBruteLoss(-1) + user.adjustFireLoss(-1) + else + to_chat(user, "You suddenly feel bamboozled because of your own luck!") + user.confused += SLIGHTLY_CONFUSED + if(result == 1) + poof() + +/obj/item/weapon/dice/ghost/d20/throw_at(mob/living/target, range, speed, mob/living/thrower) + diceroll() + ..() + if(result == 20) + if(thrower.a_intent == "help") + to_chat(target, "You suddenly feel sligly better because of [thrower]'s luck.") + target.adjustBruteLoss(-1) + target.adjustFireLoss(-1) + else + to_chat(target, "You suddenly feel bamboozled because of [thrower]'s luck!") + target.confused += SLIGHTLY_CONFUSED + if(result == 1) + poof() + +/obj/item/weapon/dice/after_throw(datum/callback/callback) + ..() + diceroll() + +/obj/item/weapon/dice/ghost/attack_ghost() + visible_message("\the [src] appears to fly up into the air, levitating.") + var/time = 15 + while(time > 0) + pixel_x = rand(-AMPLITUDE/3, AMPLITUDE/3) + pixel_y = rand(-AMPLITUDE, AMPLITUDE) + time-- + sleep(1) + pixel_x = 0 + pixel_y = 0 + diceroll() + if(prob(1)) + poof() + +/obj/item/weapon/dice/proc/diceroll(mob/user) + result = rand(1, sides) + var/comment = "" + if(sides == 20 && result == 20) + comment = "Nat 20!" + else if(sides == 20 && result == 1) + comment = "Ouch, bad luck." + icon_state = "[initial(icon_state)][result]" + if(istype(src, /obj/item/weapon/dice/d00) || istype(src, /obj/item/weapon/dice/ghost/d00)) + result = (result - 1)*10 + if(user) //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 //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 && !H.species.flags[NO_MINORCUTS]) + to_chat(H, "You step on the D4!") + H.apply_damage(4, BRUTE, pick(BP_L_LEG , BP_R_LEG)) + H.Weaken(3) + +/obj/item/weapon/dice/ghost/d4/Crossed(var/mob/living/carbon/human/H) + if(istype(H) && !H.shoes && !H.species.flags[NO_MINORCUTS]) + to_chat(H, "You really regret stepping on the accursed D4!") + H.apply_damage(4, BRUTE, pick(BP_L_LEG , BP_R_LEG)) + H.Weaken(3) + H.confused += SLIGHTLY_CONFUSED + if(prob(25)) // The chance of getting 1 on a D4. + poof() + +//bag +/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/atom_init() + . = ..() + 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/ghostdice + name = "bag of dice" + desc = "Contains all the misfortune you'll ever need." + icon = 'icons/obj/dice.dmi' + icon_state = "gdicebag" + +/obj/item/weapon/storage/pill_bottle/ghostdice/atom_init() + . = ..() + new /obj/item/weapon/dice/ghost/d4(src) + new /obj/item/weapon/dice/ghost(src) + new /obj/item/weapon/dice/ghost/d8(src) + new /obj/item/weapon/dice/ghost/d10(src) + new /obj/item/weapon/dice/ghost/d00(src) + new /obj/item/weapon/dice/ghost/d12(src) + new /obj/item/weapon/dice/ghost/d20(src) + +/obj/item/weapon/storage/pill_bottle/attackby(obj/item/weapon/W, mob/living/carbon/human/user) + ..() + if(istype(W, /obj/item/device/occult_scanner)) + var/obj/item/device/occult_scanner/OS = W + OS.scanned_type = src.type + to_chat(user, "[src] has been succesfully scanned by [OS]") + +#undef AMPLITUDE +#undef SLIGHTLY_CONFUSED diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index f6a68f83db18..2c574d5c6603 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -1,650 +1,650 @@ -/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 - 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/atom_init() - . = ..() - 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(value) - //testing("[name]: DNA2 SE blocks after SetValue: [english_list(buf.dna.SE)]") - -/obj/item/weapon/dnainjector/attack_paw(mob/user) - return attack_hand(user) - -/obj/item/weapon/dnainjector/proc/GetRealBlock(selblock) - if(selblock==0) - return block - else - return selblock - -/obj/item/weapon/dnainjector/proc/GetState(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(on, 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(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(val,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, mob/user) - user.remove_from_mob(src) - loc = null - - if(istype(M,/mob/living)) - M.radiation += rand(15,45) - M.dna_inject_count += rand(1,3) - - if (!(NOCLONE in M.mutations)) // prevents drained people from having their DNA changed - 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, block!=null, 0) //#Z2 We go thru chance check - uses-- - - if(M && prob(5 + M.dna_inject_count)) - M.dna_inject_count = 0 - trigger_side_effect(M) - - qdel(src) - -/obj/item/weapon/dnainjector/attack(mob/living/carbon/M, mob/living/user) - if (!istype(M)) - return - if(!M.try_inject(user, TRUE)) - 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])") - - if (buf.types & DNA2_BUF_SE) - if(block)// Isolated injector - //testing("Isolated block [block] injector with contents: [GetValue()]") - if (GetState() && block == MONKEYBLOCK) - message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] \red(MONKEY) [ADMIN_JMP(user)]") - 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] \red(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)) - message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name] \red(MONKEY) [ADMIN_JMP(user)]") - 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] \red(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]") - - add_fingerprint(user) - user.visible_message("[user] injects [M] with the DNA Injector!") - - inject(M, user) - - -/obj/item/weapon/dnainjector/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 - -/obj/item/weapon/dnainjector/hulkmut/atom_init() - block = HULKBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antihulk - name = "DNA-Injector (Anti-Hulk)" - desc = "Cures green skin." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - -/obj/item/weapon/dnainjector/antihulk/atom_init() - block = HULKBLOCK - . = ..() - -/obj/item/weapon/dnainjector/xraymut - name = "DNA-Injector (Xray)" - desc = "Finally you can see what the Captain does." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 8 - -/obj/item/weapon/dnainjector/xraymut/atom_init() - block = XRAYBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antixray - name = "DNA-Injector (Anti-Xray)" - desc = "It will make you see harder." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 8 - -/obj/item/weapon/dnainjector/antixray/atom_init() - block = XRAYBLOCK - . = ..() - -/obj/item/weapon/dnainjector/firemut - name = "DNA-Injector (Fire)" - desc = "Gives you fire." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 10 - - -/obj/item/weapon/dnainjector/firemut/atom_init() - block = FIREBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antifire - name = "DNA-Injector (Anti-Fire)" - desc = "Cures fire." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 10 - -/obj/item/weapon/dnainjector/antifire/atom_init() - block = FIREBLOCK - . = ..() - -/obj/item/weapon/dnainjector/telemut - name = "DNA-Injector (Tele.)" - desc = "Super brain man!" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 12 - -/obj/item/weapon/dnainjector/telemut/atom_init() - block = TELEBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antitele - name = "DNA-Injector (Anti-Tele.)" - desc = "Will make you not able to control your mind." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 12 - -/obj/item/weapon/dnainjector/antitele/atom_init() - block = TELEBLOCK - . = ..() - -/obj/item/weapon/dnainjector/nobreath - name = "DNA-Injector (No Breath)" - desc = "Hold your breath and count to infinity." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/nobreath/atom_init() - block = NOBREATHBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antinobreath - name = "DNA-Injector (Anti-No Breath)" - desc = "Hold your breath and count to 100." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - -/obj/item/weapon/dnainjector/antinobreath/atom_init() - block = NOBREATHBLOCK - . = ..() - -/obj/item/weapon/dnainjector/remoteview - name = "DNA-Injector (Remote View)" - desc = "Stare into the distance for a reason." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/remoteview/atom_init() - block = REMOTEVIEWBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antiremoteview - name = "DNA-Injector (Anti-Remote View)" - desc = "Cures green skin." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - -/obj/item/weapon/dnainjector/antiremoteview/atom_init() - block = REMOTEVIEWBLOCK - . = ..() - -/obj/item/weapon/dnainjector/regenerate - name = "DNA-Injector (Regeneration)" - desc = "Healthy but hungry." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/regenerate/atom_init() - block = REGENERATEBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antiregenerate - name = "DNA-Injector (Anti-Regeneration)" - desc = "Sickly but sated." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - -/obj/item/weapon/dnainjector/antiregenerate/atom_init() - block = REGENERATEBLOCK - . = ..() - -/obj/item/weapon/dnainjector/runfast - name = "DNA-Injector (Increase Run)" - desc = "Running Man." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/runfast/atom_init() - block = INCREASERUNBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antirunfast - name = "DNA-Injector (Anti-Increase Run)" - desc = "Walking Man." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - -/obj/item/weapon/dnainjector/antirunfast/atom_init() - block = INCREASERUNBLOCK - . = ..() - -/obj/item/weapon/dnainjector/morph - name = "DNA-Injector (Morph)" - desc = "A total makeover." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/morph/atom_init() - block = MORPHBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antimorph - name = "DNA-Injector (Anti-Morph)" - desc = "Cures identity crisis." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - -/obj/item/weapon/dnainjector/antimorph/atom_init() - block = MORPHBLOCK - . = ..() - -/* No COLDBLOCK on bay -/obj/item/weapon/dnainjector/cold - name = "DNA-Injector (Cold)" - desc = "Feels a bit chilly." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/cold/atom_init() - block = COLDBLOCK - . = ..() - -/obj/item/weapon/dnainjector/anticold - name = "DNA-Injector (Anti-Cold)" - desc = "Feels room-temperature." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - -/obj/item/weapon/dnainjector/anticold/atom_init() - block = COLDBLOCK - . = ..() -*/ - -/obj/item/weapon/dnainjector/noprints - name = "DNA-Injector (No Prints)" - desc = "Better than a pair of budget insulated gloves." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/noprints/atom_init() - block = NOPRINTSBLOCK - . = ..() - -/obj/item/weapon/dnainjector/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 - -/obj/item/weapon/dnainjector/antinoprints/atom_init() - block = NOPRINTSBLOCK - . = ..() - -/obj/item/weapon/dnainjector/insulation - name = "DNA-Injector (Shock Immunity)" - desc = "Better than a pair of real insulated gloves." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/insulation/atom_init() - block = SHOCKIMMUNITYBLOCK - . = ..() - -/obj/item/weapon/dnainjector/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 - -/obj/item/weapon/dnainjector/antiinsulation/atom_init() - block = SHOCKIMMUNITYBLOCK - . = ..() - -/obj/item/weapon/dnainjector/midgit - name = "DNA-Injector (Small Size)" - desc = "Makes you shrink." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/midgit/atom_init() - block = SMALLSIZEBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antimidgit - name = "DNA-Injector (Anti-Small Size)" - desc = "Makes you grow. But not too much." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - -/obj/item/weapon/dnainjector/antimidgit/atom_init() - block = SMALLSIZEBLOCK - . = ..() - -///////////////////////////////////// -/obj/item/weapon/dnainjector/antiglasses - name = "DNA-Injector (Anti-Glasses)" - desc = "Toss away those glasses!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 1 - -/obj/item/weapon/dnainjector/antiglasses/atom_init() - block = GLASSESBLOCK - . = ..() - -/obj/item/weapon/dnainjector/glassesmut - name = "DNA-Injector (Glasses)" - desc = "Will make you need dorkish glasses." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 1 - -/obj/item/weapon/dnainjector/glassesmut/atom_init() - block = GLASSESBLOCK - . = ..() - -/obj/item/weapon/dnainjector/epimut - name = "DNA-Injector (Epi.)" - desc = "Shake shake shake the room!" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 3 - -/obj/item/weapon/dnainjector/epimut/atom_init() - block = HEADACHEBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antiepi - name = "DNA-Injector (Anti-Epi.)" - desc = "Will fix you up from shaking the room." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 3 - -/obj/item/weapon/dnainjector/antiepi/atom_init() - block = HEADACHEBLOCK - . = ..() - -/obj/item/weapon/dnainjector/anticough - name = "DNA-Injector (Anti-Cough)" - desc = "Will stop that awful noise." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 5 - -/obj/item/weapon/dnainjector/anticough/atom_init() - block = COUGHBLOCK - . = ..() - -/obj/item/weapon/dnainjector/coughmut - name = "DNA-Injector (Cough)" - desc = "Will bring forth a sound of horror from your throat." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 5 - -/obj/item/weapon/dnainjector/coughmut/atom_init() - block = COUGHBLOCK - . = ..() - -/obj/item/weapon/dnainjector/clumsymut - name = "DNA-Injector (Clumsy)" - desc = "Makes clumsy minions." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 6 - -/obj/item/weapon/dnainjector/clumsymut/atom_init() - block = CLUMSYBLOCK - . = ..() - -/obj/item/weapon/dnainjector/anticlumsy - name = "DNA-Injector (Anti-Clumy)" - desc = "Cleans up confusion." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 6 - -/obj/item/weapon/dnainjector/anticlumsy/atom_init() - block = CLUMSYBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antitour - name = "DNA-Injector (Anti-Tour.)" - desc = "Will cure tourrets." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 7 - -/obj/item/weapon/dnainjector/antitour/atom_init() - block = TWITCHBLOCK - . = ..() - -/obj/item/weapon/dnainjector/tourmut - name = "DNA-Injector (Tour.)" - desc = "Gives you a nasty case off tourrets." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 7 - -/obj/item/weapon/dnainjector/tourmut/atom_init() - block = TWITCHBLOCK - . = ..() - -/obj/item/weapon/dnainjector/stuttmut - name = "DNA-Injector (Stutt.)" - desc = "Makes you s-s-stuttterrr." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 9 - -/obj/item/weapon/dnainjector/stuttmut/atom_init() - block = NERVOUSBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antistutt - name = "DNA-Injector (Anti-Stutt.)" - desc = "Fixes that speaking impairment." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 9 - -/obj/item/weapon/dnainjector/antistutt/atom_init() - block = NERVOUSBLOCK - . = ..() - -/obj/item/weapon/dnainjector/blindmut - name = "DNA-Injector (Blind)" - desc = "Makes you not see anything." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 11 - -/obj/item/weapon/dnainjector/blindmut/atom_init() - block = BLINDBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antiblind - name = "DNA-Injector (Anti-Blind)" - desc = "ITS A MIRACLE!!!" - datatype = DNA2_BUF_SE - value = 0x001 - //block = 11 - -/obj/item/weapon/dnainjector/antiblind/atom_init() - block = BLINDBLOCK - . = ..() - -/obj/item/weapon/dnainjector/deafmut - name = "DNA-Injector (Deaf)" - desc = "Sorry, what did you say?" - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 13 - -/obj/item/weapon/dnainjector/deafmut/atom_init() - block = DEAFBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antideaf - name = "DNA-Injector (Anti-Deaf)" - desc = "Will make you hear once more." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 13 - -/obj/item/weapon/dnainjector/antideaf/atom_init() - block = DEAFBLOCK - . = ..() - -/obj/item/weapon/dnainjector/hallucination - name = "DNA-Injector (Halluctination)" - desc = "What you see isn't always what you get." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 2 - -/obj/item/weapon/dnainjector/hallucination/atom_init() - block = HALLUCINATIONBLOCK - . = ..() - -/obj/item/weapon/dnainjector/antihallucination - name = "DNA-Injector (Anti-Hallucination)" - desc = "What you see is what you get." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 2 - -/obj/item/weapon/dnainjector/antihallucination/atom_init() - block = HALLUCINATIONBLOCK - . = ..() - -/obj/item/weapon/dnainjector/h2m - name = "DNA-Injector (Human > Monkey)" - desc = "Will make you a flea bag." - datatype = DNA2_BUF_SE - value = 0xFFF - //block = 14 - -/obj/item/weapon/dnainjector/h2m/atom_init() - block = MONKEYBLOCK - . = ..() - -/obj/item/weapon/dnainjector/m2h - name = "DNA-Injector (Monkey > Human)" - desc = "Will make you...less hairy." - datatype = DNA2_BUF_SE - value = 0x001 - //block = 14 - -/obj/item/weapon/dnainjector/m2h/atom_init() - block = MONKEYBLOCK - . = ..() +/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 + 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/atom_init() + . = ..() + 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(value) + //testing("[name]: DNA2 SE blocks after SetValue: [english_list(buf.dna.SE)]") + +/obj/item/weapon/dnainjector/attack_paw(mob/user) + return attack_hand(user) + +/obj/item/weapon/dnainjector/proc/GetRealBlock(selblock) + if(selblock==0) + return block + else + return selblock + +/obj/item/weapon/dnainjector/proc/GetState(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(on, 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(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(val,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, mob/user) + user.remove_from_mob(src) + loc = null + + if(istype(M,/mob/living)) + M.radiation += rand(15,45) + M.dna_inject_count += rand(1,3) + + if (!(NOCLONE in M.mutations)) // prevents drained people from having their DNA changed + 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, block!=null, 0) //#Z2 We go thru chance check + uses-- + + if(M && prob(5 + M.dna_inject_count)) + M.dna_inject_count = 0 + trigger_side_effect(M) + + qdel(src) + +/obj/item/weapon/dnainjector/attack(mob/living/carbon/M, mob/living/user) + if (!istype(M)) + return + if(!M.try_inject(user, TRUE)) + 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])") + + if (buf.types & DNA2_BUF_SE) + if(block)// Isolated injector + //testing("Isolated block [block] injector with contents: [GetValue()]") + if (GetState() && block == MONKEYBLOCK) + message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] \red(MONKEY) [ADMIN_JMP(user)]") + 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] \red(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)) + message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the [name] \red(MONKEY) [ADMIN_JMP(user)]") + 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] \red(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]") + + add_fingerprint(user) + user.visible_message("[user] injects [M] with the DNA Injector!") + + inject(M, user) + + +/obj/item/weapon/dnainjector/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 + +/obj/item/weapon/dnainjector/hulkmut/atom_init() + block = HULKBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antihulk + name = "DNA-Injector (Anti-Hulk)" + desc = "Cures green skin." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + +/obj/item/weapon/dnainjector/antihulk/atom_init() + block = HULKBLOCK + . = ..() + +/obj/item/weapon/dnainjector/xraymut + name = "DNA-Injector (Xray)" + desc = "Finally you can see what the Captain does." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 8 + +/obj/item/weapon/dnainjector/xraymut/atom_init() + block = XRAYBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antixray + name = "DNA-Injector (Anti-Xray)" + desc = "It will make you see harder." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 8 + +/obj/item/weapon/dnainjector/antixray/atom_init() + block = XRAYBLOCK + . = ..() + +/obj/item/weapon/dnainjector/firemut + name = "DNA-Injector (Fire)" + desc = "Gives you fire." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 10 + + +/obj/item/weapon/dnainjector/firemut/atom_init() + block = FIREBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antifire + name = "DNA-Injector (Anti-Fire)" + desc = "Cures fire." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 10 + +/obj/item/weapon/dnainjector/antifire/atom_init() + block = FIREBLOCK + . = ..() + +/obj/item/weapon/dnainjector/telemut + name = "DNA-Injector (Tele.)" + desc = "Super brain man!" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 12 + +/obj/item/weapon/dnainjector/telemut/atom_init() + block = TELEBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antitele + name = "DNA-Injector (Anti-Tele.)" + desc = "Will make you not able to control your mind." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 12 + +/obj/item/weapon/dnainjector/antitele/atom_init() + block = TELEBLOCK + . = ..() + +/obj/item/weapon/dnainjector/nobreath + name = "DNA-Injector (No Breath)" + desc = "Hold your breath and count to infinity." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/nobreath/atom_init() + block = NOBREATHBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antinobreath + name = "DNA-Injector (Anti-No Breath)" + desc = "Hold your breath and count to 100." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + +/obj/item/weapon/dnainjector/antinobreath/atom_init() + block = NOBREATHBLOCK + . = ..() + +/obj/item/weapon/dnainjector/remoteview + name = "DNA-Injector (Remote View)" + desc = "Stare into the distance for a reason." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/remoteview/atom_init() + block = REMOTEVIEWBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antiremoteview + name = "DNA-Injector (Anti-Remote View)" + desc = "Cures green skin." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + +/obj/item/weapon/dnainjector/antiremoteview/atom_init() + block = REMOTEVIEWBLOCK + . = ..() + +/obj/item/weapon/dnainjector/regenerate + name = "DNA-Injector (Regeneration)" + desc = "Healthy but hungry." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/regenerate/atom_init() + block = REGENERATEBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antiregenerate + name = "DNA-Injector (Anti-Regeneration)" + desc = "Sickly but sated." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + +/obj/item/weapon/dnainjector/antiregenerate/atom_init() + block = REGENERATEBLOCK + . = ..() + +/obj/item/weapon/dnainjector/runfast + name = "DNA-Injector (Increase Run)" + desc = "Running Man." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/runfast/atom_init() + block = INCREASERUNBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antirunfast + name = "DNA-Injector (Anti-Increase Run)" + desc = "Walking Man." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + +/obj/item/weapon/dnainjector/antirunfast/atom_init() + block = INCREASERUNBLOCK + . = ..() + +/obj/item/weapon/dnainjector/morph + name = "DNA-Injector (Morph)" + desc = "A total makeover." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/morph/atom_init() + block = MORPHBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antimorph + name = "DNA-Injector (Anti-Morph)" + desc = "Cures identity crisis." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + +/obj/item/weapon/dnainjector/antimorph/atom_init() + block = MORPHBLOCK + . = ..() + +/* No COLDBLOCK on bay +/obj/item/weapon/dnainjector/cold + name = "DNA-Injector (Cold)" + desc = "Feels a bit chilly." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/cold/atom_init() + block = COLDBLOCK + . = ..() + +/obj/item/weapon/dnainjector/anticold + name = "DNA-Injector (Anti-Cold)" + desc = "Feels room-temperature." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + +/obj/item/weapon/dnainjector/anticold/atom_init() + block = COLDBLOCK + . = ..() +*/ + +/obj/item/weapon/dnainjector/noprints + name = "DNA-Injector (No Prints)" + desc = "Better than a pair of budget insulated gloves." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/noprints/atom_init() + block = NOPRINTSBLOCK + . = ..() + +/obj/item/weapon/dnainjector/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 + +/obj/item/weapon/dnainjector/antinoprints/atom_init() + block = NOPRINTSBLOCK + . = ..() + +/obj/item/weapon/dnainjector/insulation + name = "DNA-Injector (Shock Immunity)" + desc = "Better than a pair of real insulated gloves." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/insulation/atom_init() + block = SHOCKIMMUNITYBLOCK + . = ..() + +/obj/item/weapon/dnainjector/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 + +/obj/item/weapon/dnainjector/antiinsulation/atom_init() + block = SHOCKIMMUNITYBLOCK + . = ..() + +/obj/item/weapon/dnainjector/midgit + name = "DNA-Injector (Small Size)" + desc = "Makes you shrink." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/midgit/atom_init() + block = SMALLSIZEBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antimidgit + name = "DNA-Injector (Anti-Small Size)" + desc = "Makes you grow. But not too much." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + +/obj/item/weapon/dnainjector/antimidgit/atom_init() + block = SMALLSIZEBLOCK + . = ..() + +///////////////////////////////////// +/obj/item/weapon/dnainjector/antiglasses + name = "DNA-Injector (Anti-Glasses)" + desc = "Toss away those glasses!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 1 + +/obj/item/weapon/dnainjector/antiglasses/atom_init() + block = GLASSESBLOCK + . = ..() + +/obj/item/weapon/dnainjector/glassesmut + name = "DNA-Injector (Glasses)" + desc = "Will make you need dorkish glasses." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 1 + +/obj/item/weapon/dnainjector/glassesmut/atom_init() + block = GLASSESBLOCK + . = ..() + +/obj/item/weapon/dnainjector/epimut + name = "DNA-Injector (Epi.)" + desc = "Shake shake shake the room!" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 3 + +/obj/item/weapon/dnainjector/epimut/atom_init() + block = HEADACHEBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antiepi + name = "DNA-Injector (Anti-Epi.)" + desc = "Will fix you up from shaking the room." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 3 + +/obj/item/weapon/dnainjector/antiepi/atom_init() + block = HEADACHEBLOCK + . = ..() + +/obj/item/weapon/dnainjector/anticough + name = "DNA-Injector (Anti-Cough)" + desc = "Will stop that awful noise." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 5 + +/obj/item/weapon/dnainjector/anticough/atom_init() + block = COUGHBLOCK + . = ..() + +/obj/item/weapon/dnainjector/coughmut + name = "DNA-Injector (Cough)" + desc = "Will bring forth a sound of horror from your throat." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 5 + +/obj/item/weapon/dnainjector/coughmut/atom_init() + block = COUGHBLOCK + . = ..() + +/obj/item/weapon/dnainjector/clumsymut + name = "DNA-Injector (Clumsy)" + desc = "Makes clumsy minions." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 6 + +/obj/item/weapon/dnainjector/clumsymut/atom_init() + block = CLUMSYBLOCK + . = ..() + +/obj/item/weapon/dnainjector/anticlumsy + name = "DNA-Injector (Anti-Clumy)" + desc = "Cleans up confusion." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 6 + +/obj/item/weapon/dnainjector/anticlumsy/atom_init() + block = CLUMSYBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antitour + name = "DNA-Injector (Anti-Tour.)" + desc = "Will cure tourrets." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 7 + +/obj/item/weapon/dnainjector/antitour/atom_init() + block = TWITCHBLOCK + . = ..() + +/obj/item/weapon/dnainjector/tourmut + name = "DNA-Injector (Tour.)" + desc = "Gives you a nasty case off tourrets." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 7 + +/obj/item/weapon/dnainjector/tourmut/atom_init() + block = TWITCHBLOCK + . = ..() + +/obj/item/weapon/dnainjector/stuttmut + name = "DNA-Injector (Stutt.)" + desc = "Makes you s-s-stuttterrr." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 9 + +/obj/item/weapon/dnainjector/stuttmut/atom_init() + block = NERVOUSBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antistutt + name = "DNA-Injector (Anti-Stutt.)" + desc = "Fixes that speaking impairment." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 9 + +/obj/item/weapon/dnainjector/antistutt/atom_init() + block = NERVOUSBLOCK + . = ..() + +/obj/item/weapon/dnainjector/blindmut + name = "DNA-Injector (Blind)" + desc = "Makes you not see anything." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 11 + +/obj/item/weapon/dnainjector/blindmut/atom_init() + block = BLINDBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antiblind + name = "DNA-Injector (Anti-Blind)" + desc = "ITS A MIRACLE!!!" + datatype = DNA2_BUF_SE + value = 0x001 + //block = 11 + +/obj/item/weapon/dnainjector/antiblind/atom_init() + block = BLINDBLOCK + . = ..() + +/obj/item/weapon/dnainjector/deafmut + name = "DNA-Injector (Deaf)" + desc = "Sorry, what did you say?" + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 13 + +/obj/item/weapon/dnainjector/deafmut/atom_init() + block = DEAFBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antideaf + name = "DNA-Injector (Anti-Deaf)" + desc = "Will make you hear once more." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 13 + +/obj/item/weapon/dnainjector/antideaf/atom_init() + block = DEAFBLOCK + . = ..() + +/obj/item/weapon/dnainjector/hallucination + name = "DNA-Injector (Halluctination)" + desc = "What you see isn't always what you get." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 2 + +/obj/item/weapon/dnainjector/hallucination/atom_init() + block = HALLUCINATIONBLOCK + . = ..() + +/obj/item/weapon/dnainjector/antihallucination + name = "DNA-Injector (Anti-Hallucination)" + desc = "What you see is what you get." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 2 + +/obj/item/weapon/dnainjector/antihallucination/atom_init() + block = HALLUCINATIONBLOCK + . = ..() + +/obj/item/weapon/dnainjector/h2m + name = "DNA-Injector (Human > Monkey)" + desc = "Will make you a flea bag." + datatype = DNA2_BUF_SE + value = 0xFFF + //block = 14 + +/obj/item/weapon/dnainjector/h2m/atom_init() + block = MONKEYBLOCK + . = ..() + +/obj/item/weapon/dnainjector/m2h + name = "DNA-Injector (Monkey > Human)" + desc = "Will make you...less hairy." + datatype = DNA2_BUF_SE + value = 0x001 + //block = 14 + +/obj/item/weapon/dnainjector/m2h/atom_init() + block = MONKEYBLOCK + . = ..() diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 617171855a99..b3b47ecabbc4 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -1,57 +1,57 @@ -/obj/item/weapon/plastique/attack_self(mob/user) - var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num - if(newtime < 10) - newtime = 10 - timer = newtime - to_chat(user, "Timer set for [timer] seconds.") - -/obj/item/weapon/plastique/afterattack(atom/target, mob/user, flag) - if (!flag) - return - if (istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/machinery/nuclearbomb)) - return - if(user.is_busy()) return - to_chat(user, "Planting explosives...") - if(ismob(target)) - var/mob/living/M = target - user.attack_log += "\[[time_stamp()]\] [user.real_name] tried planting [name] on [M.real_name] ([M.ckey])" - msg_admin_attack("[user.real_name] ([user.ckey]) [ADMIN_FLW(user)] tried planting [name] on [M.real_name] ([M.ckey]) [ADMIN_FLW(M)]") - user.visible_message(" [user.name] is trying to plant some kind of explosive on [M.name]!") - else - user.attack_log += "\[[time_stamp()]\] [user.real_name] tried planting [name] on [target.name]" - msg_admin_attack("[user.real_name] ([user.ckey]) [ADMIN_FLW(user)] tried planting [name] on [target.name] [ADMIN_JMP(target)]") - - if(do_after(user, 50, target = target) && in_range(user, target)) - user.drop_item() - target = target - loc = null - var/location - if(ismob(target)) - var/mob/living/M = target - M.attack_log += "\[[time_stamp()]\] Had the [name] planted on them by [user.real_name] ([user.ckey])" - user.visible_message(" [user.name] finished planting an explosive on [M.name]!") - else - location = target - target.overlays += image('icons/obj/assemblies.dmi', "plastic-explosive2") - to_chat(user, "Bomb has been planted. Timer counting down from [timer].") - addtimer(CALLBACK(src, .proc/prime_explosion, target, location), timer * 10) - -/obj/item/weapon/plastique/proc/prime_explosion(atom/target, location) - if(!target) - return - if(ismob(target) || isobj(target)) - location = target.loc - if(istype(target, /turf/simulated/wall)) - var/turf/simulated/wall/W = target - W.dismantle_wall(1) - else - target.ex_act(1) - - explosion(location, 0, 0, 2, 3) - if(target && !QDELETED(target)) - target.overlays -= image('icons/obj/assemblies.dmi', "plastic-explosive2") - if(src) - qdel(src) - -/obj/item/weapon/plastique/attack(mob/M, mob/user, def_zone) - return +/obj/item/weapon/plastique/attack_self(mob/user) + var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num + if(newtime < 10) + newtime = 10 + timer = newtime + to_chat(user, "Timer set for [timer] seconds.") + +/obj/item/weapon/plastique/afterattack(atom/target, mob/user, flag) + if (!flag) + return + if (istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/machinery/nuclearbomb)) + return + if(user.is_busy()) return + to_chat(user, "Planting explosives...") + if(ismob(target)) + var/mob/living/M = target + user.attack_log += "\[[time_stamp()]\] [user.real_name] tried planting [name] on [M.real_name] ([M.ckey])" + msg_admin_attack("[user.real_name] ([user.ckey]) [ADMIN_FLW(user)] tried planting [name] on [M.real_name] ([M.ckey]) [ADMIN_FLW(M)]") + user.visible_message(" [user.name] is trying to plant some kind of explosive on [M.name]!") + else + user.attack_log += "\[[time_stamp()]\] [user.real_name] tried planting [name] on [target.name]" + msg_admin_attack("[user.real_name] ([user.ckey]) [ADMIN_FLW(user)] tried planting [name] on [target.name] [ADMIN_JMP(target)]") + + if(do_after(user, 50, target = target) && in_range(user, target)) + user.drop_item() + target = target + loc = null + var/location + if(ismob(target)) + var/mob/living/M = target + M.attack_log += "\[[time_stamp()]\] Had the [name] planted on them by [user.real_name] ([user.ckey])" + user.visible_message(" [user.name] finished planting an explosive on [M.name]!") + else + location = target + target.overlays += image('icons/obj/assemblies.dmi', "plastic-explosive2") + to_chat(user, "Bomb has been planted. Timer counting down from [timer].") + addtimer(CALLBACK(src, .proc/prime_explosion, target, location), timer * 10) + +/obj/item/weapon/plastique/proc/prime_explosion(atom/target, location) + if(!target) + return + if(ismob(target) || isobj(target)) + location = target.loc + if(istype(target, /turf/simulated/wall)) + var/turf/simulated/wall/W = target + W.dismantle_wall(1) + else + target.ex_act(1) + + explosion(location, 0, 0, 2, 3) + if(target && !QDELETED(target)) + target.overlays -= image('icons/obj/assemblies.dmi', "plastic-explosive2") + if(src) + qdel(src) + +/obj/item/weapon/plastique/attack(mob/M, mob/user, def_zone) + return diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index 9b503497e062..1e8ea54088ae 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -1,146 +1,146 @@ -/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 = CONDUCT - throwforce = 10 - w_class = 3.0 - throw_speed = 2 - throw_range = 10 - force = 10.0 - m_amt = 90 - 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" - var/spray_amount = 1 //units of liquid per particle - var/spray_range = 4 - -/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. - throwforce = 2 - w_class = 2.0 - force = 3.0 - m_amt = 0 - max_water = 30 - sprite_name = "miniFE" - -/obj/item/weapon/extinguisher/atom_init() - . = ..() - var/datum/reagents/R = new/datum/reagents(max_water) - reagents = R - R.my_atom = src - R.add_reagent("water", max_water) - -/obj/item/weapon/extinguisher/examine(mob/user) - ..() - if(in_range(src, user)) - to_chat(user, "[reagents.total_volume] units of water left!") - -/obj/item/weapon/extinguisher/attack_self(mob/user) - 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/afterattack(atom/target, mob/user , flag) - //TODO; Add support for reagents in water. - - if( istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(src,target) <= 1) - var/obj/O = target - O.reagents.trans_to(src, 50) - to_chat(user, "[src] is now refilled.") - playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) - return - - if (!safety) - if (src.reagents.total_volume < 1) - to_chat(usr, "[src] is empty.") - return - - if (world.time < src.last_use + 20) - return - - src.last_use = world.time - - playsound(src.loc, 'sound/effects/extinguish.ogg', 75, 1, -3) - - var/direction = get_dir(src,target) - - if(usr.buckled && isobj(usr.buckled) && !usr.buckled.anchored ) - spawn(0) - var/obj/structure/stool/bed/chair/C = null - if(istype(usr.buckled, /obj/structure/stool/bed/chair)) - C = usr.buckled - var/obj/B = usr.buckled - var/movementdirection = turn(direction,180) - if(C) C.propelled = 4 - step(B, movementdirection) - sleep(1) - step(B, movementdirection) - if(C) C.propelled = 3 - sleep(1) - step(B, movementdirection) - sleep(1) - step(B, movementdirection) - if(C) C.propelled = 2 - sleep(2) - step(B, movementdirection) - if(C) C.propelled = 1 - sleep(2) - step(B, movementdirection) - if(C) C.propelled = 0 - sleep(3) - step(B, movementdirection) - sleep(3) - step(B, movementdirection) - sleep(3) - step(B, movementdirection) - else - user.newtonian_move(turn(direction, 180)) - - 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 in 0 to spray_range) - spawn(0) - var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(src)) - var/turf/my_target = pick(the_targets) - var/datum/reagents/R = new/datum/reagents(spray_amount) - if(!W) return - W.reagents = R - R.my_atom = W - if(!W || !src) return - src.reagents.trans_to(W, spray_amount) - - for(var/b in 0 to spray_range) - step_towards(W,my_target) - if(!W) return - if(!W.reagents) break - spawn_fluid(loc, spray_amount) - W.reagents.reaction(get_turf(W)) - for(var/atom/atm in get_turf(W)) - if(!W) return - if(!W.reagents) break - W.reagents.reaction(atm) - if(isliving(atm)) //For extinguishing mobs on fire - var/mob/living/M = atm - M.ExtinguishMob() - if(W.loc == my_target) break - sleep(2) - qdel(W) - 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 = CONDUCT + throwforce = 10 + w_class = 3.0 + throw_speed = 2 + throw_range = 10 + force = 10.0 + m_amt = 90 + 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" + var/spray_amount = 1 //units of liquid per particle + var/spray_range = 4 + +/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. + throwforce = 2 + w_class = 2.0 + force = 3.0 + m_amt = 0 + max_water = 30 + sprite_name = "miniFE" + +/obj/item/weapon/extinguisher/atom_init() + . = ..() + var/datum/reagents/R = new/datum/reagents(max_water) + reagents = R + R.my_atom = src + R.add_reagent("water", max_water) + +/obj/item/weapon/extinguisher/examine(mob/user) + ..() + if(in_range(src, user)) + to_chat(user, "[reagents.total_volume] units of water left!") + +/obj/item/weapon/extinguisher/attack_self(mob/user) + 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/afterattack(atom/target, mob/user , flag) + //TODO; Add support for reagents in water. + + if( istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(src,target) <= 1) + var/obj/O = target + O.reagents.trans_to(src, 50) + to_chat(user, "[src] is now refilled.") + playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) + return + + if (!safety) + if (src.reagents.total_volume < 1) + to_chat(usr, "[src] is empty.") + return + + if (world.time < src.last_use + 20) + return + + src.last_use = world.time + + playsound(src.loc, 'sound/effects/extinguish.ogg', 75, 1, -3) + + var/direction = get_dir(src,target) + + if(usr.buckled && isobj(usr.buckled) && !usr.buckled.anchored ) + spawn(0) + var/obj/structure/stool/bed/chair/C = null + if(istype(usr.buckled, /obj/structure/stool/bed/chair)) + C = usr.buckled + var/obj/B = usr.buckled + var/movementdirection = turn(direction,180) + if(C) C.propelled = 4 + step(B, movementdirection) + sleep(1) + step(B, movementdirection) + if(C) C.propelled = 3 + sleep(1) + step(B, movementdirection) + sleep(1) + step(B, movementdirection) + if(C) C.propelled = 2 + sleep(2) + step(B, movementdirection) + if(C) C.propelled = 1 + sleep(2) + step(B, movementdirection) + if(C) C.propelled = 0 + sleep(3) + step(B, movementdirection) + sleep(3) + step(B, movementdirection) + sleep(3) + step(B, movementdirection) + else + user.newtonian_move(turn(direction, 180)) + + 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 in 0 to spray_range) + spawn(0) + var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(src)) + var/turf/my_target = pick(the_targets) + var/datum/reagents/R = new/datum/reagents(spray_amount) + if(!W) return + W.reagents = R + R.my_atom = W + if(!W || !src) return + src.reagents.trans_to(W, spray_amount) + + for(var/b in 0 to spray_range) + step_towards(W,my_target) + if(!W) return + if(!W.reagents) break + spawn_fluid(loc, spray_amount) + W.reagents.reaction(get_turf(W)) + for(var/atom/atm in get_turf(W)) + if(!W) return + if(!W.reagents) break + W.reagents.reaction(atm) + if(isliving(atm)) //For extinguishing mobs on fire + var/mob/living/M = atm + M.ExtinguishMob() + if(W.loc == my_target) break + sleep(2) + qdel(W) + else + return ..() + return diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index 8d106d19fc33..a896e7c62690 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -1,202 +1,202 @@ -/obj/item/weapon/flamethrower - name = "flamethrower" - desc = "You are a firestarter!" - icon = 'icons/obj/flamethrower.dmi' - icon_state = "flamethrowerbase" - item_state = "flamethrower_0" - flags = CONDUCT - force = 3.0 - throwforce = 10.0 - throw_speed = 1 - throw_range = 5 - w_class = 3.0 - m_amt = 500 - origin_tech = "combat=1;phorontech=1" - var/status = 0 - var/throw_amount = 1 // If player turns it up higher, it may be a worldfire. - 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/phoron/ptank = null - -/obj/item/weapon/flamethrower/Destroy() - if(weldtool) - qdel(weldtool) - if(igniter) - qdel(igniter) - if(ptank) - qdel(ptank) - return ..() - -/obj/item/weapon/flamethrower/process() - if(!lit) - STOP_PROCESSING(SSobj, src) - return - - 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) - -/obj/item/weapon/flamethrower/update_icon() - overlays.Cut() - if(igniter) - overlays += "+igniter[status]" - if(ptank) - overlays += "+ptank" - if(lit) - overlays += "+lit" - item_state = "flamethrower_1" - else - item_state = "flamethrower_0" - -/obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, proximity) - // Make sure our user is still holding us - if(user && user.get_active_hand() == src) - var/turf/target_turf = get_turf(target) - if(target_turf) - var/list/turflist = getline(get_turf(src), target_turf) - flame_turf(turflist) - -/obj/item/weapon/flamethrower/attackby(obj/item/W, mob/user) - 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 - new /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 - user.drop_item() - I.loc = src - igniter = I - update_icon() - return - - if(istype(W,/obj/item/weapon/tank/phoron)) - if(ptank) - to_chat(user, "There appears to already be a phoron tank loaded in [src]!") - return - user.drop_item() - ptank = W - W.loc = src - update_icon() - return - - if(istype(W, /obj/item/device/analyzer)) - var/obj/item/device/analyzer/A = W - A.analyze_gases(src, user) - return - ..() - -/obj/item/weapon/flamethrower/attack_self(mob/user) - if(user.stat || user.restrained() || user.lying) - return - user.set_machine(src) - if(!ptank) - to_chat(user, "Attach a phoron tank first!") - return - var/dat = text("Flamethrower ([lit ? "Lit" : "Unlit"])
                    \n Tank Pressure: [ptank.air_contents.return_pressure()]
                    \nAmount to throw: - - - [throw_amount] + + +
                    \nRemove phorontank - Close
                    ") - user << browse(entity_ja(dat), "window=flamethrower;size=600x300") - onclose(entity_ja(user), "flamethrower") - -/obj/item/weapon/flamethrower/Topic(href,href_list[]) - if(href_list["close"]) - usr.unset_machine() - usr << browse(null, "window=flamethrower") - return - if(usr.incapacitated()) return - usr.set_machine(src) - if(href_list["light"]) - if(!ptank) return - if(ptank.air_contents.gas["phoron"] < 1) return - if(!status) return - lit = !lit - if(lit) - START_PROCESSING(SSobj, src) - if(href_list["amount"]) - throw_amount = throw_amount + text2num(href_list["amount"]) - throw_amount = Clamp(throw_amount, 1, 10) - 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() - -/obj/item/weapon/flamethrower/proc/flame_turf(list/turflist) - if(!lit || operating) - return - if(!ptank.air_contents.total_moles) - update_icon() - lit = FALSE - return - - operating = TRUE - - var/datum/gas_mixture/fuel_transfer = ptank.air_contents.remove(throw_amount) - var/pressure_range = min(turflist.len - 1, ptank.air_contents.return_pressure() / 75) // Normal pressure of 303.75 results in a fire spread of 4 tiles. We remove 1 from turflist because our own tile doesn't count. - var/self_turf = get_turf(src) - - if(pressure_range == 0) - return - - for(var/turf/T in turflist) - if(T == self_turf || istype(T, /turf/space)) - continue - if(get_dist(T, self_turf) > pressure_range) - break - var/datum/gas_mixture/fuel_iteration = fuel_transfer.remove_ratio(1 / pressure_range) - if(fuel_iteration.gas["phoron"] == 0) - break - new /obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel(T, fuel_iteration.gas["phoron"], get_dir(self_turf, T)) - fuel_iteration.gas["phoron"] = 0 - sleep(1) - T.assume_air(fuel_iteration) - T.hotspot_expose((ptank.air_contents.temperature * 2) + 400, 500) - sleep(2) - - operating = FALSE - - for(var/mob/M in viewers(1, loc)) - if((M.client && M.machine == src)) - attack_self(M) - -/obj/item/weapon/flamethrower/full/atom_init() - . = ..() - 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() +/obj/item/weapon/flamethrower + name = "flamethrower" + desc = "You are a firestarter!" + icon = 'icons/obj/flamethrower.dmi' + icon_state = "flamethrowerbase" + item_state = "flamethrower_0" + flags = CONDUCT + force = 3.0 + throwforce = 10.0 + throw_speed = 1 + throw_range = 5 + w_class = 3.0 + m_amt = 500 + origin_tech = "combat=1;phorontech=1" + var/status = 0 + var/throw_amount = 1 // If player turns it up higher, it may be a worldfire. + 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/phoron/ptank = null + +/obj/item/weapon/flamethrower/Destroy() + if(weldtool) + qdel(weldtool) + if(igniter) + qdel(igniter) + if(ptank) + qdel(ptank) + return ..() + +/obj/item/weapon/flamethrower/process() + if(!lit) + STOP_PROCESSING(SSobj, src) + return + + 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) + +/obj/item/weapon/flamethrower/update_icon() + overlays.Cut() + if(igniter) + overlays += "+igniter[status]" + if(ptank) + overlays += "+ptank" + if(lit) + overlays += "+lit" + item_state = "flamethrower_1" + else + item_state = "flamethrower_0" + +/obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, proximity) + // Make sure our user is still holding us + if(user && user.get_active_hand() == src) + var/turf/target_turf = get_turf(target) + if(target_turf) + var/list/turflist = getline(get_turf(src), target_turf) + flame_turf(turflist) + +/obj/item/weapon/flamethrower/attackby(obj/item/W, mob/user) + 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 + new /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 + user.drop_item() + I.loc = src + igniter = I + update_icon() + return + + if(istype(W,/obj/item/weapon/tank/phoron)) + if(ptank) + to_chat(user, "There appears to already be a phoron tank loaded in [src]!") + return + user.drop_item() + ptank = W + W.loc = src + update_icon() + return + + if(istype(W, /obj/item/device/analyzer)) + var/obj/item/device/analyzer/A = W + A.analyze_gases(src, user) + return + ..() + +/obj/item/weapon/flamethrower/attack_self(mob/user) + if(user.stat || user.restrained() || user.lying) + return + user.set_machine(src) + if(!ptank) + to_chat(user, "Attach a phoron tank first!") + return + var/dat = text("Flamethrower ([lit ? "Lit" : "Unlit"])
                    \n Tank Pressure: [ptank.air_contents.return_pressure()]
                    \nAmount to throw: - - - [throw_amount] + + +
                    \nRemove phorontank - Close
                    ") + user << browse(entity_ja(dat), "window=flamethrower;size=600x300") + onclose(entity_ja(user), "flamethrower") + +/obj/item/weapon/flamethrower/Topic(href,href_list[]) + if(href_list["close"]) + usr.unset_machine() + usr << browse(null, "window=flamethrower") + return + if(usr.incapacitated()) return + usr.set_machine(src) + if(href_list["light"]) + if(!ptank) return + if(ptank.air_contents.gas["phoron"] < 1) return + if(!status) return + lit = !lit + if(lit) + START_PROCESSING(SSobj, src) + if(href_list["amount"]) + throw_amount = throw_amount + text2num(href_list["amount"]) + throw_amount = Clamp(throw_amount, 1, 10) + 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() + +/obj/item/weapon/flamethrower/proc/flame_turf(list/turflist) + if(!lit || operating) + return + if(!ptank.air_contents.total_moles) + update_icon() + lit = FALSE + return + + operating = TRUE + + var/datum/gas_mixture/fuel_transfer = ptank.air_contents.remove(throw_amount) + var/pressure_range = min(turflist.len - 1, ptank.air_contents.return_pressure() / 75) // Normal pressure of 303.75 results in a fire spread of 4 tiles. We remove 1 from turflist because our own tile doesn't count. + var/self_turf = get_turf(src) + + if(pressure_range == 0) + return + + for(var/turf/T in turflist) + if(T == self_turf || istype(T, /turf/space)) + continue + if(get_dist(T, self_turf) > pressure_range) + break + var/datum/gas_mixture/fuel_iteration = fuel_transfer.remove_ratio(1 / pressure_range) + if(fuel_iteration.gas["phoron"] == 0) + break + new /obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel(T, fuel_iteration.gas["phoron"], get_dir(self_turf, T)) + fuel_iteration.gas["phoron"] = 0 + sleep(1) + T.assume_air(fuel_iteration) + T.hotspot_expose((ptank.air_contents.temperature * 2) + 400, 500) + sleep(2) + + operating = FALSE + + for(var/mob/M in viewers(1, loc)) + if((M.client && M.machine == src)) + attack_self(M) + +/obj/item/weapon/flamethrower/full/atom_init() + . = ..() + 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() diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 6a93cc5498fe..67b03b8ffa26 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -1,309 +1,309 @@ -/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 - -/obj/item/weapon/grenade/chem_grenade/atom_init() - . = ..() - var/datum/reagents/R = new/datum/reagents(1000) - reagents = R - R.my_atom = src - -/obj/item/weapon/grenade/chem_grenade/attack_self(mob/user) - 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) - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - if(stage > 1 && !active && clown_check(user)) - to_chat(user, "You prime \the [name]!") - - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src]. (JMP)") - - 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, mob/user) - - 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(src.loc, 'sound/items/Screwdriver2.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/weapon/screwdriver) && path != 2) - if(stage == 1) - path = 1 - if(beakers.len) - to_chat(user, "You lock the assembly.") - name = "grenade" - else -// user << "\red You need to add at least one beaker before locking the assembly." - to_chat(user, "You lock the empty assembly.") - name = "fake grenade" - playsound(src.loc, '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(src.loc, '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(W.reagents.total_volume) - to_chat(user, "You add \the [W] to the assembly.") - user.drop_item() - W.loc = src - beakers += W - stage = 1 - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - else - to_chat(user, "\the [W] is empty.") - -/obj/item/weapon/grenade/chem_grenade/examine(mob/user) - ..() - if(src in user && detonator) - to_chat(user, "With attached [detonator.name]") - -/obj/item/weapon/grenade/chem_grenade/activate(mob/user) - 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) - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") - - return - -/obj/item/weapon/grenade/chem_grenade/proc/primed(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(src.loc, 'sound/items/Screwdriver2.ogg', 50, 1) - return - - playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1) - - for(var/obj/item/weapon/reagent_containers/glass/G in beakers) - G.reagents.trans_to(src, G.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, src.loc)) - if( A == src ) continue - src.reagents.reaction(A, 1, 10) - - if(istype(loc, /mob/living/carbon)) //drop dat grenade if it goes off in your hand - var/mob/living/carbon/C = loc - C.drop_from_inventory(src) - C.throw_mode_off() - - invisibility = INVISIBILITY_MAXIMUM //Why am i doing this? - spawn(50) //To make sure all reagents can work - qdel(src) //correctly before deleting the grenade. - -/obj/item/weapon/grenade/chem_grenade/Crossed(atom/movable/AM as mob|obj) - if (detonator) - detonator.Crossed(AM) - -/obj/item/weapon/grenade/chem_grenade/hear_talk(mob/living/M, msg) - if (detonator) - detonator.hear_talk(M,msg) - -/obj/item/weapon/grenade/chem_grenade/on_found(mob/finder) - if(detonator) - detonator.on_found(finder) - -/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) - origin_tech = "combat=3;materials=3" - affected_area = 4 - - -///////Metalfoam -/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/atom_init() - . = ..() - 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" - - -///////Incendiary -/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/atom_init() - . = ..() - 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("fuel",20) - B1.reagents.add_reagent("aluminum", 15) - B2.reagents.add_reagent("phoron", 15) - B2.reagents.add_reagent("sacid", 15) - - detonator = new/obj/item/device/assembly_holder/timer_igniter(src) - - beakers += B1 - beakers += B2 - icon_state = initial(icon_state) +"_locked" - - -///////Antiweed -/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/atom_init() - . = ..() - 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" - - -///////Cleaner -/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/atom_init() - . = ..() - 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" - - -///////Teargas -/obj/item/weapon/grenade/chem_grenade/teargas - name = "teargas grenade" - desc = "Used for nonlethal riot control. Contents under pressure. Do not directly inhale contents." - stage = 2 - path = 1 - -/obj/item/weapon/grenade/chem_grenade/teargas/atom_init() - . = ..() - 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("condensedcapsaicin", 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 = initial(icon_state) +"_locked" +/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 + +/obj/item/weapon/grenade/chem_grenade/atom_init() + . = ..() + var/datum/reagents/R = new/datum/reagents(1000) + reagents = R + R.my_atom = src + +/obj/item/weapon/grenade/chem_grenade/attack_self(mob/user) + 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) + name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" + if(stage > 1 && !active && clown_check(user)) + to_chat(user, "You prime \the [name]!") + + msg_admin_attack("[user.name] ([user.ckey]) primed \a [src]. (JMP)") + + 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, mob/user) + + 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(src.loc, 'sound/items/Screwdriver2.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/weapon/screwdriver) && path != 2) + if(stage == 1) + path = 1 + if(beakers.len) + to_chat(user, "You lock the assembly.") + name = "grenade" + else +// user << "\red You need to add at least one beaker before locking the assembly." + to_chat(user, "You lock the empty assembly.") + name = "fake grenade" + playsound(src.loc, '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(src.loc, '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(W.reagents.total_volume) + to_chat(user, "You add \the [W] to the assembly.") + user.drop_item() + W.loc = src + beakers += W + stage = 1 + name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" + else + to_chat(user, "\the [W] is empty.") + +/obj/item/weapon/grenade/chem_grenade/examine(mob/user) + ..() + if(src in user && detonator) + to_chat(user, "With attached [detonator.name]") + +/obj/item/weapon/grenade/chem_grenade/activate(mob/user) + 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) + msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") + + return + +/obj/item/weapon/grenade/chem_grenade/proc/primed(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(src.loc, 'sound/items/Screwdriver2.ogg', 50, 1) + return + + playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1) + + for(var/obj/item/weapon/reagent_containers/glass/G in beakers) + G.reagents.trans_to(src, G.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, src.loc)) + if( A == src ) continue + src.reagents.reaction(A, 1, 10) + + if(istype(loc, /mob/living/carbon)) //drop dat grenade if it goes off in your hand + var/mob/living/carbon/C = loc + C.drop_from_inventory(src) + C.throw_mode_off() + + invisibility = INVISIBILITY_MAXIMUM //Why am i doing this? + spawn(50) //To make sure all reagents can work + qdel(src) //correctly before deleting the grenade. + +/obj/item/weapon/grenade/chem_grenade/Crossed(atom/movable/AM as mob|obj) + if (detonator) + detonator.Crossed(AM) + +/obj/item/weapon/grenade/chem_grenade/hear_talk(mob/living/M, msg) + if (detonator) + detonator.hear_talk(M,msg) + +/obj/item/weapon/grenade/chem_grenade/on_found(mob/finder) + if(detonator) + detonator.on_found(finder) + +/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) + origin_tech = "combat=3;materials=3" + affected_area = 4 + + +///////Metalfoam +/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/atom_init() + . = ..() + 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" + + +///////Incendiary +/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/atom_init() + . = ..() + 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("fuel",20) + B1.reagents.add_reagent("aluminum", 15) + B2.reagents.add_reagent("phoron", 15) + B2.reagents.add_reagent("sacid", 15) + + detonator = new/obj/item/device/assembly_holder/timer_igniter(src) + + beakers += B1 + beakers += B2 + icon_state = initial(icon_state) +"_locked" + + +///////Antiweed +/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/atom_init() + . = ..() + 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" + + +///////Cleaner +/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/atom_init() + . = ..() + 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" + + +///////Teargas +/obj/item/weapon/grenade/chem_grenade/teargas + name = "teargas grenade" + desc = "Used for nonlethal riot control. Contents under pressure. Do not directly inhale contents." + stage = 2 + path = 1 + +/obj/item/weapon/grenade/chem_grenade/teargas/atom_init() + . = ..() + 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("condensedcapsaicin", 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 = initial(icon_state) +"_locked" diff --git a/code/game/objects/items/weapons/grenades/emgrenade.dm b/code/game/objects/items/weapons/grenades/emgrenade.dm index 65fab5cbbe0a..36433b0a1bd5 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 = "classic emp grenade" - icon_state = "emp" - item_state = "emp" - origin_tech = "materials=2;magnets=3" - - prime() - ..() - if(empulse(src, 4, 10)) - qdel(src) - return - +/obj/item/weapon/grenade/empgrenade + name = "classic emp grenade" + icon_state = "emp" + item_state = "emp" + origin_tech = "materials=2;magnets=3" + + prime() + ..() + if(empulse(src, 4, 10)) + qdel(src) + return + diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index 8b0f2ad03ce7..2f217b32ed61 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -1,179 +1,179 @@ -/obj/item/weapon/grenade/flashbang - name = "flashbang" - icon_state = "flashbang" - item_state = "flashbang" - origin_tech = "materials=2;combat=1" - var/banglet = 0 - - prime() - ..() - for(var/obj/structure/closet/L in hear(7, get_turf(src))) - if(locate(/mob/living/carbon/, L)) - for(var/mob/living/carbon/M in L) - bang(get_turf(src), M) - - - for(var/mob/living/carbon/M in hear(7, get_turf(src))) - bang(get_turf(src), M) - - for(var/obj/effect/blob/B in hear(8,get_turf(src))) //Blob damage here - var/damage = round(30/(get_dist(B,get_turf(src))+1)) - B.health -= damage - B.update_icon() - - new/obj/effect/effect/smoke/flashbang(src.loc) - qdel(src) - return - - proc/bang(turf/T , mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged. - to_chat(M, "\red BANG") - playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 5) - -//Checking for protections - var/eye_safety = 0 - var/ear_safety = 0 - if(iscarbon(M)) - eye_safety = M.eyecheck() - if(ishuman(M)) - if(istype(M:l_ear, /obj/item/clothing/ears/earmuffs) || istype(M:r_ear, /obj/item/clothing/ears/earmuffs)) - ear_safety += 2 - if(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) - M.flash_eyes() - 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/obj/item/organ/internal/eyes/IO = H.organs_by_name[O_EYES] - if (IO.damage >= IO.min_bruised_damage) - to_chat(M, "\red Your eyes start to burn badly!") - if(!banglet && !(istype(src , /obj/item/weapon/grenade/clusterbuster))) - if (IO.damage >= IO.min_broken_damage) - to_chat(M, "\red You can't see anything!") - if(H.species.name == SHADOWLING) // BBQ from shadowling ~Zve - H.adjustFireLoss(rand(15,25)) - if (M.ear_damage >= 15) - to_chat(M, "\red Your ears start to ring badly!") - if(!banglet && !(istype(src , /obj/item/weapon/grenade/clusterbuster))) - if (prob(M.ear_damage - 10 + 5)) - to_chat(M, "\red You can't hear anything!") - M.sdisabilities |= DEAF - else - if (M.ear_damage >= 5) - to_chat(M, "\red Your ears start to ring!") - M.update_icons() - -/obj/effect/effect/smoke/flashbang - name = "illumination" - time_to_live = 10 - opacity = 0 - icon_state = "sparks" - -//////////////////// -//Clusterbang -//////////////////// -/obj/item/weapon/grenade/clusterbuster - 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" - var/payload = /obj/item/weapon/grenade/flashbang/cluster - var/numspawned = 4 - -/obj/item/weapon/grenade/clusterbuster/prime() - update_icon() - - for(var/i in 1 to numspawned) - new /obj/item/weapon/grenade/clusterbuster/segment(loc, payload) //Creates 'segments' that launches a few more payloads - - playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) - qdel(src) - - -////////////////////// -//Clusterbang segment -////////////////////// -/obj/item/weapon/grenade/clusterbuster/segment - desc = "A smaller segment of a clusterbang. Better run." - name = "clusterbang segment" - icon = 'icons/obj/grenade.dmi' - icon_state = "clusterbang_segment" - numspawned = 2 - -/obj/item/weapon/grenade/clusterbuster/segment/atom_init(mapload, payload_type = /obj/item/weapon/grenade/flashbang/cluster) - . = ..() - icon_state = "clusterbang_segment_active" - payload = payload_type - active = 1 - walk_away(src,loc,rand(1,4)) - addtimer(CALLBACK(src, .proc/prime), rand(15,60)) - -/obj/item/weapon/grenade/clusterbuster/segment/prime() - for(var/i in 1 to numspawned) - var/obj/item/weapon/grenade/P = new payload(src.loc) - P.active = 1 - walk_away(P,loc,rand(1,4)) - addtimer(CALLBACK(P, /obj/item/weapon/grenade.proc/prime), rand(15,60)) - playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) - qdel(src) - -////////////////////////////////// -//The payload spawner effect -///////////////////////////////// - -/obj/item/weapon/grenade/flashbang/cluster - icon_state = "flashbang_active" - -/obj/item/weapon/grenade/clusterbuster/emp - name = "Electromagnetic Storm" - payload = /obj/item/weapon/grenade/empgrenade - -/obj/item/weapon/grenade/clusterbuster/syndieminibomb - name = "SyndiWrath" - payload = /obj/item/weapon/grenade/syndieminibomb - -/obj/item/weapon/grenade/clusterbuster/spawner_manhacks - name = "iViscerator" - payload = /obj/item/weapon/grenade/spawnergrenade/manhacks - -/obj/item/weapon/grenade/clusterbuster/spawner_spesscarp - name = "Invasion of the Space Carps" - payload = /obj/item/weapon/grenade/spawnergrenade/spesscarp - -/obj/item/weapon/grenade/clusterbuster/soap - name = "Slipocalypse" - payload = /obj/item/weapon/grenade/spawnergrenade/syndiesoap +/obj/item/weapon/grenade/flashbang + name = "flashbang" + icon_state = "flashbang" + item_state = "flashbang" + origin_tech = "materials=2;combat=1" + var/banglet = 0 + + prime() + ..() + for(var/obj/structure/closet/L in hear(7, get_turf(src))) + if(locate(/mob/living/carbon/, L)) + for(var/mob/living/carbon/M in L) + bang(get_turf(src), M) + + + for(var/mob/living/carbon/M in hear(7, get_turf(src))) + bang(get_turf(src), M) + + for(var/obj/effect/blob/B in hear(8,get_turf(src))) //Blob damage here + var/damage = round(30/(get_dist(B,get_turf(src))+1)) + B.health -= damage + B.update_icon() + + new/obj/effect/effect/smoke/flashbang(src.loc) + qdel(src) + return + + proc/bang(turf/T , mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged. + to_chat(M, "\red BANG") + playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 5) + +//Checking for protections + var/eye_safety = 0 + var/ear_safety = 0 + if(iscarbon(M)) + eye_safety = M.eyecheck() + if(ishuman(M)) + if(istype(M:l_ear, /obj/item/clothing/ears/earmuffs) || istype(M:r_ear, /obj/item/clothing/ears/earmuffs)) + ear_safety += 2 + if(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) + M.flash_eyes() + 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/obj/item/organ/internal/eyes/IO = H.organs_by_name[O_EYES] + if (IO.damage >= IO.min_bruised_damage) + to_chat(M, "\red Your eyes start to burn badly!") + if(!banglet && !(istype(src , /obj/item/weapon/grenade/clusterbuster))) + if (IO.damage >= IO.min_broken_damage) + to_chat(M, "\red You can't see anything!") + if(H.species.name == SHADOWLING) // BBQ from shadowling ~Zve + H.adjustFireLoss(rand(15,25)) + if (M.ear_damage >= 15) + to_chat(M, "\red Your ears start to ring badly!") + if(!banglet && !(istype(src , /obj/item/weapon/grenade/clusterbuster))) + if (prob(M.ear_damage - 10 + 5)) + to_chat(M, "\red You can't hear anything!") + M.sdisabilities |= DEAF + else + if (M.ear_damage >= 5) + to_chat(M, "\red Your ears start to ring!") + M.update_icons() + +/obj/effect/effect/smoke/flashbang + name = "illumination" + time_to_live = 10 + opacity = 0 + icon_state = "sparks" + +//////////////////// +//Clusterbang +//////////////////// +/obj/item/weapon/grenade/clusterbuster + 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" + var/payload = /obj/item/weapon/grenade/flashbang/cluster + var/numspawned = 4 + +/obj/item/weapon/grenade/clusterbuster/prime() + update_icon() + + for(var/i in 1 to numspawned) + new /obj/item/weapon/grenade/clusterbuster/segment(loc, payload) //Creates 'segments' that launches a few more payloads + + playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + qdel(src) + + +////////////////////// +//Clusterbang segment +////////////////////// +/obj/item/weapon/grenade/clusterbuster/segment + desc = "A smaller segment of a clusterbang. Better run." + name = "clusterbang segment" + icon = 'icons/obj/grenade.dmi' + icon_state = "clusterbang_segment" + numspawned = 2 + +/obj/item/weapon/grenade/clusterbuster/segment/atom_init(mapload, payload_type = /obj/item/weapon/grenade/flashbang/cluster) + . = ..() + icon_state = "clusterbang_segment_active" + payload = payload_type + active = 1 + walk_away(src,loc,rand(1,4)) + addtimer(CALLBACK(src, .proc/prime), rand(15,60)) + +/obj/item/weapon/grenade/clusterbuster/segment/prime() + for(var/i in 1 to numspawned) + var/obj/item/weapon/grenade/P = new payload(src.loc) + P.active = 1 + walk_away(P,loc,rand(1,4)) + addtimer(CALLBACK(P, /obj/item/weapon/grenade.proc/prime), rand(15,60)) + playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + qdel(src) + +////////////////////////////////// +//The payload spawner effect +///////////////////////////////// + +/obj/item/weapon/grenade/flashbang/cluster + icon_state = "flashbang_active" + +/obj/item/weapon/grenade/clusterbuster/emp + name = "Electromagnetic Storm" + payload = /obj/item/weapon/grenade/empgrenade + +/obj/item/weapon/grenade/clusterbuster/syndieminibomb + name = "SyndiWrath" + payload = /obj/item/weapon/grenade/syndieminibomb + +/obj/item/weapon/grenade/clusterbuster/spawner_manhacks + name = "iViscerator" + payload = /obj/item/weapon/grenade/spawnergrenade/manhacks + +/obj/item/weapon/grenade/clusterbuster/spawner_spesscarp + name = "Invasion of the Space Carps" + payload = /obj/item/weapon/grenade/spawnergrenade/spesscarp + +/obj/item/weapon/grenade/clusterbuster/soap + name = "Slipocalypse" + payload = /obj/item/weapon/grenade/spawnergrenade/syndiesoap diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index d60a9d09ee02..357451bce9d3 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -1,128 +1,128 @@ -/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 = CONDUCT - slot_flags = SLOT_BELT - var/active = 0 - var/det_time = 50 - - action_button_name = "Activate Grenade" - -/obj/item/weapon/grenade/proc/clown_check(mob/living/user) - if((CLUMSY in user.mutations) && prob(50)) - to_chat(user, "Huh? How does this thing work?") - - activate(user) - add_fingerprint(user) - spawn(5) - prime() - return 0 - return 1 - - -/*/obj/item/weapon/grenade/afterattack(atom/target, mob/user) - 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() - var/t = (isturf(target) ? target : target.loc) - walk_towards(src, t, 3) - return*/ - - -/obj/item/weapon/grenade/examine(mob/user) - ..() - if(src in user) - if(det_time > 1) - to_chat(user, "The timer is set to [det_time/10] seconds.") - else - to_chat(user, "\The [src] is set for instant detonation.") - - -/obj/item/weapon/grenade/attack_self(mob/user) - 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) - if(active) - return - - if(user) - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") - - icon_state = initial(icon_state) + "_active" - active = 1 - playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) - - spawn(det_time) - prime() - 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) - - -/obj/item/weapon/grenade/attackby(obj/item/weapon/W, mob/user) - 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 - to_chat(user, "You set the [name] for 3 second detonation time.") - if ("30") - det_time = 50 - to_chat(user, "You set the [name] for 5 second detonation time.") - 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) - return attack_hand(user) - -/obj/item/weapon/grenade/syndieminibomb - desc = "A syndicate manufactured explosive used to sow destruction and chaos." - name = "syndicate minibomb" - icon_state = "syndicate" - item_state = "flashbang" - origin_tech = "materials=3;magnets=4;syndicate=4" - -/obj/item/weapon/grenade/syndieminibomb/prime() - explosion(src.loc,1,2,4,5) - qdel(src) +/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 = CONDUCT + slot_flags = SLOT_BELT + var/active = 0 + var/det_time = 50 + + action_button_name = "Activate Grenade" + +/obj/item/weapon/grenade/proc/clown_check(mob/living/user) + if((CLUMSY in user.mutations) && prob(50)) + to_chat(user, "Huh? How does this thing work?") + + activate(user) + add_fingerprint(user) + spawn(5) + prime() + return 0 + return 1 + + +/*/obj/item/weapon/grenade/afterattack(atom/target, mob/user) + 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() + var/t = (isturf(target) ? target : target.loc) + walk_towards(src, t, 3) + return*/ + + +/obj/item/weapon/grenade/examine(mob/user) + ..() + if(src in user) + if(det_time > 1) + to_chat(user, "The timer is set to [det_time/10] seconds.") + else + to_chat(user, "\The [src] is set for instant detonation.") + + +/obj/item/weapon/grenade/attack_self(mob/user) + 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) + if(active) + return + + if(user) + msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") + + icon_state = initial(icon_state) + "_active" + active = 1 + playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + + spawn(det_time) + prime() + 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) + + +/obj/item/weapon/grenade/attackby(obj/item/weapon/W, mob/user) + 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 + to_chat(user, "You set the [name] for 3 second detonation time.") + if ("30") + det_time = 50 + to_chat(user, "You set the [name] for 5 second detonation time.") + 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) + return attack_hand(user) + +/obj/item/weapon/grenade/syndieminibomb + desc = "A syndicate manufactured explosive used to sow destruction and chaos." + name = "syndicate minibomb" + icon_state = "syndicate" + item_state = "flashbang" + origin_tech = "materials=3;magnets=4;syndicate=4" + +/obj/item/weapon/grenade/syndieminibomb/prime() + explosion(src.loc,1,2,4,5) + qdel(src) diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm index a2b37bf83a24..68bc2afbe3e4 100644 --- a/code/game/objects/items/weapons/grenades/smokebomb.dm +++ b/code/game/objects/items/weapons/grenades/smokebomb.dm @@ -1,33 +1,33 @@ -/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" - slot_flags = SLOT_BELT - var/datum/effect/effect/system/smoke_spread/bad/smoke - -/obj/item/weapon/grenade/smokebomb/atom_init() - . = ..() - smoke = new /datum/effect/effect/system/smoke_spread/bad() - smoke.attach(src) - -/obj/item/weapon/grenade/smokebomb/prime() - playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3) - smoke.set_up(10, 0, usr.loc) - spawn(0) - smoke.start() - sleep(10) - smoke.start() - sleep(10) - smoke.start() - sleep(10) - 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) +/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" + slot_flags = SLOT_BELT + var/datum/effect/effect/system/smoke_spread/bad/smoke + +/obj/item/weapon/grenade/smokebomb/atom_init() + . = ..() + smoke = new /datum/effect/effect/system/smoke_spread/bad() + smoke.attach(src) + +/obj/item/weapon/grenade/smokebomb/prime() + playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3) + smoke.set_up(10, 0, usr.loc) + spawn(0) + smoke.start() + sleep(10) + smoke.start() + sleep(10) + smoke.start() + sleep(10) + 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) diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index 4435954a5bcd..38e3035ab835 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -1,44 +1,44 @@ -/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 - - prime() - - if(spawner_type && deliveryamt) - var/turf/T = get_turf(src) - playsound(T, 'sound/effects/phasein.ogg', 100, 1) - - for(var/i=1, i<=deliveryamt, i++) - var/atom/movable/x = new spawner_type - x.loc = T - if(prob(50)) - for(var/j = 1, j <= rand(1, 3), j++) - step(x, pick(NORTH,SOUTH,EAST,WEST)) - - // Spawn some enemies - - qdel(src) - 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/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/syndiesoap - name = "Mister Scrubby" +/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 + + prime() + + if(spawner_type && deliveryamt) + var/turf/T = get_turf(src) + playsound(T, 'sound/effects/phasein.ogg', 100, 1) + + for(var/i=1, i<=deliveryamt, i++) + var/atom/movable/x = new spawner_type + x.loc = T + if(prob(50)) + for(var/j = 1, j <= rand(1, 3), j++) + step(x, pick(NORTH,SOUTH,EAST,WEST)) + + // Spawn some enemies + + qdel(src) + 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/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/syndiesoap + name = "Mister Scrubby" spawner_type = /obj/item/weapon/soap/syndie \ No newline at end of file diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 46d069770d5d..f05d525871d3 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -1,129 +1,129 @@ -/obj/item/weapon/handcuffs - name = "handcuffs" - desc = "Use this to keep prisoners in line." - gender = PLURAL - icon = 'icons/obj/items.dmi' - icon_state = "handcuff" - flags = CONDUCT - slot_flags = SLOT_BELT - throwforce = 5 - w_class = 2.0 - throw_speed = 2 - throw_range = 5 - m_amt = 500 - origin_tech = "materials=1" - var/dispenser = 0 - var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes - var/cuff_sound = 'sound/weapons/handcuffs.ogg' - -/obj/item/weapon/handcuffs/attack(mob/living/carbon/C, mob/user) - if (!ishuman(user) && !isIAN(user)) - to_chat(user, "\red You don't have the dexterity to do this!") - return - if(!istype(C)) - return - if ((CLUMSY in usr.mutations) && prob(50)) - to_chat(user, "\red Uh ... how do those things work?!") - place_handcuffs(user, user) - return - if(!C.handcuffed) - if (C == user || isIAN(user)) - place_handcuffs(C, user) - return - - //check for an aggressive grab - for (var/obj/item/weapon/grab/G in C.grabbed_by) - if (G.loc == user && G.state >= GRAB_AGGRESSIVE) - place_handcuffs(C, user) - return - to_chat(user, "\red You need to have a firm grip on [C] before you can put \the [src] on!") - -/obj/item/weapon/handcuffs/proc/place_handcuffs(mob/living/carbon/target, mob/user) - playsound(src.loc, cuff_sound, 30, 1, -2) - - if (ishuman(target)) - var/mob/living/carbon/human/H = target - H.attack_log += text("\[[time_stamp()]\] Has been handcuffed (attempt) by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Attempted to handcuff [H.name] ([H.ckey])") - msg_admin_attack("[key_name(user)] attempted to handcuff [key_name(H)]") - - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) - O.source = user - O.target = H - O.item = user.get_active_hand() - O.s_loc = user.loc - O.t_loc = H.loc - O.place = "handcuff" - H.requests += O - spawn( 0 ) - feedback_add_details("handcuffs","H") - O.process() - return - - if (ismonkey(target)) - var/mob/living/carbon/monkey/M = target - var/obj/effect/equip_e/monkey/O = new /obj/effect/equip_e/monkey( ) - O.source = user - O.target = M - O.item = user.get_active_hand() - O.s_loc = user.loc - O.t_loc = M.loc - O.place = "handcuff" - M.requests += O - spawn( 0 ) - O.process() - return - - if (isIAN(target)) - var/mob/living/carbon/ian/IAN = target - IAN.un_equip_or_action(user, "Neck", user.get_active_hand()) - -/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_white" - breakouttime = 300 //Deciseconds = 30s - cuff_sound = 'sound/weapons/cablecuff.ogg' - -/obj/item/weapon/handcuffs/cable/red - color = "#DD0000" - -/obj/item/weapon/handcuffs/cable/yellow - color = "#DDDD00" - -/obj/item/weapon/handcuffs/cable/blue - color = "#0000DD" - -/obj/item/weapon/handcuffs/cable/green - color = "#00DD00" - -/obj/item/weapon/handcuffs/cable/pink - color = "#DD00DD" - -/obj/item/weapon/handcuffs/cable/orange - color = "#DD8800" - -/obj/item/weapon/handcuffs/cable/cyan - color = "#00DDDD" - -/obj/item/weapon/handcuffs/cable/white - color = "#FFFFFF" - -/obj/item/weapon/handcuffs/cyborg - dispenser = 1 - -/obj/item/weapon/handcuffs/cyborg/attack(mob/living/carbon/C, mob/user) - if(ishuman(C)) - var/mob/living/carbon/human/target = C - if(!target.can_use_two_hands(FALSE)) - return - if(!C.handcuffed) - var/turf/p_loc = user.loc - var/turf/p_loc_m = C.loc - playsound(src.loc, cuff_sound, 30, 1, -2) - user.visible_message("\red [user] is trying to put handcuffs on [C]!") - 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() +/obj/item/weapon/handcuffs + name = "handcuffs" + desc = "Use this to keep prisoners in line." + gender = PLURAL + icon = 'icons/obj/items.dmi' + icon_state = "handcuff" + flags = CONDUCT + slot_flags = SLOT_BELT + throwforce = 5 + w_class = 2.0 + throw_speed = 2 + throw_range = 5 + m_amt = 500 + origin_tech = "materials=1" + var/dispenser = 0 + var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes + var/cuff_sound = 'sound/weapons/handcuffs.ogg' + +/obj/item/weapon/handcuffs/attack(mob/living/carbon/C, mob/user) + if (!ishuman(user) && !isIAN(user)) + to_chat(user, "\red You don't have the dexterity to do this!") + return + if(!istype(C)) + return + if ((CLUMSY in usr.mutations) && prob(50)) + to_chat(user, "\red Uh ... how do those things work?!") + place_handcuffs(user, user) + return + if(!C.handcuffed) + if (C == user || isIAN(user)) + place_handcuffs(C, user) + return + + //check for an aggressive grab + for (var/obj/item/weapon/grab/G in C.grabbed_by) + if (G.loc == user && G.state >= GRAB_AGGRESSIVE) + place_handcuffs(C, user) + return + to_chat(user, "\red You need to have a firm grip on [C] before you can put \the [src] on!") + +/obj/item/weapon/handcuffs/proc/place_handcuffs(mob/living/carbon/target, mob/user) + playsound(src.loc, cuff_sound, 30, 1, -2) + + if (ishuman(target)) + var/mob/living/carbon/human/H = target + H.attack_log += text("\[[time_stamp()]\] Has been handcuffed (attempt) by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Attempted to handcuff [H.name] ([H.ckey])") + msg_admin_attack("[key_name(user)] attempted to handcuff [key_name(H)]") + + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) + O.source = user + O.target = H + O.item = user.get_active_hand() + O.s_loc = user.loc + O.t_loc = H.loc + O.place = "handcuff" + H.requests += O + spawn( 0 ) + feedback_add_details("handcuffs","H") + O.process() + return + + if (ismonkey(target)) + var/mob/living/carbon/monkey/M = target + var/obj/effect/equip_e/monkey/O = new /obj/effect/equip_e/monkey( ) + O.source = user + O.target = M + O.item = user.get_active_hand() + O.s_loc = user.loc + O.t_loc = M.loc + O.place = "handcuff" + M.requests += O + spawn( 0 ) + O.process() + return + + if (isIAN(target)) + var/mob/living/carbon/ian/IAN = target + IAN.un_equip_or_action(user, "Neck", user.get_active_hand()) + +/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_white" + breakouttime = 300 //Deciseconds = 30s + cuff_sound = 'sound/weapons/cablecuff.ogg' + +/obj/item/weapon/handcuffs/cable/red + color = "#DD0000" + +/obj/item/weapon/handcuffs/cable/yellow + color = "#DDDD00" + +/obj/item/weapon/handcuffs/cable/blue + color = "#0000DD" + +/obj/item/weapon/handcuffs/cable/green + color = "#00DD00" + +/obj/item/weapon/handcuffs/cable/pink + color = "#DD00DD" + +/obj/item/weapon/handcuffs/cable/orange + color = "#DD8800" + +/obj/item/weapon/handcuffs/cable/cyan + color = "#00DDDD" + +/obj/item/weapon/handcuffs/cable/white + color = "#FFFFFF" + +/obj/item/weapon/handcuffs/cyborg + dispenser = 1 + +/obj/item/weapon/handcuffs/cyborg/attack(mob/living/carbon/C, mob/user) + if(ishuman(C)) + var/mob/living/carbon/human/target = C + if(!target.can_use_two_hands(FALSE)) + return + if(!C.handcuffed) + var/turf/p_loc = user.loc + var/turf/p_loc_m = C.loc + playsound(src.loc, cuff_sound, 30, 1, -2) + user.visible_message("\red [user] is trying to put handcuffs on [C]!") + 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() diff --git a/code/game/objects/items/weapons/hydroponics.dm b/code/game/objects/items/weapons/hydroponics.dm index b1088d0af199..03bced519732 100644 --- a/code/game/objects/items/weapons/hydroponics.dm +++ b/code/game/objects/items/weapons/hydroponics.dm @@ -1,213 +1,213 @@ -/* 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/equipment.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. - slot_flags = SLOT_BELT - w_class = 1 - var/list/item_quants = list() - -/obj/item/weapon/seedbag/attack_self(mob/user) - 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) - to_chat(usr, "The bag now picks up one seed pouch at a time.") - -/obj/item/seeds/attackby(obj/item/O, mob/user) - ..() - 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, "\blue The seed bag is full.") - S.updateUsrDialog() - return - to_chat(user, "\blue 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 - to_chat(user, "\blue The seed bag is full.") - S.updateUsrDialog() - return - -/obj/item/weapon/seedbag/interact(mob/user) - - 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] - dat += "[capitalize(O)]:" - dat += " [N] " - dat += "Vend" - dat += "
                    " - - dat += "
                    Unload All" - dat += "
                    " - 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.Cut() - 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 - */ - -/obj/item/weapon/grown/sunflower/attack(mob/M, mob/user) - to_chat(M, " [user] smacks you with a sunflower!FLOWER POWER") - to_chat(user, " Your sunflower's FLOWER POWER strikes [M]") - - -/* - * Nettle - */ -/obj/item/weapon/grown/nettle/pickup(mob/living/carbon/human/user) - if(!user.gloves) - to_chat(user, "\red The nettle burns your bare hand!") - if(istype(user, /mob/living/carbon/human)) - var/obj/item/organ/external/BP = user.bodyparts_by_name[user.hand ? BP_L_ARM : BP_R_ARM] - BP.take_damage(0, force) - else - user.take_bodypart_damage(0, force) - -/obj/item/weapon/grown/nettle/afterattack(atom/A, mob/user, proximity) - if(!proximity) return - if(force > 0) - force -= rand(1,(force/3)+1) // When you whack someone with it, leaves fall off - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - else - to_chat(usr, "All the leaves have fallen off the nettle from violent whacking.") - qdel(src) - -/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) - if(!user.gloves) - if(istype(user, /mob/living/carbon/human)) - var/obj/item/organ/external/BP = user.bodyparts_by_name[user.hand ? BP_L_ARM : BP_R_ARM] - BP.take_damage(0, force) - else - user.take_bodypart_damage(0, force) - if(prob(50)) - user.Paralyse(5) - to_chat(user, "\red You are stunned by the Deathnettle when you try picking it up!") - -/obj/item/weapon/grown/deathnettle/attack(mob/living/carbon/M, mob/user) - if(!..()) return - if(istype(M, /mob/living)) - to_chat(M, "\red 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])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] on [M.name] ([M.ckey]) (JMP)") - - 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/afterattack(atom/A, mob/user, proximity) - if(!proximity) return - if (force > 0) - force -= rand(1,(force/3)+1) // When you whack someone with it, leaves fall off - - else - to_chat(usr, "All the leaves have fallen off the deathnettle from violent whacking.") - qdel(src) - -/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, mob/user) - ..() - if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || istype(W, /obj/item/weapon/kitchenknife) || istype(W, /obj/item/weapon/kitchenknife/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 +/* 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/equipment.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. + slot_flags = SLOT_BELT + w_class = 1 + var/list/item_quants = list() + +/obj/item/weapon/seedbag/attack_self(mob/user) + 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) + to_chat(usr, "The bag now picks up one seed pouch at a time.") + +/obj/item/seeds/attackby(obj/item/O, mob/user) + ..() + 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, "\blue The seed bag is full.") + S.updateUsrDialog() + return + to_chat(user, "\blue 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 + to_chat(user, "\blue The seed bag is full.") + S.updateUsrDialog() + return + +/obj/item/weapon/seedbag/interact(mob/user) + + 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] + dat += "[capitalize(O)]:" + dat += " [N] " + dat += "Vend" + dat += "
                    " + + dat += "
                    Unload All" + dat += "
                    " + 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.Cut() + 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 + */ + +/obj/item/weapon/grown/sunflower/attack(mob/M, mob/user) + to_chat(M, " [user] smacks you with a sunflower!FLOWER POWER") + to_chat(user, " Your sunflower's FLOWER POWER strikes [M]") + + +/* + * Nettle + */ +/obj/item/weapon/grown/nettle/pickup(mob/living/carbon/human/user) + if(!user.gloves) + to_chat(user, "\red The nettle burns your bare hand!") + if(istype(user, /mob/living/carbon/human)) + var/obj/item/organ/external/BP = user.bodyparts_by_name[user.hand ? BP_L_ARM : BP_R_ARM] + BP.take_damage(0, force) + else + user.take_bodypart_damage(0, force) + +/obj/item/weapon/grown/nettle/afterattack(atom/A, mob/user, proximity) + if(!proximity) return + if(force > 0) + force -= rand(1,(force/3)+1) // When you whack someone with it, leaves fall off + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + else + to_chat(usr, "All the leaves have fallen off the nettle from violent whacking.") + qdel(src) + +/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) + if(!user.gloves) + if(istype(user, /mob/living/carbon/human)) + var/obj/item/organ/external/BP = user.bodyparts_by_name[user.hand ? BP_L_ARM : BP_R_ARM] + BP.take_damage(0, force) + else + user.take_bodypart_damage(0, force) + if(prob(50)) + user.Paralyse(5) + to_chat(user, "\red You are stunned by the Deathnettle when you try picking it up!") + +/obj/item/weapon/grown/deathnettle/attack(mob/living/carbon/M, mob/user) + if(!..()) return + if(istype(M, /mob/living)) + to_chat(M, "\red 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])") + msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] on [M.name] ([M.ckey]) (JMP)") + + 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/afterattack(atom/A, mob/user, proximity) + if(!proximity) return + if (force > 0) + force -= rand(1,(force/3)+1) // When you whack someone with it, leaves fall off + + else + to_chat(usr, "All the leaves have fallen off the deathnettle from violent whacking.") + qdel(src) + +/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, mob/user) + ..() + if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || istype(W, /obj/item/weapon/kitchenknife) || istype(W, /obj/item/weapon/kitchenknife/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 diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 814d08a0b08c..0feb43a69eab 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -1,527 +1,527 @@ -#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/obj/item/organ/external/part = null - item_color = "b" - var/allow_reagents = 0 - var/malfunction = 0 - -/obj/item/weapon/implant/atom_init() - . = ..() - implant_list += src - -/obj/item/weapon/implant/Destroy() - implant_list -= src - if(part) - part.implants.Remove(src) - part = null - imp_in = null - return ..() - -/obj/item/weapon/implant/proc/trigger(emote, source) - 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(mob/source) - return 1 - -/obj/item/weapon/implant/proc/inject(mob/living/carbon/C, def_zone) - if(!C) - return - loc = C - imp_in = C - implanted = TRUE - if(ishuman(C)) - var/mob/living/carbon/human/H = C - var/obj/item/organ/external/BP = H.bodyparts_by_name[def_zone ? def_zone : BP_HEAD] - BP.implants += src - part = BP - H.hud_updateflag |= 1 << IMPLOYAL_HUD - -/obj/item/weapon/implant/proc/get_data() - return "No information available" - -/obj/item/weapon/implant/proc/hear(message, source) - 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, "\red You feel something melting inside [part ? "your [part.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/tracking - name = "tracking implant" - desc = "Track with this." - var/id = 1.0 - - -/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*60*10,15*60*10) //from 5 to 15 minutes of free time - - spawn(delay) - malfunction-- - - -/obj/item/weapon/implant/dexplosive - name = "explosive" - desc = "And boom goes the weasel." - icon_state = "implant_evil" - -/obj/item/weapon/implant/dexplosive/get_data() - var/dat = {" -Implant Specifications:
                    -Name: Robust Corp RX-78 Employee Management Implant
                    -Life: Activates upon 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/dexplosive/trigger(emote, source) - if(emote == "deathgasp") - src.activate("death") - return - - -/obj/item/weapon/implant/dexplosive/activate(cause) - if((!cause) || (!src.imp_in)) return 0 - explosion(src, -1, 0, 2, 3, 0)//This might be a bit much, dono will have to see. - if(src.imp_in) - src.imp_in.gib() - -/obj/item/weapon/implant/dexplosive/islegal() - return 0 - -//BS12 Explosive -/obj/item/weapon/implant/explosive - name = "explosive implant" - desc = "A military grade micro bio-explosive. Highly dangerous." - var/elevel = "Localized Limb" - var/phrase = "supercalifragilisticexpialidocious" - icon_state = "implant_evil" - -/obj/item/weapon/implant/explosive/get_data() - var/dat = {" -Implant Specifications:
                    -Name: Robust Corp RX-78 Intimidation Class Implant
                    -Life: Activates upon codephrase.
                    -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_talk(mob/M, msg) - hear(msg) - return - -/obj/item/weapon/implant/explosive/hear(msg) - var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "") - msg = sanitize(msg, replacechars) - if(findtext(msg,phrase)) - activate() - qdel(src) - -/obj/item/weapon/implant/explosive/activate() - if (malfunction == MALFUNCTION_PERMANENT) - return - - var/need_gib = null - if(istype(imp_in, /mob/)) - var/mob/T = imp_in - message_admins("Explosive implant triggered in [T] ([T.key]). (JMP) ") - log_game("Explosive implant triggered in [T] ([T.key]).") - need_gib = 1 - - if(ishuman(imp_in)) - if (elevel == "Localized Limb") - if(part) //For some reason, small_boom() didn't work. So have this bit of working copypaste. - imp_in.visible_message("\red Something beeps inside [imp_in][part ? "'s [part.name]" : ""]!") - playsound(loc, 'sound/items/countdown.ogg', 75, 1, -3) - sleep(25) - if (istype(part,/obj/item/organ/external/chest) || \ - istype(part,/obj/item/organ/external/groin) || \ - istype(part,/obj/item/organ/external/head)) - part.createwound(BRUISE, 60) //mangle them instead - explosion(get_turf(imp_in), -1, -1, 2, 3) - qdel(src) - else - explosion(get_turf(imp_in), -1, -1, 2, 3) - part.droplimb(null, null, DROPLIMB_BLUNT) - qdel(src) - if (elevel == "Destroy Body") - explosion(get_turf(T), -1, 0, 1, 6) - T.gib() - if (elevel == "Full Explosion") - explosion(get_turf(T), 0, 1, 3, 6) - T.gib() - - else - explosion(get_turf(imp_in), 0, 1, 3, 6) - - if(need_gib) - imp_in.gib() - - var/turf/t = get_turf(imp_in) - - if(t) - t.hotspot_expose(3500,125) - -/obj/item/weapon/implant/explosive/implanted(mob/source) - elevel = alert("What sort of explosion would you prefer?", "Implant Intent", "Localized Limb", "Destroy Body", "Full Explosion") - var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "") - phrase = sanitize_safe(replace_characters(input("Choose activation phrase:") as text, 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) - 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.") - 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 (ishuman(imp_in) && part) - imp_in.visible_message("\red Something beeps inside [imp_in][part ? "'s [part.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,/obj/item/organ/external/chest) || \ - istype(part,/obj/item/organ/external/groin) || \ - istype(part,/obj/item/organ/external/head)) - part.createwound(BRUISE, 60) //mangle them instead - else - part.droplimb(null, null, DROPLIMB_BLUNT) - explosion(get_turf(imp_in), -1, -1, 2, 3) - qdel(src) - -/obj/item/weapon/implant/chem - name = "chemical implant" - desc = "Injects things." - allow_reagents = 1 - -/obj/item/weapon/implant/chem/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/atom_init() - . = ..() - var/datum/reagents/R = new/datum/reagents(50) - reagents = R - R.my_atom = src - - -/obj/item/weapon/implant/chem/trigger(emote, source) - if(emote == "deathgasp") - src.activate(src.reagents.total_volume) - return - - -/obj/item/weapon/implant/chem/activate(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/adrenalin - name = "adrenalin" - desc = "Removes all stuns and knockdowns." - var/uses - -/obj/item/weapon/implant/adrenalin/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) - if (src.uses < 1) return 0 - if (emote == "pale") - src.uses-- - to_chat(source, "\blue 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) - 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" - -/obj/item/weapon/implant/death_alarm/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) return - var/mob/M = imp_in - - if(isnull(M)) // If the mob got gibbed - activate() - else if(M.stat == DEAD) - activate("death") - -/obj/item/weapon/implant/death_alarm/activate(cause) - var/mob/M = imp_in - var/area/t = get_area(M) - switch (cause) - if("death") - var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(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 - a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm") - else - a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm") - STOP_PROCESSING(SSobj, src) - qdel(a) - if ("emp") - var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null) - var/name = prob(50) ? t.name : pick(teleportlocs) - a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm") - qdel(a) - else - var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null) - a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm") - STOP_PROCESSING(SSobj, src) - qdel(a) - -/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 - STOP_PROCESSING(SSobj, src) - - spawn(20) - malfunction-- - -/obj/item/weapon/implant/death_alarm/implanted(mob/source) - mobname = source.real_name - START_PROCESSING(SSobj, 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 - -/obj/item/weapon/implant/compressed/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) - 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) - 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) - 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." - icon_state = "implant_evil" - /////////////////////////////////////////////////////////// -/obj/item/weapon/storage/internal/imp - name = "bluespace pocket" - max_w_class = 3 - storage_slots = 2 - cant_hold = list(/obj/item/weapon/disk/nuclear) - -/obj/item/weapon/implant/storage - name = "storage implant" - desc = "Stores up to two big items in a bluespace pocket." - icon_state = "implant_evil" - origin_tech = "materials=2;magnets=4;bluespace=5;syndicate=4" - action_button_name = "Bluespace pocket" - var/obj/item/weapon/storage/internal/imp/storage - -/obj/item/weapon/implant/storage/atom_init() - . = ..() - storage = new /obj/item/weapon/storage/internal/imp(src) - -/obj/item/weapon/implant/storage/ui_action_click() - storage.open(imp_in) - -/obj/item/weapon/implant/storage/proc/removed() - storage.close_all() - for(var/obj/item/I in storage) - storage.remove_from_storage(I, get_turf(src)) - -/obj/item/weapon/implant/storage/Destroy() - removed() - qdel(storage) - return ..() - -/obj/item/weapon/implant/storage/islegal() - return 0 +#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/obj/item/organ/external/part = null + item_color = "b" + var/allow_reagents = 0 + var/malfunction = 0 + +/obj/item/weapon/implant/atom_init() + . = ..() + implant_list += src + +/obj/item/weapon/implant/Destroy() + implant_list -= src + if(part) + part.implants.Remove(src) + part = null + imp_in = null + return ..() + +/obj/item/weapon/implant/proc/trigger(emote, source) + 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(mob/source) + return 1 + +/obj/item/weapon/implant/proc/inject(mob/living/carbon/C, def_zone) + if(!C) + return + loc = C + imp_in = C + implanted = TRUE + if(ishuman(C)) + var/mob/living/carbon/human/H = C + var/obj/item/organ/external/BP = H.bodyparts_by_name[def_zone ? def_zone : BP_HEAD] + BP.implants += src + part = BP + H.hud_updateflag |= 1 << IMPLOYAL_HUD + +/obj/item/weapon/implant/proc/get_data() + return "No information available" + +/obj/item/weapon/implant/proc/hear(message, source) + 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, "\red You feel something melting inside [part ? "your [part.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/tracking + name = "tracking implant" + desc = "Track with this." + var/id = 1.0 + + +/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*60*10,15*60*10) //from 5 to 15 minutes of free time + + spawn(delay) + malfunction-- + + +/obj/item/weapon/implant/dexplosive + name = "explosive" + desc = "And boom goes the weasel." + icon_state = "implant_evil" + +/obj/item/weapon/implant/dexplosive/get_data() + var/dat = {" +Implant Specifications:
                    +Name: Robust Corp RX-78 Employee Management Implant
                    +Life: Activates upon 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/dexplosive/trigger(emote, source) + if(emote == "deathgasp") + src.activate("death") + return + + +/obj/item/weapon/implant/dexplosive/activate(cause) + if((!cause) || (!src.imp_in)) return 0 + explosion(src, -1, 0, 2, 3, 0)//This might be a bit much, dono will have to see. + if(src.imp_in) + src.imp_in.gib() + +/obj/item/weapon/implant/dexplosive/islegal() + return 0 + +//BS12 Explosive +/obj/item/weapon/implant/explosive + name = "explosive implant" + desc = "A military grade micro bio-explosive. Highly dangerous." + var/elevel = "Localized Limb" + var/phrase = "supercalifragilisticexpialidocious" + icon_state = "implant_evil" + +/obj/item/weapon/implant/explosive/get_data() + var/dat = {" +Implant Specifications:
                    +Name: Robust Corp RX-78 Intimidation Class Implant
                    +Life: Activates upon codephrase.
                    +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_talk(mob/M, msg) + hear(msg) + return + +/obj/item/weapon/implant/explosive/hear(msg) + var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "") + msg = sanitize(msg, replacechars) + if(findtext(msg,phrase)) + activate() + qdel(src) + +/obj/item/weapon/implant/explosive/activate() + if (malfunction == MALFUNCTION_PERMANENT) + return + + var/need_gib = null + if(istype(imp_in, /mob/)) + var/mob/T = imp_in + message_admins("Explosive implant triggered in [T] ([T.key]). (JMP) ") + log_game("Explosive implant triggered in [T] ([T.key]).") + need_gib = 1 + + if(ishuman(imp_in)) + if (elevel == "Localized Limb") + if(part) //For some reason, small_boom() didn't work. So have this bit of working copypaste. + imp_in.visible_message("\red Something beeps inside [imp_in][part ? "'s [part.name]" : ""]!") + playsound(loc, 'sound/items/countdown.ogg', 75, 1, -3) + sleep(25) + if (istype(part,/obj/item/organ/external/chest) || \ + istype(part,/obj/item/organ/external/groin) || \ + istype(part,/obj/item/organ/external/head)) + part.createwound(BRUISE, 60) //mangle them instead + explosion(get_turf(imp_in), -1, -1, 2, 3) + qdel(src) + else + explosion(get_turf(imp_in), -1, -1, 2, 3) + part.droplimb(null, null, DROPLIMB_BLUNT) + qdel(src) + if (elevel == "Destroy Body") + explosion(get_turf(T), -1, 0, 1, 6) + T.gib() + if (elevel == "Full Explosion") + explosion(get_turf(T), 0, 1, 3, 6) + T.gib() + + else + explosion(get_turf(imp_in), 0, 1, 3, 6) + + if(need_gib) + imp_in.gib() + + var/turf/t = get_turf(imp_in) + + if(t) + t.hotspot_expose(3500,125) + +/obj/item/weapon/implant/explosive/implanted(mob/source) + elevel = alert("What sort of explosion would you prefer?", "Implant Intent", "Localized Limb", "Destroy Body", "Full Explosion") + var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "") + phrase = sanitize_safe(replace_characters(input("Choose activation phrase:") as text, 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) + 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.") + 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 (ishuman(imp_in) && part) + imp_in.visible_message("\red Something beeps inside [imp_in][part ? "'s [part.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,/obj/item/organ/external/chest) || \ + istype(part,/obj/item/organ/external/groin) || \ + istype(part,/obj/item/organ/external/head)) + part.createwound(BRUISE, 60) //mangle them instead + else + part.droplimb(null, null, DROPLIMB_BLUNT) + explosion(get_turf(imp_in), -1, -1, 2, 3) + qdel(src) + +/obj/item/weapon/implant/chem + name = "chemical implant" + desc = "Injects things." + allow_reagents = 1 + +/obj/item/weapon/implant/chem/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/atom_init() + . = ..() + var/datum/reagents/R = new/datum/reagents(50) + reagents = R + R.my_atom = src + + +/obj/item/weapon/implant/chem/trigger(emote, source) + if(emote == "deathgasp") + src.activate(src.reagents.total_volume) + return + + +/obj/item/weapon/implant/chem/activate(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/adrenalin + name = "adrenalin" + desc = "Removes all stuns and knockdowns." + var/uses + +/obj/item/weapon/implant/adrenalin/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) + if (src.uses < 1) return 0 + if (emote == "pale") + src.uses-- + to_chat(source, "\blue 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) + 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" + +/obj/item/weapon/implant/death_alarm/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) return + var/mob/M = imp_in + + if(isnull(M)) // If the mob got gibbed + activate() + else if(M.stat == DEAD) + activate("death") + +/obj/item/weapon/implant/death_alarm/activate(cause) + var/mob/M = imp_in + var/area/t = get_area(M) + switch (cause) + if("death") + var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(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 + a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm") + else + a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm") + STOP_PROCESSING(SSobj, src) + qdel(a) + if ("emp") + var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null) + var/name = prob(50) ? t.name : pick(teleportlocs) + a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm") + qdel(a) + else + var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null) + a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm") + STOP_PROCESSING(SSobj, src) + qdel(a) + +/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 + STOP_PROCESSING(SSobj, src) + + spawn(20) + malfunction-- + +/obj/item/weapon/implant/death_alarm/implanted(mob/source) + mobname = source.real_name + START_PROCESSING(SSobj, 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 + +/obj/item/weapon/implant/compressed/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) + 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) + 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) + 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." + icon_state = "implant_evil" + /////////////////////////////////////////////////////////// +/obj/item/weapon/storage/internal/imp + name = "bluespace pocket" + max_w_class = 3 + storage_slots = 2 + cant_hold = list(/obj/item/weapon/disk/nuclear) + +/obj/item/weapon/implant/storage + name = "storage implant" + desc = "Stores up to two big items in a bluespace pocket." + icon_state = "implant_evil" + origin_tech = "materials=2;magnets=4;bluespace=5;syndicate=4" + action_button_name = "Bluespace pocket" + var/obj/item/weapon/storage/internal/imp/storage + +/obj/item/weapon/implant/storage/atom_init() + . = ..() + storage = new /obj/item/weapon/storage/internal/imp(src) + +/obj/item/weapon/implant/storage/ui_action_click() + storage.open(imp_in) + +/obj/item/weapon/implant/storage/proc/removed() + storage.close_all() + for(var/obj/item/I in storage) + storage.remove_from_storage(I, get_turf(src)) + +/obj/item/weapon/implant/storage/Destroy() + removed() + qdel(storage) + return ..() + +/obj/item/weapon/implant/storage/islegal() + return 0 diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm index cdf2d80f88df..c29ae379a93c 100644 --- a/code/game/objects/items/weapons/implants/implantcase.dm +++ b/code/game/objects/items/weapons/implants/implantcase.dm @@ -1,137 +1,137 @@ -//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.item_color) - else - src.icon_state = "implantcase-0" - return - - - attackby(obj/item/weapon/I, mob/user) - ..() - if (istype(I, /obj/item/weapon/pen)) - var/t = sanitize_safe(input(user, "What would you like the label to be?", input_default(src.name), null) as text, MAX_NAME_LEN) - if (user.get_active_hand() != I) - return - if((!in_range(src, usr) && src.loc != user)) - return - 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, "\red [src] is full.") - else - spawn(5) - I.reagents.trans_to(src.imp, 5) - to_chat(user, "\blue 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" - -/obj/item/weapon/implantcase/tracking/atom_init() - imp = new /obj/item/weapon/implant/tracking(src) - . = ..() - - - -/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" - -/obj/item/weapon/implantcase/explosive/atom_init() - imp = new /obj/item/weapon/implant/explosive(src) - . = ..() - -/obj/item/weapon/implantcase/freedom - name = "Glass Case- 'Freedom'" - desc = "A case containing an freedom implant." - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-r" - -/obj/item/weapon/implantcase/freedom/atom_init() - imp = new /obj/item/weapon/implant/freedom(src) - . = ..() - -/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/atom_init() - imp = new /obj/item/weapon/implant/chem(src) - . = ..() - -/obj/item/weapon/implantcase/mindshield - name = "Glass Case- 'MindShield'" - desc = "A case containing a mindshield implant." - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-r" - -/obj/item/weapon/implantcase/mindshield/atom_init() - imp = new /obj/item/weapon/implant/mindshield(src) - . = ..() - -/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" - -/obj/item/weapon/implantcase/loyalty/atom_init() - imp = new /obj/item/weapon/implant/mindshield/loyalty(src) - . = ..() - -/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" - -/obj/item/weapon/implantcase/death_alarm/atom_init() - imp = new /obj/item/weapon/implant/death_alarm(src) - . = ..() +//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.item_color) + else + src.icon_state = "implantcase-0" + return + + + attackby(obj/item/weapon/I, mob/user) + ..() + if (istype(I, /obj/item/weapon/pen)) + var/t = sanitize_safe(input(user, "What would you like the label to be?", input_default(src.name), null) as text, MAX_NAME_LEN) + if (user.get_active_hand() != I) + return + if((!in_range(src, usr) && src.loc != user)) + return + 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, "\red [src] is full.") + else + spawn(5) + I.reagents.trans_to(src.imp, 5) + to_chat(user, "\blue 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" + +/obj/item/weapon/implantcase/tracking/atom_init() + imp = new /obj/item/weapon/implant/tracking(src) + . = ..() + + + +/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" + +/obj/item/weapon/implantcase/explosive/atom_init() + imp = new /obj/item/weapon/implant/explosive(src) + . = ..() + +/obj/item/weapon/implantcase/freedom + name = "Glass Case- 'Freedom'" + desc = "A case containing an freedom implant." + icon = 'icons/obj/items.dmi' + icon_state = "implantcase-r" + +/obj/item/weapon/implantcase/freedom/atom_init() + imp = new /obj/item/weapon/implant/freedom(src) + . = ..() + +/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/atom_init() + imp = new /obj/item/weapon/implant/chem(src) + . = ..() + +/obj/item/weapon/implantcase/mindshield + name = "Glass Case- 'MindShield'" + desc = "A case containing a mindshield implant." + icon = 'icons/obj/items.dmi' + icon_state = "implantcase-r" + +/obj/item/weapon/implantcase/mindshield/atom_init() + imp = new /obj/item/weapon/implant/mindshield(src) + . = ..() + +/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" + +/obj/item/weapon/implantcase/loyalty/atom_init() + imp = new /obj/item/weapon/implant/mindshield/loyalty(src) + . = ..() + +/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" + +/obj/item/weapon/implantcase/death_alarm/atom_init() + imp = new /obj/item/weapon/implant/death_alarm(src) + . = ..() diff --git a/code/game/objects/items/weapons/implants/implantchair.dm b/code/game/objects/items/weapons/implants/implantchair.dm index 4d9965883c7f..b6cfeb0b8a23 100644 --- a/code/game/objects/items/weapons/implants/implantchair.dm +++ b/code/game/objects/items/weapons/implants/implantchair.dm @@ -1,152 +1,152 @@ -//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/mindshield/implant_list = list() - var/max_implants = 5 - var/injection_cooldown = 600 - var/replenish_cooldown = 6000 - var/replenishing = 0 - var/injecting = 0 - -/obj/machinery/implantchair/atom_init() - . = ..() - add_implants() - - -/obj/machinery/implantchair/ui_interact(mob/user) - 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
                    " - - dat +="Current occupant: [src.occupant ? "
                    Name: [src.occupant]
                    Health: [health_text]
                    " : "None"]
                    " - dat += "Implants: [src.implant_list.len ? "[implant_list.len]" : "Replenish"]
                    " - if(src.occupant) - dat += "[src.ready ? "Implant" : "Recharging"]
                    " - user.set_machine(src) - user << browse(entity_ja(dat), "window=implant") - onclose(user, "implant") - - -/obj/machinery/implantchair/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 - - -/obj/machinery/implantchair/attackby(obj/item/weapon/grab/G, mob/user) - if(!istype(G)) - return - if(!ismob(G.affecting)) - return - for(var/mob/living/carbon/slime/M in range(1, G.affecting)) - if(M.Victim == G.affecting) - to_chat(user, "[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)) - qdel(G) - src.updateUsrDialog() - - -/obj/machinery/implantchair/proc/go_out(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 - - -/obj/machinery/implantchair/proc/put_mob(mob/living/carbon/M) - if(!iscarbon(M)) - to_chat(usr, "\red The [src.name] cannot hold this!") - return - if(src.occupant) - to_chat(usr, "\red 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 - - -/obj/machinery/implantchair/proc/implant(mob/M) - if (!istype(M, /mob/living/carbon)) - return - for(var/obj/item/weapon/implant/mindshield/imp in implant_list) - visible_message("[M] has been implanted by the [src.name].") - if(imp.implanted(M)) - imp.inject(M) - implant_list -= imp - break - - -/obj/machinery/implantchair/proc/add_implants() - for(var/i=0, iName: [src.occupant]
                    Health: [health_text]
                    " : "None"]
                    " + dat += "Implants: [src.implant_list.len ? "[implant_list.len]" : "Replenish"]
                    " + if(src.occupant) + dat += "[src.ready ? "Implant" : "Recharging"]
                    " + user.set_machine(src) + user << browse(entity_ja(dat), "window=implant") + onclose(user, "implant") + + +/obj/machinery/implantchair/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 + + +/obj/machinery/implantchair/attackby(obj/item/weapon/grab/G, mob/user) + if(!istype(G)) + return + if(!ismob(G.affecting)) + return + for(var/mob/living/carbon/slime/M in range(1, G.affecting)) + if(M.Victim == G.affecting) + to_chat(user, "[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)) + qdel(G) + src.updateUsrDialog() + + +/obj/machinery/implantchair/proc/go_out(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 + + +/obj/machinery/implantchair/proc/put_mob(mob/living/carbon/M) + if(!iscarbon(M)) + to_chat(usr, "\red The [src.name] cannot hold this!") + return + if(src.occupant) + to_chat(usr, "\red 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 + + +/obj/machinery/implantchair/proc/implant(mob/M) + if (!istype(M, /mob/living/carbon)) + return + for(var/obj/item/weapon/implant/mindshield/imp in implant_list) + visible_message("[M] has been implanted by the [src.name].") + if(imp.implanted(M)) + imp.inject(M) + implant_list -= imp + break + + +/obj/machinery/implantchair/proc/add_implants() + for(var/i=0, i[user] is attemping to implant [M].
                    ") - - if(M == user || (!user.is_busy() && do_after(user, 50, target = M))) - if(src && imp) - 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)") - if(imp.implanted(M)) - user.visible_message("[M] has been implanted by [user].", "You implanted the implant into [M].") - imp.inject(M, def_zone) - imp = null - update() - - - -/obj/item/weapon/implanter/mindshield - name = "implanter-mind shield" - -/obj/item/weapon/implanter/mindshield/atom_init() - imp = new /obj/item/weapon/implant/mindshield(src) - . = ..() - update() - -/obj/item/weapon/implanter/loyalty - name = "implanter-loyalty" - -/obj/item/weapon/implanter/loyalty/atom_init() - imp = new /obj/item/weapon/implant/mindshield/loyalty(src) - . = ..() - update() - -/obj/item/weapon/implanter/explosive - name = "implanter (E)" - -/obj/item/weapon/implanter/explosive/atom_init() - imp = new /obj/item/weapon/implant/explosive(src) - . = ..() - update() - -/obj/item/weapon/implanter/adrenalin - name = "implanter-adrenalin" - -/obj/item/weapon/implanter/adrenalin/atom_init() - imp = new /obj/item/weapon/implant/adrenalin(src) - . = ..() - update() - -/obj/item/weapon/implanter/compressed - name = "implanter (C)" - icon_state = "cimplanter1" - -/obj/item/weapon/implanter/compressed/atom_init() - imp = new /obj/item/weapon/implant/compressed(src) - . = ..() - update() - -/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, mob/user) - 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(atom/A, mob/user) - if(istype(A,/obj/item) && imp) - var/obj/item/weapon/implant/compressed/c = imp - if (c.scanned) - to_chat(user, "\red Something is already scanned inside the implant!") - return - c.scanned = A - if(istype(A.loc,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = A.loc - H.remove_from_mob(A) - else if(istype(A.loc,/obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = A.loc - S.remove_from_storage(A) - A.loc.contents.Remove(A) - update() - -/obj/item/weapon/implanter/storage - name = "implanter (storage)" - icon_state = "cimplanter1" - -/obj/item/weapon/implanter/storage/atom_init() - imp = new /obj/item/weapon/implant/storage(src) - . = ..() +/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 (imp) + icon_state = "implanter1" + else + icon_state = "implanter0" + + +/obj/item/weapon/implanter/attack(mob/M, mob/user, def_zone) + if (!iscarbon(M)) + return + if (!user || !imp) + return + + user.visible_message("[user] is attemping to implant [M].") + + if(M == user || (!user.is_busy() && do_after(user, 50, target = M))) + if(src && imp) + 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)") + if(imp.implanted(M)) + user.visible_message("[M] has been implanted by [user].", "You implanted the implant into [M].") + imp.inject(M, def_zone) + imp = null + update() + + + +/obj/item/weapon/implanter/mindshield + name = "implanter-mind shield" + +/obj/item/weapon/implanter/mindshield/atom_init() + imp = new /obj/item/weapon/implant/mindshield(src) + . = ..() + update() + +/obj/item/weapon/implanter/loyalty + name = "implanter-loyalty" + +/obj/item/weapon/implanter/loyalty/atom_init() + imp = new /obj/item/weapon/implant/mindshield/loyalty(src) + . = ..() + update() + +/obj/item/weapon/implanter/explosive + name = "implanter (E)" + +/obj/item/weapon/implanter/explosive/atom_init() + imp = new /obj/item/weapon/implant/explosive(src) + . = ..() + update() + +/obj/item/weapon/implanter/adrenalin + name = "implanter-adrenalin" + +/obj/item/weapon/implanter/adrenalin/atom_init() + imp = new /obj/item/weapon/implant/adrenalin(src) + . = ..() + update() + +/obj/item/weapon/implanter/compressed + name = "implanter (C)" + icon_state = "cimplanter1" + +/obj/item/weapon/implanter/compressed/atom_init() + imp = new /obj/item/weapon/implant/compressed(src) + . = ..() + update() + +/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, mob/user) + 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(atom/A, mob/user) + if(istype(A,/obj/item) && imp) + var/obj/item/weapon/implant/compressed/c = imp + if (c.scanned) + to_chat(user, "\red Something is already scanned inside the implant!") + return + c.scanned = A + if(istype(A.loc,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = A.loc + H.remove_from_mob(A) + else if(istype(A.loc,/obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = A.loc + S.remove_from_storage(A) + A.loc.contents.Remove(A) + update() + +/obj/item/weapon/implanter/storage + name = "implanter (storage)" + icon_state = "cimplanter1" + +/obj/item/weapon/implanter/storage/atom_init() + imp = new /obj/item/weapon/implant/storage(src) + . = ..() diff --git a/code/game/objects/items/weapons/implants/implantfreedom.dm b/code/game/objects/items/weapons/implants/implantfreedom.dm index e07ed75189fd..edf58d8a9fd4 100644 --- a/code/game/objects/items/weapons/implants/implantfreedom.dm +++ b/code/game/objects/items/weapons/implants/implantfreedom.dm @@ -1,50 +1,50 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/obj/item/weapon/implant/freedom - name = "freedom implant" - desc = "Use this to escape from those evil Red Shirts." - item_color = "r" - var/activation_emote = "chuckle" - var/uses = 1.0 - - -/obj/item/weapon/implant/freedom/atom_init() - activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") - uses = rand(1, 5) - . = ..() - - -/obj/item/weapon/implant/freedom/trigger(emote, mob/living/carbon/source) - if (uses < 1) - return 0 - if (emote == activation_emote) - uses-- - to_chat(source, "You feel a faint click.") - source.uncuff() - return - - -/obj/item/weapon/implant/freedom/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) - 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 - - -/obj/item/weapon/implant/freedom/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 - - +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +/obj/item/weapon/implant/freedom + name = "freedom implant" + desc = "Use this to escape from those evil Red Shirts." + item_color = "r" + var/activation_emote = "chuckle" + var/uses = 1.0 + + +/obj/item/weapon/implant/freedom/atom_init() + activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") + uses = rand(1, 5) + . = ..() + + +/obj/item/weapon/implant/freedom/trigger(emote, mob/living/carbon/source) + if (uses < 1) + return 0 + if (emote == activation_emote) + uses-- + to_chat(source, "You feel a faint click.") + source.uncuff() + return + + +/obj/item/weapon/implant/freedom/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) + 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 + + +/obj/item/weapon/implant/freedom/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 c6a3545ce2a1..91c6962de7c3 100644 --- a/code/game/objects/items/weapons/implants/implantpad.dm +++ b/code/game/objects/items/weapons/implants/implantpad.dm @@ -1,98 +1,98 @@ -//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) - 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, mob/user) - ..() - if(istype(C, /obj/item/weapon/implantcase)) - if(!( src.case )) - user.drop_item() - C.loc = src - src.case = C - else - return - src.update() - return - - - attack_self(mob/user) - 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(entity_ja(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) + 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, mob/user) + ..() + if(istype(C, /obj/item/weapon/implantcase)) + if(!( src.case )) + user.drop_item() + C.loc = src + src.case = C + else + return + src.update() + return + + + attack_self(mob/user) + 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(entity_ja(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 d23c35a65167..2b73aa6d1610 100644 --- a/code/game/objects/items/weapons/implants/implantuplink.dm +++ b/code/game/objects/items/weapons/implants/implantuplink.dm @@ -1,22 +1,22 @@ -/obj/item/weapon/implant/uplink - name = "uplink" - desc = "Summon things." - var/activation_emote = "chuckle" - -/obj/item/weapon/implant/uplink/atom_init() - 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 = 10 - . = ..() - -/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) - 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) - if(hidden_uplink && usr == source) // Let's not have another people activate our uplink - hidden_uplink.check_trigger(source, emote, activation_emote) - return +/obj/item/weapon/implant/uplink + name = "uplink" + desc = "Summon things." + var/activation_emote = "chuckle" + +/obj/item/weapon/implant/uplink/atom_init() + 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 = 10 + . = ..() + +/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) + 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) + if(hidden_uplink && usr == source) // Let's not have another people activate our uplink + hidden_uplink.check_trigger(source, emote, activation_emote) + return diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index d793885761bc..d3c6c0cab5a7 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -1,551 +1,551 @@ -/* 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 = 0 - w_class = 1.0 - throwforce = 0 - throw_speed = 3 - throw_range = 5 - flags = CONDUCT - origin_tech = "materials=1" - attack_verb = list("attacked", "stabbed", "poked") - var/max_contents = 1 - -/obj/item/weapon/kitchen/utensil/atom_init() - . = ..() - if (prob(60)) - pixel_y = rand(0, 4) - -/obj/item/weapon/kitchen/utensil/attack(mob/living/carbon/M, mob/living/carbon/user) - if(!istype(M)) - return ..() - - if(user.a_intent != "help") - if(user.zone_sel.selecting == "head" || user.zone_sel.selecting == "eyes") - if((CLUMSY in user.mutations) && prob(50)) - M = user - return eyestab(M,user) - else - return ..() - - if(contents.len) - var/obj/item/weapon/reagent_containers/food/snacks/toEat = contents[1] - if(istype(toEat)) - if(CanEat(user, M, toEat, "eat")) - toEat.On_Consume(M, user) - if(toEat) - qdel(toEat) - overlays.Cut() - return - -/* - * Spoons - */ -/obj/item/weapon/kitchen/utensil/spoon - name = "spoon" - desc = "SPOON!" - icon_state = "spoon" - attack_verb = list("attacked", "poked") - -/obj/item/weapon/kitchen/utensil/pspoon - name = "plastic spoon" - desc = "Super dull action!" - icon_state = "pspoon" - attack_verb = list("attacked", "poked") - -/* - * Forks - */ -/obj/item/weapon/kitchen/utensil/fork - name = "fork" - desc = "Pointy." - force = 3 - icon_state = "fork" - -/obj/item/weapon/kitchen/utensil/fork/afterattack(atom/target, mob/user, proximity) - if(istype(target,/obj/item/weapon/reagent_containers/food/snacks)) return // fork is not only for cleanning - if(!proximity) return - //I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. - //So this is a workaround. This also makes more sense from an IC standpoint. ~Carn - if(istype(target,/obj/effect/decal/cleanable) && !user.is_busy(target)) - user.visible_message("[user] begins to clean \the [target.name].","You begin to clean \the [target.name].") - if(do_after(user, 60, target = target)) - user.visible_message("[user] scrub \the [target.name] out.","You scrub \the [target.name] out.") - qdel(target) - -/obj/item/weapon/kitchen/utensil/fork/sticks - name = "wooden chopsticks" - desc = "How do people even hold this?" - force = 2 - icon_state = "sticks" - -/obj/item/weapon/kitchen/utensil/pfork - name = "plastic fork" - desc = "Yay, no washing up to do." - icon_state = "pfork" - force = 0 - - -/obj/item/weapon/kitchen/utensil/pfork/afterattack(atom/target, mob/user, proximity) //make them useful or some slow soap for plastic. Just copy-paste from usual fork - if(istype(target,/obj/item/weapon/reagent_containers/food/snacks)) return // fork is not only for cleanning - if(!proximity) return - //I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. - //So this is a workaround. This also makes more sense from an IC standpoint. ~Carn - if(istype(target,/obj/effect/decal/cleanable) && !user.is_busy(target)) - user.visible_message("[user] begins to clean \the [target.name].","You begin to clean \the [target.name].") - if(do_after(user, 60, target = target)) - user.visible_message("[user] scrub \the [target.name] out.","You scrub \the [target.name] out.") - qdel(target) - -/* - * Kitchen knives - */ -/obj/item/weapon/kitchenknife - 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 = CONDUCT - sharp = 1 - edge = 1 - force = 10.0 - w_class = 2.0 - throwforce = 6.0 - throw_speed = 3 - throw_range = 6 - m_amt = 12000 - origin_tech = "materials=1" - attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - - suicide_act(mob/user) - to_chat(viewers(user), pick("\red [user] is slitting \his wrists with the [src.name]! It looks like \he's trying to commit suicide.", \ - "\red [user] is slitting \his throat with the [src.name]! It looks like \he's trying to commit suicide.", \ - "\red [user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.")) - return (BRUTELOSS) - -/obj/item/weapon/kitchenknife/attack(mob/living/carbon/M, mob/living/carbon/user) - if(user.a_intent == "help" && M.attempt_harvest(src, user)) - return - return ..() - -/obj/item/weapon/kitchenknife/plastic - name = "plastic knife" - desc = "The bluntest of blades." - icon_state = "pknife" - force = 0 - w_class = 2.0 - throwforce = 0 - -/obj/item/weapon/kitchenknife/ritual - name = "ritual knife" - desc = "The unearthly energies that once powered this blade are now dormant." - icon = 'icons/obj/wizard.dmi' - icon_state = "render" - -/* - * Bucher's cleaver - */ -/obj/item/weapon/butch - name = "butcher's cleaver" - icon = 'icons/obj/kitchen.dmi' - icon_state = "butch" - desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." - flags = CONDUCT - force = 15.0 - w_class = 3.0 - throwforce = 8.0 - throw_speed = 3 - throw_range = 6 - m_amt = 12000 - origin_tech = "materials=1" - attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - sharp = 1 - edge = 1 - -/obj/item/weapon/butch/attack(mob/living/M, mob/living/user) - if(user.a_intent == I_HELP && M.attempt_harvest(src, user)) - return - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - -/* - * Rolling Pins - */ - -/obj/item/weapon/kitchen/rollingpin - name = "rolling pin" - desc = "Used to knock out the Bartender." - icon_state = "rolling_pin" - force = 8.0 - throwforce = 10.0 - throw_speed = 2 - throw_range = 7 - w_class = 3.0 - 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, mob/living/user) - if ((CLUMSY in user.mutations) && prob(50)) - to_chat(user, "\red The [src] slips out of your hand and hits your head.") - user.take_bodypart_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]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") - - var/t = user:zone_sel.selecting - if (t == BP_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, "\red 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 != DEAD) H.stat = UNCONSCIOUS - user.visible_message("\red [H] has been knocked unconscious!", "\red You knock [H] unconscious!") - return - else - H.visible_message("\red [user] tried to knock [H] unconscious!", "\red [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 - throw_range = 5 - w_class = 3.0 - flags = CONDUCT - m_amt = 3000 - /* // NOPE - var/food_total= 0 - var/burger_amt = 0 - var/cheese_amt = 0 - var/fries_amt = 0 - var/classyalcdrink_amt = 0 - var/alcdrink_amt = 0 - var/bottle_amt = 0 - var/soda_amt = 0 - var/carton_amt = 0 - var/pie_amt = 0 - var/meatbreadslice_amt = 0 - var/salad_amt = 0 - var/miscfood_amt = 0 - */ - 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, mob/living/carbon/user, def_zone) - - // Drop all the things. All of them. - overlays.Cut() - 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((CLUMSY in user.mutations) && prob(50)) //What if he's a clown? - to_chat(M, "\red You accidentally slam yourself with the [src]!") - M.Weaken(1) - user.take_bodypart_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(!(def_zone == O_EYES || def_zone == BP_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])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") - - if(prob(15)) - M.Weaken(3) - M.take_bodypart_damage(3) - else - M.take_bodypart_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("\red [] 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("\red [] slams [] with the tray!", user, M), 1) - return - - - - - if(istype(M, /mob/living/carbon/human) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) - to_chat(M, "\red 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("\red [] 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("\red [] slams [] with the tray!", user, M), 1) - if(prob(10)) - M.Stun(rand(1,3)) - M.take_bodypart_damage(3) - return - else - M.take_bodypart_damage(5) - return - - else //No eye or head protection, tough luck! - to_chat(M, "\red 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("\red [] 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("\red [] slams [] in the face with the tray!", user, M), 1) - if(prob(30)) - M.Stun(rand(2,4)) - M.take_bodypart_damage(4) - return - else - M.take_bodypart_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, mob/user) - 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) - 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.Cut() - - 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)) - -///////////////////NEW////////////////////// - -/obj/item/weapon/kitchen/mould - name = "generic candy mould" - desc = "You aren't sure what it's supposed to be." - icon_state = "mould" - force = 5 - throwforce = 5 - throw_speed = 3 - throw_range = 3 - w_class = 2 - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") - -/obj/item/weapon/kitchen/mould/bear - name = "bear-shaped candy mould" - desc = "It has the shape of a small bear imprinted into it." - icon_state = "mould_bear" - -/obj/item/weapon/kitchen/mould/worm - name = "worm-shaped candy mould" - desc = "It has the shape of a worm imprinted into it." - icon_state = "mould_worm" - -/obj/item/weapon/kitchen/mould/bean - name = "bean-shaped candy mould" - desc = "It has the shape of a bean imprinted into it." - icon_state = "mould_bean" - -/obj/item/weapon/kitchen/mould/ball - name = "ball-shaped candy mould" - desc = "It has a small sphere imprinted into it." - icon_state = "mould_ball" - -/obj/item/weapon/kitchen/mould/cane - name = "cane-shaped candy mould" - desc = "It has the shape of a cane imprinted into it." - icon_state = "mould_cane" - -/obj/item/weapon/kitchen/mould/cash - name = "cash-shaped candy mould" - desc = "It has the shape and design of fake money imprinted into it." - icon_state = "mould_cash" - -/obj/item/weapon/kitchen/mould/coin - name = "coin-shaped candy mould" - desc = "It has the shape of a coin imprinted into it." - icon_state = "mould_coin" - -/obj/item/weapon/kitchen/mould/loli - name = "sucker mould" - desc = "It has the shape of a sucker imprinted into it." - icon_state = "mould_loli" - -///////////////////////////////////////////////////////////////////////////////////////// -//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, mob/user) - if(istype(W,/obj/item/weapon/kitchen/utensil/fork)) - if (W.icon_state == "forkloaded") - to_chat(user, "\red You already have omelette on your fork.") - 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) - qdel(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)*/ +/* 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 = 0 + w_class = 1.0 + throwforce = 0 + throw_speed = 3 + throw_range = 5 + flags = CONDUCT + origin_tech = "materials=1" + attack_verb = list("attacked", "stabbed", "poked") + var/max_contents = 1 + +/obj/item/weapon/kitchen/utensil/atom_init() + . = ..() + if (prob(60)) + pixel_y = rand(0, 4) + +/obj/item/weapon/kitchen/utensil/attack(mob/living/carbon/M, mob/living/carbon/user) + if(!istype(M)) + return ..() + + if(user.a_intent != "help") + if(user.zone_sel.selecting == "head" || user.zone_sel.selecting == "eyes") + if((CLUMSY in user.mutations) && prob(50)) + M = user + return eyestab(M,user) + else + return ..() + + if(contents.len) + var/obj/item/weapon/reagent_containers/food/snacks/toEat = contents[1] + if(istype(toEat)) + if(CanEat(user, M, toEat, "eat")) + toEat.On_Consume(M, user) + if(toEat) + qdel(toEat) + overlays.Cut() + return + +/* + * Spoons + */ +/obj/item/weapon/kitchen/utensil/spoon + name = "spoon" + desc = "SPOON!" + icon_state = "spoon" + attack_verb = list("attacked", "poked") + +/obj/item/weapon/kitchen/utensil/pspoon + name = "plastic spoon" + desc = "Super dull action!" + icon_state = "pspoon" + attack_verb = list("attacked", "poked") + +/* + * Forks + */ +/obj/item/weapon/kitchen/utensil/fork + name = "fork" + desc = "Pointy." + force = 3 + icon_state = "fork" + +/obj/item/weapon/kitchen/utensil/fork/afterattack(atom/target, mob/user, proximity) + if(istype(target,/obj/item/weapon/reagent_containers/food/snacks)) return // fork is not only for cleanning + if(!proximity) return + //I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. + //So this is a workaround. This also makes more sense from an IC standpoint. ~Carn + if(istype(target,/obj/effect/decal/cleanable) && !user.is_busy(target)) + user.visible_message("[user] begins to clean \the [target.name].","You begin to clean \the [target.name].") + if(do_after(user, 60, target = target)) + user.visible_message("[user] scrub \the [target.name] out.","You scrub \the [target.name] out.") + qdel(target) + +/obj/item/weapon/kitchen/utensil/fork/sticks + name = "wooden chopsticks" + desc = "How do people even hold this?" + force = 2 + icon_state = "sticks" + +/obj/item/weapon/kitchen/utensil/pfork + name = "plastic fork" + desc = "Yay, no washing up to do." + icon_state = "pfork" + force = 0 + + +/obj/item/weapon/kitchen/utensil/pfork/afterattack(atom/target, mob/user, proximity) //make them useful or some slow soap for plastic. Just copy-paste from usual fork + if(istype(target,/obj/item/weapon/reagent_containers/food/snacks)) return // fork is not only for cleanning + if(!proximity) return + //I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. + //So this is a workaround. This also makes more sense from an IC standpoint. ~Carn + if(istype(target,/obj/effect/decal/cleanable) && !user.is_busy(target)) + user.visible_message("[user] begins to clean \the [target.name].","You begin to clean \the [target.name].") + if(do_after(user, 60, target = target)) + user.visible_message("[user] scrub \the [target.name] out.","You scrub \the [target.name] out.") + qdel(target) + +/* + * Kitchen knives + */ +/obj/item/weapon/kitchenknife + 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 = CONDUCT + sharp = 1 + edge = 1 + force = 10.0 + w_class = 2.0 + throwforce = 6.0 + throw_speed = 3 + throw_range = 6 + m_amt = 12000 + origin_tech = "materials=1" + attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + + suicide_act(mob/user) + to_chat(viewers(user), pick("\red [user] is slitting \his wrists with the [src.name]! It looks like \he's trying to commit suicide.", \ + "\red [user] is slitting \his throat with the [src.name]! It looks like \he's trying to commit suicide.", \ + "\red [user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.")) + return (BRUTELOSS) + +/obj/item/weapon/kitchenknife/attack(mob/living/carbon/M, mob/living/carbon/user) + if(user.a_intent == "help" && M.attempt_harvest(src, user)) + return + return ..() + +/obj/item/weapon/kitchenknife/plastic + name = "plastic knife" + desc = "The bluntest of blades." + icon_state = "pknife" + force = 0 + w_class = 2.0 + throwforce = 0 + +/obj/item/weapon/kitchenknife/ritual + name = "ritual knife" + desc = "The unearthly energies that once powered this blade are now dormant." + icon = 'icons/obj/wizard.dmi' + icon_state = "render" + +/* + * Bucher's cleaver + */ +/obj/item/weapon/butch + name = "butcher's cleaver" + icon = 'icons/obj/kitchen.dmi' + icon_state = "butch" + desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." + flags = CONDUCT + force = 15.0 + w_class = 3.0 + throwforce = 8.0 + throw_speed = 3 + throw_range = 6 + m_amt = 12000 + origin_tech = "materials=1" + attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + sharp = 1 + edge = 1 + +/obj/item/weapon/butch/attack(mob/living/M, mob/living/user) + if(user.a_intent == I_HELP && M.attempt_harvest(src, user)) + return + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return ..() + +/* + * Rolling Pins + */ + +/obj/item/weapon/kitchen/rollingpin + name = "rolling pin" + desc = "Used to knock out the Bartender." + icon_state = "rolling_pin" + force = 8.0 + throwforce = 10.0 + throw_speed = 2 + throw_range = 7 + w_class = 3.0 + 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, mob/living/user) + if ((CLUMSY in user.mutations) && prob(50)) + to_chat(user, "\red The [src] slips out of your hand and hits your head.") + user.take_bodypart_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]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") + + var/t = user:zone_sel.selecting + if (t == BP_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, "\red 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 != DEAD) H.stat = UNCONSCIOUS + user.visible_message("\red [H] has been knocked unconscious!", "\red You knock [H] unconscious!") + return + else + H.visible_message("\red [user] tried to knock [H] unconscious!", "\red [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 + throw_range = 5 + w_class = 3.0 + flags = CONDUCT + m_amt = 3000 + /* // NOPE + var/food_total= 0 + var/burger_amt = 0 + var/cheese_amt = 0 + var/fries_amt = 0 + var/classyalcdrink_amt = 0 + var/alcdrink_amt = 0 + var/bottle_amt = 0 + var/soda_amt = 0 + var/carton_amt = 0 + var/pie_amt = 0 + var/meatbreadslice_amt = 0 + var/salad_amt = 0 + var/miscfood_amt = 0 + */ + 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, mob/living/carbon/user, def_zone) + + // Drop all the things. All of them. + overlays.Cut() + 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((CLUMSY in user.mutations) && prob(50)) //What if he's a clown? + to_chat(M, "\red You accidentally slam yourself with the [src]!") + M.Weaken(1) + user.take_bodypart_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(!(def_zone == O_EYES || def_zone == BP_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])") + msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") + + if(prob(15)) + M.Weaken(3) + M.take_bodypart_damage(3) + else + M.take_bodypart_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("\red [] 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("\red [] slams [] with the tray!", user, M), 1) + return + + + + + if(istype(M, /mob/living/carbon/human) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) + to_chat(M, "\red 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("\red [] 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("\red [] slams [] with the tray!", user, M), 1) + if(prob(10)) + M.Stun(rand(1,3)) + M.take_bodypart_damage(3) + return + else + M.take_bodypart_damage(5) + return + + else //No eye or head protection, tough luck! + to_chat(M, "\red 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("\red [] 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("\red [] slams [] in the face with the tray!", user, M), 1) + if(prob(30)) + M.Stun(rand(2,4)) + M.take_bodypart_damage(4) + return + else + M.take_bodypart_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, mob/user) + 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) + 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.Cut() + + 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)) + +///////////////////NEW////////////////////// + +/obj/item/weapon/kitchen/mould + name = "generic candy mould" + desc = "You aren't sure what it's supposed to be." + icon_state = "mould" + force = 5 + throwforce = 5 + throw_speed = 3 + throw_range = 3 + w_class = 2 + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") + +/obj/item/weapon/kitchen/mould/bear + name = "bear-shaped candy mould" + desc = "It has the shape of a small bear imprinted into it." + icon_state = "mould_bear" + +/obj/item/weapon/kitchen/mould/worm + name = "worm-shaped candy mould" + desc = "It has the shape of a worm imprinted into it." + icon_state = "mould_worm" + +/obj/item/weapon/kitchen/mould/bean + name = "bean-shaped candy mould" + desc = "It has the shape of a bean imprinted into it." + icon_state = "mould_bean" + +/obj/item/weapon/kitchen/mould/ball + name = "ball-shaped candy mould" + desc = "It has a small sphere imprinted into it." + icon_state = "mould_ball" + +/obj/item/weapon/kitchen/mould/cane + name = "cane-shaped candy mould" + desc = "It has the shape of a cane imprinted into it." + icon_state = "mould_cane" + +/obj/item/weapon/kitchen/mould/cash + name = "cash-shaped candy mould" + desc = "It has the shape and design of fake money imprinted into it." + icon_state = "mould_cash" + +/obj/item/weapon/kitchen/mould/coin + name = "coin-shaped candy mould" + desc = "It has the shape of a coin imprinted into it." + icon_state = "mould_coin" + +/obj/item/weapon/kitchen/mould/loli + name = "sucker mould" + desc = "It has the shape of a sucker imprinted into it." + icon_state = "mould_loli" + +///////////////////////////////////////////////////////////////////////////////////////// +//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, mob/user) + if(istype(W,/obj/item/weapon/kitchen/utensil/fork)) + if (W.icon_state == "forkloaded") + to_chat(user, "\red You already have omelette on your fork.") + 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) + qdel(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 989ed1c0217f..ccfd82b995e2 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -1,405 +1,405 @@ -/*********************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/wiki - var/wiki_page = "" - window_size = "970x710" - -/obj/item/weapon/book/manual/wiki/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/item/weapon/book/manual/wiki/atom_init_late() - if(config.wikiurl) - dat = {" - - - - - - -

                    You start skimming through the manual...

                    - - - - - - "} - return ..() - -//Engineering - -/obj/item/weapon/book/manual/wiki/basic_engineering - name = "Basic Engineering" - icon_state ="bookBasicEngineering" - item_state ="book3" - author = "Einstein Engines Inc" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - title = "Basic Engineering" - wiki_page = "Guide_to_Engineering" - -/obj/item/weapon/book/manual/wiki/construction - name = "Guide to Construction" - icon_state ="bookConstruction" - item_state ="book3" - author = "Engineering Encyclopedia" - title = "Guide to Construction" - wiki_page = "Guide_to_Constructions" - -/obj/item/weapon/book/manual/wiki/atmospipes - name = "Pipes and You: Getting To Know Atmospherics" - icon_state = "bookAtmos" - item_state ="book3" - author = "Einstein Engines Inc" - title = "Pipes and You: Getting To Know Atmospherics" - wiki_page = "Atmospherics" - -/obj/item/weapon/book/manual/wiki/supermatter_engine - name = "Supermatter Engine User's Guide" - icon_state = "bookSupermatter" - item_state ="book3" - author = "Einstein Engines Inc" - title = "Supermatter Engine User's Guide" - wiki_page = "Supermatter_Engine" - -/obj/item/weapon/book/manual/wiki/engineering_hacking - name = "Hacking" - icon_state ="bookHacking" - item_state ="book3" - author = "Einstein Engines Inc" - title = "Hacking" - wiki_page = "Hacking" - -/obj/item/weapon/book/manual/wiki/engineering_singularity - name = "How to set up the Singularity Engine" - icon_state ="bookSingularityEngine" - item_state ="book3" - author = "Einstein Engines Inc" - title = "How to set up the Singularity Engine" - wiki_page = "Singularity_Engine" - -/obj/item/weapon/book/manual/wiki/engineering_tesla - name = "How to set up the Telsa Engine" - icon_state ="bookTeslaEngine" - item_state ="book3" - author = "Einstein Engines Inc" - title = "How to set up the Telsa Engine" - wiki_page = "Tesla_Engine" - -/obj/item/weapon/book/manual/wiki/engineering_solars - name = "How to set up the Solars" - icon_state ="bookSolars" - item_state ="book3" - author = "Einstein Engines Inc" - title = "How to set up the Solars" - wiki_page = "Solars" - -//Medical - -/obj/item/weapon/book/manual/wiki/medical_guide_to_medicine - name = "Medicine Manual" - icon_state ="bookMedical" - item_state ="book4" - author = "NanoTrasen" - title = "Medicine Manual" - wiki_page = "Guide_to_Medicine" - -/obj/item/weapon/book/manual/wiki/medical_genetics - name = "Wonders of Genetics" - icon_state ="bookGenetics" - item_state ="book4" - author = "NanoTrasen" - title = "Wonders of Genetics" - wiki_page = "Guide_to_Genetics" - -/obj/item/weapon/book/manual/wiki/medical_surgery - name = "Guide to Surgery" - icon_state ="bookSurgery" - item_state ="book7" - author = "NanoTrasen" - title = "Guide to Surgery" - wiki_page = "Surgery" - -/obj/item/weapon/book/manual/wiki/medical_virology - name = "Virology Protocols" - icon_state ="bookVirology" - item_state ="book7" - author = "NanoTrasen" - title = "Virology Protocols" - wiki_page = "Guide_to_Virology" - -/obj/item/weapon/book/manual/wiki/medical_chemistry - name = "Chemical Formulas" - icon_state ="bookChemistry" - item_state ="book7" - author = "NanoTrasen" - title = "Chemical Formulas" - wiki_page = "Guide_to_Chemistry" - -//Research and Development - -/obj/item/weapon/book/manual/wiki/research_and_development - name = "Basics of Research" - icon_state = "bookBasicsOfResearch" - item_state ="book6" - author = "NanoTrasen" - title = "Basics of Research" - wiki_page = "Guide_to_Research_and_Development" - -/obj/item/weapon/book/manual/wiki/guide_to_robotics - name = "Robotics for Dummies" - icon_state = "bookGuideToRobotics" - item_state ="book6" - author = "BioTech" - title = "Robotics for Dummies" - wiki_page = "Guide_to_Robotics" - -/obj/item/weapon/book/manual/wiki/guide_to_toxins - name = "Study of Phoron Properties" - icon_state = "bookGuideToToxins" - item_state ="book6" - author = "Cybersun Industries" - title = "Study of Phoron Properties" - wiki_page = "Guide_to_toxins" - -/obj/item/weapon/book/manual/wiki/guide_to_xenobiology - name = "Xenobilogy: Grow and Study" - icon_state = "bookXenobiology" - item_state ="book6" - author = "NanoTrasen" - title = "Xenobilogy: Grow and Study" - wiki_page = "Guide_to_xenobiology" - -/obj/item/weapon/book/manual/wiki/guide_to_exosuits - name = "Exosuits Construction" - icon_state = "bookExosuits" - item_state ="book6" - author = "NanoTrasen" - title = "Exosuits Construction" - wiki_page = "Guide_to_Exosuits" - -/obj/item/weapon/book/manual/wiki/guide_to_telescience - name = "TeleScience: Science of Time and Space" - icon_state = "bookTelescience" - item_state ="book6" - author = "NanoTrasen" - title = "TeleScience: Science of Time and Space" - wiki_page = "Guide_To_Telescience" - -//Law and Order - -/obj/item/weapon/book/manual/wiki/security_space_law - name = "Space Law" - desc = "A set of NanoTrasen guidelines for keeping law and order on their space stations." - icon_state = "bookSpaceLaw" - item_state = "book2" - author = "NanoTrasen" - title = "Space Law" - wiki_page = "Space Law" - -/obj/item/weapon/book/manual/wiki/sop - name = "Standard Operating Procedure" - icon_state = "bookSOP" - item_state = "book9" - author = "NanoTrasen" - title = "Standard Operating Procedure" - wiki_page = "Standard_Operating_Procedure" - -/obj/item/weapon/book/manual/wiki/lsop - name = "Legal Standard Operating Procedure" - icon_state = "bookLSOP" - item_state = "book9" - author = "NanoTrasen" - title = "Legal Standard Operating Procedure" - wiki_page = "Legal_Standard_Operating_Procedure" - -/obj/item/weapon/book/manual/detective - name = "The Film Noir: Proper Procedures for Investigations" - icon_state ="bookDetective" - item_state = "book2" - author = "NanoTrasen" - title = "The Film Noir: Proper Procedures for Investigations" - - dat = {" - - - - -

                    Detective Work

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

                    -

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

                    - It really is that easy! Good luck! - - - "} - -//Civilian guides - -/obj/item/weapon/book/manual/wiki/chefs_recipes - name = "Bon Appetite: Chef's Recipes" - icon_state = "bookChefsRecipes" - item_state = "book10" - author = "Victoria Ponsonby" - title = "Bon Appetite: Chef's Recipes" - wiki_page = "Guide_to_Food" - -/obj/item/weapon/book/manual/wiki/barman_recipes - name = "Barman Recipes" - icon_state = "bookDrinks" - item_state = "book4" - author = "Sir John Rose" - title = "Barman Recipes" - wiki_page = "Drinks" - -/obj/item/weapon/book/manual/wiki/hydroponics - name = "From Seed to Fruit: Hydroponics for dummies" - icon_state ="bookHydroponics" - item_state = "book5" - author = "Farmer John" - title = "From Seed to Fruit: Hydroponics for dummies" - wiki_page = "Guide_to_Hydroponics" - -/obj/item/weapon/book/manual/wiki/supply_crates - name = "Supply Crates Official List" - icon_state ="bookSupplyCrates" - item_state = "book8" - author = "NanoTrasen" - title = "Supply Crates Official List" - wiki_page = "Supply_crates" - -//Other - -/obj/item/weapon/book/manual/wiki/rules - name = "Rules" - desc = "Don't be a jerk. This is a corollary of ignore all rules, and most behavioural rules are special cases of this one." - icon_state = "bookRules" - item_state = "book2" - author = "Tau Ceti Classic" - title = "Rules" - wiki_page = "Rules" - -//Old manuals that we should keep for a while - -/obj/item/weapon/book/manual/hydroponics_beekeeping - name = "The Ins and Outs of Apiculture - A Precise Art" - icon_state ="bookHydroponicsBees" - item_state ="book5" - author = "Beekeeper Dave" - title = "The Ins and Outs of Apiculture - A Precise Art" - dat = {" - - - - -

                    Raising Bees

                    - - Bees are loving but fickle creatures. Don't mess with their hive and stay away from any clusters of them, and you'll avoid their ire. - Sometimes, you'll need to dig around in there for those delicious sweeties though - in that case make sure you wear sealed protection gear - and carry an extinguisher or smoker with you - any bees chasing you, once calmed down, can thusly be netted and returned safely to the hive. - BeezEez is a cure-all panacea for them, but use it too much and the hive may grow to apocalyptic proportions. Other than that, bees are excellent pets - for all the family and are excellent caretakers of one's garden: having a hive or two around will aid in the longevity and growth rate of plants, - and aid them in fighting off poisons and disease. - - - - "} - -/obj/item/weapon/book/manual/nuclear - name = "Fission Mailed: Nuclear Sabotage 101" - icon_state ="bookNuclear" - item_state = "book" - author = "Syndicate" - title = "Fission Mailed: Nuclear Sabotage 101" - - dat = {" - - - - -

                    Nuclear Explosives 101

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

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

                    To make the nuclear device functional

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

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

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

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

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

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

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

                    - - Good luck! - - - "} +/*********************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/wiki + var/wiki_page = "" + window_size = "970x710" + +/obj/item/weapon/book/manual/wiki/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/item/weapon/book/manual/wiki/atom_init_late() + if(config.wikiurl) + dat = {" + + + + + + +

                    You start skimming through the manual...

                    + + + + + + "} + return ..() + +//Engineering + +/obj/item/weapon/book/manual/wiki/basic_engineering + name = "Basic Engineering" + icon_state ="bookBasicEngineering" + item_state ="book3" + author = "Einstein Engines Inc" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned + title = "Basic Engineering" + wiki_page = "Guide_to_Engineering" + +/obj/item/weapon/book/manual/wiki/construction + name = "Guide to Construction" + icon_state ="bookConstruction" + item_state ="book3" + author = "Engineering Encyclopedia" + title = "Guide to Construction" + wiki_page = "Guide_to_Constructions" + +/obj/item/weapon/book/manual/wiki/atmospipes + name = "Pipes and You: Getting To Know Atmospherics" + icon_state = "bookAtmos" + item_state ="book3" + author = "Einstein Engines Inc" + title = "Pipes and You: Getting To Know Atmospherics" + wiki_page = "Atmospherics" + +/obj/item/weapon/book/manual/wiki/supermatter_engine + name = "Supermatter Engine User's Guide" + icon_state = "bookSupermatter" + item_state ="book3" + author = "Einstein Engines Inc" + title = "Supermatter Engine User's Guide" + wiki_page = "Supermatter_Engine" + +/obj/item/weapon/book/manual/wiki/engineering_hacking + name = "Hacking" + icon_state ="bookHacking" + item_state ="book3" + author = "Einstein Engines Inc" + title = "Hacking" + wiki_page = "Hacking" + +/obj/item/weapon/book/manual/wiki/engineering_singularity + name = "How to set up the Singularity Engine" + icon_state ="bookSingularityEngine" + item_state ="book3" + author = "Einstein Engines Inc" + title = "How to set up the Singularity Engine" + wiki_page = "Singularity_Engine" + +/obj/item/weapon/book/manual/wiki/engineering_tesla + name = "How to set up the Telsa Engine" + icon_state ="bookTeslaEngine" + item_state ="book3" + author = "Einstein Engines Inc" + title = "How to set up the Telsa Engine" + wiki_page = "Tesla_Engine" + +/obj/item/weapon/book/manual/wiki/engineering_solars + name = "How to set up the Solars" + icon_state ="bookSolars" + item_state ="book3" + author = "Einstein Engines Inc" + title = "How to set up the Solars" + wiki_page = "Solars" + +//Medical + +/obj/item/weapon/book/manual/wiki/medical_guide_to_medicine + name = "Medicine Manual" + icon_state ="bookMedical" + item_state ="book4" + author = "NanoTrasen" + title = "Medicine Manual" + wiki_page = "Guide_to_Medicine" + +/obj/item/weapon/book/manual/wiki/medical_genetics + name = "Wonders of Genetics" + icon_state ="bookGenetics" + item_state ="book4" + author = "NanoTrasen" + title = "Wonders of Genetics" + wiki_page = "Guide_to_Genetics" + +/obj/item/weapon/book/manual/wiki/medical_surgery + name = "Guide to Surgery" + icon_state ="bookSurgery" + item_state ="book7" + author = "NanoTrasen" + title = "Guide to Surgery" + wiki_page = "Surgery" + +/obj/item/weapon/book/manual/wiki/medical_virology + name = "Virology Protocols" + icon_state ="bookVirology" + item_state ="book7" + author = "NanoTrasen" + title = "Virology Protocols" + wiki_page = "Guide_to_Virology" + +/obj/item/weapon/book/manual/wiki/medical_chemistry + name = "Chemical Formulas" + icon_state ="bookChemistry" + item_state ="book7" + author = "NanoTrasen" + title = "Chemical Formulas" + wiki_page = "Guide_to_Chemistry" + +//Research and Development + +/obj/item/weapon/book/manual/wiki/research_and_development + name = "Basics of Research" + icon_state = "bookBasicsOfResearch" + item_state ="book6" + author = "NanoTrasen" + title = "Basics of Research" + wiki_page = "Guide_to_Research_and_Development" + +/obj/item/weapon/book/manual/wiki/guide_to_robotics + name = "Robotics for Dummies" + icon_state = "bookGuideToRobotics" + item_state ="book6" + author = "BioTech" + title = "Robotics for Dummies" + wiki_page = "Guide_to_Robotics" + +/obj/item/weapon/book/manual/wiki/guide_to_toxins + name = "Study of Phoron Properties" + icon_state = "bookGuideToToxins" + item_state ="book6" + author = "Cybersun Industries" + title = "Study of Phoron Properties" + wiki_page = "Guide_to_toxins" + +/obj/item/weapon/book/manual/wiki/guide_to_xenobiology + name = "Xenobilogy: Grow and Study" + icon_state = "bookXenobiology" + item_state ="book6" + author = "NanoTrasen" + title = "Xenobilogy: Grow and Study" + wiki_page = "Guide_to_xenobiology" + +/obj/item/weapon/book/manual/wiki/guide_to_exosuits + name = "Exosuits Construction" + icon_state = "bookExosuits" + item_state ="book6" + author = "NanoTrasen" + title = "Exosuits Construction" + wiki_page = "Guide_to_Exosuits" + +/obj/item/weapon/book/manual/wiki/guide_to_telescience + name = "TeleScience: Science of Time and Space" + icon_state = "bookTelescience" + item_state ="book6" + author = "NanoTrasen" + title = "TeleScience: Science of Time and Space" + wiki_page = "Guide_To_Telescience" + +//Law and Order + +/obj/item/weapon/book/manual/wiki/security_space_law + name = "Space Law" + desc = "A set of NanoTrasen guidelines for keeping law and order on their space stations." + icon_state = "bookSpaceLaw" + item_state = "book2" + author = "NanoTrasen" + title = "Space Law" + wiki_page = "Space Law" + +/obj/item/weapon/book/manual/wiki/sop + name = "Standard Operating Procedure" + icon_state = "bookSOP" + item_state = "book9" + author = "NanoTrasen" + title = "Standard Operating Procedure" + wiki_page = "Standard_Operating_Procedure" + +/obj/item/weapon/book/manual/wiki/lsop + name = "Legal Standard Operating Procedure" + icon_state = "bookLSOP" + item_state = "book9" + author = "NanoTrasen" + title = "Legal Standard Operating Procedure" + wiki_page = "Legal_Standard_Operating_Procedure" + +/obj/item/weapon/book/manual/detective + name = "The Film Noir: Proper Procedures for Investigations" + icon_state ="bookDetective" + item_state = "book2" + author = "NanoTrasen" + title = "The Film Noir: Proper Procedures for Investigations" + + dat = {" + + + + +

                    Detective Work

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

                    +

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

                    + It really is that easy! Good luck! + + + "} + +//Civilian guides + +/obj/item/weapon/book/manual/wiki/chefs_recipes + name = "Bon Appetite: Chef's Recipes" + icon_state = "bookChefsRecipes" + item_state = "book10" + author = "Victoria Ponsonby" + title = "Bon Appetite: Chef's Recipes" + wiki_page = "Guide_to_Food" + +/obj/item/weapon/book/manual/wiki/barman_recipes + name = "Barman Recipes" + icon_state = "bookDrinks" + item_state = "book4" + author = "Sir John Rose" + title = "Barman Recipes" + wiki_page = "Drinks" + +/obj/item/weapon/book/manual/wiki/hydroponics + name = "From Seed to Fruit: Hydroponics for dummies" + icon_state ="bookHydroponics" + item_state = "book5" + author = "Farmer John" + title = "From Seed to Fruit: Hydroponics for dummies" + wiki_page = "Guide_to_Hydroponics" + +/obj/item/weapon/book/manual/wiki/supply_crates + name = "Supply Crates Official List" + icon_state ="bookSupplyCrates" + item_state = "book8" + author = "NanoTrasen" + title = "Supply Crates Official List" + wiki_page = "Supply_crates" + +//Other + +/obj/item/weapon/book/manual/wiki/rules + name = "Rules" + desc = "Don't be a jerk. This is a corollary of ignore all rules, and most behavioural rules are special cases of this one." + icon_state = "bookRules" + item_state = "book2" + author = "Tau Ceti Classic" + title = "Rules" + wiki_page = "Rules" + +//Old manuals that we should keep for a while + +/obj/item/weapon/book/manual/hydroponics_beekeeping + name = "The Ins and Outs of Apiculture - A Precise Art" + icon_state ="bookHydroponicsBees" + item_state ="book5" + author = "Beekeeper Dave" + title = "The Ins and Outs of Apiculture - A Precise Art" + dat = {" + + + + +

                    Raising Bees

                    + + Bees are loving but fickle creatures. Don't mess with their hive and stay away from any clusters of them, and you'll avoid their ire. + Sometimes, you'll need to dig around in there for those delicious sweeties though - in that case make sure you wear sealed protection gear + and carry an extinguisher or smoker with you - any bees chasing you, once calmed down, can thusly be netted and returned safely to the hive. + BeezEez is a cure-all panacea for them, but use it too much and the hive may grow to apocalyptic proportions. Other than that, bees are excellent pets + for all the family and are excellent caretakers of one's garden: having a hive or two around will aid in the longevity and growth rate of plants, + and aid them in fighting off poisons and disease. + + + + "} + +/obj/item/weapon/book/manual/nuclear + name = "Fission Mailed: Nuclear Sabotage 101" + icon_state ="bookNuclear" + item_state = "book" + author = "Syndicate" + title = "Fission Mailed: Nuclear Sabotage 101" + + dat = {" + + + + +

                    Nuclear Explosives 101

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

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

                    To make the nuclear device functional

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

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

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

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

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

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

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

                    + + Good luck! + + + "} diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 1d437f33d393..761a99c2ab38 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -1,92 +1,92 @@ -/obj/item/weapon/melee/energy - var/active = 0 - flags = NOBLOODY - can_embed = 0 - - suicide_act(mob/user) - to_chat(viewers(user), pick("\red [user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.", \ - "\red [user] is falling on the [src.name]! It looks like \he's trying to commit suicide.")) - return (BRUTELOSS|FIRELOSS) - -/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 = CONDUCT | NOSHIELD | NOBLOODY - origin_tech = "combat=3" - attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") - sharp = 1 - edge = 1 - - suicide_act(mob/user) - to_chat(viewers(user), "\red [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 - color - name = "energy sword" - desc = "May the force be within you." - icon_state = "sword0" - force = 3.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - flags = NOSHIELD | NOBLOODY - origin_tech = "magnets=3;syndicate=4" - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - sharp = 1 - edge = 1 - var/hacked - -/obj/item/weapon/melee/energy/sword/attackby(obj/item/weapon/W, mob/living/user) - if(istype(W, /obj/item/weapon/melee/energy/sword) && !istype(W, /obj/item/weapon/melee/energy/sword/pirate)) - to_chat(user, "You attach the ends of the two \ - energy swords, making a single double-bladed weapon! \ - You're cool.") - var/obj/item/weapon/twohanded/dualsaber/newSaber = new(user.loc) - user.unEquip(W) - user.unEquip(src) - qdel(W) - qdel(src) - user.put_in_hands(newSaber) - if(istype(W, /obj/item/device/multitool)) - if(!hacked) - hacked = 1 - to_chat(user,"RNBW_ENGAGE") - item_color = "rainbow" - if (active) - active = 0 - icon_state = "sword0" - else - to_chat(user,"It's starting to look like a triple rainbow - no, nevermind.") - else - return ..() - -/obj/item/weapon/melee/energy/sword/pirate - name = "energy cutlass" - desc = "Arrrr matey." - icon_state = "cutlass0" - -/obj/item/weapon/melee/energy/sword/pirate/attackby() - return - -/obj/item/weapon/melee/energy/blade - name = "energy blade" - desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal." - icon_state = "blade" - force = 70.0//Normal attacks deal very high damage. - sharp = 1 - edge = 1 - throwforce = 1//Throwing or dropping the item deletes it. - throw_speed = 1 - throw_range = 1 - w_class = 4.0//So you can't hide it in your pocket or some such. - flags = NOSHIELD | NOBLOODY | DROPDEL - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - var/datum/effect/effect/system/spark_spread/spark_system +/obj/item/weapon/melee/energy + var/active = 0 + flags = NOBLOODY + can_embed = 0 + + suicide_act(mob/user) + to_chat(viewers(user), pick("\red [user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.", \ + "\red [user] is falling on the [src.name]! It looks like \he's trying to commit suicide.")) + return (BRUTELOSS|FIRELOSS) + +/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 = CONDUCT | NOSHIELD | NOBLOODY + origin_tech = "combat=3" + attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") + sharp = 1 + edge = 1 + + suicide_act(mob/user) + to_chat(viewers(user), "\red [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 + color + name = "energy sword" + desc = "May the force be within you." + icon_state = "sword0" + force = 3.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + flags = NOSHIELD | NOBLOODY + origin_tech = "magnets=3;syndicate=4" + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + sharp = 1 + edge = 1 + var/hacked + +/obj/item/weapon/melee/energy/sword/attackby(obj/item/weapon/W, mob/living/user) + if(istype(W, /obj/item/weapon/melee/energy/sword) && !istype(W, /obj/item/weapon/melee/energy/sword/pirate)) + to_chat(user, "You attach the ends of the two \ + energy swords, making a single double-bladed weapon! \ + You're cool.") + var/obj/item/weapon/twohanded/dualsaber/newSaber = new(user.loc) + user.unEquip(W) + user.unEquip(src) + qdel(W) + qdel(src) + user.put_in_hands(newSaber) + if(istype(W, /obj/item/device/multitool)) + if(!hacked) + hacked = 1 + to_chat(user,"RNBW_ENGAGE") + item_color = "rainbow" + if (active) + active = 0 + icon_state = "sword0" + else + to_chat(user,"It's starting to look like a triple rainbow - no, nevermind.") + else + return ..() + +/obj/item/weapon/melee/energy/sword/pirate + name = "energy cutlass" + desc = "Arrrr matey." + icon_state = "cutlass0" + +/obj/item/weapon/melee/energy/sword/pirate/attackby() + return + +/obj/item/weapon/melee/energy/blade + name = "energy blade" + desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal." + icon_state = "blade" + force = 70.0//Normal attacks deal very high damage. + sharp = 1 + edge = 1 + throwforce = 1//Throwing or dropping the item deletes it. + throw_speed = 1 + throw_range = 1 + w_class = 4.0//So you can't hide it in your pocket or some such. + flags = NOSHIELD | NOBLOODY | DROPDEL + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + var/datum/effect/effect/system/spark_spread/spark_system diff --git a/code/game/objects/items/weapons/melee/misc.dm b/code/game/objects/items/weapons/melee/misc.dm index b2a88fdbdcbc..7ea9e7512048 100644 --- a/code/game/objects/items/weapons/melee/misc.dm +++ b/code/game/objects/items/weapons/melee/misc.dm @@ -1,26 +1,26 @@ -/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" - flags = CONDUCT - slot_flags = SLOT_BELT - force = 10 - throwforce = 7 - w_class = 3 - origin_tech = "combat=4" - attack_verb = list("flogged", "whipped", "lashed", "disciplined") - -/obj/item/weapon/melee/chainofcommand/suicide_act(mob/user) - to_chat(viewers(user), "\red [user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.") - return (OXYLOSS) - -/obj/item/weapon/melee/icepick - name = "ice pick" - desc = "Used for chopping ice. Also excellent for mafia esque murders." - icon_state = "ice_pick" - item_state = "ice_pick" - force = 15 - throwforce = 10 - w_class = 2 - attack_verb = list("stabbed", "jabbed", "iced,") +/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" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 10 + throwforce = 7 + w_class = 3 + origin_tech = "combat=4" + attack_verb = list("flogged", "whipped", "lashed", "disciplined") + +/obj/item/weapon/melee/chainofcommand/suicide_act(mob/user) + to_chat(viewers(user), "\red [user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.") + return (OXYLOSS) + +/obj/item/weapon/melee/icepick + name = "ice pick" + desc = "Used for chopping ice. Also excellent for mafia esque murders." + icon_state = "ice_pick" + item_state = "ice_pick" + force = 15 + throwforce = 10 + w_class = 2 + attack_verb = list("stabbed", "jabbed", "iced,") diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index d023524ff33b..d5dd0691986f 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -1,65 +1,65 @@ -/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" - force = 3.0 - throwforce = 10.0 - throw_speed = 5 - throw_range = 10 - w_class = 3.0 - attack_verb = list("mopped", "bashed", "bludgeoned", "whacked") - var/mopping = 0 - var/mopcount = 0 - - -/obj/item/weapon/mop/atom_init() - create_reagents(5) - . = ..() - mop_list += src - -/obj/item/weapon/mop/Destroy() - mop_list -= src - return ..() - -obj/item/weapon/mop/proc/clean(turf/simulated/A) - if(reagents.has_reagent("water", 1)) - A.clean_blood() - A.dirt = 0 - 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) - reagents.reaction(A, TOUCH, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly. - reagents.remove_any(1) //reaction() doesn't use up the reagents - - -/obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity) - if(!proximity) return - 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 - if(user.is_busy(A)) return - user.visible_message("[user] begins to clean \the [get_turf(A)].") - - if(do_after(user, 40, target = A)) - if(A) - clean(get_turf(A)) - to_chat(user, "You have finished mopping!") - - -/obj/effect/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/mop) || istype(I, /obj/item/weapon/soap) || istype(I, /obj/item/weapon/kitchen/utensil/fork)) - user.SetNextMove(CLICK_CD_INTERACT) - return - return ..() - - -/obj/item/weapon/mop/advanced - desc = "The most advanced tool in a custodian's arsenal. Just think of all the viscera you will clean up with this!" - name = "advanced mop" - icon_state = "advmop" - item_state = "advmop" - force = 6.0 - throwforce = 10.0 - throw_range = 10.0 +/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" + force = 3.0 + throwforce = 10.0 + throw_speed = 5 + throw_range = 10 + w_class = 3.0 + attack_verb = list("mopped", "bashed", "bludgeoned", "whacked") + var/mopping = 0 + var/mopcount = 0 + + +/obj/item/weapon/mop/atom_init() + create_reagents(5) + . = ..() + mop_list += src + +/obj/item/weapon/mop/Destroy() + mop_list -= src + return ..() + +obj/item/weapon/mop/proc/clean(turf/simulated/A) + if(reagents.has_reagent("water", 1)) + A.clean_blood() + A.dirt = 0 + 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) + reagents.reaction(A, TOUCH, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly. + reagents.remove_any(1) //reaction() doesn't use up the reagents + + +/obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity) + if(!proximity) return + 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 + if(user.is_busy(A)) return + user.visible_message("[user] begins to clean \the [get_turf(A)].") + + if(do_after(user, 40, target = A)) + if(A) + clean(get_turf(A)) + to_chat(user, "You have finished mopping!") + + +/obj/effect/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/mop) || istype(I, /obj/item/weapon/soap) || istype(I, /obj/item/weapon/kitchen/utensil/fork)) + user.SetNextMove(CLICK_CD_INTERACT) + return + return ..() + + +/obj/item/weapon/mop/advanced + desc = "The most advanced tool in a custodian's arsenal. Just think of all the viscera you will clean up with this!" + name = "advanced mop" + icon_state = "advmop" + item_state = "advmop" + force = 6.0 + throwforce = 10.0 + throw_range = 10.0 diff --git a/code/game/objects/items/weapons/paint.dm b/code/game/objects/items/weapons/paint.dm index e136af93856b..b869597942ab 100644 --- a/code/game/objects/items/weapons/paint.dm +++ b/code/game/objects/items/weapons/paint.dm @@ -1,176 +1,176 @@ -//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" - m_amt = 200 - g_amt = 0 - w_class = 3.0 - amount_per_transfer_from_this = 10 - possible_transfer_amounts = list(10,20,30,50,70) - volume = 70 - flags = OPENCONTAINER - var/paint_type = "" - -/obj/item/weapon/reagent_containers/glass/paint/afterattack(turf/simulated/target, mob/user, proximity) - if(!proximity) - return - if(istype(target) && reagents.total_volume > 5) - for(var/mob/O in viewers(user)) - O.show_message("\red \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/atom_init() - if(paint_type == "remover") - name = "paint remover bucket" - else if(paint_type && lentext(paint_type) > 0) - name = paint_type + " " + name - . = ..() - reagents.add_reagent("paint_[paint_type]", volume) - -/obj/item/weapon/reagent_containers/glass/paint/on_reagent_change() //Until we have a generic "paint", this will give new colours to all paints in the can - var/mixedcolor = mix_color_from_reagents(reagents.reagent_list) - for(var/datum/reagent/paint/P in reagents.reagent_list) - P.color = mixedcolor - -/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 - gender= PLURAL - name = "paint" - 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 - gender= PLURAL - name = "any color" - icon_state = "paint_neutral" - - attack_self(mob/user) - 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, proximity) - if(!proximity) return - 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 - gender = PLURAL - name = "paint remover" - icon_state = "paint_neutral" - - afterattack(turf/target, mob/user) - if(istype(target) && target.icon != initial(target.icon)) - target.icon = initial(target.icon) - return -*/ +//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" + m_amt = 200 + g_amt = 0 + w_class = 3.0 + amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(10,20,30,50,70) + volume = 70 + flags = OPENCONTAINER + var/paint_type = "" + +/obj/item/weapon/reagent_containers/glass/paint/afterattack(turf/simulated/target, mob/user, proximity) + if(!proximity) + return + if(istype(target) && reagents.total_volume > 5) + for(var/mob/O in viewers(user)) + O.show_message("\red \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/atom_init() + if(paint_type == "remover") + name = "paint remover bucket" + else if(paint_type && lentext(paint_type) > 0) + name = paint_type + " " + name + . = ..() + reagents.add_reagent("paint_[paint_type]", volume) + +/obj/item/weapon/reagent_containers/glass/paint/on_reagent_change() //Until we have a generic "paint", this will give new colours to all paints in the can + var/mixedcolor = mix_color_from_reagents(reagents.reagent_list) + for(var/datum/reagent/paint/P in reagents.reagent_list) + P.color = mixedcolor + +/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 + gender= PLURAL + name = "paint" + 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 + gender= PLURAL + name = "any color" + icon_state = "paint_neutral" + + attack_self(mob/user) + 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, proximity) + if(!proximity) return + 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 + gender = PLURAL + name = "paint remover" + icon_state = "paint_neutral" + + afterattack(turf/target, mob/user) + if(istype(target) && target.icon != initial(target.icon)) + target.icon = initial(target.icon) + return +*/ diff --git a/code/game/objects/items/weapons/paiwire.dm b/code/game/objects/items/weapons/paiwire.dm index 3c334781179c..948be58ba801 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, mob/user) - 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.") - user.drop_item() - src.loc = M - 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, mob/user) - src.plugin(M, user) +/obj/item/weapon/pai_cable/proc/plugin(obj/machinery/M, mob/user) + 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.") + user.drop_item() + src.loc = M + 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, mob/user) + src.plugin(M, user) diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm index 4f607456a161..8507c6190c5f 100644 --- a/code/game/objects/items/weapons/power_cells.dm +++ b/code/game/objects/items/weapons/power_cells.dm @@ -1,137 +1,137 @@ -/obj/item/weapon/stock_parts/cell - name = "power cell" - desc = "A rechargable electrochemical power cell." - icon = 'icons/obj/power.dmi' - icon_state = "cell" - item_state = "cell" - origin_tech = "powerstorage=1" - 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 - m_amt = 700 - g_amt = 50 - var/rigged = 0 // true if rigged to explode - var/minor_fault = 0 //If not 100% reliable, it will build up faults. - -/obj/item/weapon/stock_parts/cell/suicide_act(mob/user) - to_chat(viewers(user), "\red [user] is licking the electrodes of the [src.name]! It looks like \he's trying to commit suicide.") - return (FIRELOSS) - -/obj/item/weapon/stock_parts/cell/crap - name = "\improper Nanotrasen brand rechargable AA battery" - desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT - origin_tech = "powerstorage=0" - maxcharge = 500 - g_amt = 40 - rating = 2 - -/obj/item/weapon/stock_parts/cell/crap/empty/atom_init() - . = ..() - charge = 0 - -/obj/item/weapon/stock_parts/cell/secborg - name = "security borg rechargable D battery" - origin_tech = "powerstorage=0" - maxcharge = 600 //600 max charge / 100 charge per shot = six shots - g_amt = 40 - rating = 2.5 - -/obj/item/weapon/stock_parts/cell/secborg/empty/atom_init() - . = ..() - charge = 0 - -/obj/item/weapon/stock_parts/cell/apc - name = "APC power cell" - desc = "A special power cell designed for heavy-duty use in area power controllers." - origin_tech = "powerstorage=1" - maxcharge = 500 - g_amt = 40 - -/obj/item/weapon/stock_parts/cell/high - name = "high-capacity power cell" - origin_tech = "powerstorage=2" - icon_state = "hcell" - maxcharge = 10000 - g_amt = 60 - rating = 3 - -/obj/item/weapon/stock_parts/cell/high/empty/atom_init() - . = ..() - charge = 0 - -/obj/item/weapon/stock_parts/cell/super - name = "super-capacity power cell" - origin_tech = "powerstorage=5" - icon_state = "scell" - maxcharge = 20000 - g_amt = 70 - rating = 4 - -/obj/item/weapon/stock_parts/cell/super/empty/atom_init() - . = ..() - charge = 0 - -/obj/item/weapon/stock_parts/cell/hyper - name = "hyper-capacity power cell" - origin_tech = "powerstorage=6" - icon_state = "hpcell" - maxcharge = 30000 - g_amt = 80 - rating = 5 - -/obj/item/weapon/stock_parts/cell/hyper/empty/atom_init() - . = ..() - charge = 0 - -/obj/item/weapon/stock_parts/cell/bluespace - name = "bluespace power cell" - origin_tech = "powerstorage=7" - icon_state = "bscell" - maxcharge = 40000 - g_amt = 80 - rating = 6 - //chargerate = 4000 - -/obj/item/weapon/stock_parts/cell/bluespace/empty/atom_init() - . = ..() - charge = 0 - -/obj/item/weapon/stock_parts/cell/infinite - name = "infinite-capacity power cell!" - icon_state = "icell" - origin_tech = null - maxcharge = 30000 - g_amt = 80 - rating = 6 - -/obj/item/weapon/stock_parts/cell/infinite/use() - return 1 - -/obj/item/weapon/stock_parts/cell/potato - name = "potato battery" - desc = "A rechargable 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 - m_amt = 0 - g_amt = 0 - minor_fault = 1 - rating = 1 - -/obj/item/weapon/stock_parts/cell/slime - name = "charged slime core" - desc = "A yellow slime core infused with phoron, 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 - maxcharge = 10000 - m_amt = 0 - g_amt = 0 - rating = 3 +/obj/item/weapon/stock_parts/cell + name = "power cell" + desc = "A rechargable electrochemical power cell." + icon = 'icons/obj/power.dmi' + icon_state = "cell" + item_state = "cell" + origin_tech = "powerstorage=1" + 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 + m_amt = 700 + g_amt = 50 + var/rigged = 0 // true if rigged to explode + var/minor_fault = 0 //If not 100% reliable, it will build up faults. + +/obj/item/weapon/stock_parts/cell/suicide_act(mob/user) + to_chat(viewers(user), "\red [user] is licking the electrodes of the [src.name]! It looks like \he's trying to commit suicide.") + return (FIRELOSS) + +/obj/item/weapon/stock_parts/cell/crap + name = "\improper Nanotrasen brand rechargable AA battery" + desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT + origin_tech = "powerstorage=0" + maxcharge = 500 + g_amt = 40 + rating = 2 + +/obj/item/weapon/stock_parts/cell/crap/empty/atom_init() + . = ..() + charge = 0 + +/obj/item/weapon/stock_parts/cell/secborg + name = "security borg rechargable D battery" + origin_tech = "powerstorage=0" + maxcharge = 600 //600 max charge / 100 charge per shot = six shots + g_amt = 40 + rating = 2.5 + +/obj/item/weapon/stock_parts/cell/secborg/empty/atom_init() + . = ..() + charge = 0 + +/obj/item/weapon/stock_parts/cell/apc + name = "APC power cell" + desc = "A special power cell designed for heavy-duty use in area power controllers." + origin_tech = "powerstorage=1" + maxcharge = 500 + g_amt = 40 + +/obj/item/weapon/stock_parts/cell/high + name = "high-capacity power cell" + origin_tech = "powerstorage=2" + icon_state = "hcell" + maxcharge = 10000 + g_amt = 60 + rating = 3 + +/obj/item/weapon/stock_parts/cell/high/empty/atom_init() + . = ..() + charge = 0 + +/obj/item/weapon/stock_parts/cell/super + name = "super-capacity power cell" + origin_tech = "powerstorage=5" + icon_state = "scell" + maxcharge = 20000 + g_amt = 70 + rating = 4 + +/obj/item/weapon/stock_parts/cell/super/empty/atom_init() + . = ..() + charge = 0 + +/obj/item/weapon/stock_parts/cell/hyper + name = "hyper-capacity power cell" + origin_tech = "powerstorage=6" + icon_state = "hpcell" + maxcharge = 30000 + g_amt = 80 + rating = 5 + +/obj/item/weapon/stock_parts/cell/hyper/empty/atom_init() + . = ..() + charge = 0 + +/obj/item/weapon/stock_parts/cell/bluespace + name = "bluespace power cell" + origin_tech = "powerstorage=7" + icon_state = "bscell" + maxcharge = 40000 + g_amt = 80 + rating = 6 + //chargerate = 4000 + +/obj/item/weapon/stock_parts/cell/bluespace/empty/atom_init() + . = ..() + charge = 0 + +/obj/item/weapon/stock_parts/cell/infinite + name = "infinite-capacity power cell!" + icon_state = "icell" + origin_tech = null + maxcharge = 30000 + g_amt = 80 + rating = 6 + +/obj/item/weapon/stock_parts/cell/infinite/use() + return 1 + +/obj/item/weapon/stock_parts/cell/potato + name = "potato battery" + desc = "A rechargable 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 + m_amt = 0 + g_amt = 0 + minor_fault = 1 + rating = 1 + +/obj/item/weapon/stock_parts/cell/slime + name = "charged slime core" + desc = "A yellow slime core infused with phoron, 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 + maxcharge = 10000 + m_amt = 0 + g_amt = 0 + rating = 3 diff --git a/code/game/objects/items/weapons/scrolls.dm b/code/game/objects/items/weapons/scrolls.dm index 73a6662b43ea..10321f7fc2ff 100644 --- a/code/game/objects/items/weapons/scrolls.dm +++ b/code/game/objects/items/weapons/scrolls.dm @@ -1,91 +1,91 @@ -/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 - w_class = 2.0 - item_state = "paper" - throw_speed = 4 - throw_range = 20 - origin_tech = "bluespace=4" - - action_button_name = "Use Scroll of Teleportation" - -/obj/item/weapon/teleportation_scroll/attack_self(mob/user) - 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(entity_ja(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) - attack_self(H) - return - -/obj/item/weapon/teleportation_scroll/proc/teleportscroll(mob/user) - - var/A - - A = input(user, "Area to jump to", "BOOYEA", A) in teleportlocs - var/area/thearea = teleportlocs[A] - - if (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.buckled) - user.buckled.unbuckle_mob() - - 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 +/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 + w_class = 2.0 + item_state = "paper" + throw_speed = 4 + throw_range = 20 + origin_tech = "bluespace=4" + + action_button_name = "Use Scroll of Teleportation" + +/obj/item/weapon/teleportation_scroll/attack_self(mob/user) + 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(entity_ja(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) + attack_self(H) + return + +/obj/item/weapon/teleportation_scroll/proc/teleportscroll(mob/user) + + var/A + + A = input(user, "Area to jump to", "BOOYEA", A) in teleportlocs + var/area/thearea = teleportlocs[A] + + if (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.buckled) + user.buckled.unbuckle_mob() + + 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 diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index fd11870340ba..b2cba6d2f85f 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -1,147 +1,147 @@ -/obj/item/weapon/shield - name = "shield" - var/block_chance = 65 - -/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 = CONDUCT - slot_flags = SLOT_BACK - force = 5.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 4 - w_class = 4.0 - g_amt = 7500 - m_amt = 1000 - origin_tech = "materials=2" - attack_verb = list("shoved", "bashed") - var/cooldown = 0 //shield bash cooldown. based on world.time - - Get_shield_chance() - return block_chance - - attackby(obj/item/weapon/W, mob/user) - 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/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 - flags = CONDUCT - force = 3.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 4 - w_class = 2 - block_chance = 30 - origin_tech = "materials=4;magnets=3;syndicate=4" - attack_verb = list("shoved", "bashed") - var/active = 0 - var/emp_cooldown = 0 - -/obj/item/weapon/shield/energy/IsReflect(def_zone, hol_dir, hit_dir) - if(active) - return is_the_opposite_dir(hol_dir, hit_dir) - return FALSE - -/obj/item/weapon/shield/energy/emp_act(severity) - if(active) - if(severity == 2 && prob(35)) - active = !active - emp_cooldown = world.time + 200 - turn_off() - else if(severity == 1) - active = !active - emp_cooldown = world.time + rand(200, 400) - turn_off() - - -/obj/item/weapon/shield/riot/tele - name = "telescopic shield" - desc = "An advanced riot shield made of lightweight materials that collapses for easy storage." - icon = 'icons/obj/weapons.dmi' - icon_state = "teleriot0" - origin_tech = "materials=3;combat=4;engineering=4" - slot_flags = null - force = 3 - throwforce = 3 - throw_speed = 3 - throw_range = 4 - block_chance = 50 - var/active = 0 - -/obj/item/weapon/shield/riot/tele/Get_shield_chance() - if(active) - return block_chance - return 0 - -/obj/item/weapon/shield/riot/tele/attack_self(mob/living/user) - active = !active - icon_state = "teleriot[active]" - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) - - if(active) - force = 8 - throwforce = 5 - throw_speed = 2 - w_class = 4 - slot_flags = SLOT_BACK - to_chat(user, "You extend \the [src].") - else - force = 3 - throwforce = 3 - throw_speed = 3 - w_class = 3 - slot_flags = null - to_chat(user, "[src] can now be concealed.") - add_fingerprint(user) - -/obj/item/weapon/shield/riot/roman - name = "roman shield" - desc = "Bears an inscription on the inside: \"Romanes venio domus\"." - icon_state = "roman_shield" - item_state = "roman_shield" - -/* -/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 = CONDUCT - 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) - src.active = !( src.active ) - if (src.active) - to_chat(user, "\blue The cloaking device is now active.") - src.icon_state = "shield1" - else - to_chat(user, "\blue 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 + name = "shield" + var/block_chance = 65 + +/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 = CONDUCT + slot_flags = SLOT_BACK + force = 5.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 4 + w_class = 4.0 + g_amt = 7500 + m_amt = 1000 + origin_tech = "materials=2" + attack_verb = list("shoved", "bashed") + var/cooldown = 0 //shield bash cooldown. based on world.time + + Get_shield_chance() + return block_chance + + attackby(obj/item/weapon/W, mob/user) + 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/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 + flags = CONDUCT + force = 3.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 4 + w_class = 2 + block_chance = 30 + origin_tech = "materials=4;magnets=3;syndicate=4" + attack_verb = list("shoved", "bashed") + var/active = 0 + var/emp_cooldown = 0 + +/obj/item/weapon/shield/energy/IsReflect(def_zone, hol_dir, hit_dir) + if(active) + return is_the_opposite_dir(hol_dir, hit_dir) + return FALSE + +/obj/item/weapon/shield/energy/emp_act(severity) + if(active) + if(severity == 2 && prob(35)) + active = !active + emp_cooldown = world.time + 200 + turn_off() + else if(severity == 1) + active = !active + emp_cooldown = world.time + rand(200, 400) + turn_off() + + +/obj/item/weapon/shield/riot/tele + name = "telescopic shield" + desc = "An advanced riot shield made of lightweight materials that collapses for easy storage." + icon = 'icons/obj/weapons.dmi' + icon_state = "teleriot0" + origin_tech = "materials=3;combat=4;engineering=4" + slot_flags = null + force = 3 + throwforce = 3 + throw_speed = 3 + throw_range = 4 + block_chance = 50 + var/active = 0 + +/obj/item/weapon/shield/riot/tele/Get_shield_chance() + if(active) + return block_chance + return 0 + +/obj/item/weapon/shield/riot/tele/attack_self(mob/living/user) + active = !active + icon_state = "teleriot[active]" + playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) + + if(active) + force = 8 + throwforce = 5 + throw_speed = 2 + w_class = 4 + slot_flags = SLOT_BACK + to_chat(user, "You extend \the [src].") + else + force = 3 + throwforce = 3 + throw_speed = 3 + w_class = 3 + slot_flags = null + to_chat(user, "[src] can now be concealed.") + add_fingerprint(user) + +/obj/item/weapon/shield/riot/roman + name = "roman shield" + desc = "Bears an inscription on the inside: \"Romanes venio domus\"." + icon_state = "roman_shield" + item_state = "roman_shield" + +/* +/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 = CONDUCT + 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) + src.active = !( src.active ) + if (src.active) + to_chat(user, "\blue The cloaking device is now active.") + src.icon_state = "shield1" + else + to_chat(user, "\blue 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() + ..() +*/ diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 1494b68e4244..f7f58c565166 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -1,339 +1,339 @@ - -/* - * 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 = ITEM_SIZE_LARGE - slot_flags = SLOT_BACK //ERROOOOO - action_button_name = "Storage" - max_w_class = ITEM_SIZE_NORMAL - max_storage_space = DEFAULT_BACKPACK_STORAGE - var/opened = 0 - -/obj/item/weapon/storage/backpack/ui_action_click() - if(!opened) - open(loc) - else - close(loc) - opened = !opened - -/obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W, mob/user) - if (src.use_sound) - playsound(src.loc, src.use_sound, 50, 1, -5) - return ..() - -/obj/item/weapon/storage/backpack/equipped(mob/user, slot) - if (slot == slot_back && src.use_sound) - playsound(src.loc, src.use_sound, 50, 1, -5) - ..(user, slot) - -/* - * 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" - icon_state = "holdingpack" - max_w_class = ITEM_SIZE_LARGE - max_storage_space = 56 - -/obj/item/weapon/storage/backpack/holding/attackby(obj/item/weapon/W, mob/user) - if(crit_fail) - to_chat(user, "The Bluespace generator isn't working.
                    ") - return - if(istype(W, /obj/item/weapon/storage/backpack/holding) && !W.crit_fail) - to_chat(user, "The Bluespace interfaces of the two devices conflict and malfunction.
                    ") - qdel(W) - return - ..() - -/obj/item/weapon/storage/backpack/holding/proc/failcheck(mob/user) - 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(current_size) - var/dist = max((current_size - 2),1) - explosion(src.loc,(dist),(dist*2),(dist*4)) - 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 = ITEM_SIZE_LARGE - max_w_class = ITEM_SIZE_NORMAL - max_storage_space = 80 // can store a ton of shit! - -/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" - -/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" - item_state = "satchel" - -/obj/item/weapon/storage/backpack/satchel/withwallet - - -/obj/item/weapon/storage/backpack/satchel/withwallet/atom_init() - . = ..() - 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" - -//ERT backpacks. -/obj/item/weapon/storage/backpack/ert - name = "emergency response team backpack" - desc = "A spacious backpack with lots of pockets, used by members of the Nanotrasen Emergency Response Team." - icon_state = "ert_commander" - item_state = "backpack" - -//Commander -/obj/item/weapon/storage/backpack/ert/commander - name = "emergency response team commander backpack" - desc = "A spacious backpack with lots of pockets, worn by the commander of a Nanotrasen Emergency Response Team." - -//Security -/obj/item/weapon/storage/backpack/ert/security - name = "emergency response team security backpack" - desc = "A spacious backpack with lots of pockets, worn by security members of a Nanotrasen Emergency Response Team." - icon_state = "ert_security" - -//Engineering -/obj/item/weapon/storage/backpack/ert/engineer - name = "emergency response team engineer backpack" - desc = "A spacious backpack with lots of pockets, worn by engineering members of a Nanotrasen Emergency Response Team." - icon_state = "ert_engineering" - -//Medical -/obj/item/weapon/storage/backpack/ert/medical - name = "emergency response team medical backpack" - desc = "A spacious backpack with lots of pockets, worn by medical members of a Nanotrasen Emergency Response Team." - icon_state = "ert_medical" - -/obj/item/weapon/storage/backpack/kitbag - name = "kitbag" - icon_state = "kitbag" - -/obj/item/weapon/storage/backpack/medbag - name = "medbag" - icon_state = "medbag" - -/obj/item/weapon/storage/backpack/alt - icon_state = "backpack-alt" - item_state = "backpack" - -/obj/item/weapon/storage/backpack/backpack_vir - name = "virologist backpack" - desc = "A sterile backpack with virologist colours." - icon_state = "backpack-vir" - item_state = "backpack-vir" - -/obj/item/weapon/storage/backpack/backpack_chem - name = "chemist backpack" - desc = "A sterile backpack with chemist colours." - icon_state = "backpack-chem" - item_state = "backpack-chem" - -/obj/item/weapon/storage/backpack/backpack_gen - name = "geneticist backpack" - desc = "A sterile backpack with geneticist colours." - icon_state = "backpack-gen" - item_state = "backpack-gen" - -/obj/item/weapon/storage/backpack/backpack_tox - name = "scientist backpack" - desc = "Useful for holding research materials." - icon_state = "backpack-tox" - item_state = "backpack-tox" - -/obj/item/weapon/storage/backpack/backpack_hyd - name = "hydroponics backpack" - desc = "A green backpack for plant related work." - icon_state = "backpack-hyd" - item_state = "backpack-hyd" - -/obj/item/weapon/storage/backpack/mime - name = "Parcel Parceaux" - desc = "A silent backpack made for those silent workers. Silence Co." - icon_state = "mimepack" - item_state = "mimepack" - -/obj/item/weapon/storage/backpack/satchel/flat - name = "smuggler's satchel" - desc = "A very slim satchel that can easily fit into tight spaces." - icon_state = "satchel-flat" - item_state = "satchel-flat" - w_class = ITEM_SIZE_NORMAL //Can fit in backpacks itself. - max_storage_space = DEFAULT_BACKPACK_STORAGE - 10 - level = 1 - cant_hold = list(/obj/item/weapon/storage/backpack/satchel/flat) //muh recursive backpacks - -/obj/item/weapon/storage/backpack/satchel/flat/hide(var/intact) - if(intact) - invisibility = 101 - anchored = 1 //otherwise you can start pulling, cover it, and drag around an invisible backpack. - icon_state = "[initial(icon_state)]2" - else - invisibility = initial(invisibility) - anchored = 0 - icon_state = initial(icon_state) - -/obj/item/weapon/storage/backpack/satchel/flat/atom_init() - . = ..() - new /obj/item/stack/tile/plasteel(src) - new /obj/item/weapon/crowbar(src) - -/obj/item/weapon/storage/backpack/dufflebag - name = "suspicious looking dufflebag" - desc = "A large dufflebag for holding extra tactical supplies." - icon_state = "duffle-syndie" - item_state = "duffle-syndie" - origin_tech = "syndicate=1" - max_storage_space = DEFAULT_BACKPACK_STORAGE + 10 - slowdown = 1 - -/obj/item/weapon/storage/backpack/dufflebag/marinad - name = "marine dufflebag" - desc = "A large dufflebag for holding extra tactical supplies. Waterproof." - icon_state = "marinad" - item_state = "marinad_duffle" - origin_tech = "" - -/obj/item/weapon/storage/backpack/dufflebag/c4/atom_init() - . = ..() - for(var/i = 1 to 5) - new /obj/item/weapon/plastique(src) - -/obj/item/weapon/storage/backpack/dufflebag/med - name = "medical dufflebag" - desc = "A large dufflebag for holding extra tactical medical supplies." - icon_state = "duffle-syndiemed" - item_state = "duffle-syndiemed" - -/obj/item/weapon/storage/backpack/dufflebag/surgery - name = "surgery dufflebag" - desc = "A suspicious looking dufflebag for holding surgery tools." - icon_state = "duffle-syndiemed" - item_state = "duffle-syndiemed" - max_storage_space = DEFAULT_BACKPACK_STORAGE + 20 - -/obj/item/weapon/storage/backpack/dufflebag/surgery/atom_init() - . = ..() - new /obj/item/weapon/scalpel(src) - new /obj/item/weapon/hemostat(src) - new /obj/item/weapon/retractor(src) - new /obj/item/weapon/circular_saw(src) - new /obj/item/weapon/surgicaldrill(src) - new /obj/item/weapon/cautery(src) - new /obj/item/weapon/bonesetter(src) - new /obj/item/weapon/bonegel(src) - new /obj/item/weapon/FixOVein(src) - new /obj/item/clothing/suit/straight_jacket(src) - new /obj/item/clothing/mask/muzzle(src) - new /obj/item/stack/medical/advanced/bruise_pack(src) + +/* + * 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 = ITEM_SIZE_LARGE + slot_flags = SLOT_BACK //ERROOOOO + action_button_name = "Storage" + max_w_class = ITEM_SIZE_NORMAL + max_storage_space = DEFAULT_BACKPACK_STORAGE + var/opened = 0 + +/obj/item/weapon/storage/backpack/ui_action_click() + if(!opened) + open(loc) + else + close(loc) + opened = !opened + +/obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W, mob/user) + if (src.use_sound) + playsound(src.loc, src.use_sound, 50, 1, -5) + return ..() + +/obj/item/weapon/storage/backpack/equipped(mob/user, slot) + if (slot == slot_back && src.use_sound) + playsound(src.loc, src.use_sound, 50, 1, -5) + ..(user, slot) + +/* + * 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" + icon_state = "holdingpack" + max_w_class = ITEM_SIZE_LARGE + max_storage_space = 56 + +/obj/item/weapon/storage/backpack/holding/attackby(obj/item/weapon/W, mob/user) + if(crit_fail) + to_chat(user, "The Bluespace generator isn't working.
                    ") + return + if(istype(W, /obj/item/weapon/storage/backpack/holding) && !W.crit_fail) + to_chat(user, "The Bluespace interfaces of the two devices conflict and malfunction.
                    ") + qdel(W) + return + ..() + +/obj/item/weapon/storage/backpack/holding/proc/failcheck(mob/user) + 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(current_size) + var/dist = max((current_size - 2),1) + explosion(src.loc,(dist),(dist*2),(dist*4)) + 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 = ITEM_SIZE_LARGE + max_w_class = ITEM_SIZE_NORMAL + max_storage_space = 80 // can store a ton of shit! + +/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" + +/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" + item_state = "satchel" + +/obj/item/weapon/storage/backpack/satchel/withwallet + + +/obj/item/weapon/storage/backpack/satchel/withwallet/atom_init() + . = ..() + 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" + +//ERT backpacks. +/obj/item/weapon/storage/backpack/ert + name = "emergency response team backpack" + desc = "A spacious backpack with lots of pockets, used by members of the Nanotrasen Emergency Response Team." + icon_state = "ert_commander" + item_state = "backpack" + +//Commander +/obj/item/weapon/storage/backpack/ert/commander + name = "emergency response team commander backpack" + desc = "A spacious backpack with lots of pockets, worn by the commander of a Nanotrasen Emergency Response Team." + +//Security +/obj/item/weapon/storage/backpack/ert/security + name = "emergency response team security backpack" + desc = "A spacious backpack with lots of pockets, worn by security members of a Nanotrasen Emergency Response Team." + icon_state = "ert_security" + +//Engineering +/obj/item/weapon/storage/backpack/ert/engineer + name = "emergency response team engineer backpack" + desc = "A spacious backpack with lots of pockets, worn by engineering members of a Nanotrasen Emergency Response Team." + icon_state = "ert_engineering" + +//Medical +/obj/item/weapon/storage/backpack/ert/medical + name = "emergency response team medical backpack" + desc = "A spacious backpack with lots of pockets, worn by medical members of a Nanotrasen Emergency Response Team." + icon_state = "ert_medical" + +/obj/item/weapon/storage/backpack/kitbag + name = "kitbag" + icon_state = "kitbag" + +/obj/item/weapon/storage/backpack/medbag + name = "medbag" + icon_state = "medbag" + +/obj/item/weapon/storage/backpack/alt + icon_state = "backpack-alt" + item_state = "backpack" + +/obj/item/weapon/storage/backpack/backpack_vir + name = "virologist backpack" + desc = "A sterile backpack with virologist colours." + icon_state = "backpack-vir" + item_state = "backpack-vir" + +/obj/item/weapon/storage/backpack/backpack_chem + name = "chemist backpack" + desc = "A sterile backpack with chemist colours." + icon_state = "backpack-chem" + item_state = "backpack-chem" + +/obj/item/weapon/storage/backpack/backpack_gen + name = "geneticist backpack" + desc = "A sterile backpack with geneticist colours." + icon_state = "backpack-gen" + item_state = "backpack-gen" + +/obj/item/weapon/storage/backpack/backpack_tox + name = "scientist backpack" + desc = "Useful for holding research materials." + icon_state = "backpack-tox" + item_state = "backpack-tox" + +/obj/item/weapon/storage/backpack/backpack_hyd + name = "hydroponics backpack" + desc = "A green backpack for plant related work." + icon_state = "backpack-hyd" + item_state = "backpack-hyd" + +/obj/item/weapon/storage/backpack/mime + name = "Parcel Parceaux" + desc = "A silent backpack made for those silent workers. Silence Co." + icon_state = "mimepack" + item_state = "mimepack" + +/obj/item/weapon/storage/backpack/satchel/flat + name = "smuggler's satchel" + desc = "A very slim satchel that can easily fit into tight spaces." + icon_state = "satchel-flat" + item_state = "satchel-flat" + w_class = ITEM_SIZE_NORMAL //Can fit in backpacks itself. + max_storage_space = DEFAULT_BACKPACK_STORAGE - 10 + level = 1 + cant_hold = list(/obj/item/weapon/storage/backpack/satchel/flat) //muh recursive backpacks + +/obj/item/weapon/storage/backpack/satchel/flat/hide(var/intact) + if(intact) + invisibility = 101 + anchored = 1 //otherwise you can start pulling, cover it, and drag around an invisible backpack. + icon_state = "[initial(icon_state)]2" + else + invisibility = initial(invisibility) + anchored = 0 + icon_state = initial(icon_state) + +/obj/item/weapon/storage/backpack/satchel/flat/atom_init() + . = ..() + new /obj/item/stack/tile/plasteel(src) + new /obj/item/weapon/crowbar(src) + +/obj/item/weapon/storage/backpack/dufflebag + name = "suspicious looking dufflebag" + desc = "A large dufflebag for holding extra tactical supplies." + icon_state = "duffle-syndie" + item_state = "duffle-syndie" + origin_tech = "syndicate=1" + max_storage_space = DEFAULT_BACKPACK_STORAGE + 10 + slowdown = 1 + +/obj/item/weapon/storage/backpack/dufflebag/marinad + name = "marine dufflebag" + desc = "A large dufflebag for holding extra tactical supplies. Waterproof." + icon_state = "marinad" + item_state = "marinad_duffle" + origin_tech = "" + +/obj/item/weapon/storage/backpack/dufflebag/c4/atom_init() + . = ..() + for(var/i = 1 to 5) + new /obj/item/weapon/plastique(src) + +/obj/item/weapon/storage/backpack/dufflebag/med + name = "medical dufflebag" + desc = "A large dufflebag for holding extra tactical medical supplies." + icon_state = "duffle-syndiemed" + item_state = "duffle-syndiemed" + +/obj/item/weapon/storage/backpack/dufflebag/surgery + name = "surgery dufflebag" + desc = "A suspicious looking dufflebag for holding surgery tools." + icon_state = "duffle-syndiemed" + item_state = "duffle-syndiemed" + max_storage_space = DEFAULT_BACKPACK_STORAGE + 20 + +/obj/item/weapon/storage/backpack/dufflebag/surgery/atom_init() + . = ..() + new /obj/item/weapon/scalpel(src) + new /obj/item/weapon/hemostat(src) + new /obj/item/weapon/retractor(src) + new /obj/item/weapon/circular_saw(src) + new /obj/item/weapon/surgicaldrill(src) + new /obj/item/weapon/cautery(src) + new /obj/item/weapon/bonesetter(src) + new /obj/item/weapon/bonegel(src) + new /obj/item/weapon/FixOVein(src) + new /obj/item/clothing/suit/straight_jacket(src) + new /obj/item/clothing/mask/muzzle(src) + new /obj/item/stack/medical/advanced/bruise_pack(src) diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 95bff5051ed5..c55564862ada 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -1,284 +1,284 @@ -/* - * 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: - * Book bag - * Trash Bag - * Bluespace trash bag - * Mining Satchel - * Plant Bag - * Sheet Snatcher - * Cash Bag - * - * -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 - -// ----------------------------- -// Book bag -// ----------------------------- -/obj/item/weapon/storage/bag/bookbag - name = "book bag" - desc = "A bag for knowledge." - icon = 'icons/obj/library.dmi' - icon_state = "bookbag" - item_state = "bookbag" - display_contents_with_number = 0 //This would look really stupid otherwise - storage_slots = 7 - max_w_class = ITEM_SIZE_NORMAL - max_storage_space = DEFAULT_BACKPACK_STORAGE - w_class = ITEM_SIZE_LARGE //Bigger than a book because physics - can_hold = list("/obj/item/weapon/book", "/obj/item/weapon/storage/bible", "/obj/item/weapon/spellbook") - -// ----------------------------- -// 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/janitor.dmi' - icon_state = "trashbag" - item_state = "trashbag" - - w_class = ITEM_SIZE_SMALL - max_w_class = ITEM_SIZE_NORMAL - max_storage_space = DEFAULT_BACKPACK_STORAGE - can_hold = list() // any - cant_hold = list("/obj/item/weapon/disk/nuclear") - -/obj/item/weapon/storage/bag/trash/handle_item_insertion(obj/item/W, prevent_warning = FALSE, NoUpdate = FALSE) - . = ..() - if(.) - update_w_class() - -/obj/item/weapon/storage/bag/trash/remove_from_storage(obj/item/W, atom/new_location, NoUpdate = FALSE) - . = ..() - if(.) - update_w_class() - -/obj/item/weapon/storage/bag/trash/can_be_inserted(obj/item/W, mob/user, stop_messages = FALSE) - if(istype(loc, /obj/item/weapon/storage)) - if(!stop_messages) - to_chat(user, "Take [src] out of [loc] first.") - return FALSE //causes problems if the bag expands and becomes larger than loc can hold, so disallow it - return ..() - -/obj/item/weapon/storage/bag/trash/proc/update_w_class() - w_class = initial(w_class) - for(var/obj/item/I in contents) - w_class = max(w_class, I.w_class) - - var/cur_storage_space = storage_space_used() - while(base_storage_capacity(w_class) < cur_storage_space) - w_class++ - - w_class = min(ITEM_SIZE_HUGE, w_class) - - update_icon() - -/obj/item/weapon/storage/bag/trash/get_storage_cost() - var/used_ratio = storage_space_used()/max_storage_space - return max(base_storage_cost(w_class), round(used_ratio*base_storage_cost(max_w_class), 1)) - -/obj/item/weapon/storage/bag/trash/update_icon() - switch(w_class) - if(2) - icon_state = "[initial(icon_state)]" - if(3) - icon_state = "[initial(icon_state)]1" - if(4) - icon_state = "[initial(icon_state)]2" - if(5 to INFINITY) - icon_state = "[initial(icon_state)]3" - -/obj/item/weapon/storage/bag/trash/bluespace - name = "trash bag of holding" - desc = "The latest and greatest in custodial convenience, a trashbag that is capable of holding vast quantities of garbage." - icon_state = "bluetrashbag" - max_storage_space = 56 - - -// ----------------------------- -// 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 = ITEM_SIZE_LARGE - max_w_class = ITEM_SIZE_NORMAL - max_storage_space = DEFAULT_BOX_STORAGE - can_hold = list() // any - cant_hold = list("/obj/item/weapon/disk/nuclear") - -// ----------------------------- -// Mining Satchel -// ----------------------------- - -/obj/item/weapon/storage/bag/ore - name = "Mining Satchel" - 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 = ITEM_SIZE_NORMAL - max_storage_space = 100 - can_hold = list("/obj/item/weapon/ore", "/obj/item/bluespace_crystal") - -/obj/item/weapon/storage/bag/ore/holding - name = "Mining satchel of holding" - desc = "A revolution in convenience, this satchel allows for huge amounts of ore storage. It's been outfitted with anti-malfunction safety measures." - max_storage_space = 300 - origin_tech = "bluespace=4;materials=3;engineering=3" - icon_state = "satchel_bspace" - -// ----------------------------- -// Plant bag -// ----------------------------- - -/obj/item/weapon/storage/bag/plants - icon = 'icons/obj/hydroponics/equipment.dmi' - icon_state = "plantbag" - name = "Plant Bag" - max_storage_space = 100 - max_w_class = ITEM_SIZE_NORMAL - w_class = ITEM_SIZE_SMALL - can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/grown","/obj/item/seeds","/obj/item/weapon/grown") - - -// ----------------------------- -// 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 = ITEM_SIZE_NORMAL - storage_slots = 7 - - allow_quick_empty = 1 // this function is superceded - -/obj/item/weapon/storage/bag/sheetsnatcher/can_be_inserted(obj/item/W, 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.get_amount() - if(capacity == current)//If it's full, you're done - if(!stop_messages) - to_chat(usr, "\red The snatcher is full.") - return 0 - return 1 - - -// Modified handle_item_insertion. Would prefer not to, but... -/obj/item/weapon/storage/bag/sheetsnatcher/handle_item_insertion(obj/item/W, prevent_warning = FALSE, NoUpdate = FALSE) - 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.get_amount() - if(capacity < current + S.get_amount())//If the stack will fill it up - amount = capacity - current - else - amount = S.get_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.get_amount()) - usr.remove_from_mob(S) - usr.update_icons() //update our overlays - if(!S.get_amount()) - qdel(S) - else - S.loc = src - - if(!NoUpdate) - update_ui_after_item_insertion() - update_icon() - return 1 - -// Modified quick_empty verb drops appropriate sized stacks -/obj/item/weapon/storage/bag/sheetsnatcher/quick_empty() - var/location = get_turf(src) - for(var/obj/item/stack/sheet/S in contents) - while(S.get_amount()) - var/obj/item/stack/sheet/N = new S.type(location) - var/stacksize = min(S.get_amount(),N.max_amount) - N.amount = stacksize - S.amount -= stacksize - if(!S.get_amount()) - qdel(S) // todo: there's probably something missing here - update_ui_after_item_removal() - update_icon() - -// Instead of removing -/obj/item/weapon/storage/bag/sheetsnatcher/remove_from_storage(obj/item/W, atom/new_location, NoUpdate = FALSE) - 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.get_amount() > S.max_amount) - var/obj/item/stack/sheet/temp = new S.type(src) - temp.amount = S.get_amount() - S.max_amount - S.amount = S.max_amount - - return ..(S, new_location, NoUpdate) - -// ----------------------------- -// Sheet Snatcher (Cyborg) -// ----------------------------- - -/obj/item/weapon/storage/bag/sheetsnatcher/borg - name = "Sheet Snatcher 9000" - desc = "" - capacity = 500//Borgs get more because >specialization - -// ----------------------------- -// Cash Bag -// ----------------------------- - -/obj/item/weapon/storage/bag/cash - icon = 'icons/obj/storage.dmi' - icon_state = "cashbag" - name = "Cash bag" - desc = "A bag for carrying lots of cash. It's got a big dollar sign printed on the front." - max_storage_space = 100 - max_w_class = ITEM_SIZE_HUGE - w_class = ITEM_SIZE_SMALL - can_hold = list("/obj/item/weapon/coin","/obj/item/weapon/spacecash") +/* + * 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: + * Book bag + * Trash Bag + * Bluespace trash bag + * Mining Satchel + * Plant Bag + * Sheet Snatcher + * Cash Bag + * + * -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 + +// ----------------------------- +// Book bag +// ----------------------------- +/obj/item/weapon/storage/bag/bookbag + name = "book bag" + desc = "A bag for knowledge." + icon = 'icons/obj/library.dmi' + icon_state = "bookbag" + item_state = "bookbag" + display_contents_with_number = 0 //This would look really stupid otherwise + storage_slots = 7 + max_w_class = ITEM_SIZE_NORMAL + max_storage_space = DEFAULT_BACKPACK_STORAGE + w_class = ITEM_SIZE_LARGE //Bigger than a book because physics + can_hold = list("/obj/item/weapon/book", "/obj/item/weapon/storage/bible", "/obj/item/weapon/spellbook") + +// ----------------------------- +// 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/janitor.dmi' + icon_state = "trashbag" + item_state = "trashbag" + + w_class = ITEM_SIZE_SMALL + max_w_class = ITEM_SIZE_NORMAL + max_storage_space = DEFAULT_BACKPACK_STORAGE + can_hold = list() // any + cant_hold = list("/obj/item/weapon/disk/nuclear") + +/obj/item/weapon/storage/bag/trash/handle_item_insertion(obj/item/W, prevent_warning = FALSE, NoUpdate = FALSE) + . = ..() + if(.) + update_w_class() + +/obj/item/weapon/storage/bag/trash/remove_from_storage(obj/item/W, atom/new_location, NoUpdate = FALSE) + . = ..() + if(.) + update_w_class() + +/obj/item/weapon/storage/bag/trash/can_be_inserted(obj/item/W, mob/user, stop_messages = FALSE) + if(istype(loc, /obj/item/weapon/storage)) + if(!stop_messages) + to_chat(user, "Take [src] out of [loc] first.") + return FALSE //causes problems if the bag expands and becomes larger than loc can hold, so disallow it + return ..() + +/obj/item/weapon/storage/bag/trash/proc/update_w_class() + w_class = initial(w_class) + for(var/obj/item/I in contents) + w_class = max(w_class, I.w_class) + + var/cur_storage_space = storage_space_used() + while(base_storage_capacity(w_class) < cur_storage_space) + w_class++ + + w_class = min(ITEM_SIZE_HUGE, w_class) + + update_icon() + +/obj/item/weapon/storage/bag/trash/get_storage_cost() + var/used_ratio = storage_space_used()/max_storage_space + return max(base_storage_cost(w_class), round(used_ratio*base_storage_cost(max_w_class), 1)) + +/obj/item/weapon/storage/bag/trash/update_icon() + switch(w_class) + if(2) + icon_state = "[initial(icon_state)]" + if(3) + icon_state = "[initial(icon_state)]1" + if(4) + icon_state = "[initial(icon_state)]2" + if(5 to INFINITY) + icon_state = "[initial(icon_state)]3" + +/obj/item/weapon/storage/bag/trash/bluespace + name = "trash bag of holding" + desc = "The latest and greatest in custodial convenience, a trashbag that is capable of holding vast quantities of garbage." + icon_state = "bluetrashbag" + max_storage_space = 56 + + +// ----------------------------- +// 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 = ITEM_SIZE_LARGE + max_w_class = ITEM_SIZE_NORMAL + max_storage_space = DEFAULT_BOX_STORAGE + can_hold = list() // any + cant_hold = list("/obj/item/weapon/disk/nuclear") + +// ----------------------------- +// Mining Satchel +// ----------------------------- + +/obj/item/weapon/storage/bag/ore + name = "Mining Satchel" + 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 = ITEM_SIZE_NORMAL + max_storage_space = 100 + can_hold = list("/obj/item/weapon/ore", "/obj/item/bluespace_crystal") + +/obj/item/weapon/storage/bag/ore/holding + name = "Mining satchel of holding" + desc = "A revolution in convenience, this satchel allows for huge amounts of ore storage. It's been outfitted with anti-malfunction safety measures." + max_storage_space = 300 + origin_tech = "bluespace=4;materials=3;engineering=3" + icon_state = "satchel_bspace" + +// ----------------------------- +// Plant bag +// ----------------------------- + +/obj/item/weapon/storage/bag/plants + icon = 'icons/obj/hydroponics/equipment.dmi' + icon_state = "plantbag" + name = "Plant Bag" + max_storage_space = 100 + max_w_class = ITEM_SIZE_NORMAL + w_class = ITEM_SIZE_SMALL + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/grown","/obj/item/seeds","/obj/item/weapon/grown") + + +// ----------------------------- +// 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 = ITEM_SIZE_NORMAL + storage_slots = 7 + + allow_quick_empty = 1 // this function is superceded + +/obj/item/weapon/storage/bag/sheetsnatcher/can_be_inserted(obj/item/W, 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.get_amount() + if(capacity == current)//If it's full, you're done + if(!stop_messages) + to_chat(usr, "\red The snatcher is full.") + return 0 + return 1 + + +// Modified handle_item_insertion. Would prefer not to, but... +/obj/item/weapon/storage/bag/sheetsnatcher/handle_item_insertion(obj/item/W, prevent_warning = FALSE, NoUpdate = FALSE) + 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.get_amount() + if(capacity < current + S.get_amount())//If the stack will fill it up + amount = capacity - current + else + amount = S.get_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.get_amount()) + usr.remove_from_mob(S) + usr.update_icons() //update our overlays + if(!S.get_amount()) + qdel(S) + else + S.loc = src + + if(!NoUpdate) + update_ui_after_item_insertion() + update_icon() + return 1 + +// Modified quick_empty verb drops appropriate sized stacks +/obj/item/weapon/storage/bag/sheetsnatcher/quick_empty() + var/location = get_turf(src) + for(var/obj/item/stack/sheet/S in contents) + while(S.get_amount()) + var/obj/item/stack/sheet/N = new S.type(location) + var/stacksize = min(S.get_amount(),N.max_amount) + N.amount = stacksize + S.amount -= stacksize + if(!S.get_amount()) + qdel(S) // todo: there's probably something missing here + update_ui_after_item_removal() + update_icon() + +// Instead of removing +/obj/item/weapon/storage/bag/sheetsnatcher/remove_from_storage(obj/item/W, atom/new_location, NoUpdate = FALSE) + 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.get_amount() > S.max_amount) + var/obj/item/stack/sheet/temp = new S.type(src) + temp.amount = S.get_amount() - S.max_amount + S.amount = S.max_amount + + return ..(S, new_location, NoUpdate) + +// ----------------------------- +// Sheet Snatcher (Cyborg) +// ----------------------------- + +/obj/item/weapon/storage/bag/sheetsnatcher/borg + name = "Sheet Snatcher 9000" + desc = "" + capacity = 500//Borgs get more because >specialization + +// ----------------------------- +// Cash Bag +// ----------------------------- + +/obj/item/weapon/storage/bag/cash + icon = 'icons/obj/storage.dmi' + icon_state = "cashbag" + name = "Cash bag" + desc = "A bag for carrying lots of cash. It's got a big dollar sign printed on the front." + max_storage_space = 100 + max_w_class = ITEM_SIZE_HUGE + w_class = ITEM_SIZE_SMALL + can_hold = list("/obj/item/weapon/coin","/obj/item/weapon/spacecash") diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 1b323c0bc5ca..d41547e577c4 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -1,211 +1,211 @@ -/obj/item/weapon/storage/belt - name = "belt" - desc = "Can hold various things." - icon = 'icons/obj/clothing/belts.dmi' - icon_state = "utilitybelt" - item_state = "utility" - storage_slots = 7 - slot_flags = SLOT_BELT - attack_verb = list("whipped", "lashed", "disciplined") - use_to_pickup = TRUE - -/obj/item/weapon/storage/belt/utility - name = "tool-belt" //Carn: utility belt is nicer, but it bamboozles the text parsing. - desc = "Can hold various tools." - icon_state = "utilitybelt" - item_state = "utility" - can_hold = list( - "/obj/item/weapon/crowbar", - "/obj/item/weapon/screwdriver", - "/obj/item/weapon/weldingtool", - "/obj/item/weapon/wirecutters", - "/obj/item/weapon/wrench", - "/obj/item/device/multitool", - "/obj/item/device/flashlight", - "/obj/item/stack/cable_coil", - "/obj/item/device/t_scanner", - "/obj/item/device/analyzer", - "/obj/item/taperoll/engineering") - - -/obj/item/weapon/storage/belt/utility/full/atom_init() - . = ..() - new /obj/item/weapon/screwdriver(src) - new /obj/item/weapon/wrench(src) - new /obj/item/weapon/weldingtool(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/weapon/wirecutters(src) - new /obj/item/stack/cable_coil(src, 30, pick(COLOR_RED, COLOR_YELLOW, COLOR_ORANGE)) - - -/obj/item/weapon/storage/belt/utility/atmostech/atom_init() - . = ..() - new /obj/item/weapon/screwdriver(src) - new /obj/item/weapon/wrench(src) - new /obj/item/weapon/weldingtool(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/weapon/wirecutters(src) - new /obj/item/device/t_scanner(src) - - - -/obj/item/weapon/storage/belt/medical - name = "medical belt" - desc = "Can hold various medical equipment." - icon_state = "medicalbelt" - item_state = "medical" - can_hold = list( - "/obj/item/device/healthanalyzer", - "/obj/item/weapon/dnainjector", - "/obj/item/weapon/reagent_containers/dropper", - "/obj/item/weapon/reagent_containers/glass/beaker", - "/obj/item/weapon/reagent_containers/glass/bottle", - "/obj/item/weapon/reagent_containers/pill", - "/obj/item/weapon/reagent_containers/syringe", - "/obj/item/weapon/reagent_containers/glass/dispenser", - "/obj/item/weapon/lighter/zippo", - "/obj/item/weapon/storage/fancy/cigarettes", - "/obj/item/weapon/storage/pill_bottle", - "/obj/item/stack/medical", - "/obj/item/device/flashlight/pen", - "/obj/item/clothing/mask/surgical", - "/obj/item/clothing/gloves/latex", - "/obj/item/weapon/reagent_containers/hypospray", - "/obj/item/device/sensor_device", - "/obj/item/device/mass_spectrometer", - "/obj/item/device/reagent_scanner" - ) -/obj/item/weapon/storage/belt/medical/surg - name = "Surgery belt" - desc = "Can hold various medical equipment." - icon_state = "medicalbelt" - item_state = "medical" - storage_slots = 9 - max_w_class = 3 - can_hold = list( - "/obj/item/device/healthanalyzer", - "/obj/item/weapon/reagent_containers/glass/beaker", - "/obj/item/weapon/reagent_containers/glass/bottle", - "/obj/item/weapon/reagent_containers/pill", - "/obj/item/weapon/reagent_containers/syringe", - "/obj/item/weapon/storage/fancy/cigarettes", - "/obj/item/weapon/storage/pill_bottle", - "/obj/item/stack/medical", - "/obj/item/device/flashlight/pen", - "/obj/item/clothing/mask/surgical", - "/obj/item/clothing/gloves/latex", - "/obj/item/weapon/reagent_containers/hypospray", - "/obj/item/weapon/retractor", - "/obj/item/weapon/hemostat", - "/obj/item/weapon/cautery", - "/obj/item/weapon/surgicaldrill", - "/obj/item/weapon/scalpel", - "/obj/item/weapon/circular_saw", - "/obj/item/weapon/bonegel", - "/obj/item/weapon/FixOVein", - "/obj/item/weapon/bonesetter" - ) -/obj/item/weapon/storage/belt/medical/surg/full/atom_init() - . = ..() - new /obj/item/weapon/retractor(src) - new /obj/item/weapon/hemostat(src) - new /obj/item/weapon/cautery(src) - new /obj/item/weapon/surgicaldrill(src) - new /obj/item/weapon/scalpel(src) - new /obj/item/weapon/circular_saw(src) - new /obj/item/weapon/bonegel(src) - new /obj/item/weapon/FixOVein(src) - new /obj/item/weapon/bonesetter(src) - -/obj/item/weapon/storage/belt/security - name = "security belt" - desc = "Can hold security gear like handcuffs and flashes." - icon_state = "securitybelt" - item_state = "security"//Could likely use a better one. - storage_slots = 7 - max_w_class = 3 - can_hold = list( - "/obj/item/weapon/grenade/flashbang", - "/obj/item/weapon/reagent_containers/spray/pepper", - "/obj/item/weapon/handcuffs", - "/obj/item/device/hailer", - "/obj/item/device/flash", - "/obj/item/clothing/glasses", - "/obj/item/ammo_casing/shotgun", - "/obj/item/ammo_box/magazine", - "/obj/item/weapon/reagent_containers/food/snacks/donut/normal", - "/obj/item/weapon/reagent_containers/food/snacks/donut/jelly", - "/obj/item/weapon/melee/baton", - "/obj/item/weapon/lighter/zippo", - "/obj/item/weapon/cigpacket", - "/obj/item/clothing/glasses/hud/security", - "/obj/item/device/flashlight", - "/obj/item/device/pda", - "/obj/item/weapon/melee", - "/obj/item/taperoll/police", - "/obj/item/weapon/gun/energy/taser", - "/obj/item/weapon/shield/riot/tele", - "/obj/item/device/flashlight/seclite" - ) - -/obj/item/weapon/storage/belt/soulstone - name = "soul stone belt" - desc = "Designed for ease of access to the shards during a fight, as to not let a single enemy spirit slip away." - icon_state = "soulstonebelt" - item_state = "soulstonebelt" - storage_slots = 6 - can_hold = list( - "/obj/item/device/soulstone" - ) - -/obj/item/weapon/storage/belt/soulstone/full/atom_init() - . = ..() - for (var/i in 1 to 6) - new /obj/item/device/soulstone(src) - -/obj/item/weapon/storage/belt/champion - name = "championship belt" - desc = "Proves to the world that you are the strongest!" - icon_state = "championbelt" - item_state = "champion" - storage_slots = 1 - can_hold = list( - "/obj/item/clothing/mask/luchador" - ) - -/obj/item/weapon/storage/belt/security/tactical - name = "combat belt" - desc = "Can hold security gear like handcuffs and flashes, with more pouches for more storage." - icon_state = "swatbelt" - item_state = "swatbelt" - storage_slots = 9 - max_w_class = 3 - can_hold = list( - "/obj/item/weapon/grenade/flashbang", - "/obj/item/weapon/reagent_containers/spray/pepper", - "/obj/item/weapon/handcuffs", - "/obj/item/device/flash", - "/obj/item/clothing/glasses", - "/obj/item/ammo_casing/shotgun", - "/obj/item/ammo_box/magazine", - "/obj/item/weapon/reagent_containers/food/snacks/donut/normal", - "/obj/item/weapon/reagent_containers/food/snacks/donut/jelly", - "/obj/item/weapon/melee/baton", - "/obj/item/weapon/gun/energy/taser", - "/obj/item/weapon/lighter/zippo", - "/obj/item/weapon/cigpacket", - "/obj/item/clothing/glasses/hud/security", - "/obj/item/device/flashlight", - "/obj/item/device/pda", - "/obj/item/taperoll/police", - "/obj/item/device/radio/headset", - "/obj/item/weapon/melee", - "/obj/item/device/flashlight/seclite" - ) - -/obj/item/weapon/storage/belt/military - name = "military belt" - desc = "A syndicate belt designed to be used by boarding parties. Its style is modeled after the hardsuits they wear." - icon_state = "militarybelt" - item_state = "militarybelt" - can_hold = list() +/obj/item/weapon/storage/belt + name = "belt" + desc = "Can hold various things." + icon = 'icons/obj/clothing/belts.dmi' + icon_state = "utilitybelt" + item_state = "utility" + storage_slots = 7 + slot_flags = SLOT_BELT + attack_verb = list("whipped", "lashed", "disciplined") + use_to_pickup = TRUE + +/obj/item/weapon/storage/belt/utility + name = "tool-belt" //Carn: utility belt is nicer, but it bamboozles the text parsing. + desc = "Can hold various tools." + icon_state = "utilitybelt" + item_state = "utility" + can_hold = list( + "/obj/item/weapon/crowbar", + "/obj/item/weapon/screwdriver", + "/obj/item/weapon/weldingtool", + "/obj/item/weapon/wirecutters", + "/obj/item/weapon/wrench", + "/obj/item/device/multitool", + "/obj/item/device/flashlight", + "/obj/item/stack/cable_coil", + "/obj/item/device/t_scanner", + "/obj/item/device/analyzer", + "/obj/item/taperoll/engineering") + + +/obj/item/weapon/storage/belt/utility/full/atom_init() + . = ..() + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/wrench(src) + new /obj/item/weapon/weldingtool(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/weapon/wirecutters(src) + new /obj/item/stack/cable_coil(src, 30, pick(COLOR_RED, COLOR_YELLOW, COLOR_ORANGE)) + + +/obj/item/weapon/storage/belt/utility/atmostech/atom_init() + . = ..() + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/wrench(src) + new /obj/item/weapon/weldingtool(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/weapon/wirecutters(src) + new /obj/item/device/t_scanner(src) + + + +/obj/item/weapon/storage/belt/medical + name = "medical belt" + desc = "Can hold various medical equipment." + icon_state = "medicalbelt" + item_state = "medical" + can_hold = list( + "/obj/item/device/healthanalyzer", + "/obj/item/weapon/dnainjector", + "/obj/item/weapon/reagent_containers/dropper", + "/obj/item/weapon/reagent_containers/glass/beaker", + "/obj/item/weapon/reagent_containers/glass/bottle", + "/obj/item/weapon/reagent_containers/pill", + "/obj/item/weapon/reagent_containers/syringe", + "/obj/item/weapon/reagent_containers/glass/dispenser", + "/obj/item/weapon/lighter/zippo", + "/obj/item/weapon/storage/fancy/cigarettes", + "/obj/item/weapon/storage/pill_bottle", + "/obj/item/stack/medical", + "/obj/item/device/flashlight/pen", + "/obj/item/clothing/mask/surgical", + "/obj/item/clothing/gloves/latex", + "/obj/item/weapon/reagent_containers/hypospray", + "/obj/item/device/sensor_device", + "/obj/item/device/mass_spectrometer", + "/obj/item/device/reagent_scanner" + ) +/obj/item/weapon/storage/belt/medical/surg + name = "Surgery belt" + desc = "Can hold various medical equipment." + icon_state = "medicalbelt" + item_state = "medical" + storage_slots = 9 + max_w_class = 3 + can_hold = list( + "/obj/item/device/healthanalyzer", + "/obj/item/weapon/reagent_containers/glass/beaker", + "/obj/item/weapon/reagent_containers/glass/bottle", + "/obj/item/weapon/reagent_containers/pill", + "/obj/item/weapon/reagent_containers/syringe", + "/obj/item/weapon/storage/fancy/cigarettes", + "/obj/item/weapon/storage/pill_bottle", + "/obj/item/stack/medical", + "/obj/item/device/flashlight/pen", + "/obj/item/clothing/mask/surgical", + "/obj/item/clothing/gloves/latex", + "/obj/item/weapon/reagent_containers/hypospray", + "/obj/item/weapon/retractor", + "/obj/item/weapon/hemostat", + "/obj/item/weapon/cautery", + "/obj/item/weapon/surgicaldrill", + "/obj/item/weapon/scalpel", + "/obj/item/weapon/circular_saw", + "/obj/item/weapon/bonegel", + "/obj/item/weapon/FixOVein", + "/obj/item/weapon/bonesetter" + ) +/obj/item/weapon/storage/belt/medical/surg/full/atom_init() + . = ..() + new /obj/item/weapon/retractor(src) + new /obj/item/weapon/hemostat(src) + new /obj/item/weapon/cautery(src) + new /obj/item/weapon/surgicaldrill(src) + new /obj/item/weapon/scalpel(src) + new /obj/item/weapon/circular_saw(src) + new /obj/item/weapon/bonegel(src) + new /obj/item/weapon/FixOVein(src) + new /obj/item/weapon/bonesetter(src) + +/obj/item/weapon/storage/belt/security + name = "security belt" + desc = "Can hold security gear like handcuffs and flashes." + icon_state = "securitybelt" + item_state = "security"//Could likely use a better one. + storage_slots = 7 + max_w_class = 3 + can_hold = list( + "/obj/item/weapon/grenade/flashbang", + "/obj/item/weapon/reagent_containers/spray/pepper", + "/obj/item/weapon/handcuffs", + "/obj/item/device/hailer", + "/obj/item/device/flash", + "/obj/item/clothing/glasses", + "/obj/item/ammo_casing/shotgun", + "/obj/item/ammo_box/magazine", + "/obj/item/weapon/reagent_containers/food/snacks/donut/normal", + "/obj/item/weapon/reagent_containers/food/snacks/donut/jelly", + "/obj/item/weapon/melee/baton", + "/obj/item/weapon/lighter/zippo", + "/obj/item/weapon/cigpacket", + "/obj/item/clothing/glasses/hud/security", + "/obj/item/device/flashlight", + "/obj/item/device/pda", + "/obj/item/weapon/melee", + "/obj/item/taperoll/police", + "/obj/item/weapon/gun/energy/taser", + "/obj/item/weapon/shield/riot/tele", + "/obj/item/device/flashlight/seclite" + ) + +/obj/item/weapon/storage/belt/soulstone + name = "soul stone belt" + desc = "Designed for ease of access to the shards during a fight, as to not let a single enemy spirit slip away." + icon_state = "soulstonebelt" + item_state = "soulstonebelt" + storage_slots = 6 + can_hold = list( + "/obj/item/device/soulstone" + ) + +/obj/item/weapon/storage/belt/soulstone/full/atom_init() + . = ..() + for (var/i in 1 to 6) + new /obj/item/device/soulstone(src) + +/obj/item/weapon/storage/belt/champion + name = "championship belt" + desc = "Proves to the world that you are the strongest!" + icon_state = "championbelt" + item_state = "champion" + storage_slots = 1 + can_hold = list( + "/obj/item/clothing/mask/luchador" + ) + +/obj/item/weapon/storage/belt/security/tactical + name = "combat belt" + desc = "Can hold security gear like handcuffs and flashes, with more pouches for more storage." + icon_state = "swatbelt" + item_state = "swatbelt" + storage_slots = 9 + max_w_class = 3 + can_hold = list( + "/obj/item/weapon/grenade/flashbang", + "/obj/item/weapon/reagent_containers/spray/pepper", + "/obj/item/weapon/handcuffs", + "/obj/item/device/flash", + "/obj/item/clothing/glasses", + "/obj/item/ammo_casing/shotgun", + "/obj/item/ammo_box/magazine", + "/obj/item/weapon/reagent_containers/food/snacks/donut/normal", + "/obj/item/weapon/reagent_containers/food/snacks/donut/jelly", + "/obj/item/weapon/melee/baton", + "/obj/item/weapon/gun/energy/taser", + "/obj/item/weapon/lighter/zippo", + "/obj/item/weapon/cigpacket", + "/obj/item/clothing/glasses/hud/security", + "/obj/item/device/flashlight", + "/obj/item/device/pda", + "/obj/item/taperoll/police", + "/obj/item/device/radio/headset", + "/obj/item/weapon/melee", + "/obj/item/device/flashlight/seclite" + ) + +/obj/item/weapon/storage/belt/military + name = "military belt" + desc = "A syndicate belt designed to be used by boarding parties. Its style is modeled after the hardsuits they wear." + icon_state = "militarybelt" + item_state = "militarybelt" + can_hold = list() diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm index 083e19446d6f..fae7b76b3755 100644 --- a/code/game/objects/items/weapons/storage/bible.dm +++ b/code/game/objects/items/weapons/storage/bible.dm @@ -1,44 +1,44 @@ -/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 - var/mob/affecting = null - var/deity_name = "Christ" - max_storage_space = DEFAULT_BOX_STORAGE - -/obj/item/weapon/storage/bible/booze - name = "bible" - desc = "To be applied to the head repeatedly." - icon_state ="bible" - -/obj/item/weapon/storage/bible/booze/atom_init() - . = ..() - for (var/i in 1 to 2) - new /obj/item/weapon/reagent_containers/food/drinks/bottle/beer(src) - for (var/i in 1 to 3) - new /obj/item/weapon/spacecash(src) - -/obj/item/weapon/storage/bible/afterattack(atom/A, mob/user, proximity) - if(!proximity) - return - if(user.mind && (user.mind.assigned_role == "Chaplain")) - if(A.reagents && A.reagents.has_reagent("water")) //blesses/curses all the water in the holder - var/water2convert = A.reagents.get_reagent_amount("water") - A.reagents.del_reagent("water") - if(icon_state == "necronomicon") - to_chat(user, "You curse [A].") - A.reagents.add_reagent("unholywater",water2convert) - else if(icon_state == "bible" && prob(10)) - to_chat(user, "You have just created wine!") - A.reagents.add_reagent("wine",water2convert) - else - to_chat(user, "You bless [A].") - A.reagents.add_reagent("holywater",water2convert) - -/obj/item/weapon/storage/bible/attackby(obj/item/weapon/W, mob/user) - if (src.use_sound) - playsound(src.loc, src.use_sound, 50, 1, -5) - ..() +/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 + var/mob/affecting = null + var/deity_name = "Christ" + max_storage_space = DEFAULT_BOX_STORAGE + +/obj/item/weapon/storage/bible/booze + name = "bible" + desc = "To be applied to the head repeatedly." + icon_state ="bible" + +/obj/item/weapon/storage/bible/booze/atom_init() + . = ..() + for (var/i in 1 to 2) + new /obj/item/weapon/reagent_containers/food/drinks/bottle/beer(src) + for (var/i in 1 to 3) + new /obj/item/weapon/spacecash(src) + +/obj/item/weapon/storage/bible/afterattack(atom/A, mob/user, proximity) + if(!proximity) + return + if(user.mind && (user.mind.assigned_role == "Chaplain")) + if(A.reagents && A.reagents.has_reagent("water")) //blesses/curses all the water in the holder + var/water2convert = A.reagents.get_reagent_amount("water") + A.reagents.del_reagent("water") + if(icon_state == "necronomicon") + to_chat(user, "You curse [A].") + A.reagents.add_reagent("unholywater",water2convert) + else if(icon_state == "bible" && prob(10)) + to_chat(user, "You have just created wine!") + A.reagents.add_reagent("wine",water2convert) + else + to_chat(user, "You bless [A].") + A.reagents.add_reagent("holywater",water2convert) + +/obj/item/weapon/storage/bible/attackby(obj/item/weapon/W, mob/user) + if (src.use_sound) + playsound(src.loc, src.use_sound, 50, 1, -5) + ..() diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 0b3f7efa8c36..aa3913a6d187 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -1,689 +1,689 @@ -/* - * Everything derived from the common cardboard box. - * Basically everything except the original is a kit (starts full). - * - * Contains: - * -Box -Starter boxes (survival/engineer) - * -Alien -Latex gloves - * -Masks -Syringes - * -Beakers -Injectors - * -Beanbags -Flashbangs - * -Teargas -Smokegrenades - * -Rubber 40x46mm -EMPs - * -Track implant -Chemical implant - * -Stimpack -Prescription glasses - * -Drinking glasses -Death alarm - * -Condiment bottles -Paper cups - * -Donk-pockets -Monkey cube - * -Farwa cube -Stok cube - * -Neaera cube -Spare IDs - * -R.O.B.U.S.T. Cartridges -Handcuffs - * -Alien handcuffs -Mousetraps - * -Pill bottles -Snap pop - * -Matchbox -Autoinjectors - * -Replacement bulbs -Replacement tubes - * -Mixed replacement lights -Body bags - * -Holobadge -Evidence bag - * -Solution tray -Spare PDAs - * -Shotgun ammo -Hair dyes - * - * For syndicate call-ins see uplink_kits.dm - */ - -//Box -/obj/item/weapon/storage/box - name = "box" - desc = "It's just an ordinary box. Nothing special." - icon_state = "box" - item_state = "syringe_kit" - max_storage_space = DEFAULT_BOX_STORAGE - foldable = /obj/item/stack/sheet/cardboard //BubbleWrap - -//Survival boxes, given by NanoTrasen -/obj/item/weapon/storage/box/survival - name = "emergency box" - desc = "It's a box, issued to every employee of NanoTrasen, contains a mask and a spare air tank. It has a ton of ads all over its back." - -/obj/item/weapon/storage/box/survival/atom_init() - . = ..() - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/tank/emergency_oxygen(src) - new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src) - -/obj/item/weapon/storage/box/diona_survival - name = "emergency box" - desc = "It's a box, issued to every diona working for NanoTrasen, contains a flare and a plant analyzer. It has a ton of ads all over its back." - -/obj/item/weapon/storage/box/diona_survival/atom_init() - . = ..() - new /obj/item/device/flashlight/flare(src) - new /obj/item/device/plant_analyzer(src) - -/obj/item/weapon/storage/box/ipc_survival - name = "emergency box" - desc = "It's a box, issued to every IPC working for NanoTrasen, contains a flare and a plant analyzer. It has a ton of ads all over its back." - -/obj/item/weapon/storage/box/ipc_survival/atom_init() - . = ..() - new /obj/item/weapon/stock_parts/cell/crap(src) - new /obj/item/device/robotanalyzer(src) - -//Engineer -/obj/item/weapon/storage/box/engineer - name = "emergency box" - desc = "It's a box, issued to every employee of NanoTrasen, contains a mask and a spare air tank. It has a ton of ads all over its back." - -/obj/item/weapon/storage/box/engineer/atom_init() - . = ..() - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - -//Alien -/obj/item/weapon/storage/box/alien - name = "alien box" - icon_state = "alien_box" - -//Latex gloves -/obj/item/weapon/storage/box/gloves - name = "box of latex gloves" - desc = "Contains white gloves. Must-have of a doctor." - icon_state = "latex_box" - -/obj/item/weapon/storage/box/gloves/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/clothing/gloves/latex(src) - -//Masks -/obj/item/weapon/storage/box/masks - name = "box of sterile masks" - desc = "This box contains masks of sterility." - icon_state = "sterile_mask_box" - -/obj/item/weapon/storage/box/masks/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/clothing/mask/surgical(src) - -//Syringes -/obj/item/weapon/storage/box/syringes - name = "box of syringes" - desc = "A box full of syringes." - icon_state = "syringe_box" - -/obj/item/weapon/storage/box/syringes/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/reagent_containers/syringe(src) - -//Beakers -/obj/item/weapon/storage/box/beakers - name = "box of beakers" - icon_state = "beaker_box" - -/obj/item/weapon/storage/box/beakers/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/reagent_containers/glass/beaker(src) - -//Injectors -/obj/item/weapon/storage/box/injectors - name = "box of DNA injectors" - desc = "This box contains injectors it seems." - icon_state = "dnainjector_box" - -/obj/item/weapon/storage/box/injectors/atom_init() - . = ..() - for(var/i in 1 to 3) - new /obj/item/weapon/dnainjector/h2m(src) - for(var/i in 1 to 3) - new /obj/item/weapon/dnainjector/m2h(src) - -//Beanbags -/obj/item/weapon/storage/box/beanbags - name = "box of beanbag shells" - desc = "It has a picture of a gun and several warning symbols on the front.
                    WARNING: Live ammunition. Misuse may result in serious injury or death." - icon_state = "shotgun_ammo_beanbag" - -/obj/item/weapon/storage/box/beanbags/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/ammo_casing/shotgun/beanbag(src) - -//Flashbangs -/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_box" - -/obj/item/weapon/storage/box/flashbangs/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/grenade/flashbang(src) - -//Teargas -/obj/item/weapon/storage/box/teargas - name = "box of tear gas grenades (WARNING)" - desc = "WARNING: These devices are extremely dangerous and can cause blindness and skin irritation." - icon_state = "flashbang_box" - -/obj/item/weapon/storage/box/teargas/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/grenade/chem_grenade/teargas(src) - -//Smokegrenades -/obj/item/weapon/storage/box/smokegrenades - name = "box of smoke grenades" - desc = "This box contains smoke grenades it seems." - icon_state = "flashbang_box" - -/obj/item/weapon/storage/box/smokegrenades/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/grenade/smokebomb(src) - -//Rubber 40x46mm -/obj/item/weapon/storage/box/r4046 - name = "box of 40x46mm rubber grenades (WARNING)" - desc = "WARNING: These devices are extremely dangerous and can cause injury." - icon_state = "4046_box" - -/obj/item/weapon/storage/box/r4046/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/ammo_casing/r4046(src) - -//EMPs -/obj/item/weapon/storage/box/emps - name = "box of emp grenades" - desc = "A box with 5 emp grenades." - icon_state = "flashbang_box" - -/obj/item/weapon/storage/box/emps/atom_init() - . = ..() - for(var/i in 1 to 5) - new /obj/item/weapon/grenade/empgrenade(src) - -//Track implant -/obj/item/weapon/storage/box/trackimp - name = "boxed tracking implant kit" - desc = "Box full of scum-bag tracking utensils." - icon_state = "implant_box" - -/obj/item/weapon/storage/box/trackimp/atom_init() - . = ..() - new /obj/item/weapon/implanter(src) - new /obj/item/weapon/implantpad(src) - new /obj/item/weapon/locator(src) - for(var/i in 1 to 4) - new /obj/item/weapon/implantcase/tracking(src) - -//Chemical implant -/obj/item/weapon/storage/box/chemimp - name = "boxed chemical implant kit" - desc = "Box of stuff used to implant chemicals." - icon_state = "implant_box" - -/obj/item/weapon/storage/box/chemimp/atom_init() - . = ..() - new /obj/item/weapon/implanter(src) - new /obj/item/weapon/implantpad(src) - for(var/i in 1 to 5) - new /obj/item/weapon/implantcase/chem(src) - -//Stimpack -/obj/item/weapon/storage/box/autoinjector/stimpack - name = "stimpack value kit" - desc = "A box with several stimpack autoinjectors for the economical miner." - icon_state = "box" - -/obj/item/weapon/storage/box/autoinjector/stimpack/atom_init() - . = ..() - for(var/i in 1 to 5) - new /obj/item/weapon/reagent_containers/hypospray/autoinjector/stimpack(src) - -//Prescription glasses -/obj/item/weapon/storage/box/rxglasses - name = "box of prescription glasses" - desc = "This box contains nerd glasses." - icon_state = "glasses_box" - -/obj/item/weapon/storage/box/rxglasses/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/clothing/glasses/regular(src) - -//Drinking glasses -/obj/item/weapon/storage/box/drinkingglasses - name = "box of drinking glasses" - desc = "It has a picture of drinking glasses on it." - icon_state = "drinking_glass_box" - -/obj/item/weapon/storage/box/drinkingglasses/atom_init() - . = ..() - for(var/i in 1 to 6) - new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass(src) - -//Death alarm -/obj/item/weapon/storage/box/cdeathalarm_kit - name = "Death Alarm Kit" - desc = "Box of stuff used to implant death alarms." - icon_state = "implant_box" - -/obj/item/weapon/storage/box/cdeathalarm_kit/atom_init() - . = ..() - new /obj/item/weapon/implanter(src) - for(var/i in 1 to 6) - new /obj/item/weapon/implantcase/death_alarm(src) - -//Condiment bottles -/obj/item/weapon/storage/box/condimentbottles - name = "box of condiment bottles" - desc = "It has a large ketchup smear on it." - -/obj/item/weapon/storage/box/condimentbottles/atom_init() - . = ..() - for(var/i in 1 to 6) - new /obj/item/weapon/reagent_containers/food/condiment(src) - -//Paper cups -/obj/item/weapon/storage/box/cups - name = "box of paper cups" - desc = "It has pictures of paper cups on the front." - icon_state = "cups_box" - -/obj/item/weapon/storage/box/cups/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/reagent_containers/food/drinks/sillycup( src ) - -//Donk-pockets -/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_box" - -/obj/item/weapon/storage/box/donkpockets/atom_init() - . = ..() - for(var/i in 1 to 6) - new /obj/item/weapon/reagent_containers/food/snacks/donkpocket(src) - -//Monkey cube -/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") - -/obj/item/weapon/storage/box/monkeycubes/atom_init() - . = ..() - for(var/i in 1 to 5) - new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped(src) - -//Farwa cube -/obj/item/weapon/storage/box/monkeycubes/farwacubes - name = "farwa cube box" - desc = "Drymate brand farwa cubes, shipped from Ahdomai. Just add water!" - -/obj/item/weapon/storage/box/monkeycubes/farwacubes/atom_init() - . = ..() - for(var/i in 1 to 5) - new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/farwacube(src) - -//Stok cube -/obj/item/weapon/storage/box/monkeycubes/stokcubes - name = "stok cube box" - desc = "Drymate brand stok cubes, shipped from Moghes. Just add water!" - -/obj/item/weapon/storage/box/monkeycubes/stokcubes/atom_init() - . = ..() - for(var/i in 1 to 5) - new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/stokcube(src) - -//Neaera cube -/obj/item/weapon/storage/box/monkeycubes/neaeracubes - name = "neaera cube box" - desc = "Drymate brand neaera cubes, shipped from Jargon 4. Just add water!" - -/obj/item/weapon/storage/box/monkeycubes/neaeracubes/atom_init() - . = ..() - for(var/i in 1 to 5) - new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/neaeracube(src) - -//Spare IDs -/obj/item/weapon/storage/box/ids - name = "box of spare IDs" - desc = "Has so many empty IDs." - icon_state = "id_box" - -/obj/item/weapon/storage/box/ids/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/card/id(src) - -//R.O.B.U.S.T. Cartridges -/obj/item/weapon/storage/box/seccarts - name = "box of 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_box" - -/obj/item/weapon/storage/box/seccarts/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/cartridge/security(src) - -//Handcuffs -/obj/item/weapon/storage/box/handcuffs - name = "box of spare handcuffs" - desc = "A box full of handcuffs." - icon_state = "handcuff_box" - -/obj/item/weapon/storage/box/handcuffs/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/handcuffs(src) - -//Alien handcuffs -/obj/item/weapon/storage/box/alienhandcuffs - name = "box of spare alien handcuffs" - desc = "A box full of handcuffs." - icon_state = "aliencuffs_box" - -/obj/item/weapon/storage/box/alienhandcuffs/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/handcuffs/alien(src) - -//Mousetraps -/obj/item/weapon/storage/box/mousetraps - name = "box of Pest-B-Gon mousetraps" - desc = "WARNING: Keep out of reach of children." - icon_state = "mousetraps_box" - -/obj/item/weapon/storage/box/mousetraps/atom_init() - . = ..() - for(var/i in 1 to 6) - new /obj/item/device/assembly/mousetrap(src) - -//Pill bottles -/obj/item/weapon/storage/box/pillbottles - name = "box of pill bottles" - desc = "It has pictures of pill bottles on its front." - icon_state = "pills_box" - -/obj/item/weapon/storage/box/pillbottles/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/storage/pill_bottle( src ) - -//Snap pop -/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") - -/obj/item/weapon/storage/box/snappops/atom_init() - . = ..() - for(var/i in 1 to storage_slots) - new /obj/item/toy/snappop(src) - -//Matchbox -/obj/item/weapon/storage/box/matches - name = "matchbox" - desc = "A small box of 'Space-Proof' premium matches." - icon = 'icons/obj/cigarettes.dmi' - icon_state = "matchbox" - item_state = "zippo" - storage_slots = 10 - w_class = 1 - slot_flags = SLOT_BELT - can_hold = list("/obj/item/weapon/match") - -/obj/item/weapon/storage/box/matches/atom_init() - . = ..() - for(var/i in 1 to storage_slots) - new /obj/item/weapon/match(src) - -/obj/item/weapon/storage/box/matches/attackby(obj/item/weapon/match/W, mob/user) - if(istype(W) && !W.lit && !W.burnt) - if (prob (20)) - playsound(src, 'sound/items/matchstick_hit.ogg', 20, 1, 1) - return - playsound(src, 'sound/items/matchstick_light.ogg', 20, 1, 1) - W.lit = 1 - W.damtype = "burn" - W.icon_state = "match_lit" - START_PROCESSING(SSobj, W) - W.update_icon() - return - -//Autoinjectors -/obj/item/weapon/storage/box/autoinjectors - name = "box of injectors" - desc = "Contains autoinjectors." - icon_state = "syringe_box" - -/obj/item/weapon/storage/box/autoinjectors/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src) - -//Replacement bulbs -/obj/item/weapon/storage/box/lights - name = "box of replacement bulbs" - icon_state = "lightbulb_box" - 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 - max_storage_space = 42 - can_hold = list("/obj/item/weapon/light/tube", "/obj/item/weapon/light/bulb") - use_to_pickup = 1 // for picking up broken bulbs, not that most people will try - -/obj/item/weapon/storage/box/lights/bulbs/atom_init() - . = ..() - for(var/i in 1 to storage_slots) - new /obj/item/weapon/light/bulb(src) - -//Replacement tubes -/obj/item/weapon/storage/box/lights/tubes - name = "box of replacement tubes" - icon_state = "lighttube_box" - -/obj/item/weapon/storage/box/lights/tubes/atom_init() - . = ..() - for(var/i in 1 to storage_slots) - new /obj/item/weapon/light/tube(src) - -//Mixed replacement lights -/obj/item/weapon/storage/box/lights/mixed - name = "box of replacement lights" - icon_state = "lightmixed_box" - -/obj/item/weapon/storage/box/lights/mixed/atom_init() - . = ..() - for(var/i in 1 to 14) - new /obj/item/weapon/light/tube(src) - for(var/i in 1 to 7) - new /obj/item/weapon/light/bulb(src) - -//Body bags -/obj/item/weapon/storage/box/bodybags - name = "body bags" - desc = "This box contains body bags." - icon_state = "bodybags_box" - -/obj/item/weapon/storage/box/bodybags/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/bodybag(src) - -//Holobadge -/obj/item/weapon/storage/box/holobadge - name = "holobadge box" - desc = "A box claiming to contain holobadges." - icon_state = "holobadge_box" - -/obj/item/weapon/storage/box/holobadge/atom_init() - . = ..() - for(var/i in 1 to 4) - new /obj/item/clothing/accessory/holobadge(src) - for(var/i in 1 to 3) - new /obj/item/clothing/accessory/holobadge/cord(src) - -//Evidence bag -/obj/item/weapon/storage/box/evidence - name = "evidence bag box" - desc = "A box claiming to contain evidence bags." - icon_state = "evidence_box" - -/obj/item/weapon/storage/box/evidence/atom_init() - . = ..() - for(var/i in 1 to 6) - new /obj/item/weapon/evidencebag(src) - -//Solution tray -/obj/item/weapon/storage/box/solution_trays - name = "solution tray box" - icon_state = "solution_trays_box" - -/obj/item/weapon/storage/box/solution_trays/atom_init() - . = ..() - for(var/i in 1 to 7) - new /obj/item/weapon/reagent_containers/glass/solution_tray(src) - -//Spare PDAs -/obj/item/weapon/storage/box/PDAs - name = "box of spare PDAs" - desc = "A box of spare PDA microcomputers." - icon_state = "pda_box" - -/obj/item/weapon/storage/box/PDAs/atom_init() - . = ..() - var/newcart = pick( /obj/item/weapon/cartridge/engineering, - /obj/item/weapon/cartridge/security, - /obj/item/weapon/cartridge/medical, - /obj/item/weapon/cartridge/signal/science, - /obj/item/weapon/cartridge/quartermaster) - new newcart(src) - new /obj/item/weapon/cartridge/head(src) - for(var/i in 1 to 4) - new /obj/item/device/pda(src) - -//Shotgun ammo - -/obj/item/weapon/storage/box/shotgun - name = "box of shotgun shell" - icon_state = "shotgun_ammo_slug" - foldable = /obj/item/stack/sheet/cardboard - can_hold = list("/obj/item/ammo_casing/shotgun") - -/obj/item/weapon/storage/box/shotgun/slug - name = "box of shotgun shell (slug)" - icon_state = "shotgun_ammo_slug" - -/obj/item/weapon/storage/box/shotgun/slug/atom_init() - . = ..() - for(var/i in 1 to 16) - new /obj/item/ammo_casing/shotgun(src) - make_exact_fit() - - -/obj/item/weapon/storage/box/shotgun/buckshot - name = "box of shotgun shell (buckshot)" - icon_state = "shotgun_ammo_buckshot" - -/obj/item/weapon/storage/box/shotgun/buckshot/atom_init() - . = ..() - for(var/i in 1 to 16) - new /obj/item/ammo_casing/shotgun/buckshot(src) - make_exact_fit() - - -/obj/item/weapon/storage/box/shotgun/beanbag - name = "box of shotgun shell (beanbag)" - icon_state = "shotgun_ammo_beanbag" - -/obj/item/weapon/storage/box/shotgun/beanbag/atom_init() - . = ..() - for(var/i in 1 to 16) - new /obj/item/ammo_casing/shotgun/beanbag(src) - make_exact_fit() - -//Hair sprays -/obj/item/weapon/storage/box/hairdyes - name = "hair spray dye box" - desc = "A box full of hair spray dyes." - -/obj/item/weapon/storage/box/hairdyes/atom_init() - . = ..() - new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/white(src) - new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/red(src) - new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/green(src) - new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/blue(src) - new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/black(src) - new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/brown(src) - new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/blond(src) - -/obj/item/weapon/storage/box/lipstick - name = "lipstick box" - desc = "A box full of lipstick." - -/obj/item/weapon/storage/box/lipstick/atom_init() - . = ..() - new /obj/item/weapon/lipstick(src) - new /obj/item/weapon/lipstick/purple(src) - new /obj/item/weapon/lipstick/jade(src) - new /obj/item/weapon/lipstick/black(src) - new /obj/item/weapon/paper(src) - -// Don't know where is original box itself, so just put it here. -/obj/item/weapon/storage/box/contraband - name = "box" - desc = "Strange box." - icon_state = "doom_box" - -/obj/item/weapon/storage/box/contraband/atom_init() - . = ..() - if(prob(30)) - new /obj/item/weapon/storage/box/matches(src) - new /obj/item/clothing/mask/cigarette/cigar/cohiba(src) - else if(prob(10)) - new /obj/item/device/guitar(src) - new /obj/item/clothing/head/sombrero(src) - new /obj/item/weapon/reagent_containers/food/drinks/bottle/tequilla(src) - else - new /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka(src) - new /obj/item/weapon/storage/fancy/cigarettes(src) - new /obj/item/weapon/lighter/random(src) - -/obj/item/weapon/storage/box/ians_box - name = "Ian's box" - desc = "It's a box with a corgi on it. YAP! Looks like somebody lost it." - icon_state = "corgi_box" - -/obj/item/weapon/storage/box/ians_box/atom_init() - . = ..() - new /obj/item/weapon/bikehorn/dogtoy(src) - new /obj/item/weapon/reagent_containers/food/snacks/cookie(src) - new /obj/item/weapon/reagent_containers/food/snacks/cookie(src) - new /obj/item/weapon/reagent_containers/food/snacks/cookie(src) - new /obj/item/weapon/reagent_containers/food/snacks/cookie(src) - new /obj/item/toy/plushie/girly_corgi(src) - -//NOT USED ANYWHERE -/obj/item/weapon/storage/box/syndielogo_box - name = "syndie box" - desc = "It's a red box with an 'S' on it. Strange." - icon_state = "syndie_box" - -/obj/item/weapon/storage/box/nanotrasenlogo_box - name = "NT box" - desc = "It's a blue box with an 'N' on it. Glory to NanoTrasen!" - icon_state = "nanotrasen_box" +/* + * Everything derived from the common cardboard box. + * Basically everything except the original is a kit (starts full). + * + * Contains: + * -Box -Starter boxes (survival/engineer) + * -Alien -Latex gloves + * -Masks -Syringes + * -Beakers -Injectors + * -Beanbags -Flashbangs + * -Teargas -Smokegrenades + * -Rubber 40x46mm -EMPs + * -Track implant -Chemical implant + * -Stimpack -Prescription glasses + * -Drinking glasses -Death alarm + * -Condiment bottles -Paper cups + * -Donk-pockets -Monkey cube + * -Farwa cube -Stok cube + * -Neaera cube -Spare IDs + * -R.O.B.U.S.T. Cartridges -Handcuffs + * -Alien handcuffs -Mousetraps + * -Pill bottles -Snap pop + * -Matchbox -Autoinjectors + * -Replacement bulbs -Replacement tubes + * -Mixed replacement lights -Body bags + * -Holobadge -Evidence bag + * -Solution tray -Spare PDAs + * -Shotgun ammo -Hair dyes + * + * For syndicate call-ins see uplink_kits.dm + */ + +//Box +/obj/item/weapon/storage/box + name = "box" + desc = "It's just an ordinary box. Nothing special." + icon_state = "box" + item_state = "syringe_kit" + max_storage_space = DEFAULT_BOX_STORAGE + foldable = /obj/item/stack/sheet/cardboard //BubbleWrap + +//Survival boxes, given by NanoTrasen +/obj/item/weapon/storage/box/survival + name = "emergency box" + desc = "It's a box, issued to every employee of NanoTrasen, contains a mask and a spare air tank. It has a ton of ads all over its back." + +/obj/item/weapon/storage/box/survival/atom_init() + . = ..() + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/tank/emergency_oxygen(src) + new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src) + +/obj/item/weapon/storage/box/diona_survival + name = "emergency box" + desc = "It's a box, issued to every diona working for NanoTrasen, contains a flare and a plant analyzer. It has a ton of ads all over its back." + +/obj/item/weapon/storage/box/diona_survival/atom_init() + . = ..() + new /obj/item/device/flashlight/flare(src) + new /obj/item/device/plant_analyzer(src) + +/obj/item/weapon/storage/box/ipc_survival + name = "emergency box" + desc = "It's a box, issued to every IPC working for NanoTrasen, contains a flare and a plant analyzer. It has a ton of ads all over its back." + +/obj/item/weapon/storage/box/ipc_survival/atom_init() + . = ..() + new /obj/item/weapon/stock_parts/cell/crap(src) + new /obj/item/device/robotanalyzer(src) + +//Engineer +/obj/item/weapon/storage/box/engineer + name = "emergency box" + desc = "It's a box, issued to every employee of NanoTrasen, contains a mask and a spare air tank. It has a ton of ads all over its back." + +/obj/item/weapon/storage/box/engineer/atom_init() + . = ..() + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + +//Alien +/obj/item/weapon/storage/box/alien + name = "alien box" + icon_state = "alien_box" + +//Latex gloves +/obj/item/weapon/storage/box/gloves + name = "box of latex gloves" + desc = "Contains white gloves. Must-have of a doctor." + icon_state = "latex_box" + +/obj/item/weapon/storage/box/gloves/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/clothing/gloves/latex(src) + +//Masks +/obj/item/weapon/storage/box/masks + name = "box of sterile masks" + desc = "This box contains masks of sterility." + icon_state = "sterile_mask_box" + +/obj/item/weapon/storage/box/masks/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/clothing/mask/surgical(src) + +//Syringes +/obj/item/weapon/storage/box/syringes + name = "box of syringes" + desc = "A box full of syringes." + icon_state = "syringe_box" + +/obj/item/weapon/storage/box/syringes/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/reagent_containers/syringe(src) + +//Beakers +/obj/item/weapon/storage/box/beakers + name = "box of beakers" + icon_state = "beaker_box" + +/obj/item/weapon/storage/box/beakers/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/reagent_containers/glass/beaker(src) + +//Injectors +/obj/item/weapon/storage/box/injectors + name = "box of DNA injectors" + desc = "This box contains injectors it seems." + icon_state = "dnainjector_box" + +/obj/item/weapon/storage/box/injectors/atom_init() + . = ..() + for(var/i in 1 to 3) + new /obj/item/weapon/dnainjector/h2m(src) + for(var/i in 1 to 3) + new /obj/item/weapon/dnainjector/m2h(src) + +//Beanbags +/obj/item/weapon/storage/box/beanbags + name = "box of beanbag shells" + desc = "It has a picture of a gun and several warning symbols on the front.
                    WARNING: Live ammunition. Misuse may result in serious injury or death." + icon_state = "shotgun_ammo_beanbag" + +/obj/item/weapon/storage/box/beanbags/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/ammo_casing/shotgun/beanbag(src) + +//Flashbangs +/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_box" + +/obj/item/weapon/storage/box/flashbangs/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/grenade/flashbang(src) + +//Teargas +/obj/item/weapon/storage/box/teargas + name = "box of tear gas grenades (WARNING)" + desc = "WARNING: These devices are extremely dangerous and can cause blindness and skin irritation." + icon_state = "flashbang_box" + +/obj/item/weapon/storage/box/teargas/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/grenade/chem_grenade/teargas(src) + +//Smokegrenades +/obj/item/weapon/storage/box/smokegrenades + name = "box of smoke grenades" + desc = "This box contains smoke grenades it seems." + icon_state = "flashbang_box" + +/obj/item/weapon/storage/box/smokegrenades/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/grenade/smokebomb(src) + +//Rubber 40x46mm +/obj/item/weapon/storage/box/r4046 + name = "box of 40x46mm rubber grenades (WARNING)" + desc = "WARNING: These devices are extremely dangerous and can cause injury." + icon_state = "4046_box" + +/obj/item/weapon/storage/box/r4046/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/ammo_casing/r4046(src) + +//EMPs +/obj/item/weapon/storage/box/emps + name = "box of emp grenades" + desc = "A box with 5 emp grenades." + icon_state = "flashbang_box" + +/obj/item/weapon/storage/box/emps/atom_init() + . = ..() + for(var/i in 1 to 5) + new /obj/item/weapon/grenade/empgrenade(src) + +//Track implant +/obj/item/weapon/storage/box/trackimp + name = "boxed tracking implant kit" + desc = "Box full of scum-bag tracking utensils." + icon_state = "implant_box" + +/obj/item/weapon/storage/box/trackimp/atom_init() + . = ..() + new /obj/item/weapon/implanter(src) + new /obj/item/weapon/implantpad(src) + new /obj/item/weapon/locator(src) + for(var/i in 1 to 4) + new /obj/item/weapon/implantcase/tracking(src) + +//Chemical implant +/obj/item/weapon/storage/box/chemimp + name = "boxed chemical implant kit" + desc = "Box of stuff used to implant chemicals." + icon_state = "implant_box" + +/obj/item/weapon/storage/box/chemimp/atom_init() + . = ..() + new /obj/item/weapon/implanter(src) + new /obj/item/weapon/implantpad(src) + for(var/i in 1 to 5) + new /obj/item/weapon/implantcase/chem(src) + +//Stimpack +/obj/item/weapon/storage/box/autoinjector/stimpack + name = "stimpack value kit" + desc = "A box with several stimpack autoinjectors for the economical miner." + icon_state = "box" + +/obj/item/weapon/storage/box/autoinjector/stimpack/atom_init() + . = ..() + for(var/i in 1 to 5) + new /obj/item/weapon/reagent_containers/hypospray/autoinjector/stimpack(src) + +//Prescription glasses +/obj/item/weapon/storage/box/rxglasses + name = "box of prescription glasses" + desc = "This box contains nerd glasses." + icon_state = "glasses_box" + +/obj/item/weapon/storage/box/rxglasses/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/clothing/glasses/regular(src) + +//Drinking glasses +/obj/item/weapon/storage/box/drinkingglasses + name = "box of drinking glasses" + desc = "It has a picture of drinking glasses on it." + icon_state = "drinking_glass_box" + +/obj/item/weapon/storage/box/drinkingglasses/atom_init() + . = ..() + for(var/i in 1 to 6) + new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass(src) + +//Death alarm +/obj/item/weapon/storage/box/cdeathalarm_kit + name = "Death Alarm Kit" + desc = "Box of stuff used to implant death alarms." + icon_state = "implant_box" + +/obj/item/weapon/storage/box/cdeathalarm_kit/atom_init() + . = ..() + new /obj/item/weapon/implanter(src) + for(var/i in 1 to 6) + new /obj/item/weapon/implantcase/death_alarm(src) + +//Condiment bottles +/obj/item/weapon/storage/box/condimentbottles + name = "box of condiment bottles" + desc = "It has a large ketchup smear on it." + +/obj/item/weapon/storage/box/condimentbottles/atom_init() + . = ..() + for(var/i in 1 to 6) + new /obj/item/weapon/reagent_containers/food/condiment(src) + +//Paper cups +/obj/item/weapon/storage/box/cups + name = "box of paper cups" + desc = "It has pictures of paper cups on the front." + icon_state = "cups_box" + +/obj/item/weapon/storage/box/cups/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/reagent_containers/food/drinks/sillycup( src ) + +//Donk-pockets +/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_box" + +/obj/item/weapon/storage/box/donkpockets/atom_init() + . = ..() + for(var/i in 1 to 6) + new /obj/item/weapon/reagent_containers/food/snacks/donkpocket(src) + +//Monkey cube +/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") + +/obj/item/weapon/storage/box/monkeycubes/atom_init() + . = ..() + for(var/i in 1 to 5) + new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped(src) + +//Farwa cube +/obj/item/weapon/storage/box/monkeycubes/farwacubes + name = "farwa cube box" + desc = "Drymate brand farwa cubes, shipped from Ahdomai. Just add water!" + +/obj/item/weapon/storage/box/monkeycubes/farwacubes/atom_init() + . = ..() + for(var/i in 1 to 5) + new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/farwacube(src) + +//Stok cube +/obj/item/weapon/storage/box/monkeycubes/stokcubes + name = "stok cube box" + desc = "Drymate brand stok cubes, shipped from Moghes. Just add water!" + +/obj/item/weapon/storage/box/monkeycubes/stokcubes/atom_init() + . = ..() + for(var/i in 1 to 5) + new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/stokcube(src) + +//Neaera cube +/obj/item/weapon/storage/box/monkeycubes/neaeracubes + name = "neaera cube box" + desc = "Drymate brand neaera cubes, shipped from Jargon 4. Just add water!" + +/obj/item/weapon/storage/box/monkeycubes/neaeracubes/atom_init() + . = ..() + for(var/i in 1 to 5) + new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/neaeracube(src) + +//Spare IDs +/obj/item/weapon/storage/box/ids + name = "box of spare IDs" + desc = "Has so many empty IDs." + icon_state = "id_box" + +/obj/item/weapon/storage/box/ids/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/card/id(src) + +//R.O.B.U.S.T. Cartridges +/obj/item/weapon/storage/box/seccarts + name = "box of 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_box" + +/obj/item/weapon/storage/box/seccarts/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/cartridge/security(src) + +//Handcuffs +/obj/item/weapon/storage/box/handcuffs + name = "box of spare handcuffs" + desc = "A box full of handcuffs." + icon_state = "handcuff_box" + +/obj/item/weapon/storage/box/handcuffs/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/handcuffs(src) + +//Alien handcuffs +/obj/item/weapon/storage/box/alienhandcuffs + name = "box of spare alien handcuffs" + desc = "A box full of handcuffs." + icon_state = "aliencuffs_box" + +/obj/item/weapon/storage/box/alienhandcuffs/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/handcuffs/alien(src) + +//Mousetraps +/obj/item/weapon/storage/box/mousetraps + name = "box of Pest-B-Gon mousetraps" + desc = "WARNING: Keep out of reach of children." + icon_state = "mousetraps_box" + +/obj/item/weapon/storage/box/mousetraps/atom_init() + . = ..() + for(var/i in 1 to 6) + new /obj/item/device/assembly/mousetrap(src) + +//Pill bottles +/obj/item/weapon/storage/box/pillbottles + name = "box of pill bottles" + desc = "It has pictures of pill bottles on its front." + icon_state = "pills_box" + +/obj/item/weapon/storage/box/pillbottles/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/storage/pill_bottle( src ) + +//Snap pop +/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") + +/obj/item/weapon/storage/box/snappops/atom_init() + . = ..() + for(var/i in 1 to storage_slots) + new /obj/item/toy/snappop(src) + +//Matchbox +/obj/item/weapon/storage/box/matches + name = "matchbox" + desc = "A small box of 'Space-Proof' premium matches." + icon = 'icons/obj/cigarettes.dmi' + icon_state = "matchbox" + item_state = "zippo" + storage_slots = 10 + w_class = 1 + slot_flags = SLOT_BELT + can_hold = list("/obj/item/weapon/match") + +/obj/item/weapon/storage/box/matches/atom_init() + . = ..() + for(var/i in 1 to storage_slots) + new /obj/item/weapon/match(src) + +/obj/item/weapon/storage/box/matches/attackby(obj/item/weapon/match/W, mob/user) + if(istype(W) && !W.lit && !W.burnt) + if (prob (20)) + playsound(src, 'sound/items/matchstick_hit.ogg', 20, 1, 1) + return + playsound(src, 'sound/items/matchstick_light.ogg', 20, 1, 1) + W.lit = 1 + W.damtype = "burn" + W.icon_state = "match_lit" + START_PROCESSING(SSobj, W) + W.update_icon() + return + +//Autoinjectors +/obj/item/weapon/storage/box/autoinjectors + name = "box of injectors" + desc = "Contains autoinjectors." + icon_state = "syringe_box" + +/obj/item/weapon/storage/box/autoinjectors/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src) + +//Replacement bulbs +/obj/item/weapon/storage/box/lights + name = "box of replacement bulbs" + icon_state = "lightbulb_box" + 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 + max_storage_space = 42 + can_hold = list("/obj/item/weapon/light/tube", "/obj/item/weapon/light/bulb") + use_to_pickup = 1 // for picking up broken bulbs, not that most people will try + +/obj/item/weapon/storage/box/lights/bulbs/atom_init() + . = ..() + for(var/i in 1 to storage_slots) + new /obj/item/weapon/light/bulb(src) + +//Replacement tubes +/obj/item/weapon/storage/box/lights/tubes + name = "box of replacement tubes" + icon_state = "lighttube_box" + +/obj/item/weapon/storage/box/lights/tubes/atom_init() + . = ..() + for(var/i in 1 to storage_slots) + new /obj/item/weapon/light/tube(src) + +//Mixed replacement lights +/obj/item/weapon/storage/box/lights/mixed + name = "box of replacement lights" + icon_state = "lightmixed_box" + +/obj/item/weapon/storage/box/lights/mixed/atom_init() + . = ..() + for(var/i in 1 to 14) + new /obj/item/weapon/light/tube(src) + for(var/i in 1 to 7) + new /obj/item/weapon/light/bulb(src) + +//Body bags +/obj/item/weapon/storage/box/bodybags + name = "body bags" + desc = "This box contains body bags." + icon_state = "bodybags_box" + +/obj/item/weapon/storage/box/bodybags/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/bodybag(src) + +//Holobadge +/obj/item/weapon/storage/box/holobadge + name = "holobadge box" + desc = "A box claiming to contain holobadges." + icon_state = "holobadge_box" + +/obj/item/weapon/storage/box/holobadge/atom_init() + . = ..() + for(var/i in 1 to 4) + new /obj/item/clothing/accessory/holobadge(src) + for(var/i in 1 to 3) + new /obj/item/clothing/accessory/holobadge/cord(src) + +//Evidence bag +/obj/item/weapon/storage/box/evidence + name = "evidence bag box" + desc = "A box claiming to contain evidence bags." + icon_state = "evidence_box" + +/obj/item/weapon/storage/box/evidence/atom_init() + . = ..() + for(var/i in 1 to 6) + new /obj/item/weapon/evidencebag(src) + +//Solution tray +/obj/item/weapon/storage/box/solution_trays + name = "solution tray box" + icon_state = "solution_trays_box" + +/obj/item/weapon/storage/box/solution_trays/atom_init() + . = ..() + for(var/i in 1 to 7) + new /obj/item/weapon/reagent_containers/glass/solution_tray(src) + +//Spare PDAs +/obj/item/weapon/storage/box/PDAs + name = "box of spare PDAs" + desc = "A box of spare PDA microcomputers." + icon_state = "pda_box" + +/obj/item/weapon/storage/box/PDAs/atom_init() + . = ..() + var/newcart = pick( /obj/item/weapon/cartridge/engineering, + /obj/item/weapon/cartridge/security, + /obj/item/weapon/cartridge/medical, + /obj/item/weapon/cartridge/signal/science, + /obj/item/weapon/cartridge/quartermaster) + new newcart(src) + new /obj/item/weapon/cartridge/head(src) + for(var/i in 1 to 4) + new /obj/item/device/pda(src) + +//Shotgun ammo + +/obj/item/weapon/storage/box/shotgun + name = "box of shotgun shell" + icon_state = "shotgun_ammo_slug" + foldable = /obj/item/stack/sheet/cardboard + can_hold = list("/obj/item/ammo_casing/shotgun") + +/obj/item/weapon/storage/box/shotgun/slug + name = "box of shotgun shell (slug)" + icon_state = "shotgun_ammo_slug" + +/obj/item/weapon/storage/box/shotgun/slug/atom_init() + . = ..() + for(var/i in 1 to 16) + new /obj/item/ammo_casing/shotgun(src) + make_exact_fit() + + +/obj/item/weapon/storage/box/shotgun/buckshot + name = "box of shotgun shell (buckshot)" + icon_state = "shotgun_ammo_buckshot" + +/obj/item/weapon/storage/box/shotgun/buckshot/atom_init() + . = ..() + for(var/i in 1 to 16) + new /obj/item/ammo_casing/shotgun/buckshot(src) + make_exact_fit() + + +/obj/item/weapon/storage/box/shotgun/beanbag + name = "box of shotgun shell (beanbag)" + icon_state = "shotgun_ammo_beanbag" + +/obj/item/weapon/storage/box/shotgun/beanbag/atom_init() + . = ..() + for(var/i in 1 to 16) + new /obj/item/ammo_casing/shotgun/beanbag(src) + make_exact_fit() + +//Hair sprays +/obj/item/weapon/storage/box/hairdyes + name = "hair spray dye box" + desc = "A box full of hair spray dyes." + +/obj/item/weapon/storage/box/hairdyes/atom_init() + . = ..() + new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/white(src) + new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/red(src) + new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/green(src) + new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/blue(src) + new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/black(src) + new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/brown(src) + new /obj/item/weapon/reagent_containers/glass/bottle/hair_dye/blond(src) + +/obj/item/weapon/storage/box/lipstick + name = "lipstick box" + desc = "A box full of lipstick." + +/obj/item/weapon/storage/box/lipstick/atom_init() + . = ..() + new /obj/item/weapon/lipstick(src) + new /obj/item/weapon/lipstick/purple(src) + new /obj/item/weapon/lipstick/jade(src) + new /obj/item/weapon/lipstick/black(src) + new /obj/item/weapon/paper(src) + +// Don't know where is original box itself, so just put it here. +/obj/item/weapon/storage/box/contraband + name = "box" + desc = "Strange box." + icon_state = "doom_box" + +/obj/item/weapon/storage/box/contraband/atom_init() + . = ..() + if(prob(30)) + new /obj/item/weapon/storage/box/matches(src) + new /obj/item/clothing/mask/cigarette/cigar/cohiba(src) + else if(prob(10)) + new /obj/item/device/guitar(src) + new /obj/item/clothing/head/sombrero(src) + new /obj/item/weapon/reagent_containers/food/drinks/bottle/tequilla(src) + else + new /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka(src) + new /obj/item/weapon/storage/fancy/cigarettes(src) + new /obj/item/weapon/lighter/random(src) + +/obj/item/weapon/storage/box/ians_box + name = "Ian's box" + desc = "It's a box with a corgi on it. YAP! Looks like somebody lost it." + icon_state = "corgi_box" + +/obj/item/weapon/storage/box/ians_box/atom_init() + . = ..() + new /obj/item/weapon/bikehorn/dogtoy(src) + new /obj/item/weapon/reagent_containers/food/snacks/cookie(src) + new /obj/item/weapon/reagent_containers/food/snacks/cookie(src) + new /obj/item/weapon/reagent_containers/food/snacks/cookie(src) + new /obj/item/weapon/reagent_containers/food/snacks/cookie(src) + new /obj/item/toy/plushie/girly_corgi(src) + +//NOT USED ANYWHERE +/obj/item/weapon/storage/box/syndielogo_box + name = "syndie box" + desc = "It's a red box with an 'S' on it. Strange." + icon_state = "syndie_box" + +/obj/item/weapon/storage/box/nanotrasenlogo_box + name = "NT box" + desc = "It's a blue box with an 'N' on it. Glory to NanoTrasen!" + icon_state = "nanotrasen_box" diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm index 12dff4608bdd..511eb687634d 100644 --- a/code/game/objects/items/weapons/storage/briefcase.dm +++ b/code/game/objects/items/weapons/storage/briefcase.dm @@ -1,50 +1,50 @@ -/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" - item_state = "briefcase" - flags = CONDUCT - force = 8.0 - throw_speed = 1 - throw_range = 4 - w_class = ITEM_SIZE_LARGE - max_w_class = ITEM_SIZE_NORMAL - max_storage_space = DEFAULT_BACKPACK_STORAGE - -/obj/item/weapon/storage/briefcase/attack(mob/living/M, mob/living/user) - //..() - - if ((CLUMSY in user.mutations) && prob(50)) - to_chat(user, "\red The [src] slips out of your hand and hits your head.") - user.take_bodypart_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 (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, "\red 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 != DEAD) M.stat = UNCONSCIOUS - for(var/mob/O in viewers(M, null)) - O.show_message(text("\red [] has been knocked unconscious!", M), 1, "\red You hear someone fall.", 2) - else - to_chat(M, text("\red [] tried to knock you unconcious!",user)) - M.eye_blurry += 3 - - return - -/obj/item/weapon/storage/briefcase/centcomm - icon_state = "briefcase-centcomm" - item_state = "briefcase-centcomm" +/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" + item_state = "briefcase" + flags = CONDUCT + force = 8.0 + throw_speed = 1 + throw_range = 4 + w_class = ITEM_SIZE_LARGE + max_w_class = ITEM_SIZE_NORMAL + max_storage_space = DEFAULT_BACKPACK_STORAGE + +/obj/item/weapon/storage/briefcase/attack(mob/living/M, mob/living/user) + //..() + + if ((CLUMSY in user.mutations) && prob(50)) + to_chat(user, "\red The [src] slips out of your hand and hits your head.") + user.take_bodypart_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 (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, "\red 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 != DEAD) M.stat = UNCONSCIOUS + for(var/mob/O in viewers(M, null)) + O.show_message(text("\red [] has been knocked unconscious!", M), 1, "\red You hear someone fall.", 2) + else + to_chat(M, text("\red [] tried to knock you unconcious!",user)) + M.eye_blurry += 3 + + return + +/obj/item/weapon/storage/briefcase/centcomm + icon_state = "briefcase-centcomm" + item_state = "briefcase-centcomm" diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 63614f08411c..767e9a37d3a1 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -1,390 +1,390 @@ -/* - * 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 - * Glowsticks Box - * Cigarette Box - */ - -/obj/item/weapon/storage/fancy/ - icon = 'icons/obj/food.dmi' - icon_state = "donutbox6" - name = "donut box" - var/icon_type = "donut" - -/obj/item/weapon/storage/fancy/update_icon(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(src in view(1, user)) - if(contents.len <= 0) - to_chat(user, "There are no [src.icon_type]s left in the box.") - else if(contents.len == 1) - to_chat(user, "There is one [src.icon_type] left in the box.") - else - to_chat(user, "There are [src.contents.len] [src.icon_type]s 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/storage/fancy/donut_box/atom_init() - . = ..() - for (var/i in 1 to storage_slots) - new /obj/item/weapon/reagent_containers/food/snacks/donut/normal(src) - -/* - * 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") - -/obj/item/weapon/storage/fancy/egg_box/atom_init() - . = ..() - for (var/i in 1 to storage_slots) - new /obj/item/weapon/reagent_containers/food/snacks/egg(src) - -/* - * Candle Box - */ - -/obj/item/weapon/storage/fancy/candle_box - name = "white candle pack" - desc = "A pack of white candles." - icon = 'icons/obj/candle.dmi' - icon_state = "candlebox" - icon_type = "candle" - item_state = "candlebox" - storage_slots = 5 - throwforce = 2 - slot_flags = SLOT_BELT - var/candle_type = "white" - -/obj/item/weapon/storage/fancy/candle_box/atom_init() - . = ..() - if(candle_type == "white") - for (var/i in 1 to storage_slots) - new /obj/item/candle(src) - if(candle_type == "red") - for (var/i in 1 to storage_slots) - new /obj/item/candle/red(src) - update_icon() - -/obj/item/weapon/storage/fancy/candle_box/update_icon() - var/list/candle_overlays = list() - var/candle_position = 0 - for(var/obj/item/candle/C in contents) - candle_position ++ - var/candle_color = "red_" - if(C.name == "white candle") - candle_color = "white_" - if(C.name == "black candle") - candle_color = "black_" - candle_overlays += image('icons/obj/candle.dmi', "[candle_color][candle_position]") - overlays = candle_overlays - return - -/obj/item/weapon/storage/fancy/candle_box/red - name = "red candle pack" - desc = "A pack of red candles." - candle_type = "red" - -/obj/item/weapon/storage/fancy/black_candle_box - name = "black candle pack" - desc = "A pack of black candles." - icon = 'icons/obj/candle.dmi' - icon_state = "black_candlebox5" - icon_type = "black_candle" - item_state = "black_candlebox5" - storage_slots = 5 - throwforce = 2 - slot_flags = SLOT_BELT - var/cooldown = 0 - var/teleporter_delay = 0 - -/obj/item/weapon/storage/fancy/black_candle_box/atom_init() - . = ..() - for (var/i in 1 to storage_slots) - new /obj/item/candle/ghost(src) - START_PROCESSING(SSobj, src) - -/obj/item/weapon/storage/fancy/black_candle_box/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/weapon/storage/fancy/black_candle_box/process() - if(cooldown > 0) - cooldown-- - else - cooldown = 300 - - if(contents.len >= storage_slots) - return - - for(var/mob/living/M in viewers(7, loc)) - return - - for(var/obj/item/candle/ghost/CG in range(1, get_turf(src))) - loc.visible_message("[src] is nomming on [CG]... This looks oddly creepy.") - CG.forceMove(src) - update_icon() - break - - teleporter_delay-- - if(teleporter_delay <= 0) - for(var/obj/item/candle/ghost/target in ghost_candles) - if(istype(target.loc, /turf)) - loc.visible_message("You hear a loud pop, as [src] poofs out of existence.") - playsound(loc, 'sound/effects/bubble_pop.ogg', 50, 1) - forceMove(get_turf(target)) - visible_message("You hear a loud pop, as [src] poofs into existence.") - playsound(loc, 'sound/effects/bubble_pop.ogg', 50, 1) - for(var/mob/living/A in viewers(3, loc)) - A.confused += 10 - A.make_jittery(150) - break - teleporter_delay += rand(5,10) // teleporter_delay-- is ran only once half a minute. This seems reasonable. - -/obj/item/weapon/storage/fancy/black_candle_box/attackby(obj/item/W, mob/user) - ..() - if(istype(W, /obj/item/device/occult_scanner)) - var/obj/item/device/occult_scanner/OS = W - OS.scanned_type = src.type - to_chat(user, "[src] has been succesfully scanned by [OS]") -/* - * 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" - w_class = 2.0 - storage_slots = 6 - icon_type = "crayon" - can_hold = list( - "/obj/item/toy/crayon" - ) - -/obj/item/weapon/storage/fancy/crayons/atom_init() - . = ..() - 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/toy/crayon/W, mob/user) - if(istype(W)) - switch(W.colourName) - if("mime") - to_chat(user, "This crayon is too sad to be contained in this box.") - return - if("rainbow") - to_chat(user, "This crayon is too powerful to be contained in this box.") - return - ..() - -/* - * Glowsticks Box - */ - -/obj/item/weapon/storage/fancy/glowsticks - name = "box of glowsticks" - desc = "A box of glowsticks (Do not eat)." - icon = 'icons/obj/glowsticks.dmi' - icon_state = "sticksbox" - w_class = 2.0 - storage_slots = 5 - icon_type = "glowstick" - can_hold = list( - "/obj/item/weapon/reagent_containers/food/snacks/glowstick" - ) - -/obj/item/weapon/storage/fancy/glowsticks/atom_init() - . = ..() - add_stick() - update_icon() - -/obj/item/weapon/storage/fancy/glowsticks/proc/add_stick() - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/green(src) - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/red(src) - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/blue(src) - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/yellow(src) - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/orange(src) - -/obj/item/weapon/storage/fancy/glowsticks/update_icon() - overlays = list() //resets list - overlays += image('icons/obj/glowsticks.dmi',"sticksbox") - for(var/obj/item/weapon/reagent_containers/food/snacks/glowstick/glowstick in contents) - overlays += image('icons/obj/glowsticks.dmi',glowstick.colourName) - -/obj/item/weapon/storage/fancy/glowsticks/adv - name = "box of advanced glowsticks" - -/obj/item/weapon/storage/fancy/glowsticks/adv/add_stick() - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/green(src) - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/red(src) - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/blue(src) - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/yellow(src) - new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/orange(src) - -//////////// -//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 - slot_flags = SLOT_BELT - storage_slots = 6 - can_hold = list("/obj/item/clothing/mask/cigarette","/obj/item/weapon/lighter") - icon_type = "cigarette" - -/obj/item/weapon/storage/fancy/cigarettes/atom_init() - . = ..() - 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/update_icon() - icon_state = "[initial(icon_state)][contents.len]" - return - -/obj/item/weapon/storage/fancy/cigarettes/remove_from_storage(obj/item/W, atom/new_location) - if(istype(W, /obj/item/clothing/mask/cigarette)) - if(reagents) - reagents.trans_to(W, (reagents.total_volume/contents.len)) - ..() - -/obj/item/weapon/storage/fancy/cigarettes/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) - if(!istype(M)) - return - - if(M == user && def_zone == O_MOUTH && contents.len > 0 && !user.wear_mask) - var/has_cigarette = 0 - for(var/obj/item/I in contents) - if(istype(I, /obj/item/clothing/mask/cigarette)) - var/obj/item/clothing/mask/cigarette/C = I - has_cigarette = 1 - contents.Remove(C) - user.equip_to_slot_if_possible(C, slot_wear_mask) - to_chat(user, "You take a cigarette out of the pack.") - update_icon() - break - if(!has_cigarette) - to_chat(user, "You tried to get any cigarette, but they ran out.") - 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" - -/obj/item/weapon/storage/fancy/cigarettes/cigpack_syndicate - name = "unknown" - desc = "An obscure brand of cigarettes." - icon_state = "syndie" - -/obj/item/weapon/storage/fancy/cigarettes/cigpack_syndicate/atom_init() - . = ..() - for (var/i in 1 to storage_slots) - reagents.add_reagent("tricordrazine",15) - name = "cigarette packet" - -/obj/item/weapon/storage/fancy/cigarettes/menthol - name = "Uplit Cigs" - desc = "A packet of six menthol cigarettes." - icon_state = "ucig" - -/* - * 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") - - -/obj/item/weapon/storage/fancy/vials/atom_init() - . = ..() - for (var/i in 1 to storage_slots) - new /obj/item/weapon/reagent_containers/glass/beaker/vial(src) - -/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") - storage_slots = 6 - req_access = list(access_virology) - -/obj/item/weapon/storage/lockbox/vials/atom_init() - . = ..() - update_icon() - -/obj/item/weapon/storage/lockbox/vials/update_icon(itemremoved = 0) - var/total_contents = src.contents.len - itemremoved - src.icon_state = "vialbox[total_contents]" - src.overlays.Cut() - 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, mob/user) - ..() - update_icon() +/* + * 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 + * Glowsticks Box + * Cigarette Box + */ + +/obj/item/weapon/storage/fancy/ + icon = 'icons/obj/food.dmi' + icon_state = "donutbox6" + name = "donut box" + var/icon_type = "donut" + +/obj/item/weapon/storage/fancy/update_icon(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(src in view(1, user)) + if(contents.len <= 0) + to_chat(user, "There are no [src.icon_type]s left in the box.") + else if(contents.len == 1) + to_chat(user, "There is one [src.icon_type] left in the box.") + else + to_chat(user, "There are [src.contents.len] [src.icon_type]s 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/storage/fancy/donut_box/atom_init() + . = ..() + for (var/i in 1 to storage_slots) + new /obj/item/weapon/reagent_containers/food/snacks/donut/normal(src) + +/* + * 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") + +/obj/item/weapon/storage/fancy/egg_box/atom_init() + . = ..() + for (var/i in 1 to storage_slots) + new /obj/item/weapon/reagent_containers/food/snacks/egg(src) + +/* + * Candle Box + */ + +/obj/item/weapon/storage/fancy/candle_box + name = "white candle pack" + desc = "A pack of white candles." + icon = 'icons/obj/candle.dmi' + icon_state = "candlebox" + icon_type = "candle" + item_state = "candlebox" + storage_slots = 5 + throwforce = 2 + slot_flags = SLOT_BELT + var/candle_type = "white" + +/obj/item/weapon/storage/fancy/candle_box/atom_init() + . = ..() + if(candle_type == "white") + for (var/i in 1 to storage_slots) + new /obj/item/candle(src) + if(candle_type == "red") + for (var/i in 1 to storage_slots) + new /obj/item/candle/red(src) + update_icon() + +/obj/item/weapon/storage/fancy/candle_box/update_icon() + var/list/candle_overlays = list() + var/candle_position = 0 + for(var/obj/item/candle/C in contents) + candle_position ++ + var/candle_color = "red_" + if(C.name == "white candle") + candle_color = "white_" + if(C.name == "black candle") + candle_color = "black_" + candle_overlays += image('icons/obj/candle.dmi', "[candle_color][candle_position]") + overlays = candle_overlays + return + +/obj/item/weapon/storage/fancy/candle_box/red + name = "red candle pack" + desc = "A pack of red candles." + candle_type = "red" + +/obj/item/weapon/storage/fancy/black_candle_box + name = "black candle pack" + desc = "A pack of black candles." + icon = 'icons/obj/candle.dmi' + icon_state = "black_candlebox5" + icon_type = "black_candle" + item_state = "black_candlebox5" + storage_slots = 5 + throwforce = 2 + slot_flags = SLOT_BELT + var/cooldown = 0 + var/teleporter_delay = 0 + +/obj/item/weapon/storage/fancy/black_candle_box/atom_init() + . = ..() + for (var/i in 1 to storage_slots) + new /obj/item/candle/ghost(src) + START_PROCESSING(SSobj, src) + +/obj/item/weapon/storage/fancy/black_candle_box/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/weapon/storage/fancy/black_candle_box/process() + if(cooldown > 0) + cooldown-- + else + cooldown = 300 + + if(contents.len >= storage_slots) + return + + for(var/mob/living/M in viewers(7, loc)) + return + + for(var/obj/item/candle/ghost/CG in range(1, get_turf(src))) + loc.visible_message("[src] is nomming on [CG]... This looks oddly creepy.") + CG.forceMove(src) + update_icon() + break + + teleporter_delay-- + if(teleporter_delay <= 0) + for(var/obj/item/candle/ghost/target in ghost_candles) + if(istype(target.loc, /turf)) + loc.visible_message("You hear a loud pop, as [src] poofs out of existence.") + playsound(loc, 'sound/effects/bubble_pop.ogg', 50, 1) + forceMove(get_turf(target)) + visible_message("You hear a loud pop, as [src] poofs into existence.") + playsound(loc, 'sound/effects/bubble_pop.ogg', 50, 1) + for(var/mob/living/A in viewers(3, loc)) + A.confused += 10 + A.make_jittery(150) + break + teleporter_delay += rand(5,10) // teleporter_delay-- is ran only once half a minute. This seems reasonable. + +/obj/item/weapon/storage/fancy/black_candle_box/attackby(obj/item/W, mob/user) + ..() + if(istype(W, /obj/item/device/occult_scanner)) + var/obj/item/device/occult_scanner/OS = W + OS.scanned_type = src.type + to_chat(user, "[src] has been succesfully scanned by [OS]") +/* + * 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" + w_class = 2.0 + storage_slots = 6 + icon_type = "crayon" + can_hold = list( + "/obj/item/toy/crayon" + ) + +/obj/item/weapon/storage/fancy/crayons/atom_init() + . = ..() + 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/toy/crayon/W, mob/user) + if(istype(W)) + switch(W.colourName) + if("mime") + to_chat(user, "This crayon is too sad to be contained in this box.") + return + if("rainbow") + to_chat(user, "This crayon is too powerful to be contained in this box.") + return + ..() + +/* + * Glowsticks Box + */ + +/obj/item/weapon/storage/fancy/glowsticks + name = "box of glowsticks" + desc = "A box of glowsticks (Do not eat)." + icon = 'icons/obj/glowsticks.dmi' + icon_state = "sticksbox" + w_class = 2.0 + storage_slots = 5 + icon_type = "glowstick" + can_hold = list( + "/obj/item/weapon/reagent_containers/food/snacks/glowstick" + ) + +/obj/item/weapon/storage/fancy/glowsticks/atom_init() + . = ..() + add_stick() + update_icon() + +/obj/item/weapon/storage/fancy/glowsticks/proc/add_stick() + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/green(src) + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/red(src) + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/blue(src) + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/yellow(src) + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/orange(src) + +/obj/item/weapon/storage/fancy/glowsticks/update_icon() + overlays = list() //resets list + overlays += image('icons/obj/glowsticks.dmi',"sticksbox") + for(var/obj/item/weapon/reagent_containers/food/snacks/glowstick/glowstick in contents) + overlays += image('icons/obj/glowsticks.dmi',glowstick.colourName) + +/obj/item/weapon/storage/fancy/glowsticks/adv + name = "box of advanced glowsticks" + +/obj/item/weapon/storage/fancy/glowsticks/adv/add_stick() + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/green(src) + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/red(src) + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/blue(src) + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/yellow(src) + new /obj/item/weapon/reagent_containers/food/snacks/glowstick/power/orange(src) + +//////////// +//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 + slot_flags = SLOT_BELT + storage_slots = 6 + can_hold = list("/obj/item/clothing/mask/cigarette","/obj/item/weapon/lighter") + icon_type = "cigarette" + +/obj/item/weapon/storage/fancy/cigarettes/atom_init() + . = ..() + 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/update_icon() + icon_state = "[initial(icon_state)][contents.len]" + return + +/obj/item/weapon/storage/fancy/cigarettes/remove_from_storage(obj/item/W, atom/new_location) + if(istype(W, /obj/item/clothing/mask/cigarette)) + if(reagents) + reagents.trans_to(W, (reagents.total_volume/contents.len)) + ..() + +/obj/item/weapon/storage/fancy/cigarettes/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) + if(!istype(M)) + return + + if(M == user && def_zone == O_MOUTH && contents.len > 0 && !user.wear_mask) + var/has_cigarette = 0 + for(var/obj/item/I in contents) + if(istype(I, /obj/item/clothing/mask/cigarette)) + var/obj/item/clothing/mask/cigarette/C = I + has_cigarette = 1 + contents.Remove(C) + user.equip_to_slot_if_possible(C, slot_wear_mask) + to_chat(user, "You take a cigarette out of the pack.") + update_icon() + break + if(!has_cigarette) + to_chat(user, "You tried to get any cigarette, but they ran out.") + 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" + +/obj/item/weapon/storage/fancy/cigarettes/cigpack_syndicate + name = "unknown" + desc = "An obscure brand of cigarettes." + icon_state = "syndie" + +/obj/item/weapon/storage/fancy/cigarettes/cigpack_syndicate/atom_init() + . = ..() + for (var/i in 1 to storage_slots) + reagents.add_reagent("tricordrazine",15) + name = "cigarette packet" + +/obj/item/weapon/storage/fancy/cigarettes/menthol + name = "Uplit Cigs" + desc = "A packet of six menthol cigarettes." + icon_state = "ucig" + +/* + * 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") + + +/obj/item/weapon/storage/fancy/vials/atom_init() + . = ..() + for (var/i in 1 to storage_slots) + new /obj/item/weapon/reagent_containers/glass/beaker/vial(src) + +/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") + storage_slots = 6 + req_access = list(access_virology) + +/obj/item/weapon/storage/lockbox/vials/atom_init() + . = ..() + update_icon() + +/obj/item/weapon/storage/lockbox/vials/update_icon(itemremoved = 0) + var/total_contents = src.contents.len - itemremoved + src.icon_state = "vialbox[total_contents]" + src.overlays.Cut() + 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, mob/user) + ..() + update_icon() diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index d4fa65e83891..e6c0c22f70ae 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -1,257 +1,257 @@ -/* First aid storage - * Contains: - * First Aid Kits - * Pill Bottles - */ - -/* - * 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 - max_storage_space = DEFAULT_BOX_STORAGE - 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" - -/obj/item/weapon/storage/firstaid/fire/atom_init() - . = ..() - if (empty) - return - - icon_state = pick("ointment","firefirstaid") - - new /obj/item/device/healthanalyzer(src) - new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src) - for (var/i in 1 to 2) - new /obj/item/stack/medical/ointment(src) - for (var/i in 1 to 3) - new /obj/item/weapon/reagent_containers/pill/kelotane(src)// Replaced ointment with these since they actually work --Errorage - -/obj/item/weapon/storage/firstaid/regular - icon_state = "firstaid" - -/obj/item/weapon/storage/firstaid/regular/atom_init() - . = ..() - if (empty) - return - for (var/i in 1 to 3) - new /obj/item/stack/medical/bruise_pack(src) - for (var/i in 1 to 2) - new /obj/item/stack/medical/ointment(src) - new /obj/item/device/healthanalyzer(src) - new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) - -/obj/item/weapon/storage/firstaid/toxin - name = "toxin first aid" - desc = "Used to treat when you have a high amoutn of toxins in your body." - icon_state = "antitoxin" - item_state = "firstaid-toxin" - -/obj/item/weapon/storage/firstaid/toxin/atom_init() - . = ..() - if (empty) - return - - icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3") - - for (var/i in 1 to 3) - new /obj/item/weapon/reagent_containers/syringe/antitoxin( src ) - for (var/i in 1 to 3) - new /obj/item/weapon/reagent_containers/pill/dylovene( src ) - new /obj/item/device/healthanalyzer( src ) - -/obj/item/weapon/storage/firstaid/o2 - name = "oxygen deprivation first aid" - desc = "A box full of oxygen goodies." - icon_state = "o2" - item_state = "firstaid-o2" - -/obj/item/weapon/storage/firstaid/o2/atom_init() - . = ..() - if (empty) - return - for (var/i in 1 to 4) - 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) - -/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/atom_init() - . = ..() - if (empty) - return - new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) - for (var/i in 1 to 3) - new /obj/item/stack/medical/advanced/bruise_pack(src) - for (var/i in 1 to 2) - new /obj/item/stack/medical/advanced/ointment(src) - new /obj/item/stack/medical/splint(src) - -/* - * 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" - flags = NOBLUDGEON - w_class = ITEM_SIZE_SMALL - max_storage_space = 21 - 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 - use_sound = 'sound/effects/pillbottle.ogg' - var/wrapper_color - var/label - -/obj/item/weapon/storage/pill_bottle/afterattack(mob/living/target, mob/living/user, proximity_flag) - if(!proximity_flag || !istype(target) || target != user) - return 1 - if(!contents.len) - to_chat(user, "It's empty!") - return 1 - var/zone = user.zone_sel.selecting - if(zone == O_MOUTH && CanEat(user, target, src, "eat")) - user.visible_message("[user] pops a pill from \the [src].") - playsound(get_turf(src), 'sound/effects/peelz.ogg', 50) - var/list/peelz = filter_list(contents,/obj/item/weapon/reagent_containers/pill/) - if(peelz.len) - var/obj/item/weapon/reagent_containers/pill/P = pick(peelz) - remove_from_storage(P) - P.attack(target,user) - return 1 - -/obj/item/weapon/storage/pill_bottle/atom_init() - . = ..() - update_icon() - -/obj/item/weapon/storage/pill_bottle/update_icon() - overlays.Cut() - if(wrapper_color) - var/image/I = image(icon, "pillbottle_wrap") - I.color = wrapper_color - overlays += I - -/obj/item/weapon/storage/pill_bottle/bicaridine - name = "pill bottle (Bicaridine)" - desc = "Contains pills used to stabilize the severely injured." - - startswith = list(/obj/item/weapon/reagent_containers/pill/bicaridine = 12) - wrapper_color = COLOR_MAROON - -/obj/item/weapon/storage/pill_bottle/dexalin_plus - name = "pill bottle (Dexalin Plus)" - desc = "Contains pills used to treat extreme cases of oxygen deprivation." - - startswith = list(/obj/item/weapon/reagent_containers/pill/dexalin_plus = 12) - wrapper_color = COLOR_CYAN_BLUE - -/obj/item/weapon/storage/pill_bottle/dexalin - name = "pill bottle (Dexalin)" - desc = "Contains pills used to treat oxygen deprivation." - - startswith = list(/obj/item/weapon/reagent_containers/pill/dexalin = 12) - wrapper_color = COLOR_LIGHT_CYAN - -/obj/item/weapon/storage/pill_bottle/dermaline - name = "pill bottle (Dermaline)" - desc = "Contains pills used to treat burn wounds." - - startswith = list(/obj/item/weapon/reagent_containers/pill/dermaline = 8) - wrapper_color = "#e8d131" - -/obj/item/weapon/storage/pill_bottle/dylovene - name = "pill bottle (Dylovene)" - desc = "Contains pills used to treat toxic substances in the blood." - - startswith = list(/obj/item/weapon/reagent_containers/pill/dylovene = 12) - wrapper_color = COLOR_GREEN - -/obj/item/weapon/storage/pill_bottle/inaprovaline - name = "pill bottle (Inaprovaline)" - desc = "Contains pills used to stabilize patients." - - startswith = list(/obj/item/weapon/reagent_containers/pill/inaprovaline = 12) - wrapper_color = COLOR_PALE_BLUE_GRAY - -/obj/item/weapon/storage/pill_bottle/kelotane - name = "pill bottle (Kelotane)" - desc = "Contains pills used to treat burns." - - startswith = list(/obj/item/weapon/reagent_containers/pill/kelotane = 12) - wrapper_color = COLOR_SUN - -/obj/item/weapon/storage/pill_bottle/spaceacillin - name = "pill bottle (Spaceacillin)" - desc = "A theta-lactam antibiotic. Effective against many diseases likely to be encountered in space." - - startswith = list(/obj/item/weapon/reagent_containers/pill/spaceacillin = 7) - wrapper_color = COLOR_PALE_GREEN_GRAY - -/obj/item/weapon/storage/pill_bottle/tramadol - name = "pill bottle (Tramadol)" - desc = "Contains pills used to relieve pain." - - startswith = list(/obj/item/weapon/reagent_containers/pill/tramadol = 7) - wrapper_color = COLOR_PURPLE_GRAY - -//Baycode specific Psychiatry pills. -/obj/item/weapon/storage/pill_bottle/citalopram - name = "pill bottle (Citalopram)" - desc = "Mild antidepressant. For use in individuals suffering from depression or anxiety. 15u dose per pill." - - startswith = list(/obj/item/weapon/reagent_containers/pill/citalopram = 12) - wrapper_color = COLOR_GRAY - -/obj/item/weapon/storage/pill_bottle/methylphenidate - name = "pill bottle (Methylphenidate)" - desc = "Mental stimulant. For use in individuals suffering from ADHD, or general concentration issues. 15u dose per pill." - - startswith = list(/obj/item/weapon/reagent_containers/pill/methylphenidate = 12) - wrapper_color = COLOR_GRAY - -/obj/item/weapon/storage/pill_bottle/paroxetine - name = "pill bottle (Paroxetine)" - desc = "High-strength antidepressant. Only for use in severe depression. 10u dose per pill. WARNING: side-effects may include hallucinations." - - startswith = list(/obj/item/weapon/reagent_containers/pill/paroxetine = 7) - wrapper_color = COLOR_GRAY - -/obj/item/weapon/storage/pill_bottle/paracetamol - name = "pill bottle (Paracetamol)" - desc = "Mild painkiller, also known as Tylenol. Won't fix the cause of your headache (unlike cyanide), but might make it bearable." - - startswith = list(/obj/item/weapon/reagent_containers/pill/paracetamol = 12) - wrapper_color = "#a2819e" - -/obj/item/weapon/storage/pill_bottle/assorted - name = "pill bottle (assorted)" - desc = "Commonly found on paramedics, these assorted pill bottles contain all the basics." - - startswith = list( - /obj/item/weapon/reagent_containers/pill/inaprovaline = 6, - /obj/item/weapon/reagent_containers/pill/dylovene = 6, - /obj/item/weapon/reagent_containers/pill/tramadol = 2, - /obj/item/weapon/reagent_containers/pill/dexalin = 2, - /obj/item/weapon/reagent_containers/pill/kelotane = 2, - /obj/item/weapon/reagent_containers/pill/hyronalin = 2 +/* First aid storage + * Contains: + * First Aid Kits + * Pill Bottles + */ + +/* + * 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 + max_storage_space = DEFAULT_BOX_STORAGE + 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" + +/obj/item/weapon/storage/firstaid/fire/atom_init() + . = ..() + if (empty) + return + + icon_state = pick("ointment","firefirstaid") + + new /obj/item/device/healthanalyzer(src) + new /obj/item/weapon/reagent_containers/hypospray/autoinjector(src) + for (var/i in 1 to 2) + new /obj/item/stack/medical/ointment(src) + for (var/i in 1 to 3) + new /obj/item/weapon/reagent_containers/pill/kelotane(src)// Replaced ointment with these since they actually work --Errorage + +/obj/item/weapon/storage/firstaid/regular + icon_state = "firstaid" + +/obj/item/weapon/storage/firstaid/regular/atom_init() + . = ..() + if (empty) + return + for (var/i in 1 to 3) + new /obj/item/stack/medical/bruise_pack(src) + for (var/i in 1 to 2) + new /obj/item/stack/medical/ointment(src) + new /obj/item/device/healthanalyzer(src) + new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) + +/obj/item/weapon/storage/firstaid/toxin + name = "toxin first aid" + desc = "Used to treat when you have a high amoutn of toxins in your body." + icon_state = "antitoxin" + item_state = "firstaid-toxin" + +/obj/item/weapon/storage/firstaid/toxin/atom_init() + . = ..() + if (empty) + return + + icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3") + + for (var/i in 1 to 3) + new /obj/item/weapon/reagent_containers/syringe/antitoxin( src ) + for (var/i in 1 to 3) + new /obj/item/weapon/reagent_containers/pill/dylovene( src ) + new /obj/item/device/healthanalyzer( src ) + +/obj/item/weapon/storage/firstaid/o2 + name = "oxygen deprivation first aid" + desc = "A box full of oxygen goodies." + icon_state = "o2" + item_state = "firstaid-o2" + +/obj/item/weapon/storage/firstaid/o2/atom_init() + . = ..() + if (empty) + return + for (var/i in 1 to 4) + 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) + +/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/atom_init() + . = ..() + if (empty) + return + new /obj/item/weapon/reagent_containers/hypospray/autoinjector( src ) + for (var/i in 1 to 3) + new /obj/item/stack/medical/advanced/bruise_pack(src) + for (var/i in 1 to 2) + new /obj/item/stack/medical/advanced/ointment(src) + new /obj/item/stack/medical/splint(src) + +/* + * 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" + flags = NOBLUDGEON + w_class = ITEM_SIZE_SMALL + max_storage_space = 21 + 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 + use_sound = 'sound/effects/pillbottle.ogg' + var/wrapper_color + var/label + +/obj/item/weapon/storage/pill_bottle/afterattack(mob/living/target, mob/living/user, proximity_flag) + if(!proximity_flag || !istype(target) || target != user) + return 1 + if(!contents.len) + to_chat(user, "It's empty!") + return 1 + var/zone = user.zone_sel.selecting + if(zone == O_MOUTH && CanEat(user, target, src, "eat")) + user.visible_message("[user] pops a pill from \the [src].") + playsound(get_turf(src), 'sound/effects/peelz.ogg', 50) + var/list/peelz = filter_list(contents,/obj/item/weapon/reagent_containers/pill/) + if(peelz.len) + var/obj/item/weapon/reagent_containers/pill/P = pick(peelz) + remove_from_storage(P) + P.attack(target,user) + return 1 + +/obj/item/weapon/storage/pill_bottle/atom_init() + . = ..() + update_icon() + +/obj/item/weapon/storage/pill_bottle/update_icon() + overlays.Cut() + if(wrapper_color) + var/image/I = image(icon, "pillbottle_wrap") + I.color = wrapper_color + overlays += I + +/obj/item/weapon/storage/pill_bottle/bicaridine + name = "pill bottle (Bicaridine)" + desc = "Contains pills used to stabilize the severely injured." + + startswith = list(/obj/item/weapon/reagent_containers/pill/bicaridine = 12) + wrapper_color = COLOR_MAROON + +/obj/item/weapon/storage/pill_bottle/dexalin_plus + name = "pill bottle (Dexalin Plus)" + desc = "Contains pills used to treat extreme cases of oxygen deprivation." + + startswith = list(/obj/item/weapon/reagent_containers/pill/dexalin_plus = 12) + wrapper_color = COLOR_CYAN_BLUE + +/obj/item/weapon/storage/pill_bottle/dexalin + name = "pill bottle (Dexalin)" + desc = "Contains pills used to treat oxygen deprivation." + + startswith = list(/obj/item/weapon/reagent_containers/pill/dexalin = 12) + wrapper_color = COLOR_LIGHT_CYAN + +/obj/item/weapon/storage/pill_bottle/dermaline + name = "pill bottle (Dermaline)" + desc = "Contains pills used to treat burn wounds." + + startswith = list(/obj/item/weapon/reagent_containers/pill/dermaline = 8) + wrapper_color = "#e8d131" + +/obj/item/weapon/storage/pill_bottle/dylovene + name = "pill bottle (Dylovene)" + desc = "Contains pills used to treat toxic substances in the blood." + + startswith = list(/obj/item/weapon/reagent_containers/pill/dylovene = 12) + wrapper_color = COLOR_GREEN + +/obj/item/weapon/storage/pill_bottle/inaprovaline + name = "pill bottle (Inaprovaline)" + desc = "Contains pills used to stabilize patients." + + startswith = list(/obj/item/weapon/reagent_containers/pill/inaprovaline = 12) + wrapper_color = COLOR_PALE_BLUE_GRAY + +/obj/item/weapon/storage/pill_bottle/kelotane + name = "pill bottle (Kelotane)" + desc = "Contains pills used to treat burns." + + startswith = list(/obj/item/weapon/reagent_containers/pill/kelotane = 12) + wrapper_color = COLOR_SUN + +/obj/item/weapon/storage/pill_bottle/spaceacillin + name = "pill bottle (Spaceacillin)" + desc = "A theta-lactam antibiotic. Effective against many diseases likely to be encountered in space." + + startswith = list(/obj/item/weapon/reagent_containers/pill/spaceacillin = 7) + wrapper_color = COLOR_PALE_GREEN_GRAY + +/obj/item/weapon/storage/pill_bottle/tramadol + name = "pill bottle (Tramadol)" + desc = "Contains pills used to relieve pain." + + startswith = list(/obj/item/weapon/reagent_containers/pill/tramadol = 7) + wrapper_color = COLOR_PURPLE_GRAY + +//Baycode specific Psychiatry pills. +/obj/item/weapon/storage/pill_bottle/citalopram + name = "pill bottle (Citalopram)" + desc = "Mild antidepressant. For use in individuals suffering from depression or anxiety. 15u dose per pill." + + startswith = list(/obj/item/weapon/reagent_containers/pill/citalopram = 12) + wrapper_color = COLOR_GRAY + +/obj/item/weapon/storage/pill_bottle/methylphenidate + name = "pill bottle (Methylphenidate)" + desc = "Mental stimulant. For use in individuals suffering from ADHD, or general concentration issues. 15u dose per pill." + + startswith = list(/obj/item/weapon/reagent_containers/pill/methylphenidate = 12) + wrapper_color = COLOR_GRAY + +/obj/item/weapon/storage/pill_bottle/paroxetine + name = "pill bottle (Paroxetine)" + desc = "High-strength antidepressant. Only for use in severe depression. 10u dose per pill. WARNING: side-effects may include hallucinations." + + startswith = list(/obj/item/weapon/reagent_containers/pill/paroxetine = 7) + wrapper_color = COLOR_GRAY + +/obj/item/weapon/storage/pill_bottle/paracetamol + name = "pill bottle (Paracetamol)" + desc = "Mild painkiller, also known as Tylenol. Won't fix the cause of your headache (unlike cyanide), but might make it bearable." + + startswith = list(/obj/item/weapon/reagent_containers/pill/paracetamol = 12) + wrapper_color = "#a2819e" + +/obj/item/weapon/storage/pill_bottle/assorted + name = "pill bottle (assorted)" + desc = "Commonly found on paramedics, these assorted pill bottles contain all the basics." + + startswith = list( + /obj/item/weapon/reagent_containers/pill/inaprovaline = 6, + /obj/item/weapon/reagent_containers/pill/dylovene = 6, + /obj/item/weapon/reagent_containers/pill/tramadol = 2, + /obj/item/weapon/reagent_containers/pill/dexalin = 2, + /obj/item/weapon/reagent_containers/pill/kelotane = 2, + /obj/item/weapon/reagent_containers/pill/hyronalin = 2 ) \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm index ccc5d8f545aa..ef2d57d6f91d 100644 --- a/code/game/objects/items/weapons/storage/lockbox.dm +++ b/code/game/objects/items/weapons/storage/lockbox.dm @@ -1,96 +1,96 @@ -//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 = ITEM_SIZE_LARGE - max_w_class = ITEM_SIZE_NORMAL - max_storage_space = 10 //The sum of the w_classes of all the items in this storage item. - req_access = list(access_armory) - var/locked = TRUE - var/broken = FALSE - var/icon_locked = "lockbox+l" - var/icon_closed = "lockbox" - var/icon_broken = "lockbox+b" - - -/obj/item/weapon/storage/lockbox/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/card/id)) - if(broken) - to_chat(user, "It appears to be broken.") - return - if(allowed(user)) - locked = !( locked ) - if(locked) - icon_state = icon_locked - to_chat(user, "You lock the [src]!") - return - else - icon_state = icon_closed - to_chat(user, "You unlock the [src]!") - return - else - to_chat(user, "Access Denied") - else if((istype(W, /obj/item/weapon/card/emag) || istype(W, /obj/item/weapon/melee/energy/blade)) && !broken) - broken = TRUE - locked = FALSE - desc = "It appears to be broken." - icon_state = icon_broken - if(istype(W, /obj/item/weapon/melee/energy/blade)) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, loc) - spark_system.start() - playsound(loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(loc, "sparks", 50, 1) - for(var/mob/O in viewers(user, 3)) - O.show_message(text("The locker has been sliced open by [] with an energy blade!", user), 1, text("You hear metal being sliced and sparks flying."), 2) - else - 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, "Its locked!") - return - - -/obj/item/weapon/storage/lockbox/open(mob/user) - if(locked) - to_chat(user, "Its locked!") - else - ..() - return - - -/obj/item/weapon/storage/lockbox/mind_shields - name = "lockbox of Mind Shields implants" - req_access = list(access_brig) - -/obj/item/weapon/storage/lockbox/mind_shields/atom_init() - . = ..() - for (var/i in 1 to 3) - new /obj/item/weapon/implantcase/mindshield(src) - new /obj/item/weapon/implanter/mindshield(src) - -/obj/item/weapon/storage/lockbox/loyalty - name = "lockbox of Loyalty implants" - req_access = list(access_brig) - -/obj/item/weapon/storage/lockbox/loyalty/atom_init() - . = ..() - for (var/i in 1 to 3) - new /obj/item/weapon/implantcase/loyalty(src) - new /obj/item/weapon/implanter/loyalty(src) - - -/obj/item/weapon/storage/lockbox/clusterbang - name = "lockbox of clusterbangs" - desc = "You have a bad feeling about opening this." - req_access = list(access_security) - -/obj/item/weapon/storage/lockbox/clusterbang/atom_init() - . = ..() - new /obj/item/weapon/grenade/clusterbuster(src) +//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 = ITEM_SIZE_LARGE + max_w_class = ITEM_SIZE_NORMAL + max_storage_space = 10 //The sum of the w_classes of all the items in this storage item. + req_access = list(access_armory) + var/locked = TRUE + var/broken = FALSE + var/icon_locked = "lockbox+l" + var/icon_closed = "lockbox" + var/icon_broken = "lockbox+b" + + +/obj/item/weapon/storage/lockbox/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/card/id)) + if(broken) + to_chat(user, "It appears to be broken.") + return + if(allowed(user)) + locked = !( locked ) + if(locked) + icon_state = icon_locked + to_chat(user, "You lock the [src]!") + return + else + icon_state = icon_closed + to_chat(user, "You unlock the [src]!") + return + else + to_chat(user, "Access Denied") + else if((istype(W, /obj/item/weapon/card/emag) || istype(W, /obj/item/weapon/melee/energy/blade)) && !broken) + broken = TRUE + locked = FALSE + desc = "It appears to be broken." + icon_state = icon_broken + if(istype(W, /obj/item/weapon/melee/energy/blade)) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, loc) + spark_system.start() + playsound(loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(loc, "sparks", 50, 1) + for(var/mob/O in viewers(user, 3)) + O.show_message(text("The locker has been sliced open by [] with an energy blade!", user), 1, text("You hear metal being sliced and sparks flying."), 2) + else + 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, "Its locked!") + return + + +/obj/item/weapon/storage/lockbox/open(mob/user) + if(locked) + to_chat(user, "Its locked!") + else + ..() + return + + +/obj/item/weapon/storage/lockbox/mind_shields + name = "lockbox of Mind Shields implants" + req_access = list(access_brig) + +/obj/item/weapon/storage/lockbox/mind_shields/atom_init() + . = ..() + for (var/i in 1 to 3) + new /obj/item/weapon/implantcase/mindshield(src) + new /obj/item/weapon/implanter/mindshield(src) + +/obj/item/weapon/storage/lockbox/loyalty + name = "lockbox of Loyalty implants" + req_access = list(access_brig) + +/obj/item/weapon/storage/lockbox/loyalty/atom_init() + . = ..() + for (var/i in 1 to 3) + new /obj/item/weapon/implantcase/loyalty(src) + new /obj/item/weapon/implanter/loyalty(src) + + +/obj/item/weapon/storage/lockbox/clusterbang + name = "lockbox of clusterbangs" + desc = "You have a bad feeling about opening this." + req_access = list(access_security) + +/obj/item/weapon/storage/lockbox/clusterbang/atom_init() + . = ..() + new /obj/item/weapon/grenade/clusterbuster(src) diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm index a5598a032951..42db0927dd1b 100644 --- a/code/game/objects/items/weapons/storage/secure.dm +++ b/code/game/objects/items/weapons/storage/secure.dm @@ -1,236 +1,236 @@ -/* - * Absorbs /obj/item/weapon/secstorage. - * Reimplements it only slightly to use existing storage functionality. - * - * Contains: - * Secure Briefcase - * Wall Safe - * Syndie Briefcase - */ - -// ----------------------------- -// 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 = ITEM_SIZE_NORMAL - max_w_class = ITEM_SIZE_SMALL - max_storage_space = DEFAULT_BOX_STORAGE - - examine(mob/user) - ..() - if(src in oview(1, user)) - to_chat(user, "The service panel is [src.open ? "open" : "closed"].") - - attack_alien(mob/user) - return attack_hand(user) - - attack_paw(mob/user) - return attack_hand(user) - - attackby(obj/item/weapon/W, mob/user) - if(locked) - if ( (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)) && (!src.emagged)) - emagged = 1 - user.SetNextMove(CLICK_CD_MELEE) - src.overlays += image('icons/obj/storage.dmi', icon_sparking) - sleep(6) - overlays.Cut() - overlays += image('icons/obj/storage.dmi', icon_locking) - locked = 0 - if(istype(W, /obj/item/weapon/melee/energy/blade)) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(src.loc, "sparks", 50, 1) - to_chat(user, "You slice through the lock on [src].") - else - to_chat(user, "You short out the lock on [src].") - return - - if (istype(W, /obj/item/weapon/screwdriver)) - if (!user.is_busy(src) && do_after(user, 20, target = src)) - src.open =! src.open - user.show_message(text("\blue 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("\red Now attempting to reset internal memory, please hold."), 1) - src.l_hacking = 1 - if (!user.is_busy() && do_after(usr, 100, target = src)) - if (prob(40)) - src.l_setshort = 1 - src.l_set = 0 - user.show_message(text("\red 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("\red 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 - ..() - - - MouseDrop(over_object, src_location, over_location) - if (locked) - src.add_fingerprint(usr) - return - ..() - - - attack_self(mob/user) - 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(entity_ja(dat), "window=caselock;size=300x280") - - 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 = "secure-r" - desc = "A large briefcase with a digital locking system." - force = 8.0 - throw_speed = 1 - throw_range = 4 - w_class = ITEM_SIZE_LARGE - -/obj/item/weapon/storage/secure/briefcase/atom_init() - . = ..() - new /obj/item/weapon/paper(src) - new /obj/item/weapon/pen(src) - -/obj/item/weapon/storage/secure/briefcase/attack_hand(mob/user) - if ((src.loc == user) && (src.locked == 1)) - to_chat(usr, "\red [src] is locked and cannot be opened!") - else if ((src.loc == user) && (!src.locked)) - src.open(usr) - else - ..() - for(var/mob/M in range(1)) - if (M.s_active == src) - src.close(M) - src.add_fingerprint(user) - -/obj/item/weapon/storage/secure/briefcase/attackby(obj/item/weapon/W, mob/user) - ..() - update_icon() - -/obj/item/weapon/storage/secure/briefcase/Topic(href, href_list) - ..() - update_icon() - -/obj/item/weapon/storage/secure/briefcase/update_icon() - if(!locked || emagged) - item_state = "secure-g" - else - item_state = "secure-r" - - if(ismob(loc)) - var/mob/M = loc - M.update_inv_l_hand() - M.update_inv_r_hand() - -//Syndie variant of Secure Briefcase. Contains space cash, slightly more robust. -/obj/item/weapon/storage/secure/briefcase/syndie - force = 15.0 - -/obj/item/weapon/storage/secure/briefcase/syndie/atom_init() - for (var/i in 1 to 4) - new /obj/item/weapon/spacecash/c1000(src) - . = ..() - - -// ----------------------------- -// 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" - 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/atom_init() - . = ..() - new /obj/item/weapon/paper(src) - new /obj/item/weapon/pen(src) - -/obj/item/weapon/storage/secure/safe/attack_hand(mob/user) - return attack_self(user) - -//obj/item/weapon/storage/secure/safe/HoS/atom_init() -// . = ..() - //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) +/* + * Absorbs /obj/item/weapon/secstorage. + * Reimplements it only slightly to use existing storage functionality. + * + * Contains: + * Secure Briefcase + * Wall Safe + * Syndie Briefcase + */ + +// ----------------------------- +// 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 = ITEM_SIZE_NORMAL + max_w_class = ITEM_SIZE_SMALL + max_storage_space = DEFAULT_BOX_STORAGE + + examine(mob/user) + ..() + if(src in oview(1, user)) + to_chat(user, "The service panel is [src.open ? "open" : "closed"].") + + attack_alien(mob/user) + return attack_hand(user) + + attack_paw(mob/user) + return attack_hand(user) + + attackby(obj/item/weapon/W, mob/user) + if(locked) + if ( (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)) && (!src.emagged)) + emagged = 1 + user.SetNextMove(CLICK_CD_MELEE) + src.overlays += image('icons/obj/storage.dmi', icon_sparking) + sleep(6) + overlays.Cut() + overlays += image('icons/obj/storage.dmi', icon_locking) + locked = 0 + if(istype(W, /obj/item/weapon/melee/energy/blade)) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src.loc) + spark_system.start() + playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(src.loc, "sparks", 50, 1) + to_chat(user, "You slice through the lock on [src].") + else + to_chat(user, "You short out the lock on [src].") + return + + if (istype(W, /obj/item/weapon/screwdriver)) + if (!user.is_busy(src) && do_after(user, 20, target = src)) + src.open =! src.open + user.show_message(text("\blue 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("\red Now attempting to reset internal memory, please hold."), 1) + src.l_hacking = 1 + if (!user.is_busy() && do_after(usr, 100, target = src)) + if (prob(40)) + src.l_setshort = 1 + src.l_set = 0 + user.show_message(text("\red 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("\red 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 + ..() + + + MouseDrop(over_object, src_location, over_location) + if (locked) + src.add_fingerprint(usr) + return + ..() + + + attack_self(mob/user) + 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(entity_ja(dat), "window=caselock;size=300x280") + + 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 = "secure-r" + desc = "A large briefcase with a digital locking system." + force = 8.0 + throw_speed = 1 + throw_range = 4 + w_class = ITEM_SIZE_LARGE + +/obj/item/weapon/storage/secure/briefcase/atom_init() + . = ..() + new /obj/item/weapon/paper(src) + new /obj/item/weapon/pen(src) + +/obj/item/weapon/storage/secure/briefcase/attack_hand(mob/user) + if ((src.loc == user) && (src.locked == 1)) + to_chat(usr, "\red [src] is locked and cannot be opened!") + else if ((src.loc == user) && (!src.locked)) + src.open(usr) + else + ..() + for(var/mob/M in range(1)) + if (M.s_active == src) + src.close(M) + src.add_fingerprint(user) + +/obj/item/weapon/storage/secure/briefcase/attackby(obj/item/weapon/W, mob/user) + ..() + update_icon() + +/obj/item/weapon/storage/secure/briefcase/Topic(href, href_list) + ..() + update_icon() + +/obj/item/weapon/storage/secure/briefcase/update_icon() + if(!locked || emagged) + item_state = "secure-g" + else + item_state = "secure-r" + + if(ismob(loc)) + var/mob/M = loc + M.update_inv_l_hand() + M.update_inv_r_hand() + +//Syndie variant of Secure Briefcase. Contains space cash, slightly more robust. +/obj/item/weapon/storage/secure/briefcase/syndie + force = 15.0 + +/obj/item/weapon/storage/secure/briefcase/syndie/atom_init() + for (var/i in 1 to 4) + new /obj/item/weapon/spacecash/c1000(src) + . = ..() + + +// ----------------------------- +// 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" + 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/atom_init() + . = ..() + new /obj/item/weapon/paper(src) + new /obj/item/weapon/pen(src) + +/obj/item/weapon/storage/secure/safe/attack_hand(mob/user) + return attack_self(user) + +//obj/item/weapon/storage/secure/safe/HoS/atom_init() +// . = ..() + //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 ab8bb235ce3d..d2cfedbe1a0e 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -1,509 +1,509 @@ -// 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 = ITEM_SIZE_NORMAL - 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/max_w_class = ITEM_SIZE_SMALL //Max size of objects that this object can store (in effect only if can_hold isn't set) - var/max_storage_space = null //Total storage cost of items this can hold. Will be autoset based on storage_slots if left null. - var/storage_slots = null //The number of storage slots in this container. - - 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/use_sound = "rustle" //sound played when used. null for no sound. - - var/storage_ui_path = /datum/storage_ui/default - var/datum/storage_ui/storage_ui = null - //initializes the contents of the storage with some items based on an assoc list. The assoc key must be an item path, - //the assoc value can either be the quantity, or a list whose first value is the quantity and the rest are args. - var/list/startswith -/obj/item/weapon/storage/Destroy() - QDEL_NULL(storage_ui) - return ..() - -/obj/item/weapon/storage/MouseDrop(obj/over_object as obj) - if (ishuman(usr) || ismonkey(usr) || isIAN(usr)) //so monkeys can take off their backpacks -- Urist - var/mob/M = usr - - if(!over_object) - return - - if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech - return - - if(over_object == usr && Adjacent(usr)) // this must come before the screen objects only block - src.open(usr) - return - - if (!( istype(over_object, /obj/screen) )) - return ..() - - //makes sure that the storage is equipped, so that we can't drag it into our hand from miles away. - //there's got to be a better way of doing this. - if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) - return - - if (!( usr.restrained() ) && !( usr.stat )) - switch(over_object.name) - if("r_hand") - if(!M.unEquip(src)) - return - M.put_in_r_hand(src) - if("l_hand") - if(!M.unEquip(src)) - return - M.put_in_l_hand(src) - if("mouth") - if(!M.unEquip(src)) - return - M.put_in_active_hand(src) - src.add_fingerprint(usr) - return - return - - -/obj/item/weapon/storage/proc/return_inv() - var/list/L = list( ) - L += contents - - for(var/obj/item/weapon/storage/S in src) - L += S.return_inv() - return L - -/obj/item/weapon/storage/proc/show_to(mob/user as mob) - if(storage_ui) - storage_ui.show_to(user) - -/obj/item/weapon/storage/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback) - if(storage_ui) - storage_ui.close_all() - return ..() - -/obj/item/weapon/storage/proc/hide_from(mob/user as mob) - if(storage_ui) - storage_ui.hide_from(user) - -/obj/item/weapon/storage/proc/open(mob/user) - if (use_sound) - playsound(loc, use_sound, 50, 1, -5) - - prepare_ui() - storage_ui.on_open(user) - storage_ui.show_to(user) - -/obj/item/weapon/storage/proc/prepare_ui() - storage_ui.prepare_ui() - -/obj/item/weapon/storage/proc/close(mob/user) - hide_from(user) - if(storage_ui) - storage_ui.after_close(user) - -/obj/item/weapon/storage/proc/close_all() - if(storage_ui) - return storage_ui.close_all() - -/obj/item/weapon/storage/proc/storage_space_used() - . = 0 - for(var/obj/item/I in contents) - . += I.get_storage_cost() - -/*/obj/item/weapon/storage/proc/can_see_contents() - var/list/cansee = list() - for(var/mob/M in is_seeing) - if(M.s_active == src) - cansee |= M - else - is_seeing -= M - return cansee*/ - -//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, stop_messages = FALSE) - if(!istype(W) || (W.flags & ABSTRACT) || W.anchored) - return FALSE//Not an item - - if(loc == W) - return FALSE //Means the item is already in the storage item - - if(storage_slots != null && contents.len >= storage_slots) - if(!stop_messages) - to_chat(usr, "[src] is full, make some space.") - return FALSE //Storage item is full - - if(can_hold.len) - var/ok = FALSE - for(var/A in can_hold) - if(istype(W, text2path(A) )) - ok = TRUE - break - if(!ok) - if(!stop_messages) - if (istype(W, /obj/item/weapon/hand_labeler)) - return FALSE - to_chat(usr, "[src] cannot hold [W].") - return FALSE - - for(var/A in cant_hold) //Check for specific items which this container can't hold. - if(istype(W, text2path(A) )) - if(!stop_messages) - to_chat(usr, "[src] cannot hold [W].") - return FALSE - - if (max_w_class != null && W.w_class > max_w_class) - if(!stop_messages) - to_chat(usr, "[W] is too big for this [src].") - return FALSE - - 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, "[src] cannot hold [W] as it's a storage item of the same size.") - return FALSE //To prevent the stacking of same sized storage items. - - var/total_storage_space = W.get_storage_cost() - if(total_storage_space == ITEM_SIZE_NO_CONTAINER) - if(!stop_messages) - to_chat(usr, "\The [W] cannot be placed in [src].") - return FALSE - - total_storage_space += storage_space_used() //Adds up the combined w_classes which will be in the storage item if the item is added to it. - if(total_storage_space > max_storage_space) - if(!stop_messages) - to_chat(usr, "\The [src] is too full, make some space.") - return FALSE - - return TRUE - -//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, prevent_warning = FALSE, NoUpdate = FALSE) - if(!istype(W)) - return FALSE - if(usr) - usr.remove_from_mob(W) - usr.update_icons() //update our overlays - W.loc = 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 [src].") - else if (M in range(1)) //If someone is standing close enough, they can tell what it is... - M.show_message("[usr] puts [W] into [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 [W] into [src].") - if(crit_fail && prob(25)) - remove_from_storage(W, get_turf(src)) - if(!NoUpdate) - update_ui_after_item_insertion() - update_icon() - return TRUE - -/obj/item/weapon/storage/proc/update_ui_after_item_insertion() - prepare_ui() - if(storage_ui) - storage_ui.on_insertion(usr) - -/obj/item/weapon/storage/proc/update_ui_after_item_removal() - prepare_ui() - if(storage_ui) - storage_ui.on_post_remove(usr) - -//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 -/obj/item/weapon/storage/proc/remove_from_storage(obj/item/W, atom/new_location, var/NoUpdate = FALSE) - if(!istype(W)) - return FALSE - - if(istype(src, /obj/item/weapon/storage/fancy)) - var/obj/item/weapon/storage/fancy/F = src - F.update_icon(1) - - if(storage_ui) - storage_ui.on_pre_remove(usr, W) - - if(new_location) - if(ismob(loc)) - var/mob/M = loc - W.dropped(M) - if(ismob(new_location)) - W.layer = ABOVE_HUD_LAYER - W.plane = ABOVE_HUD_PLANE - else - W.layer = initial(W.layer) - W.plane = initial(W.plane) - W.loc = new_location - else - W.loc = get_turf(src) - - if(usr && !NoUpdate) - update_ui_after_item_removal() - if(W.maptext) - W.maptext = "" - W.on_exit_storage(src) - if(!NoUpdate) - update_icon() - return TRUE - -//Run once after using remove_from_storage with NoUpdate = 1 -/obj/item/weapon/storage/proc/finish_bulk_removal() - update_ui_after_item_removal() - update_icon() - -//This proc is called when you want to place an item into the storage item. -/obj/item/weapon/storage/attackby(obj/item/W, mob/user) - ..() - - if(isrobot(user)) - to_chat(user, "\blue You're a robot. No.") - return //Robots can't interact with storage items. FALSE - - if(!can_be_inserted(W)) - return FALSE - - if(istype(W, /obj/item/weapon/implanter/compressed)) - return FALSE - - 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, "\red The tray won't fit in [src].") - return FALSE - else - W.loc = user.loc - if ((user.client && user.s_active != src)) - user.client.screen -= W - W.dropped(user) - to_chat(user, "\red God damnit!") - - if(istype(W, /obj/item/weapon/packageWrap) && !(src in user)) //prevents package wrap being put inside the backpack when the backpack is not being worn/held (hence being wrappable) - return FALSE - - W.add_fingerprint(user) - handle_item_insertion(W) - return TRUE - -/obj/item/weapon/storage/dropped(mob/user) - return - -/obj/item/weapon/storage/attack_hand(mob/user) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.l_store == src && !H.get_active_hand()) //Prevents opening if it's in a pocket. - H.put_in_hands(src) - H.l_store = null - return - if(H.r_store == src && !H.get_active_hand()) - H.put_in_hands(src) - H.r_store = null - return - - if (src.loc == user) - src.open(user) - else - ..() - storage_ui.on_hand_attack(user) - src.add_fingerprint(user) - -//Should be merged into attack_hand() later, i mean whole attack_paw() proc, but thats probably a lot of work. -/obj/item/weapon/storage/attack_paw(mob/user) // so monkey, ian or something will open it, istead of unequip from back - return attack_hand(user) // to unequip - there is drag n drop available for this task - same as humans do. - -/obj/item/weapon/storage/proc/gather_all(var/turf/T, var/mob/user) - var/success = 0 - var/failure = 0 - - for(var/obj/item/I in T) - if(!can_be_inserted(I, user, 0)) // Note can_be_inserted still makes noise when the answer is no - failure = 1 - continue - success = 1 - handle_item_insertion(I, prevent_warning = TRUE, NoUpdate = TRUE) // First 1 is no messages, second 1 is no ui updates - if(success && !failure) - to_chat(user, "You put everything into \the [src].") - update_ui_after_item_insertion() - else if(success) - to_chat(user, "You put some things into \the [src].") - update_ui_after_item_insertion() - else - to_chat(user, "You fail to pick anything up with \the [src].") - -/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, "[src] now picks up all items in a tile at once.") - if(0) - to_chat(usr, "[src] now picks 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.stat || usr.restrained()) - return - - var/turf/T = get_turf(src) - hide_from(usr) - for(var/obj/item/I in contents) - remove_from_storage(I, T, NoUpdate = TRUE) - finish_bulk_removal() - -/obj/item/weapon/storage/atom_init() - . = ..() - 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 - - if(isnull(max_storage_space) && !isnull(storage_slots)) - max_storage_space = storage_slots*base_storage_cost(max_w_class) - - storage_ui = new storage_ui_path(src) - prepare_ui() - - if(startswith) - for(var/item_path in startswith) - var/list/data = startswith[item_path] - if(islist(data)) - var/qty = data[1] - var/list/argsl = data.Copy() - argsl[1] = src - for(var/i in 1 to qty) - new item_path(arglist(argsl)) - else - for(var/i in 1 to (isnull(data)? 1 : data)) - new item_path(src) - update_icon() - -/obj/item/weapon/storage/emp_act(severity) - if(!istype(src.loc, /mob/living)) - for(var/obj/O in contents) - O.emp_act(severity) - ..() - -// BubbleWrap - A box can be folded up to make card -/obj/item/weapon/storage/attack_self(mob/user) - - //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 [src] flat.") - new src.foldable(get_turf(src)) - qdel(src) -//BubbleWrap END - -/obj/item/weapon/storage/hear_talk(mob/M, text, verb, datum/language/speaking) - for (var/atom/A in src) - if(istype(A,/obj/)) - var/obj/O = A - O.hear_talk(M, text, verb, speaking) - -/obj/item/weapon/storage/proc/make_exact_fit(use_slots = FALSE) - if(use_slots) - storage_slots = contents.len - else - storage_slots = null - - can_hold.Cut() - max_w_class = 0 - max_storage_space = 0 - for(var/obj/item/I in src) - var/texttype = "[I.type]" - if(!(texttype in can_hold)) - can_hold += texttype - max_w_class = max(I.w_class, max_w_class) - max_storage_space += I.get_storage_cost() - -//Returns the storage depth of an atom. This is the number of storage items the atom is contained in before reaching toplevel (the area). -//Returns -1 if the atom was not found on container. -/atom/proc/storage_depth(atom/container) - var/depth = 0 - var/atom/cur_atom = src - - while (cur_atom && !(cur_atom in container.contents)) - if (isarea(cur_atom)) - return -1 - if (istype(cur_atom.loc, /obj/item/weapon/storage)) - depth++ - cur_atom = cur_atom.loc - - if (!cur_atom) - return -1 //inside something with a null loc. - - return depth - -//Like storage depth, but returns the depth to the nearest turf -//Returns -1 if no top level turf (a loc was null somewhere, or a non-turf atom's loc was an area somehow). -/atom/proc/storage_depth_turf() - var/depth = 0 - var/atom/cur_atom = src - - while (cur_atom && !isturf(cur_atom)) - if (isarea(cur_atom)) - return -1 - if (istype(cur_atom.loc, /obj/item/weapon/storage)) - depth++ - cur_atom = cur_atom.loc - - if (!cur_atom) - return -1 //inside something with a null loc. - - return depth - -/obj/item/weapon/storage/handle_atom_del(atom/A) - if(A in contents) - usr = null - remove_from_storage(A, loc) - -/obj/item/proc/get_storage_cost() - //If you want to prevent stuff above a certain w_class from being stored, use max_w_class +// 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 = ITEM_SIZE_NORMAL + 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/max_w_class = ITEM_SIZE_SMALL //Max size of objects that this object can store (in effect only if can_hold isn't set) + var/max_storage_space = null //Total storage cost of items this can hold. Will be autoset based on storage_slots if left null. + var/storage_slots = null //The number of storage slots in this container. + + 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/use_sound = "rustle" //sound played when used. null for no sound. + + var/storage_ui_path = /datum/storage_ui/default + var/datum/storage_ui/storage_ui = null + //initializes the contents of the storage with some items based on an assoc list. The assoc key must be an item path, + //the assoc value can either be the quantity, or a list whose first value is the quantity and the rest are args. + var/list/startswith +/obj/item/weapon/storage/Destroy() + QDEL_NULL(storage_ui) + return ..() + +/obj/item/weapon/storage/MouseDrop(obj/over_object as obj) + if (ishuman(usr) || ismonkey(usr) || isIAN(usr)) //so monkeys can take off their backpacks -- Urist + var/mob/M = usr + + if(!over_object) + return + + if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech + return + + if(over_object == usr && Adjacent(usr)) // this must come before the screen objects only block + src.open(usr) + return + + if (!( istype(over_object, /obj/screen) )) + return ..() + + //makes sure that the storage is equipped, so that we can't drag it into our hand from miles away. + //there's got to be a better way of doing this. + if (!(src.loc == usr) || (src.loc && src.loc.loc == usr)) + return + + if (!( usr.restrained() ) && !( usr.stat )) + switch(over_object.name) + if("r_hand") + if(!M.unEquip(src)) + return + M.put_in_r_hand(src) + if("l_hand") + if(!M.unEquip(src)) + return + M.put_in_l_hand(src) + if("mouth") + if(!M.unEquip(src)) + return + M.put_in_active_hand(src) + src.add_fingerprint(usr) + return + return + + +/obj/item/weapon/storage/proc/return_inv() + var/list/L = list( ) + L += contents + + for(var/obj/item/weapon/storage/S in src) + L += S.return_inv() + return L + +/obj/item/weapon/storage/proc/show_to(mob/user as mob) + if(storage_ui) + storage_ui.show_to(user) + +/obj/item/weapon/storage/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback) + if(storage_ui) + storage_ui.close_all() + return ..() + +/obj/item/weapon/storage/proc/hide_from(mob/user as mob) + if(storage_ui) + storage_ui.hide_from(user) + +/obj/item/weapon/storage/proc/open(mob/user) + if (use_sound) + playsound(loc, use_sound, 50, 1, -5) + + prepare_ui() + storage_ui.on_open(user) + storage_ui.show_to(user) + +/obj/item/weapon/storage/proc/prepare_ui() + storage_ui.prepare_ui() + +/obj/item/weapon/storage/proc/close(mob/user) + hide_from(user) + if(storage_ui) + storage_ui.after_close(user) + +/obj/item/weapon/storage/proc/close_all() + if(storage_ui) + return storage_ui.close_all() + +/obj/item/weapon/storage/proc/storage_space_used() + . = 0 + for(var/obj/item/I in contents) + . += I.get_storage_cost() + +/*/obj/item/weapon/storage/proc/can_see_contents() + var/list/cansee = list() + for(var/mob/M in is_seeing) + if(M.s_active == src) + cansee |= M + else + is_seeing -= M + return cansee*/ + +//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, stop_messages = FALSE) + if(!istype(W) || (W.flags & ABSTRACT) || W.anchored) + return FALSE//Not an item + + if(loc == W) + return FALSE //Means the item is already in the storage item + + if(storage_slots != null && contents.len >= storage_slots) + if(!stop_messages) + to_chat(usr, "[src] is full, make some space.") + return FALSE //Storage item is full + + if(can_hold.len) + var/ok = FALSE + for(var/A in can_hold) + if(istype(W, text2path(A) )) + ok = TRUE + break + if(!ok) + if(!stop_messages) + if (istype(W, /obj/item/weapon/hand_labeler)) + return FALSE + to_chat(usr, "[src] cannot hold [W].") + return FALSE + + for(var/A in cant_hold) //Check for specific items which this container can't hold. + if(istype(W, text2path(A) )) + if(!stop_messages) + to_chat(usr, "[src] cannot hold [W].") + return FALSE + + if (max_w_class != null && W.w_class > max_w_class) + if(!stop_messages) + to_chat(usr, "[W] is too big for this [src].") + return FALSE + + 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, "[src] cannot hold [W] as it's a storage item of the same size.") + return FALSE //To prevent the stacking of same sized storage items. + + var/total_storage_space = W.get_storage_cost() + if(total_storage_space == ITEM_SIZE_NO_CONTAINER) + if(!stop_messages) + to_chat(usr, "\The [W] cannot be placed in [src].") + return FALSE + + total_storage_space += storage_space_used() //Adds up the combined w_classes which will be in the storage item if the item is added to it. + if(total_storage_space > max_storage_space) + if(!stop_messages) + to_chat(usr, "\The [src] is too full, make some space.") + return FALSE + + return TRUE + +//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, prevent_warning = FALSE, NoUpdate = FALSE) + if(!istype(W)) + return FALSE + if(usr) + usr.remove_from_mob(W) + usr.update_icons() //update our overlays + W.loc = 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 [src].") + else if (M in range(1)) //If someone is standing close enough, they can tell what it is... + M.show_message("[usr] puts [W] into [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 [W] into [src].") + if(crit_fail && prob(25)) + remove_from_storage(W, get_turf(src)) + if(!NoUpdate) + update_ui_after_item_insertion() + update_icon() + return TRUE + +/obj/item/weapon/storage/proc/update_ui_after_item_insertion() + prepare_ui() + if(storage_ui) + storage_ui.on_insertion(usr) + +/obj/item/weapon/storage/proc/update_ui_after_item_removal() + prepare_ui() + if(storage_ui) + storage_ui.on_post_remove(usr) + +//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 +/obj/item/weapon/storage/proc/remove_from_storage(obj/item/W, atom/new_location, var/NoUpdate = FALSE) + if(!istype(W)) + return FALSE + + if(istype(src, /obj/item/weapon/storage/fancy)) + var/obj/item/weapon/storage/fancy/F = src + F.update_icon(1) + + if(storage_ui) + storage_ui.on_pre_remove(usr, W) + + if(new_location) + if(ismob(loc)) + var/mob/M = loc + W.dropped(M) + if(ismob(new_location)) + W.layer = ABOVE_HUD_LAYER + W.plane = ABOVE_HUD_PLANE + else + W.layer = initial(W.layer) + W.plane = initial(W.plane) + W.loc = new_location + else + W.loc = get_turf(src) + + if(usr && !NoUpdate) + update_ui_after_item_removal() + if(W.maptext) + W.maptext = "" + W.on_exit_storage(src) + if(!NoUpdate) + update_icon() + return TRUE + +//Run once after using remove_from_storage with NoUpdate = 1 +/obj/item/weapon/storage/proc/finish_bulk_removal() + update_ui_after_item_removal() + update_icon() + +//This proc is called when you want to place an item into the storage item. +/obj/item/weapon/storage/attackby(obj/item/W, mob/user) + ..() + + if(isrobot(user)) + to_chat(user, "\blue You're a robot. No.") + return //Robots can't interact with storage items. FALSE + + if(!can_be_inserted(W)) + return FALSE + + if(istype(W, /obj/item/weapon/implanter/compressed)) + return FALSE + + 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, "\red The tray won't fit in [src].") + return FALSE + else + W.loc = user.loc + if ((user.client && user.s_active != src)) + user.client.screen -= W + W.dropped(user) + to_chat(user, "\red God damnit!") + + if(istype(W, /obj/item/weapon/packageWrap) && !(src in user)) //prevents package wrap being put inside the backpack when the backpack is not being worn/held (hence being wrappable) + return FALSE + + W.add_fingerprint(user) + handle_item_insertion(W) + return TRUE + +/obj/item/weapon/storage/dropped(mob/user) + return + +/obj/item/weapon/storage/attack_hand(mob/user) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.l_store == src && !H.get_active_hand()) //Prevents opening if it's in a pocket. + H.put_in_hands(src) + H.l_store = null + return + if(H.r_store == src && !H.get_active_hand()) + H.put_in_hands(src) + H.r_store = null + return + + if (src.loc == user) + src.open(user) + else + ..() + storage_ui.on_hand_attack(user) + src.add_fingerprint(user) + +//Should be merged into attack_hand() later, i mean whole attack_paw() proc, but thats probably a lot of work. +/obj/item/weapon/storage/attack_paw(mob/user) // so monkey, ian or something will open it, istead of unequip from back + return attack_hand(user) // to unequip - there is drag n drop available for this task - same as humans do. + +/obj/item/weapon/storage/proc/gather_all(var/turf/T, var/mob/user) + var/success = 0 + var/failure = 0 + + for(var/obj/item/I in T) + if(!can_be_inserted(I, user, 0)) // Note can_be_inserted still makes noise when the answer is no + failure = 1 + continue + success = 1 + handle_item_insertion(I, prevent_warning = TRUE, NoUpdate = TRUE) // First 1 is no messages, second 1 is no ui updates + if(success && !failure) + to_chat(user, "You put everything into \the [src].") + update_ui_after_item_insertion() + else if(success) + to_chat(user, "You put some things into \the [src].") + update_ui_after_item_insertion() + else + to_chat(user, "You fail to pick anything up with \the [src].") + +/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, "[src] now picks up all items in a tile at once.") + if(0) + to_chat(usr, "[src] now picks 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.stat || usr.restrained()) + return + + var/turf/T = get_turf(src) + hide_from(usr) + for(var/obj/item/I in contents) + remove_from_storage(I, T, NoUpdate = TRUE) + finish_bulk_removal() + +/obj/item/weapon/storage/atom_init() + . = ..() + 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 + + if(isnull(max_storage_space) && !isnull(storage_slots)) + max_storage_space = storage_slots*base_storage_cost(max_w_class) + + storage_ui = new storage_ui_path(src) + prepare_ui() + + if(startswith) + for(var/item_path in startswith) + var/list/data = startswith[item_path] + if(islist(data)) + var/qty = data[1] + var/list/argsl = data.Copy() + argsl[1] = src + for(var/i in 1 to qty) + new item_path(arglist(argsl)) + else + for(var/i in 1 to (isnull(data)? 1 : data)) + new item_path(src) + update_icon() + +/obj/item/weapon/storage/emp_act(severity) + if(!istype(src.loc, /mob/living)) + for(var/obj/O in contents) + O.emp_act(severity) + ..() + +// BubbleWrap - A box can be folded up to make card +/obj/item/weapon/storage/attack_self(mob/user) + + //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 [src] flat.") + new src.foldable(get_turf(src)) + qdel(src) +//BubbleWrap END + +/obj/item/weapon/storage/hear_talk(mob/M, text, verb, datum/language/speaking) + for (var/atom/A in src) + if(istype(A,/obj/)) + var/obj/O = A + O.hear_talk(M, text, verb, speaking) + +/obj/item/weapon/storage/proc/make_exact_fit(use_slots = FALSE) + if(use_slots) + storage_slots = contents.len + else + storage_slots = null + + can_hold.Cut() + max_w_class = 0 + max_storage_space = 0 + for(var/obj/item/I in src) + var/texttype = "[I.type]" + if(!(texttype in can_hold)) + can_hold += texttype + max_w_class = max(I.w_class, max_w_class) + max_storage_space += I.get_storage_cost() + +//Returns the storage depth of an atom. This is the number of storage items the atom is contained in before reaching toplevel (the area). +//Returns -1 if the atom was not found on container. +/atom/proc/storage_depth(atom/container) + var/depth = 0 + var/atom/cur_atom = src + + while (cur_atom && !(cur_atom in container.contents)) + if (isarea(cur_atom)) + return -1 + if (istype(cur_atom.loc, /obj/item/weapon/storage)) + depth++ + cur_atom = cur_atom.loc + + if (!cur_atom) + return -1 //inside something with a null loc. + + return depth + +//Like storage depth, but returns the depth to the nearest turf +//Returns -1 if no top level turf (a loc was null somewhere, or a non-turf atom's loc was an area somehow). +/atom/proc/storage_depth_turf() + var/depth = 0 + var/atom/cur_atom = src + + while (cur_atom && !isturf(cur_atom)) + if (isarea(cur_atom)) + return -1 + if (istype(cur_atom.loc, /obj/item/weapon/storage)) + depth++ + cur_atom = cur_atom.loc + + if (!cur_atom) + return -1 //inside something with a null loc. + + return depth + +/obj/item/weapon/storage/handle_atom_del(atom/A) + if(A in contents) + usr = null + remove_from_storage(A, loc) + +/obj/item/proc/get_storage_cost() + //If you want to prevent stuff above a certain w_class from being stored, use max_w_class return base_storage_cost(w_class) \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm index e2bb6be343f9..5812ed7b0d1b 100644 --- a/code/game/objects/items/weapons/storage/toolbox.dm +++ b/code/game/objects/items/weapons/storage/toolbox.dm @@ -1,86 +1,86 @@ -/obj/item/weapon/storage/toolbox - name = "toolbox" - desc = "Danger. Very robust." - icon = 'icons/obj/storage.dmi' - icon_state = "red" - item_state = "toolbox_red" - flags = CONDUCT - force = 5.0 - throwforce = 10.0 - throw_speed = 1 - throw_range = 7 - w_class = ITEM_SIZE_LARGE - max_storage_space = DEFAULT_BOX_STORAGE + 2 // fits all tools and around 2 extra items - origin_tech = "combat=1" - attack_verb = list("robusted") - -/obj/item/weapon/storage/toolbox/atom_init() - . = ..() - if (src.type == /obj/item/weapon/storage/toolbox) - to_chat(world, "BAD: [src] ([type]) spawned at [COORD(src)]") - return INITIALIZE_HINT_QDEL - -/obj/item/weapon/storage/toolbox/emergency - name = "emergency toolbox" - icon_state = "red" - item_state = "toolbox_red" - -/obj/item/weapon/storage/toolbox/emergency/atom_init() - . = ..() - new /obj/item/weapon/crowbar/red(src) - new /obj/item/weapon/extinguisher/mini(src) - if(prob(50)) - new /obj/item/device/flashlight(src) - else - new /obj/item/device/flashlight/flare(src) - new /obj/item/device/radio(src) - new /obj/item/weapon/storage/fancy/glowsticks(src) //Gloooouuuwstiicks :3 - -/obj/item/weapon/storage/toolbox/mechanical - name = "mechanical toolbox" - icon_state = "blue" - item_state = "toolbox_blue" - -/obj/item/weapon/storage/toolbox/mechanical/atom_init() - . = ..() - 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/atom_init() - . = ..() - 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) - for (var/i in 1 to 2) - new /obj/item/stack/cable_coil/random(src) - if(prob(5)) - new /obj/item/clothing/gloves/yellow(src) - else - new /obj/item/stack/cable_coil/random(src) - -/obj/item/weapon/storage/toolbox/syndicate - name = "suspicious looking toolbox" - icon_state = "syndicate" - item_state = "toolbox_syndi" - origin_tech = "combat=1;syndicate=1" - force = 7.0 - -/obj/item/weapon/storage/toolbox/syndicate/atom_init() - . = ..() - new /obj/item/weapon/screwdriver(src) - new /obj/item/weapon/wrench(src) - new /obj/item/weapon/weldingtool(src) - new /obj/item/weapon/crowbar(src) - new /obj/item/weapon/wirecutters(src) - new /obj/item/device/multitool(src) - new /obj/item/clothing/gloves/combat(src) +/obj/item/weapon/storage/toolbox + name = "toolbox" + desc = "Danger. Very robust." + icon = 'icons/obj/storage.dmi' + icon_state = "red" + item_state = "toolbox_red" + flags = CONDUCT + force = 5.0 + throwforce = 10.0 + throw_speed = 1 + throw_range = 7 + w_class = ITEM_SIZE_LARGE + max_storage_space = DEFAULT_BOX_STORAGE + 2 // fits all tools and around 2 extra items + origin_tech = "combat=1" + attack_verb = list("robusted") + +/obj/item/weapon/storage/toolbox/atom_init() + . = ..() + if (src.type == /obj/item/weapon/storage/toolbox) + to_chat(world, "BAD: [src] ([type]) spawned at [COORD(src)]") + return INITIALIZE_HINT_QDEL + +/obj/item/weapon/storage/toolbox/emergency + name = "emergency toolbox" + icon_state = "red" + item_state = "toolbox_red" + +/obj/item/weapon/storage/toolbox/emergency/atom_init() + . = ..() + new /obj/item/weapon/crowbar/red(src) + new /obj/item/weapon/extinguisher/mini(src) + if(prob(50)) + new /obj/item/device/flashlight(src) + else + new /obj/item/device/flashlight/flare(src) + new /obj/item/device/radio(src) + new /obj/item/weapon/storage/fancy/glowsticks(src) //Gloooouuuwstiicks :3 + +/obj/item/weapon/storage/toolbox/mechanical + name = "mechanical toolbox" + icon_state = "blue" + item_state = "toolbox_blue" + +/obj/item/weapon/storage/toolbox/mechanical/atom_init() + . = ..() + 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/atom_init() + . = ..() + 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) + for (var/i in 1 to 2) + new /obj/item/stack/cable_coil/random(src) + if(prob(5)) + new /obj/item/clothing/gloves/yellow(src) + else + new /obj/item/stack/cable_coil/random(src) + +/obj/item/weapon/storage/toolbox/syndicate + name = "suspicious looking toolbox" + icon_state = "syndicate" + item_state = "toolbox_syndi" + origin_tech = "combat=1;syndicate=1" + force = 7.0 + +/obj/item/weapon/storage/toolbox/syndicate/atom_init() + . = ..() + new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/wrench(src) + new /obj/item/weapon/weldingtool(src) + new /obj/item/weapon/crowbar(src) + new /obj/item/weapon/wirecutters(src) + new /obj/item/device/multitool(src) + new /obj/item/clothing/gloves/combat(src) diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm index b58d76c783b5..550bea82aeb5 100644 --- a/code/game/objects/items/weapons/swords_axes_etc.dm +++ b/code/game/objects/items/weapons/swords_axes_etc.dm @@ -1,292 +1,292 @@ -/* Weapons - * Contains: - * Banhammer - * Sword - * Classic Baton - * Energy Blade - * Energy Axe - * Energy Shield - */ - -/* - * Banhammer - */ -/obj/item/weapon/banhammer/attack(mob/M, mob/user) - to_chat(M, " You have been banned FOR NO REISIN by [user]") - to_chat(user, " You have BANNED [M]") - -/* - * Sword - */ -/obj/item/weapon/melee/energy/sword/Get_shield_chance() - if(active) - return 40 - return 0 - -/obj/item/weapon/melee/energy/add_blood() - return - -/obj/item/weapon/melee/energy/sword/atom_init() - . = ..() - item_color = pick("red","blue","green","purple","yellow","pink","black") - -/obj/item/weapon/melee/energy/sword/attack_self(mob/living/user) - if ((CLUMSY in user.mutations) && prob(50)) - to_chat(user, "\red You accidentally cut yourself with [src].") - user.take_bodypart_damage(5, 5) - active = !active - if (active) - force = 30 - if(istype(src,/obj/item/weapon/melee/energy/sword/pirate)) - icon_state = "cutlass1" - else - icon_state = "sword[item_color]" - w_class = 4 - playsound(user, 'sound/weapons/saberon.ogg', 50, 1) - to_chat(user, "\blue [src] is now active.") - - else - force = 3 - if(istype(src,/obj/item/weapon/melee/energy/sword/pirate)) - icon_state = "cutlass0" - else - icon_state = "sword0" - w_class = 2 - playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) - to_chat(user, "\blue [src] can now be concealed.") - - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - H.update_inv_l_hand() - H.update_inv_r_hand() - - add_fingerprint(user) - return - - -/* - * 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" - item_state = "classic_baton" - slot_flags = SLOT_BELT - force = 10 - -/obj/item/weapon/melee/classic_baton/attack(mob/M, mob/living/user) - if ((CLUMSY in user.mutations) && prob(50)) - to_chat(user, "\red 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, BP_HEAD) - else - user.take_bodypart_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 == "hurt") - if(!..()) return - playsound(src.loc, "swing_hit", 50, 1, -1) - if (M.stuttering < 8 && (!(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("\red [M] has been beaten with \the [src] by [user]!", 1, "\red You hear someone fall", 2) - else - playsound(src.loc, '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])") - msg_admin_attack("[key_name(user)] attacked [key_name(user)] with [src.name] (INTENT: [uppertext(user.a_intent)])") - src.add_fingerprint(user) - - for(var/mob/O in viewers(M)) - if (O.client) O.show_message("\red [M] has been stunned with \the [src] by [user]!", 1, "\red You hear someone fall", 2) - -//Telescopic baton -/obj/item/weapon/melee/telebaton - name = "telescopic baton" - desc = "A compact yet rebalanced personal defense weapon. Can be concealed when folded." - icon = 'icons/obj/weapons.dmi' - icon_state = "telebaton_0" - item_state = null - slot_flags = SLOT_BELT - w_class = 2 - force = 3 - var/on = 0 - - -/obj/item/weapon/melee/telebaton/attack_self(mob/user) - on = !on - if(on) - user.visible_message("\red With a flick of their wrist, [user] extends their telescopic baton.",\ - "\red You extend the baton.",\ - "You hear an ominous click.") - icon_state = "telebaton_1" - item_state = "nullrod" - w_class = 3 - force = 15//quite robust - attack_verb = list("smacked", "struck", "slapped") - else - user.visible_message("\blue [user] collapses their telescopic baton.",\ - "\blue You collapse the baton.",\ - "You hear a click.") - icon_state = "telebaton_0" - item_state = null - w_class = 2 - force = 3//not so robust now - attack_verb = list("hit", "punched") - - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - H.update_inv_l_hand() - H.update_inv_r_hand() - - playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) - add_fingerprint(user) - - if(blood_overlay && blood_DNA && (blood_DNA.len >= 1)) //updates blood overlay, if any - overlays.Cut()//this might delete other item overlays as well but eeeeeeeh - - var/icon/I = new /icon(src.icon, src.icon_state) - I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) - I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) - blood_overlay = I - - overlays += blood_overlay - - return - -/obj/item/weapon/melee/telebaton/attack(mob/target, mob/living/user) - if(on) - if ((CLUMSY in user.mutations) && prob(50)) - to_chat(user, "\red 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, BP_HEAD) - else - user.take_bodypart_damage(2 * force) - return - if(..()) - playsound(src.loc, "swing_hit", 50, 1, -1) - return - else - return ..() - - -/* - *Energy Blade - */ -//Most of the other special functions are handled in their own files. - -/obj/item/weapon/melee/energy/sword/green/atom_init() - . = ..() - item_color = "green" - -/obj/item/weapon/melee/energy/sword/red/atom_init() - . = ..() - item_color = "red" - -/obj/item/weapon/melee/energy/sword/blue/atom_init() - . = ..() - item_color = "blue" - -/obj/item/weapon/melee/energy/sword/purple/atom_init() - . = ..() - item_color = "purple" - -/obj/item/weapon/melee/energy/sword/yellow/atom_init() - . = ..() - item_color = "yellow" - -/obj/item/weapon/melee/energy/sword/pink/atom_init() - . = ..() - item_color = "pink" - -/obj/item/weapon/melee/energy/sword/black/atom_init() - . = ..() - item_color = "black" - - -/obj/item/weapon/melee/energy/blade/atom_init() - . = ..() - spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src) - spark_system.attach(src) - -/* - * Energy Axe - */ - -/obj/item/weapon/melee/energy/axe/attack_self(mob/user) - src.active = !( src.active ) - if (src.active) - to_chat(user, "\blue The axe is now energised.") - src.force = 150 - src.icon_state = "axe1" - src.w_class = 5 - else - to_chat(user, "\blue The axe can now be concealed.") - src.force = 40 - src.icon_state = "axe0" - src.w_class = 5 - src.add_fingerprint(user) - return - - -/* - * Energy Shield - */ -/obj/item/weapon/shield/energy/Get_shield_chance() - if(active) - return block_chance - return 0 - -/obj/item/weapon/shield/energy/attack_self(mob/living/user) - if ((CLUMSY in user.mutations) && prob(50)) - to_chat(user, " You beat yourself in the head with [src].") - user.take_bodypart_damage(5) - if(emp_cooldown >= world.time) - to_chat(user, "[src] is recalibrating!") - return - active = !active - if(active) - turn_on(user) - else - turn_off(user) - add_fingerprint(user) - -/obj/item/weapon/shield/energy/proc/turn_on(mob/living/user) - force = 10 - icon_state = "eshield[active]" - w_class = 4 - playsound(loc, 'sound/weapons/saberon.ogg', 50, 1) - to_chat(user, " [src] is now active.") - update_icon() - -/obj/item/weapon/shield/energy/proc/turn_off(mob/living/user) - force = 3 - icon_state = "eshield[active]" - w_class = 1 - playsound(loc, 'sound/weapons/saberoff.ogg', 50, 1) - update_icon() - if(user) - to_chat(user, " [src] can now be concealed.") - -/obj/item/weapon/shield/energy/update_icon() - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - H.update_inv_l_hand() - H.update_inv_r_hand() +/* Weapons + * Contains: + * Banhammer + * Sword + * Classic Baton + * Energy Blade + * Energy Axe + * Energy Shield + */ + +/* + * Banhammer + */ +/obj/item/weapon/banhammer/attack(mob/M, mob/user) + to_chat(M, " You have been banned FOR NO REISIN by [user]") + to_chat(user, " You have BANNED [M]") + +/* + * Sword + */ +/obj/item/weapon/melee/energy/sword/Get_shield_chance() + if(active) + return 40 + return 0 + +/obj/item/weapon/melee/energy/add_blood() + return + +/obj/item/weapon/melee/energy/sword/atom_init() + . = ..() + item_color = pick("red","blue","green","purple","yellow","pink","black") + +/obj/item/weapon/melee/energy/sword/attack_self(mob/living/user) + if ((CLUMSY in user.mutations) && prob(50)) + to_chat(user, "\red You accidentally cut yourself with [src].") + user.take_bodypart_damage(5, 5) + active = !active + if (active) + force = 30 + if(istype(src,/obj/item/weapon/melee/energy/sword/pirate)) + icon_state = "cutlass1" + else + icon_state = "sword[item_color]" + w_class = 4 + playsound(user, 'sound/weapons/saberon.ogg', 50, 1) + to_chat(user, "\blue [src] is now active.") + + else + force = 3 + if(istype(src,/obj/item/weapon/melee/energy/sword/pirate)) + icon_state = "cutlass0" + else + icon_state = "sword0" + w_class = 2 + playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) + to_chat(user, "\blue [src] can now be concealed.") + + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.update_inv_l_hand() + H.update_inv_r_hand() + + add_fingerprint(user) + return + + +/* + * 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" + item_state = "classic_baton" + slot_flags = SLOT_BELT + force = 10 + +/obj/item/weapon/melee/classic_baton/attack(mob/M, mob/living/user) + if ((CLUMSY in user.mutations) && prob(50)) + to_chat(user, "\red 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, BP_HEAD) + else + user.take_bodypart_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 == "hurt") + if(!..()) return + playsound(src.loc, "swing_hit", 50, 1, -1) + if (M.stuttering < 8 && (!(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("\red [M] has been beaten with \the [src] by [user]!", 1, "\red You hear someone fall", 2) + else + playsound(src.loc, '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])") + msg_admin_attack("[key_name(user)] attacked [key_name(user)] with [src.name] (INTENT: [uppertext(user.a_intent)])") + src.add_fingerprint(user) + + for(var/mob/O in viewers(M)) + if (O.client) O.show_message("\red [M] has been stunned with \the [src] by [user]!", 1, "\red You hear someone fall", 2) + +//Telescopic baton +/obj/item/weapon/melee/telebaton + name = "telescopic baton" + desc = "A compact yet rebalanced personal defense weapon. Can be concealed when folded." + icon = 'icons/obj/weapons.dmi' + icon_state = "telebaton_0" + item_state = null + slot_flags = SLOT_BELT + w_class = 2 + force = 3 + var/on = 0 + + +/obj/item/weapon/melee/telebaton/attack_self(mob/user) + on = !on + if(on) + user.visible_message("\red With a flick of their wrist, [user] extends their telescopic baton.",\ + "\red You extend the baton.",\ + "You hear an ominous click.") + icon_state = "telebaton_1" + item_state = "nullrod" + w_class = 3 + force = 15//quite robust + attack_verb = list("smacked", "struck", "slapped") + else + user.visible_message("\blue [user] collapses their telescopic baton.",\ + "\blue You collapse the baton.",\ + "You hear a click.") + icon_state = "telebaton_0" + item_state = null + w_class = 2 + force = 3//not so robust now + attack_verb = list("hit", "punched") + + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.update_inv_l_hand() + H.update_inv_r_hand() + + playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) + add_fingerprint(user) + + if(blood_overlay && blood_DNA && (blood_DNA.len >= 1)) //updates blood overlay, if any + overlays.Cut()//this might delete other item overlays as well but eeeeeeeh + + var/icon/I = new /icon(src.icon, src.icon_state) + I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) + I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) + blood_overlay = I + + overlays += blood_overlay + + return + +/obj/item/weapon/melee/telebaton/attack(mob/target, mob/living/user) + if(on) + if ((CLUMSY in user.mutations) && prob(50)) + to_chat(user, "\red 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, BP_HEAD) + else + user.take_bodypart_damage(2 * force) + return + if(..()) + playsound(src.loc, "swing_hit", 50, 1, -1) + return + else + return ..() + + +/* + *Energy Blade + */ +//Most of the other special functions are handled in their own files. + +/obj/item/weapon/melee/energy/sword/green/atom_init() + . = ..() + item_color = "green" + +/obj/item/weapon/melee/energy/sword/red/atom_init() + . = ..() + item_color = "red" + +/obj/item/weapon/melee/energy/sword/blue/atom_init() + . = ..() + item_color = "blue" + +/obj/item/weapon/melee/energy/sword/purple/atom_init() + . = ..() + item_color = "purple" + +/obj/item/weapon/melee/energy/sword/yellow/atom_init() + . = ..() + item_color = "yellow" + +/obj/item/weapon/melee/energy/sword/pink/atom_init() + . = ..() + item_color = "pink" + +/obj/item/weapon/melee/energy/sword/black/atom_init() + . = ..() + item_color = "black" + + +/obj/item/weapon/melee/energy/blade/atom_init() + . = ..() + spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src) + spark_system.attach(src) + +/* + * Energy Axe + */ + +/obj/item/weapon/melee/energy/axe/attack_self(mob/user) + src.active = !( src.active ) + if (src.active) + to_chat(user, "\blue The axe is now energised.") + src.force = 150 + src.icon_state = "axe1" + src.w_class = 5 + else + to_chat(user, "\blue The axe can now be concealed.") + src.force = 40 + src.icon_state = "axe0" + src.w_class = 5 + src.add_fingerprint(user) + return + + +/* + * Energy Shield + */ +/obj/item/weapon/shield/energy/Get_shield_chance() + if(active) + return block_chance + return 0 + +/obj/item/weapon/shield/energy/attack_self(mob/living/user) + if ((CLUMSY in user.mutations) && prob(50)) + to_chat(user, " You beat yourself in the head with [src].") + user.take_bodypart_damage(5) + if(emp_cooldown >= world.time) + to_chat(user, "[src] is recalibrating!") + return + active = !active + if(active) + turn_on(user) + else + turn_off(user) + add_fingerprint(user) + +/obj/item/weapon/shield/energy/proc/turn_on(mob/living/user) + force = 10 + icon_state = "eshield[active]" + w_class = 4 + playsound(loc, 'sound/weapons/saberon.ogg', 50, 1) + to_chat(user, " [src] is now active.") + update_icon() + +/obj/item/weapon/shield/energy/proc/turn_off(mob/living/user) + force = 3 + icon_state = "eshield[active]" + w_class = 1 + playsound(loc, 'sound/weapons/saberoff.ogg', 50, 1) + update_icon() + if(user) + to_chat(user, " [src] can now be concealed.") + +/obj/item/weapon/shield/energy/update_icon() + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + H.update_inv_l_hand() + H.update_inv_r_hand() diff --git a/code/game/objects/items/weapons/table_rack_parts.dm b/code/game/objects/items/weapons/table_rack_parts.dm index 6567f78b2a20..a3dca97921b1 100644 --- a/code/game/objects/items/weapons/table_rack_parts.dm +++ b/code/game/objects/items/weapons/table_rack_parts.dm @@ -1,147 +1,147 @@ -/* Table parts and rack parts - * Contains: - * Table Parts - * Reinforced Table Parts - * Glass Table Parts - * Wooden Table Parts - * Fancy Table Parts - * Black Fancy Table Parts - * Rack Parts - */ - - - -/* - * Table Parts - */ -/obj/item/weapon/table_parts/attackby(obj/item/weapon/W, mob/user) - ..() - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/metal( user.loc ) - //SN src = null - qdel(src) - if (istype(W, /obj/item/stack/rods)) - var/obj/item/stack/rods/R = W - if (R.use(4)) - new /obj/item/weapon/table_parts/reinforced( user.loc ) - to_chat(user, "\blue You reinforce the [name].") - qdel(src) - else - to_chat(user, "\red You need at least four rods to do this.") - -/obj/item/weapon/table_parts/attack_self(mob/user) - new /obj/structure/table( user.loc ) - user.drop_item() - qdel(src) - return - - -/* - * Reinforced Table Parts - */ -/obj/item/weapon/table_parts/reinforced/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/metal( user.loc ) - new /obj/item/stack/rods( user.loc ) - qdel(src) - -/obj/item/weapon/table_parts/reinforced/attack_self(mob/user) - new /obj/structure/table/reinforced( user.loc ) - user.drop_item() - qdel(src) - return - -/* - * Glass Table Parts - */ -/obj/item/weapon/table_parts/glass/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/glass( user.loc ) - qdel(src) - -/obj/item/weapon/table_parts/glass/attack_self(mob/user) - new /obj/structure/table/glass( user.loc ) - user.drop_item() - qdel(src) - return - -/* - * Wooden Table Parts - */ -/obj/item/weapon/table_parts/wood/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/wood( user.loc ) - qdel(src) - - if (istype(W, /obj/item/stack/tile/grass)) - var/obj/item/stack/tile/grass/Grass = W - Grass.use(1) - new /obj/item/weapon/table_parts/wood/poker( src.loc ) - visible_message("[user] adds grass to the wooden table parts") - qdel(src) - -/obj/item/weapon/table_parts/wood/attack_self(mob/user) - new /obj/structure/table/woodentable( user.loc ) - user.drop_item() - qdel(src) - return - -/* - * Fancy Wooden Table Parts - */ -/obj/item/weapon/table_parts/wood/fancy/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/wood( user.loc ) - qdel(src) - -/obj/item/weapon/table_parts/wood/fancy/attack_self(mob/user) - new /obj/structure/table/woodentable/fancy( user.loc ) - user.drop_item() - qdel(src) - return - -/obj/item/weapon/table_parts/wood/fancy/black/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/wood( user.loc ) - qdel(src) - -/obj/item/weapon/table_parts/wood/fancy/black/attack_self(mob/user) - new /obj/structure/table/woodentable/fancy/black( user.loc ) - user.drop_item() - qdel(src) - return - - -/* - * Poker Table Parts - */ - -/obj/item/weapon/table_parts/wood/poker/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/wood( user.loc ) - new /obj/item/stack/tile/grass( user.loc ) - qdel(src) - -/obj/item/weapon/table_parts/wood/poker/attack_self(mob/user) - new /obj/structure/table/woodentable/poker( user.loc ) - user.drop_item() - qdel(src) - return - -/* - * Rack Parts - */ -/obj/item/weapon/rack_parts/attackby(obj/item/weapon/W, mob/user) - ..() - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/stack/sheet/metal( user.loc ) - qdel(src) - return - return - -/obj/item/weapon/rack_parts/attack_self(mob/user) - var/obj/structure/rack/R = new /obj/structure/rack( user.loc ) - R.add_fingerprint(user) - user.drop_item() - qdel(src) - return +/* Table parts and rack parts + * Contains: + * Table Parts + * Reinforced Table Parts + * Glass Table Parts + * Wooden Table Parts + * Fancy Table Parts + * Black Fancy Table Parts + * Rack Parts + */ + + + +/* + * Table Parts + */ +/obj/item/weapon/table_parts/attackby(obj/item/weapon/W, mob/user) + ..() + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/metal( user.loc ) + //SN src = null + qdel(src) + if (istype(W, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = W + if (R.use(4)) + new /obj/item/weapon/table_parts/reinforced( user.loc ) + to_chat(user, "\blue You reinforce the [name].") + qdel(src) + else + to_chat(user, "\red You need at least four rods to do this.") + +/obj/item/weapon/table_parts/attack_self(mob/user) + new /obj/structure/table( user.loc ) + user.drop_item() + qdel(src) + return + + +/* + * Reinforced Table Parts + */ +/obj/item/weapon/table_parts/reinforced/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/metal( user.loc ) + new /obj/item/stack/rods( user.loc ) + qdel(src) + +/obj/item/weapon/table_parts/reinforced/attack_self(mob/user) + new /obj/structure/table/reinforced( user.loc ) + user.drop_item() + qdel(src) + return + +/* + * Glass Table Parts + */ +/obj/item/weapon/table_parts/glass/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/glass( user.loc ) + qdel(src) + +/obj/item/weapon/table_parts/glass/attack_self(mob/user) + new /obj/structure/table/glass( user.loc ) + user.drop_item() + qdel(src) + return + +/* + * Wooden Table Parts + */ +/obj/item/weapon/table_parts/wood/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/wood( user.loc ) + qdel(src) + + if (istype(W, /obj/item/stack/tile/grass)) + var/obj/item/stack/tile/grass/Grass = W + Grass.use(1) + new /obj/item/weapon/table_parts/wood/poker( src.loc ) + visible_message("[user] adds grass to the wooden table parts") + qdel(src) + +/obj/item/weapon/table_parts/wood/attack_self(mob/user) + new /obj/structure/table/woodentable( user.loc ) + user.drop_item() + qdel(src) + return + +/* + * Fancy Wooden Table Parts + */ +/obj/item/weapon/table_parts/wood/fancy/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/wood( user.loc ) + qdel(src) + +/obj/item/weapon/table_parts/wood/fancy/attack_self(mob/user) + new /obj/structure/table/woodentable/fancy( user.loc ) + user.drop_item() + qdel(src) + return + +/obj/item/weapon/table_parts/wood/fancy/black/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/wood( user.loc ) + qdel(src) + +/obj/item/weapon/table_parts/wood/fancy/black/attack_self(mob/user) + new /obj/structure/table/woodentable/fancy/black( user.loc ) + user.drop_item() + qdel(src) + return + + +/* + * Poker Table Parts + */ + +/obj/item/weapon/table_parts/wood/poker/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/wood( user.loc ) + new /obj/item/stack/tile/grass( user.loc ) + qdel(src) + +/obj/item/weapon/table_parts/wood/poker/attack_self(mob/user) + new /obj/structure/table/woodentable/poker( user.loc ) + user.drop_item() + qdel(src) + return + +/* + * Rack Parts + */ +/obj/item/weapon/rack_parts/attackby(obj/item/weapon/W, mob/user) + ..() + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/stack/sheet/metal( user.loc ) + qdel(src) + return + return + +/obj/item/weapon/rack_parts/attack_self(mob/user) + var/obj/structure/rack/R = new /obj/structure/rack( user.loc ) + R.add_fingerprint(user) + user.drop_item() + qdel(src) + return diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm index 82cdbb46af23..6e526d05b066 100644 --- a/code/game/objects/items/weapons/tanks/jetpack.dm +++ b/code/game/objects/items/weapons/tanks/jetpack.dm @@ -1,110 +1,110 @@ -//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 = 4.0 - item_state = "jetpack" - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD - var/datum/effect/effect/system/ion_trail_follow/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/atom_init() - . = ..() - ion_trail = new - ion_trail.set_up(src) - -/obj/item/weapon/tank/jetpack/Destroy() - QDEL_NULL(ion_trail) - return ..() - - -/obj/item/weapon/tank/jetpack/examine(mob/user) - ..() - if(air_contents.total_moles < 5) - to_chat(user, "The meter on \the [src] indicates you are almost out of gas!") - -/obj/item/weapon/tank/jetpack/verb/toggle_rockets() - set name = "Toggle Jetpack Stabilization" - set category = "Object" - - stabilization_on = !stabilization_on - to_chat(usr, "You toggle the stabilization [stabilization_on? "on":"off"].") - -/obj/item/weapon/tank/jetpack/verb/toggle() - set name = "Toggle Jetpack" - set category = "Object" - - on = !on - - if(on) - icon_state = "[icon_state]-on" - ion_trail.start() - usr.update_inv_back() - else - icon_state = initial(icon_state) - ion_trail.stop() - usr.update_inv_back() - -/obj/item/weapon/tank/jetpack/proc/allow_thrust(num, mob/living/user) - if(!on) - return FALSE - if((num < 0.005 || air_contents.total_moles < num)) - ion_trail.stop() - return FALSE - - var/datum/gas_mixture/G = air_contents.remove(num) - - var/allgases = G.gas["carbon_dioxide"] + G.gas["nitrogen"] + G.gas["oxygen"] + G.gas["phoron"] - if(allgases >= 0.005) - return TRUE - - qdel(G) - -/obj/item/weapon/tank/jetpack/ui_action_click() - toggle() - - -/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/atom_init() - . = ..() - air_contents.adjust_gas("oxygen", (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/atom_init() - . = ..() - air_contents.adjust_gas("oxygen", (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/atom_init() - . = ..() - air_contents.adjust_gas("carbon_dioxide", (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - -/obj/item/weapon/tank/jetpack/oxygen/harness //TG-nuke jetpack - name = "jet harness (oxygen)" - desc = "A lightweight tactical harness, used by those who don't want to be weighed down by traditional jetpacks." - icon_state = "jetpack-mini" - item_state = "jetpack-mini" - volume = 40 - throw_range = 7 - w_class = 3 +//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 = 4.0 + item_state = "jetpack" + distribute_pressure = ONE_ATMOSPHERE*O2STANDARD + var/datum/effect/effect/system/ion_trail_follow/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/atom_init() + . = ..() + ion_trail = new + ion_trail.set_up(src) + +/obj/item/weapon/tank/jetpack/Destroy() + QDEL_NULL(ion_trail) + return ..() + + +/obj/item/weapon/tank/jetpack/examine(mob/user) + ..() + if(air_contents.total_moles < 5) + to_chat(user, "The meter on \the [src] indicates you are almost out of gas!") + +/obj/item/weapon/tank/jetpack/verb/toggle_rockets() + set name = "Toggle Jetpack Stabilization" + set category = "Object" + + stabilization_on = !stabilization_on + to_chat(usr, "You toggle the stabilization [stabilization_on? "on":"off"].") + +/obj/item/weapon/tank/jetpack/verb/toggle() + set name = "Toggle Jetpack" + set category = "Object" + + on = !on + + if(on) + icon_state = "[icon_state]-on" + ion_trail.start() + usr.update_inv_back() + else + icon_state = initial(icon_state) + ion_trail.stop() + usr.update_inv_back() + +/obj/item/weapon/tank/jetpack/proc/allow_thrust(num, mob/living/user) + if(!on) + return FALSE + if((num < 0.005 || air_contents.total_moles < num)) + ion_trail.stop() + return FALSE + + var/datum/gas_mixture/G = air_contents.remove(num) + + var/allgases = G.gas["carbon_dioxide"] + G.gas["nitrogen"] + G.gas["oxygen"] + G.gas["phoron"] + if(allgases >= 0.005) + return TRUE + + qdel(G) + +/obj/item/weapon/tank/jetpack/ui_action_click() + toggle() + + +/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/atom_init() + . = ..() + air_contents.adjust_gas("oxygen", (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/atom_init() + . = ..() + air_contents.adjust_gas("oxygen", (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/atom_init() + . = ..() + air_contents.adjust_gas("carbon_dioxide", (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + +/obj/item/weapon/tank/jetpack/oxygen/harness //TG-nuke jetpack + name = "jet harness (oxygen)" + desc = "A lightweight tactical harness, used by those who don't want to be weighed down by traditional jetpacks." + icon_state = "jetpack-mini" + item_state = "jetpack-mini" + volume = 40 + throw_range = 7 + w_class = 3 diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm index e60bdf51ff53..c37c50ab3bb6 100644 --- a/code/game/objects/items/weapons/tanks/tank_types.dm +++ b/code/game/objects/items/weapons/tanks/tank_types.dm @@ -1,129 +1,129 @@ -/* Types of tanks! - * Contains: - * Oxygen - * Anesthetic - * Air - * Phoron - * 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/atom_init() - . = ..() - air_contents.adjust_gas("oxygen", (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/atom_init() - . = ..() - - air_contents.gas["oxygen"] = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD - air_contents.gas["sleeping_agent"] = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD - air_contents.update_values() - -/* - * Air - */ -/obj/item/weapon/tank/air - name = "air tank" - desc = "Mixed anyone?" - icon_state = "oxygen" - -/obj/item/weapon/tank/air/atom_init() - . = ..() - air_contents.adjust_multi("oxygen", (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD, "nitrogen", (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD) - -/* - * Phoron - */ -/obj/item/weapon/tank/phoron - name = "phoron tank" - desc = "Contains dangerous phoron. Do not inhale. Warning: extremely flammable." - icon_state = "phoron" - item_state = "plasma" - flags = CONDUCT - slot_flags = null //they have no straps! - - -/obj/item/weapon/tank/phoron/atom_init() - . = ..() - air_contents.adjust_gas("phoron", (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C)) - -/obj/item/weapon/tank/phoron/attackby(obj/item/weapon/W, mob/user) - ..() - if(istype(W, /obj/item/weapon/flamethrower)) - var/obj/item/weapon/flamethrower/F = W - if (!F.status || F.ptank) - return - - master = F - F.ptank = src - user.remove_from_mob(src) - forceMove(F) - -/* - * 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 = CONDUCT - 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/atom_init() - . = ..() - air_contents.adjust_gas("oxygen", (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 - -/* - * 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/atom_init() - . = ..() - air_contents.adjust_gas("nitrogen", (3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) +/* Types of tanks! + * Contains: + * Oxygen + * Anesthetic + * Air + * Phoron + * 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/atom_init() + . = ..() + air_contents.adjust_gas("oxygen", (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/atom_init() + . = ..() + + air_contents.gas["oxygen"] = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD + air_contents.gas["sleeping_agent"] = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD + air_contents.update_values() + +/* + * Air + */ +/obj/item/weapon/tank/air + name = "air tank" + desc = "Mixed anyone?" + icon_state = "oxygen" + +/obj/item/weapon/tank/air/atom_init() + . = ..() + air_contents.adjust_multi("oxygen", (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD, "nitrogen", (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD) + +/* + * Phoron + */ +/obj/item/weapon/tank/phoron + name = "phoron tank" + desc = "Contains dangerous phoron. Do not inhale. Warning: extremely flammable." + icon_state = "phoron" + item_state = "plasma" + flags = CONDUCT + slot_flags = null //they have no straps! + + +/obj/item/weapon/tank/phoron/atom_init() + . = ..() + air_contents.adjust_gas("phoron", (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C)) + +/obj/item/weapon/tank/phoron/attackby(obj/item/weapon/W, mob/user) + ..() + if(istype(W, /obj/item/weapon/flamethrower)) + var/obj/item/weapon/flamethrower/F = W + if (!F.status || F.ptank) + return + + master = F + F.ptank = src + user.remove_from_mob(src) + forceMove(F) + +/* + * 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 = CONDUCT + 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/atom_init() + . = ..() + air_contents.adjust_gas("oxygen", (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 + +/* + * 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/atom_init() + . = ..() + air_contents.adjust_gas("nitrogen", (3 * ONE_ATMOSPHERE) * volume / (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 f1f674772df9..f138f7154514 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -1,251 +1,251 @@ -#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 = CONDUCT - slot_flags = SLOT_BACK - w_class = 3 - - 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/atom_init() - . = ..() - - air_contents = new - air_contents.volume = volume //liters - air_contents.temperature = T20C - - START_PROCESSING(SSobj, src) - -/obj/item/weapon/tank/Destroy() - STOP_PROCESSING(SSobj, src) - QDEL_NULL(air_contents) - return ..() - -/obj/item/weapon/tank/examine(mob/user) - ..() - var/obj/O = src - if (istype(src.loc, /obj/item/assembly)) - O = src.loc - if (!in_range(src, usr)) - if (O == src) - to_chat(user, "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" - - to_chat(user, "[bicon(src)] \The [src] feels [descriptive].") - -/obj/item/weapon/tank/blob_act() - if(prob(50)) - var/turf/location = loc - if(!isturf(location)) - qdel(src) - - if(air_contents) - location.assume_air(air_contents) - - qdel(src) - -/obj/item/weapon/tank/attackby(obj/item/weapon/W, mob/user) - ..() - //var/obj/icon = src - - //if (istype(src.loc, /obj/item/assembly)) - // icon = src.loc // wtf is this? - - if (istype(W, /obj/item/device/analyzer)) - return - else if (istype(W,/obj/item/latexballon)) - var/obj/item/latexballon/LB = W - LB.blow(src) - add_fingerprint(user) - - if(istype(W, /obj/item/device/assembly_holder)) - bomb_assemble(W,user) - -/obj/item/weapon/tank/attack_self(mob/user) - if (!(src.air_contents)) - return - - ui_interact(user) - -/obj/item/weapon/tank/ui_interact(mob/user, ui_key = "main", 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 (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, "\blue 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 - to_chat(usr, "\blue You open \the [src] valve.") - if (location.internals) - location.internals.icon_state = "internal1" - else - to_chat(usr, "\blue 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 - air_contents.react() - check_status() - - -/obj/item/weapon/tank/proc/check_status() - //Handle exploding, leaking, and rupturing of the tank - - 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]. (JMP)") - log_game("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].") - //world << "\blue[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 - range = min(range, MAX_EXPLOSION_RANGE) // was 8 - - - Changed to a configurable define -- TLE - var/turf/epicenter = get_turf(loc) - - //world << "\blue Exploding Pressure: [pressure] kPa, intensity: [range]" - - explosion(epicenter, round(range*0.25), round(range*0.5), round(range), round(range*1.5)) - qdel(src) - - else if(pressure > TANK_RUPTURE_PRESSURE) - //world << "\blue[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(src.loc, 'sound/effects/spray.ogg', 10, 1, -3) - qdel(src) - else - integrity-- - - else if(pressure > TANK_LEAK_PRESSURE) - //world << "\blue[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++ +#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 = CONDUCT + slot_flags = SLOT_BACK + w_class = 3 + + 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/atom_init() + . = ..() + + air_contents = new + air_contents.volume = volume //liters + air_contents.temperature = T20C + + START_PROCESSING(SSobj, src) + +/obj/item/weapon/tank/Destroy() + STOP_PROCESSING(SSobj, src) + QDEL_NULL(air_contents) + return ..() + +/obj/item/weapon/tank/examine(mob/user) + ..() + var/obj/O = src + if (istype(src.loc, /obj/item/assembly)) + O = src.loc + if (!in_range(src, usr)) + if (O == src) + to_chat(user, "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" + + to_chat(user, "[bicon(src)] \The [src] feels [descriptive].") + +/obj/item/weapon/tank/blob_act() + if(prob(50)) + var/turf/location = loc + if(!isturf(location)) + qdel(src) + + if(air_contents) + location.assume_air(air_contents) + + qdel(src) + +/obj/item/weapon/tank/attackby(obj/item/weapon/W, mob/user) + ..() + //var/obj/icon = src + + //if (istype(src.loc, /obj/item/assembly)) + // icon = src.loc // wtf is this? + + if (istype(W, /obj/item/device/analyzer)) + return + else if (istype(W,/obj/item/latexballon)) + var/obj/item/latexballon/LB = W + LB.blow(src) + add_fingerprint(user) + + if(istype(W, /obj/item/device/assembly_holder)) + bomb_assemble(W,user) + +/obj/item/weapon/tank/attack_self(mob/user) + if (!(src.air_contents)) + return + + ui_interact(user) + +/obj/item/weapon/tank/ui_interact(mob/user, ui_key = "main", 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 (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, "\blue 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 + to_chat(usr, "\blue You open \the [src] valve.") + if (location.internals) + location.internals.icon_state = "internal1" + else + to_chat(usr, "\blue 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 + air_contents.react() + check_status() + + +/obj/item/weapon/tank/proc/check_status() + //Handle exploding, leaking, and rupturing of the tank + + 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]. (JMP)") + log_game("Explosive tank rupture! last key to touch the tank was [src.fingerprintslast].") + //world << "\blue[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 + range = min(range, MAX_EXPLOSION_RANGE) // was 8 - - - Changed to a configurable define -- TLE + var/turf/epicenter = get_turf(loc) + + //world << "\blue Exploding Pressure: [pressure] kPa, intensity: [range]" + + explosion(epicenter, round(range*0.25), round(range*0.5), round(range), round(range*1.5)) + qdel(src) + + else if(pressure > TANK_RUPTURE_PRESSURE) + //world << "\blue[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(src.loc, 'sound/effects/spray.ogg', 10, 1, -3) + qdel(src) + else + integrity-- + + else if(pressure > TANK_LEAK_PRESSURE) + //world << "\blue[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++ diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index 9d3e624b27a5..c0a10881fc90 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -1,180 +1,180 @@ -/* 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 = CONDUCT - w_class = 2.0 - item_state = "electronic" - throw_speed = 4 - throw_range = 20 - m_amt = 400 - origin_tech = "magnets=1" - -/obj/item/weapon/locator/attack_self(mob/user) - 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(entity_ja(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/device/radio/beacon/W in radio_beacon_list) - 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 implant_list) - if (!W.implanted || !(istype(W.loc,/obj/item/organ/external) || ismob(W.loc))) - continue - else - var/mob/M = W.loc - if (M.stat == DEAD) - 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],[sr.y],[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 - */ -/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 - m_amt = 10000 - origin_tech = "magnets=1;bluespace=3" - -/obj/item/weapon/hand_tele/attack_self(mob/user) - if(!user.IsAdvancedToolUser()) - to_chat(user, "You don't have the dexterity to do this!") - return - 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/com in teleporter_list) - if(com.target) - if(com.target.z == ZLEVEL_CENTCOMM) - continue - if(com.power_station && com.power_station.teleporter_hub && com.power_station.engaged) - L["[com.id] (Active)"] = com.target - else - L["[com.id] (Inactive)"] = com.target - var/list/turfs = list( ) - for(var/turf/T in orange(10)) - if(T.x>world.maxx-8 || T.x<8) continue //putting them at the edge is dumb - if(T.y>world.maxy-8 || T.y<8) continue - turfs += T - if(turfs.len) - L["None (Dangerous)"] = pick(turfs) - 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 - var/count = 0 //num of portals from this teleport in world - for(var/obj/effect/portal/PO in portal_list) - if(PO.creator == src) count++ - if(count >= 3) - user.show_message("\The [src] is recharging!") - return - var/T = L[t1] - for(var/mob/O in hearers(user, null)) - O.show_message("Locked In.", 2) - var/obj/effect/portal/P = new /obj/effect/portal( get_turf(src) ) - P.target = T - P.creator = src - src.add_fingerprint(user) - return - - +/* 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 = CONDUCT + w_class = 2.0 + item_state = "electronic" + throw_speed = 4 + throw_range = 20 + m_amt = 400 + origin_tech = "magnets=1" + +/obj/item/weapon/locator/attack_self(mob/user) + 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(entity_ja(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/device/radio/beacon/W in radio_beacon_list) + 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 implant_list) + if (!W.implanted || !(istype(W.loc,/obj/item/organ/external) || ismob(W.loc))) + continue + else + var/mob/M = W.loc + if (M.stat == DEAD) + 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],[sr.y],[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 + */ +/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 + m_amt = 10000 + origin_tech = "magnets=1;bluespace=3" + +/obj/item/weapon/hand_tele/attack_self(mob/user) + if(!user.IsAdvancedToolUser()) + to_chat(user, "You don't have the dexterity to do this!") + return + 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/com in teleporter_list) + if(com.target) + if(com.target.z == ZLEVEL_CENTCOMM) + continue + if(com.power_station && com.power_station.teleporter_hub && com.power_station.engaged) + L["[com.id] (Active)"] = com.target + else + L["[com.id] (Inactive)"] = com.target + var/list/turfs = list( ) + for(var/turf/T in orange(10)) + if(T.x>world.maxx-8 || T.x<8) continue //putting them at the edge is dumb + if(T.y>world.maxy-8 || T.y<8) continue + turfs += T + if(turfs.len) + L["None (Dangerous)"] = pick(turfs) + 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 + var/count = 0 //num of portals from this teleport in world + for(var/obj/effect/portal/PO in portal_list) + if(PO.creator == src) count++ + if(count >= 3) + user.show_message("\The [src] is recharging!") + return + var/T = L[t1] + for(var/mob/O in hearers(user, null)) + O.show_message("Locked In.", 2) + var/obj/effect/portal/P = new /obj/effect/portal( get_turf(src) ) + P.target = T + P.creator = src + src.add_fingerprint(user) + return + + diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index e489476916d1..a022969972a7 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -1,570 +1,570 @@ -//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 - */ - -/* - * Wrench - */ -/obj/item/weapon/wrench - name = "wrench" - desc = "A wrench with many common uses. Can be usually found in your hand." - icon = 'icons/obj/tools.dmi' - icon_state = "wrench" - flags = CONDUCT - slot_flags = SLOT_BELT - force = 5.0 - throwforce = 7.0 - w_class = 2.0 - m_amt = 150 - origin_tech = "materials=1;engineering=1" - attack_verb = list("bashed", "battered", "bludgeoned", "whacked") - -/obj/item/weapon/wrench/power - name = "Hand Drill" - desc ="A simple powered drill with a bolt bit" - icon_state = "drill_bolt" - item_state = "drill" - materials = list(MAT_METAL=150, MAT_SILVER=50) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - throwforce = 8 - attack_verb = list("drilled", "screwed", "jabbed") - action_button_name = "Change mode" - -/obj/item/weapon/wrench/power/attack_self(mob/user) - playsound(user, 'sound/items/change_drill.ogg', 50, 1) - var/obj/item/weapon/screwdriver/power/s_drill = new - to_chat(user, "You attach the screw driver bit to [src].") - qdel(src) - user.put_in_active_hand(s_drill) - -/* - * Screwdriver - */ -/obj/item/weapon/screwdriver - name = "screwdriver" - desc = "You can be totally screwwy with this." - icon = 'icons/obj/tools.dmi' - icon_state = "screwdriver_map" - flags = CONDUCT - slot_flags = SLOT_BELT - force = 5.0 - w_class = 1.0 - throwforce = 5.0 - throw_speed = 3 - throw_range = 5 - g_amt = 0 - m_amt = 75 - attack_verb = list("stabbed") - var/random_color = TRUE - - 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/atom_init(mapload, param_color) - . = ..() - if(random_color) - if(!param_color) - param_color = pick("red", "blue", "purple", "brown", "green", "cyan", "yellow") - icon_state = "screwdriver_[param_color]" - item_state = "screwdriver_[param_color]" - - pixel_y = rand(-6, 6) - pixel_x = rand(-4, 4) - -/obj/item/weapon/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) - if(!istype(M) || user.a_intent == "help") - return ..() - if(def_zone != O_EYES && def_zone != BP_HEAD) - return ..() - if((CLUMSY in user.mutations) && prob(50)) - M = user - return eyestab(M,user) - -/obj/item/weapon/screwdriver/power - name = "Hand Drill" - desc = "A simple hand drill with a screwdriver bit attached." - icon_state = "drill_screw" - item_state = "drill" - materials = list(MAT_METAL=150, MAT_SILVER=50) - origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get - force = 8 //might or might not be too high, subject to change - throwforce = 8 - throw_speed = 2 - throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far - attack_verb = list("drilled", "screwed", "jabbed","whacked") - hitsound = 'sound/items/drill_hit.ogg' - action_button_name = "Change mode" - random_color = FALSE - -/obj/item/weapon/screwdriver/power/attack_self(mob/user) - playsound(user, 'sound/items/change_drill.ogg', 50, 1) - var/obj/item/weapon/wrench/power/b_drill = new - to_chat(user, "You attach the bolt driver bit to [src].") - qdel(src) - user.put_in_active_hand(b_drill) -/* - * Wirecutters - */ -/obj/item/weapon/wirecutters - name = "wirecutters" - desc = "This cuts wires." - icon = 'icons/obj/tools.dmi' - icon_state = "cutters_map" - flags = CONDUCT - slot_flags = SLOT_BELT - force = 6.0 - throw_speed = 2 - throw_range = 9 - w_class = 2.0 - m_amt = 80 - origin_tech = "materials=1;engineering=1" - attack_verb = list("pinched", "nipped") - sharp = 1 - edge = 1 - var/random_color = TRUE - -/obj/item/weapon/wirecutters/atom_init(mapload, param_color) - . = ..() - if(random_color) - if(!param_color) - param_color = pick("yellow","red","orange") - icon_state = "cutters_[param_color]" - item_state = "cutters_[param_color]" - -/obj/item/weapon/wirecutters/attack(mob/living/carbon/C, mob/user) - if(istype(C) && 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 = null - if(C.buckled && C.buckled.buckle_require_restraints) - C.buckled.unbuckle_mob() - C.update_inv_handcuffed() - return - else - ..() - -/obj/item/weapon/wirecutters/power - name = "Jaws of Life" - desc = "A set of jaws of life, the magic of science has managed to fit it down into a device small enough to fit in a tool belt. It's fitted with a cutting head." - icon = 'icons/obj/tools.dmi' - icon_state = "jaws_cutter" - item_state = "jawsoflife" - origin_tech = "materials=2;engineering=2" - materials = list(MAT_METAL=150, MAT_SILVER=50) - action_button_name = "Change mode" - random_color = FALSE - -/obj/item/weapon/wirecutters/power/attack_self(mob/user) - playsound(user, 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/weapon/crowbar/power/pryjaws = new - to_chat(user, "You attach the pry jaws to [src].") - qdel(src) - user.put_in_active_hand(pryjaws) - -/* - * Welding Tool - */ -/obj/item/weapon/weldingtool - name = "welding tool" - icon = 'icons/obj/tools.dmi' - icon_state = "welder" - flags = CONDUCT - slot_flags = SLOT_BELT - action_button_name = "Switch Welding tool" - - //Amount of OUCH when it's thrown - force = 3.0 - throwforce = 5.0 - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - - //Cost to make in the autolathe - m_amt = 70 - g_amt = 30 - - //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 - -/obj/item/weapon/weldingtool/atom_init() - . = ..() -// var/random_fuel = min(rand(10,20),max_fuel) - var/datum/reagents/R = new/datum/reagents(max_fuel) - reagents = R - R.my_atom = src - R.add_reagent("fuel", max_fuel) - - -/obj/item/weapon/weldingtool/examine(mob/user) - ..() - if(src in user) - to_chat(user, "[src] contains [get_fuel()]/[max_fuel] units of fuel!") - - -/obj/item/weapon/weldingtool/attackby(obj/item/W, mob/user) - if(istype(W,/obj/item/weapon/screwdriver)) - if(welding) - to_chat(user, "Stop welding first!") - return - status = !status - if(status) - to_chat(user, "You resecure the welder.") - 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 - if(!R.use(1)) - return - 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.remove_from_mob(src) - else - user.remove_from_mob(src) - src.master = F - src.layer = initial(src.layer) - user.remove_from_mob(src) - 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 = initial(src.icon_state) - src.welding = 0 - set_light(0) - if (!istype(src, /obj/item/weapon/weldingtool/experimental)) - STOP_PROCESSING(SSobj, 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 = initial(src.icon_state) + "1" - if(prob(5)) - remove_fuel(1) - light_color = LIGHT_COLOR_FIRE - set_light(2) - - //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, src) - - -/obj/item/weapon/weldingtool/afterattack(obj/O, mob/user, 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(src.loc, '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. (JMP)") - 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, src) - - if(isliving(O)) //Welding can ignite mobs, splashed with fuel - var/mob/living/L = O - L.IgniteMob() - if(isturf(O)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() - s.set_up(3, 1, O) - s.start() - else if(isobj(O)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() - s.set_up(3, 1, O) - s.start() - return - - -/obj/item/weapon/weldingtool/attack_self(mob/user) - 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(amount = 1, 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 - -//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(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 = initial(src.icon_state) + "1" - START_PROCESSING(SSobj, src) - else - to_chat(usr, "Need more fuel!") - src.welding = 0 - return - //Otherwise - else - to_chat(usr, "The [src] switches off.") - src.force = 3 - src.damtype = "brute" - src.icon_state = initial(src.icon_state) - 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(message = 0) - if(!status) return - if(!usr) 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 = initial(src.icon_state) + "1" - START_PROCESSING(SSobj, src) - else - to_chat(usr, "Need more fuel!") - src.welding = 0 - return - else - if(!message) - to_chat(usr, "You switch the [src] off.") - else - to_chat(usr, "The [src] shuts off!") - src.force = 3 - src.damtype = "brute" - src.icon_state = initial(src.icon_state) - src.welding = 0 - - if(usr.hand) - usr.update_inv_l_hand() - else - usr.update_inv_r_hand() - -//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) - if(!iscarbon(user)) return 1 - var/safety = user:eyecheck() - if(istype(user, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - var/obj/item/organ/internal/eyes/IO = H.organs_by_name[O_EYES] - if(H.species.flags[IS_SYNTHETIC]) - return - switch(safety) - if(1) - to_chat(usr, "Your eyes sting a little.") - IO.damage += rand(1, 2) - if(IO.damage > 12) - user.eye_blurry += rand(3,6) - if(0) - to_chat(usr, "Your eyes burn.") - IO.damage += rand(2, 4) - if(IO.damage > 10) - IO.damage += rand(4,10) - if(-1) - to_chat(usr, "Your thermals intensify the welder's glow. Your eyes itch and burn severely.") - user.eye_blurry += rand(12,20) - IO.damage += rand(12, 16) - if(safety<2) - - if(IO.damage > 10) - to_chat(user, "Your eyes are really starting to hurt. This can't be good for you!") - - if (IO.damage >= IO.min_broken_damage) - to_chat(user, "You go blind!") - user.sdisabilities |= BLIND - else if (IO.damage >= IO.min_bruised_damage) - to_chat(user, "You go blind!") - user.eye_blind = 5 - user.eye_blurry = 5 - user.disabilities |= NEARSIGHTED - spawn(100) - user.disabilities &= ~NEARSIGHTED - return - - -/obj/item/weapon/weldingtool/largetank - name = "Industrial Welding Tool" - icon = 'icons/obj/tools.dmi' - icon_state = "indwelder" - max_fuel = 40 - m_amt = 70 - g_amt = 60 - origin_tech = "engineering=2" - -/obj/item/weapon/weldingtool/hugetank - name = "Upgraded Welding Tool" - icon = 'icons/obj/tools.dmi' - icon_state = "hugewelder" - max_fuel = 80 - w_class = 3.0 - m_amt = 70 - g_amt = 120 - origin_tech = "engineering=3" - -/obj/item/weapon/weldingtool/experimental - name = "Experimental Welding Tool" - icon = 'icons/obj/tools.dmi' - icon_state = "expwelder" - max_fuel = 40 - w_class = 3.0 - m_amt = 70 - g_amt = 120 - origin_tech = "materials=4;engineering=4;bluespace=2;phorontech=3" - var/next_refuel_tick = 0 - -/obj/item/weapon/weldingtool/experimental/process() - ..() - if((get_fuel() < max_fuel) && (next_refuel_tick < world.time) && !welding) - next_refuel_tick = world.time + 2.5 SECONDS - reagents.add_reagent("fuel", 1) - if(!welding && (get_fuel() == max_fuel)) - STOP_PROCESSING(SSobj, src) -/* - * Crowbar - */ - -/obj/item/weapon/crowbar - name = "crowbar" - desc = "Used to remove floors and to pry open doors." - icon = 'icons/obj/tools.dmi' - icon_state = "crowbar" - flags = CONDUCT - slot_flags = SLOT_BELT - force = 5.0 - throwforce = 7.0 - item_state = "crowbar" - w_class = 2.0 - m_amt = 50 - origin_tech = "engineering=1" - attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") - -/obj/item/weapon/crowbar/red - icon_state = "red_crowbar" - item_state = "crowbar_red" - -/obj/item/weapon/crowbar/power - name = "Jaws of Life" - desc = "A set of jaws of life, the magic of science has managed to fit it down into a device small enough to fit in a tool belt. It's fitted with a prying head" - icon_state = "jaws_pry" - item_state = "jawsoflife" - materials = list(MAT_METAL=150, MAT_SILVER=50) - origin_tech = "materials=2;engineering=2" - force = 15 - action_button_name = "Change mode" - -/obj/item/weapon/crowbar/power/attack_self(mob/user) - playsound(user, 'sound/items/change_jaws.ogg', 50, 1) - var/obj/item/weapon/wirecutters/power/cutjaws = new - to_chat(user, "You attach the cutting jaws to [src].") - qdel(src) - user.put_in_active_hand(cutjaws) - -/obj/item/weapon/weldingtool/attack(mob/M, mob/user, def_zone) - - if(ishuman(M)) - var/mob/living/carbon/human/H = M - - var/obj/item/organ/external/BP = H.get_bodypart(def_zone) - if(!BP) - return - if(!(BP.status & ORGAN_ROBOT) || user.a_intent != "help") - return ..() - - if(H.species.flags[IS_SYNTHETIC]) - if(M == user) - to_chat(user, "You can't repair damage to your own body - it's against OH&S.") - return - - if(BP.brute_dam) - BP.heal_damage(15,0,0,1) - user.visible_message("\The [user] patches some dents on \the [M]'s [BP.name] with \the [src].") - else - to_chat(user, "Nothing to fix!") - - else - return ..() +//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 + */ + +/* + * Wrench + */ +/obj/item/weapon/wrench + name = "wrench" + desc = "A wrench with many common uses. Can be usually found in your hand." + icon = 'icons/obj/tools.dmi' + icon_state = "wrench" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 5.0 + throwforce = 7.0 + w_class = 2.0 + m_amt = 150 + origin_tech = "materials=1;engineering=1" + attack_verb = list("bashed", "battered", "bludgeoned", "whacked") + +/obj/item/weapon/wrench/power + name = "Hand Drill" + desc ="A simple powered drill with a bolt bit" + icon_state = "drill_bolt" + item_state = "drill" + materials = list(MAT_METAL=150, MAT_SILVER=50) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + throwforce = 8 + attack_verb = list("drilled", "screwed", "jabbed") + action_button_name = "Change mode" + +/obj/item/weapon/wrench/power/attack_self(mob/user) + playsound(user, 'sound/items/change_drill.ogg', 50, 1) + var/obj/item/weapon/screwdriver/power/s_drill = new + to_chat(user, "You attach the screw driver bit to [src].") + qdel(src) + user.put_in_active_hand(s_drill) + +/* + * Screwdriver + */ +/obj/item/weapon/screwdriver + name = "screwdriver" + desc = "You can be totally screwwy with this." + icon = 'icons/obj/tools.dmi' + icon_state = "screwdriver_map" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 5.0 + w_class = 1.0 + throwforce = 5.0 + throw_speed = 3 + throw_range = 5 + g_amt = 0 + m_amt = 75 + attack_verb = list("stabbed") + var/random_color = TRUE + + 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/atom_init(mapload, param_color) + . = ..() + if(random_color) + if(!param_color) + param_color = pick("red", "blue", "purple", "brown", "green", "cyan", "yellow") + icon_state = "screwdriver_[param_color]" + item_state = "screwdriver_[param_color]" + + pixel_y = rand(-6, 6) + pixel_x = rand(-4, 4) + +/obj/item/weapon/screwdriver/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) + if(!istype(M) || user.a_intent == "help") + return ..() + if(def_zone != O_EYES && def_zone != BP_HEAD) + return ..() + if((CLUMSY in user.mutations) && prob(50)) + M = user + return eyestab(M,user) + +/obj/item/weapon/screwdriver/power + name = "Hand Drill" + desc = "A simple hand drill with a screwdriver bit attached." + icon_state = "drill_screw" + item_state = "drill" + materials = list(MAT_METAL=150, MAT_SILVER=50) + origin_tech = "materials=2;engineering=2" //done for balance reasons, making them high value for research, but harder to get + force = 8 //might or might not be too high, subject to change + throwforce = 8 + throw_speed = 2 + throw_range = 3//it's heavier than a screw driver/wrench, so it does more damage, but can't be thrown as far + attack_verb = list("drilled", "screwed", "jabbed","whacked") + hitsound = 'sound/items/drill_hit.ogg' + action_button_name = "Change mode" + random_color = FALSE + +/obj/item/weapon/screwdriver/power/attack_self(mob/user) + playsound(user, 'sound/items/change_drill.ogg', 50, 1) + var/obj/item/weapon/wrench/power/b_drill = new + to_chat(user, "You attach the bolt driver bit to [src].") + qdel(src) + user.put_in_active_hand(b_drill) +/* + * Wirecutters + */ +/obj/item/weapon/wirecutters + name = "wirecutters" + desc = "This cuts wires." + icon = 'icons/obj/tools.dmi' + icon_state = "cutters_map" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 6.0 + throw_speed = 2 + throw_range = 9 + w_class = 2.0 + m_amt = 80 + origin_tech = "materials=1;engineering=1" + attack_verb = list("pinched", "nipped") + sharp = 1 + edge = 1 + var/random_color = TRUE + +/obj/item/weapon/wirecutters/atom_init(mapload, param_color) + . = ..() + if(random_color) + if(!param_color) + param_color = pick("yellow","red","orange") + icon_state = "cutters_[param_color]" + item_state = "cutters_[param_color]" + +/obj/item/weapon/wirecutters/attack(mob/living/carbon/C, mob/user) + if(istype(C) && 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 = null + if(C.buckled && C.buckled.buckle_require_restraints) + C.buckled.unbuckle_mob() + C.update_inv_handcuffed() + return + else + ..() + +/obj/item/weapon/wirecutters/power + name = "Jaws of Life" + desc = "A set of jaws of life, the magic of science has managed to fit it down into a device small enough to fit in a tool belt. It's fitted with a cutting head." + icon = 'icons/obj/tools.dmi' + icon_state = "jaws_cutter" + item_state = "jawsoflife" + origin_tech = "materials=2;engineering=2" + materials = list(MAT_METAL=150, MAT_SILVER=50) + action_button_name = "Change mode" + random_color = FALSE + +/obj/item/weapon/wirecutters/power/attack_self(mob/user) + playsound(user, 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/weapon/crowbar/power/pryjaws = new + to_chat(user, "You attach the pry jaws to [src].") + qdel(src) + user.put_in_active_hand(pryjaws) + +/* + * Welding Tool + */ +/obj/item/weapon/weldingtool + name = "welding tool" + icon = 'icons/obj/tools.dmi' + icon_state = "welder" + flags = CONDUCT + slot_flags = SLOT_BELT + action_button_name = "Switch Welding tool" + + //Amount of OUCH when it's thrown + force = 3.0 + throwforce = 5.0 + throw_speed = 1 + throw_range = 5 + w_class = 2.0 + + //Cost to make in the autolathe + m_amt = 70 + g_amt = 30 + + //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 + +/obj/item/weapon/weldingtool/atom_init() + . = ..() +// var/random_fuel = min(rand(10,20),max_fuel) + var/datum/reagents/R = new/datum/reagents(max_fuel) + reagents = R + R.my_atom = src + R.add_reagent("fuel", max_fuel) + + +/obj/item/weapon/weldingtool/examine(mob/user) + ..() + if(src in user) + to_chat(user, "[src] contains [get_fuel()]/[max_fuel] units of fuel!") + + +/obj/item/weapon/weldingtool/attackby(obj/item/W, mob/user) + if(istype(W,/obj/item/weapon/screwdriver)) + if(welding) + to_chat(user, "Stop welding first!") + return + status = !status + if(status) + to_chat(user, "You resecure the welder.") + 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 + if(!R.use(1)) + return + 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.remove_from_mob(src) + else + user.remove_from_mob(src) + src.master = F + src.layer = initial(src.layer) + user.remove_from_mob(src) + 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 = initial(src.icon_state) + src.welding = 0 + set_light(0) + if (!istype(src, /obj/item/weapon/weldingtool/experimental)) + STOP_PROCESSING(SSobj, 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 = initial(src.icon_state) + "1" + if(prob(5)) + remove_fuel(1) + light_color = LIGHT_COLOR_FIRE + set_light(2) + + //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, src) + + +/obj/item/weapon/weldingtool/afterattack(obj/O, mob/user, 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(src.loc, '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. (JMP)") + 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, src) + + if(isliving(O)) //Welding can ignite mobs, splashed with fuel + var/mob/living/L = O + L.IgniteMob() + if(isturf(O)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + s.set_up(3, 1, O) + s.start() + else if(isobj(O)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + s.set_up(3, 1, O) + s.start() + return + + +/obj/item/weapon/weldingtool/attack_self(mob/user) + 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(amount = 1, 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 + +//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(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 = initial(src.icon_state) + "1" + START_PROCESSING(SSobj, src) + else + to_chat(usr, "Need more fuel!") + src.welding = 0 + return + //Otherwise + else + to_chat(usr, "The [src] switches off.") + src.force = 3 + src.damtype = "brute" + src.icon_state = initial(src.icon_state) + 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(message = 0) + if(!status) return + if(!usr) 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 = initial(src.icon_state) + "1" + START_PROCESSING(SSobj, src) + else + to_chat(usr, "Need more fuel!") + src.welding = 0 + return + else + if(!message) + to_chat(usr, "You switch the [src] off.") + else + to_chat(usr, "The [src] shuts off!") + src.force = 3 + src.damtype = "brute" + src.icon_state = initial(src.icon_state) + src.welding = 0 + + if(usr.hand) + usr.update_inv_l_hand() + else + usr.update_inv_r_hand() + +//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) + if(!iscarbon(user)) return 1 + var/safety = user:eyecheck() + if(istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + var/obj/item/organ/internal/eyes/IO = H.organs_by_name[O_EYES] + if(H.species.flags[IS_SYNTHETIC]) + return + switch(safety) + if(1) + to_chat(usr, "Your eyes sting a little.") + IO.damage += rand(1, 2) + if(IO.damage > 12) + user.eye_blurry += rand(3,6) + if(0) + to_chat(usr, "Your eyes burn.") + IO.damage += rand(2, 4) + if(IO.damage > 10) + IO.damage += rand(4,10) + if(-1) + to_chat(usr, "Your thermals intensify the welder's glow. Your eyes itch and burn severely.") + user.eye_blurry += rand(12,20) + IO.damage += rand(12, 16) + if(safety<2) + + if(IO.damage > 10) + to_chat(user, "Your eyes are really starting to hurt. This can't be good for you!") + + if (IO.damage >= IO.min_broken_damage) + to_chat(user, "You go blind!") + user.sdisabilities |= BLIND + else if (IO.damage >= IO.min_bruised_damage) + to_chat(user, "You go blind!") + user.eye_blind = 5 + user.eye_blurry = 5 + user.disabilities |= NEARSIGHTED + spawn(100) + user.disabilities &= ~NEARSIGHTED + return + + +/obj/item/weapon/weldingtool/largetank + name = "Industrial Welding Tool" + icon = 'icons/obj/tools.dmi' + icon_state = "indwelder" + max_fuel = 40 + m_amt = 70 + g_amt = 60 + origin_tech = "engineering=2" + +/obj/item/weapon/weldingtool/hugetank + name = "Upgraded Welding Tool" + icon = 'icons/obj/tools.dmi' + icon_state = "hugewelder" + max_fuel = 80 + w_class = 3.0 + m_amt = 70 + g_amt = 120 + origin_tech = "engineering=3" + +/obj/item/weapon/weldingtool/experimental + name = "Experimental Welding Tool" + icon = 'icons/obj/tools.dmi' + icon_state = "expwelder" + max_fuel = 40 + w_class = 3.0 + m_amt = 70 + g_amt = 120 + origin_tech = "materials=4;engineering=4;bluespace=2;phorontech=3" + var/next_refuel_tick = 0 + +/obj/item/weapon/weldingtool/experimental/process() + ..() + if((get_fuel() < max_fuel) && (next_refuel_tick < world.time) && !welding) + next_refuel_tick = world.time + 2.5 SECONDS + reagents.add_reagent("fuel", 1) + if(!welding && (get_fuel() == max_fuel)) + STOP_PROCESSING(SSobj, src) +/* + * Crowbar + */ + +/obj/item/weapon/crowbar + name = "crowbar" + desc = "Used to remove floors and to pry open doors." + icon = 'icons/obj/tools.dmi' + icon_state = "crowbar" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 5.0 + throwforce = 7.0 + item_state = "crowbar" + w_class = 2.0 + m_amt = 50 + origin_tech = "engineering=1" + attack_verb = list("attacked", "bashed", "battered", "bludgeoned", "whacked") + +/obj/item/weapon/crowbar/red + icon_state = "red_crowbar" + item_state = "crowbar_red" + +/obj/item/weapon/crowbar/power + name = "Jaws of Life" + desc = "A set of jaws of life, the magic of science has managed to fit it down into a device small enough to fit in a tool belt. It's fitted with a prying head" + icon_state = "jaws_pry" + item_state = "jawsoflife" + materials = list(MAT_METAL=150, MAT_SILVER=50) + origin_tech = "materials=2;engineering=2" + force = 15 + action_button_name = "Change mode" + +/obj/item/weapon/crowbar/power/attack_self(mob/user) + playsound(user, 'sound/items/change_jaws.ogg', 50, 1) + var/obj/item/weapon/wirecutters/power/cutjaws = new + to_chat(user, "You attach the cutting jaws to [src].") + qdel(src) + user.put_in_active_hand(cutjaws) + +/obj/item/weapon/weldingtool/attack(mob/M, mob/user, def_zone) + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + + var/obj/item/organ/external/BP = H.get_bodypart(def_zone) + if(!BP) + return + if(!(BP.status & ORGAN_ROBOT) || user.a_intent != "help") + return ..() + + if(H.species.flags[IS_SYNTHETIC]) + if(M == user) + to_chat(user, "You can't repair damage to your own body - it's against OH&S.") + return + + if(BP.brute_dam) + BP.heal_damage(15,0,0,1) + user.visible_message("\The [user] patches some dents on \the [M]'s [BP.name] with \the [src].") + else + to_chat(user, "Nothing to fix!") + + else + return ..() diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index c82d6594679f..e1f67cc1e317 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -1,272 +1,272 @@ -#define DUALSABER_BLOCK_CHANCE_MODIFIER 1.2 - -/* Two-handed Weapons - * Contains: - * Twohanded - * Fireaxe - * Double-Bladed Energy Swords - */ - -/*################################################################## -##################### TWO HANDED WEAPONS BE HERE~ -Agouri :3 ######## -####################################################################*/ - -//Rewrote TwoHanded weapons stuff and put it all here. Just copypasta fireaxe to make new ones ~Carn -//This rewrite means we don't have two variables for EVERY item which are used only by a few weapons. -//It also tidies stuff up elsewhere. - -/* - * Twohanded - */ -/obj/item/weapon/twohanded - var/wielded = 0 - var/force_unwielded = 0 - var/force_wielded = 0 - var/wieldsound = null - var/unwieldsound = null - var/obj/item/weapon/twohanded/offhand/offhand_item = /obj/item/weapon/twohanded/offhand - -/obj/item/weapon/twohanded/proc/unwield() - wielded = 0 - force = force_unwielded - name = "[initial(name)]" - update_icon() - -/obj/item/weapon/twohanded/proc/wield() - wielded = 1 - force = force_wielded - name = "[initial(name)] (Wielded)" - update_icon() - -/obj/item/weapon/twohanded/mob_can_equip(M, slot) - //Cannot equip wielded items. - if(wielded) - to_chat(M, "Unwield the [initial(name)] first!") - return 0 - - return ..() - -/obj/item/weapon/twohanded/dropped(mob/user) - //handles unwielding a twohanded weapon when dropped as well as clearing up the offhand - if(user) - var/obj/item/weapon/twohanded/O = user.get_inactive_hand() - if(istype(O)) - user.drop_from_inventory(O) - return unwield() - -/obj/item/weapon/twohanded/update_icon() - return - -/obj/item/weapon/twohanded/pickup(mob/user) - unwield() - -/obj/item/weapon/twohanded/attack_self(mob/user) - if(istype(user,/mob/living/carbon/monkey)) - to_chat(user, "It's too heavy for you to wield fully.") - return - - ..() - if(wielded) //Trying to unwield it - unwield() - to_chat(user, "You are now carrying the [name] with one hand.") - if(user.hand) - user.update_inv_l_hand() - else - user.update_inv_r_hand() - - if (src.unwieldsound) - playsound(src.loc, unwieldsound, 50, 1) - - var/obj/item/weapon/twohanded/offhand/O = user.get_inactive_hand() - if(istype(O)) - user.drop_from_inventory(O) - return - - else //Trying to wield it - if(ishuman(user)) - var/mob/living/carbon/human/H = user - var/W = H.wield(src, initial(name), wieldsound) - if(W) - wield() - -///////////OFFHAND/////////////// -/obj/item/weapon/twohanded/offhand - w_class = 5.0 - icon_state = "offhand" - name = "offhand" - flags = ABSTRACT - -/obj/item/weapon/twohanded/offhand/unwield() - qdel(src) - -/obj/item/weapon/twohanded/offhand/wield() - qdel(src) - -/* - * Fireaxe - */ -/obj/item/weapon/twohanded/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?" - force = 5 - sharp = 1 - edge = 1 - w_class = 4.0 - slot_flags = SLOT_BACK - force_unwielded = 10 - force_wielded = 40 - attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") - -/obj/item/weapon/twohanded/fireaxe/update_icon() //Currently only here to fuck with the on-mob icons. - icon_state = "fireaxe[wielded]" - return - -/obj/item/weapon/twohanded/fireaxe/afterattack(atom/A, mob/user, proximity) - if(!proximity) return - ..() - if(A && wielded) //destroys windows and grilles in one hit - if(istype(A,/obj/structure/window)) //should just make a window.Break() proc but couldn't bother with it - var/obj/structure/window/W = A - W.shatter() - else if(istype(A,/obj/structure/grille)) - var/obj/structure/grille/G = A - new /obj/item/stack/rods(G.loc) - qdel(A) - - -/* - * Double-Bladed Energy Swords - Cheridan - */ -/obj/item/weapon/twohanded/dualsaber - var/reflect_chance = 0 - 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 - item_color = "green" - force_unwielded = 3 - force_wielded = 45 - var/hacked - var/slicing - wieldsound = 'sound/weapons/saberon.ogg' - unwieldsound = 'sound/weapons/saberoff.ogg' - flags = NOSHIELD - origin_tech = "magnets=3;syndicate=4" - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - sharp = 1 - edge = 1 - can_embed = 0 - -/obj/item/weapon/twohanded/dualsaber/atom_init() - . = ..() - reflect_chance = rand(50, 65) - item_color = pick("red", "blue", "green", "purple","yellow","pink","black") - switch(item_color) - if("red") - light_color = COLOR_RED - if("blue") - light_color = COLOR_BLUE - if("green") - light_color = COLOR_GREEN - if("purple") - light_color = COLOR_PURPLE - light_power = 2 - if("yellow") - light_color = COLOR_YELLOW - if("pink") - light_color = COLOR_PINK - if("black") - light_color = COLOR_GRAY - -/obj/item/weapon/twohanded/dualsaber/update_icon() - if(wielded) - icon_state = "dualsaber[item_color][wielded]" - else - icon_state = "dualsaber0" - clean_blood()//blood overlays get weird otherwise, because the sprite changes. - -/obj/item/weapon/twohanded/dualsaber/attack(target, mob/living/user) - ..() - if((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_bodypart_damage(20, 25) - return - if(wielded && prob(50)) - spawn(0) - for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2)) - user.dir = i - sleep(1) - -/obj/item/weapon/twohanded/dualsaber/Get_shield_chance() - if(wielded && !slicing) - return reflect_chance * DUALSABER_BLOCK_CHANCE_MODIFIER - 5 - else - return 0 - -/obj/item/weapon/twohanded/dualsaber/IsReflect(def_zone, hol_dir, hit_dir) - return !slicing && wielded && prob(reflect_chance) && is_the_opposite_dir(hol_dir, hit_dir) - -/obj/item/weapon/twohanded/dualsaber/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/device/multitool)) - if(!hacked) - hacked = 1 - to_chat(user,"2XRNBW_ENGAGE") - item_color = "rainbow" - light_color = "" - update_icon() - else - to_chat(user,"It's starting to look like a triple rainbow - no, nevermind.") - else - return ..() - -/obj/item/weapon/twohanded/dualsaber/afterattack(obj/O, mob/user, proximity) - if(!istype(O,/obj/machinery/door/airlock) || slicing) - return - if(O.density && wielded && proximity && in_range(user, O)) - user.visible_message("[user] start slicing the [O] ") - playsound(user.loc, 'sound/items/Welder2.ogg', 100, 1, -1) - slicing = TRUE - var/obj/machinery/door/airlock/D = O - var/obj/effect/I = new /obj/effect/overlay/slice(D.loc) - if(do_after(user, 450, target = D) && D.density && !(D.operating == -1) && in_range(user, O)) - sleep(6) - var/obj/structure/door_scrap/S = new /obj/structure/door_scrap(D.loc) - var/iconpath = D.icon - var/icon/IC = new(iconpath, "closed") - IC.Blend(S.door, ICON_OVERLAY, 1, 1) - IC.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) - S.icon = IC - S.name = D.name - S.name += " remains" - qdel(D) - qdel(IC) - playsound(user.loc, 'sound/weapons/blade1.ogg', 100, 1, -1) - slicing = FALSE - qdel(I) - - -/obj/item/weapon/twohanded/dualsaber/dropped(mob/user) - ..() - slicing = FALSE - -/obj/item/weapon/twohanded/dualsaber/attack_self(mob/user) - if(slicing) - return - ..() - -/obj/item/weapon/twohanded/dualsaber/unwield() - set_light(0) - w_class = initial(w_class) - return ..() - -/obj/item/weapon/twohanded/dualsaber/wield() - set_light(2) - w_class = 5 - return ..() - -#undef DUALSABER_BLOCK_CHANCE_MODIFIER +#define DUALSABER_BLOCK_CHANCE_MODIFIER 1.2 + +/* Two-handed Weapons + * Contains: + * Twohanded + * Fireaxe + * Double-Bladed Energy Swords + */ + +/*################################################################## +##################### TWO HANDED WEAPONS BE HERE~ -Agouri :3 ######## +####################################################################*/ + +//Rewrote TwoHanded weapons stuff and put it all here. Just copypasta fireaxe to make new ones ~Carn +//This rewrite means we don't have two variables for EVERY item which are used only by a few weapons. +//It also tidies stuff up elsewhere. + +/* + * Twohanded + */ +/obj/item/weapon/twohanded + var/wielded = 0 + var/force_unwielded = 0 + var/force_wielded = 0 + var/wieldsound = null + var/unwieldsound = null + var/obj/item/weapon/twohanded/offhand/offhand_item = /obj/item/weapon/twohanded/offhand + +/obj/item/weapon/twohanded/proc/unwield() + wielded = 0 + force = force_unwielded + name = "[initial(name)]" + update_icon() + +/obj/item/weapon/twohanded/proc/wield() + wielded = 1 + force = force_wielded + name = "[initial(name)] (Wielded)" + update_icon() + +/obj/item/weapon/twohanded/mob_can_equip(M, slot) + //Cannot equip wielded items. + if(wielded) + to_chat(M, "Unwield the [initial(name)] first!") + return 0 + + return ..() + +/obj/item/weapon/twohanded/dropped(mob/user) + //handles unwielding a twohanded weapon when dropped as well as clearing up the offhand + if(user) + var/obj/item/weapon/twohanded/O = user.get_inactive_hand() + if(istype(O)) + user.drop_from_inventory(O) + return unwield() + +/obj/item/weapon/twohanded/update_icon() + return + +/obj/item/weapon/twohanded/pickup(mob/user) + unwield() + +/obj/item/weapon/twohanded/attack_self(mob/user) + if(istype(user,/mob/living/carbon/monkey)) + to_chat(user, "It's too heavy for you to wield fully.") + return + + ..() + if(wielded) //Trying to unwield it + unwield() + to_chat(user, "You are now carrying the [name] with one hand.") + if(user.hand) + user.update_inv_l_hand() + else + user.update_inv_r_hand() + + if (src.unwieldsound) + playsound(src.loc, unwieldsound, 50, 1) + + var/obj/item/weapon/twohanded/offhand/O = user.get_inactive_hand() + if(istype(O)) + user.drop_from_inventory(O) + return + + else //Trying to wield it + if(ishuman(user)) + var/mob/living/carbon/human/H = user + var/W = H.wield(src, initial(name), wieldsound) + if(W) + wield() + +///////////OFFHAND/////////////// +/obj/item/weapon/twohanded/offhand + w_class = 5.0 + icon_state = "offhand" + name = "offhand" + flags = ABSTRACT + +/obj/item/weapon/twohanded/offhand/unwield() + qdel(src) + +/obj/item/weapon/twohanded/offhand/wield() + qdel(src) + +/* + * Fireaxe + */ +/obj/item/weapon/twohanded/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?" + force = 5 + sharp = 1 + edge = 1 + w_class = 4.0 + slot_flags = SLOT_BACK + force_unwielded = 10 + force_wielded = 40 + attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") + +/obj/item/weapon/twohanded/fireaxe/update_icon() //Currently only here to fuck with the on-mob icons. + icon_state = "fireaxe[wielded]" + return + +/obj/item/weapon/twohanded/fireaxe/afterattack(atom/A, mob/user, proximity) + if(!proximity) return + ..() + if(A && wielded) //destroys windows and grilles in one hit + if(istype(A,/obj/structure/window)) //should just make a window.Break() proc but couldn't bother with it + var/obj/structure/window/W = A + W.shatter() + else if(istype(A,/obj/structure/grille)) + var/obj/structure/grille/G = A + new /obj/item/stack/rods(G.loc) + qdel(A) + + +/* + * Double-Bladed Energy Swords - Cheridan + */ +/obj/item/weapon/twohanded/dualsaber + var/reflect_chance = 0 + 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 + item_color = "green" + force_unwielded = 3 + force_wielded = 45 + var/hacked + var/slicing + wieldsound = 'sound/weapons/saberon.ogg' + unwieldsound = 'sound/weapons/saberoff.ogg' + flags = NOSHIELD + origin_tech = "magnets=3;syndicate=4" + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + sharp = 1 + edge = 1 + can_embed = 0 + +/obj/item/weapon/twohanded/dualsaber/atom_init() + . = ..() + reflect_chance = rand(50, 65) + item_color = pick("red", "blue", "green", "purple","yellow","pink","black") + switch(item_color) + if("red") + light_color = COLOR_RED + if("blue") + light_color = COLOR_BLUE + if("green") + light_color = COLOR_GREEN + if("purple") + light_color = COLOR_PURPLE + light_power = 2 + if("yellow") + light_color = COLOR_YELLOW + if("pink") + light_color = COLOR_PINK + if("black") + light_color = COLOR_GRAY + +/obj/item/weapon/twohanded/dualsaber/update_icon() + if(wielded) + icon_state = "dualsaber[item_color][wielded]" + else + icon_state = "dualsaber0" + clean_blood()//blood overlays get weird otherwise, because the sprite changes. + +/obj/item/weapon/twohanded/dualsaber/attack(target, mob/living/user) + ..() + if((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_bodypart_damage(20, 25) + return + if(wielded && prob(50)) + spawn(0) + for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2)) + user.dir = i + sleep(1) + +/obj/item/weapon/twohanded/dualsaber/Get_shield_chance() + if(wielded && !slicing) + return reflect_chance * DUALSABER_BLOCK_CHANCE_MODIFIER - 5 + else + return 0 + +/obj/item/weapon/twohanded/dualsaber/IsReflect(def_zone, hol_dir, hit_dir) + return !slicing && wielded && prob(reflect_chance) && is_the_opposite_dir(hol_dir, hit_dir) + +/obj/item/weapon/twohanded/dualsaber/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/device/multitool)) + if(!hacked) + hacked = 1 + to_chat(user,"2XRNBW_ENGAGE") + item_color = "rainbow" + light_color = "" + update_icon() + else + to_chat(user,"It's starting to look like a triple rainbow - no, nevermind.") + else + return ..() + +/obj/item/weapon/twohanded/dualsaber/afterattack(obj/O, mob/user, proximity) + if(!istype(O,/obj/machinery/door/airlock) || slicing) + return + if(O.density && wielded && proximity && in_range(user, O)) + user.visible_message("[user] start slicing the [O] ") + playsound(user.loc, 'sound/items/Welder2.ogg', 100, 1, -1) + slicing = TRUE + var/obj/machinery/door/airlock/D = O + var/obj/effect/I = new /obj/effect/overlay/slice(D.loc) + if(do_after(user, 450, target = D) && D.density && !(D.operating == -1) && in_range(user, O)) + sleep(6) + var/obj/structure/door_scrap/S = new /obj/structure/door_scrap(D.loc) + var/iconpath = D.icon + var/icon/IC = new(iconpath, "closed") + IC.Blend(S.door, ICON_OVERLAY, 1, 1) + IC.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0)) + S.icon = IC + S.name = D.name + S.name += " remains" + qdel(D) + qdel(IC) + playsound(user.loc, 'sound/weapons/blade1.ogg', 100, 1, -1) + slicing = FALSE + qdel(I) + + +/obj/item/weapon/twohanded/dualsaber/dropped(mob/user) + ..() + slicing = FALSE + +/obj/item/weapon/twohanded/dualsaber/attack_self(mob/user) + if(slicing) + return + ..() + +/obj/item/weapon/twohanded/dualsaber/unwield() + set_light(0) + w_class = initial(w_class) + return ..() + +/obj/item/weapon/twohanded/dualsaber/wield() + set_light(2) + w_class = 5 + return ..() + +#undef DUALSABER_BLOCK_CHANCE_MODIFIER diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 6a27f19e284e..7dbf2bf089ed 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -1,205 +1,205 @@ -/obj/item/weapon/banhammer - desc = "A banhammer." - name = "banhammer" - icon = 'icons/obj/items.dmi' - icon_state = "toyhammer" - slot_flags = SLOT_BELT - throwforce = 0 - w_class = 2.0 - throw_speed = 7 - throw_range = 15 - attack_verb = list("banned") - - suicide_act(mob/user) - to_chat(viewers(user), "\red [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/nullrod - name = "null rod" - desc = "A rod of pure obsidian, its very presence disrupts and dampens the powers of paranormal phenomenae." - icon_state = "nullrod" - item_state = "nullrod" - slot_flags = SLOT_BELT - force = 15 - throw_speed = 1 - throw_range = 4 - throwforce = 10 - light_color = "#4c4cff" - light_power = 3 - w_class = 2 - var/last_process = 0 - var/datum/cult/reveal/power - var/static/list/scum - -/obj/item/weapon/nullrod/suicide_act(mob/user) - user.visible_message("[user] is impaling himself with the [name]! It looks like \he's trying to commit suicide.") - return (BRUTELOSS|FIRELOSS) - -/obj/item/weapon/nullrod/atom_init() - . = ..() - if(!scum) - scum = typecacheof(list(/mob/living/simple_animal/construct, /obj/structure/cult, /obj/effect/rune, /mob/dead/observer)) - power = new(src) - -/obj/item/weapon/nullrod/equipped(mob/user, slot) - if(user.mind && user.mind.assigned_role == "Chaplain") - START_PROCESSING(SSobj, src) - ..() - -/obj/item/weapon/nullrod/Destroy() - STOP_PROCESSING(SSobj, src) - QDEL_NULL(power) - return ..() - -/obj/item/weapon/nullrod/dropped(mob/user) - if(isprocessing) - STOP_PROCESSING(SSobj, src) - ..() - -/obj/item/weapon/nullrod/process() - if(last_process + 60 >= world.time) - return - last_process = world.time - var/turf/turf = get_turf(loc) - for(var/A in range(6, turf)) - if(iscultist(A) || is_type_in_typecache(A, scum)) - set_light(3) - addtimer(CALLBACK(src, .atom/proc/set_light, 0), 20) - return - -/obj/item/weapon/nullrod/attack(mob/M, mob/living/user) //Paste from old-code to decult with a null rod. - if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") - to_chat(user, " You don't have the dexterity to do this!") - return - - 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]) ([ADMIN_JMP(user)]) ([ADMIN_FLW(user)])") - - if ((CLUMSY in user.mutations) && prob(50)) - to_chat(user, "The rod slips out of your hand and hits your head.") - user.adjustBruteLoss(10) - user.Paralyse(20) - return - - if (M.stat != DEAD) - if((M.mind in ticker.mode.cult) && user.mind && user.mind.assigned_role == "Chaplain" && prob(33)) - to_chat(M, "The power of [src] clears your mind of the cult's influence!") - to_chat(user, "You wave [src] over [M]'s head and see their eyes become clear, their mind returning to normal.") - ticker.mode.remove_cultist(M.mind) - else - to_chat(user, "The rod appears to do nothing.") - M.visible_message("[user] waves [src] over [M.name]'s head") - -/obj/item/weapon/nullrod/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if (proximity_flag && istype(target, /turf/simulated/floor) && user.mind && user.mind.assigned_role == "Chaplain") - to_chat(user, "You hit the floor with the [src].") - power.action(user, 1) - -/obj/item/weapon/sord/attack(mob/living/carbon/M, mob/living/carbon/user) - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - 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" - flags = CONDUCT - slot_flags = SLOT_BELT - force = 40 - throwforce = 10 - sharp = 1 - edge = 1 - w_class = 3 - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - - Get_shield_chance() - return 50 - - suicide_act(mob/user) - to_chat(viewers(user), "\red [user] is falling on the [src.name]! It looks like \he's trying to commit suicide.") - return(BRUTELOSS) - -/obj/item/weapon/claymore/light - force = 20 - can_embed = 0 - -/obj/item/weapon/claymore/attack(mob/living/carbon/M, mob/living/carbon/user) - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - -/obj/item/weapon/katana - name = "katana" - desc = "Woefully underpowered in D20." - icon_state = "katana" - item_state = "katana" - flags = CONDUCT - slot_flags = SLOT_BELT | SLOT_BACK - force = 40 - throwforce = 10 - sharp = 1 - edge = 1 - w_class = 3 - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - - suicide_act(mob/user) - to_chat(viewers(user), "\red [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/Get_shield_chance() - return 50 - -/obj/item/weapon/katana/attack(mob/living/carbon/M, mob/living/carbon/user) - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return ..() - -/obj/item/weapon/harpoon - name = "harpoon" - sharp = 1 - edge = 0 - desc = "Tharr she blows!" - icon_state = "harpoon" - item_state = "harpoon" - force = 20 - throwforce = 15 - w_class = 3 - attack_verb = list("jabbed","stabbed","ripped") - -/obj/item/weapon/switchblade - name = "switchblade" - icon_state = "switchblade" - desc = "A sharp, concealable, spring-loaded knife." - flags = CONDUCT - force = 20 - w_class = 2 - throwforce = 15 - throw_speed = 3 - throw_range = 6 - m_amt = 12000 - origin_tech = "materials=1" - hitsound = 'sound/weapons/Genhit.ogg' - attack_verb = list("stubbed", "poked") - var/extended - -/obj/item/weapon/switchblade/attack_self(mob/user) - extended = !extended - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) - if(extended) - force = 20 - w_class = 3 - throwforce = 15 - icon_state = "switchblade_ext" - attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - hitsound = 'sound/weapons/bladeslice.ogg' - else - force = 1 - w_class = 2 - throwforce = 5 - icon_state = "switchblade" - attack_verb = list("stubbed", "poked") - hitsound = 'sound/weapons/Genhit.ogg' - -/obj/item/weapon/switchblade/suicide_act(mob/user) - user.visible_message("[user] is slitting \his own throat with the [src.name]! It looks like \he's trying to commit suicide.") - return (BRUTELOSS) +/obj/item/weapon/banhammer + desc = "A banhammer." + name = "banhammer" + icon = 'icons/obj/items.dmi' + icon_state = "toyhammer" + slot_flags = SLOT_BELT + throwforce = 0 + w_class = 2.0 + throw_speed = 7 + throw_range = 15 + attack_verb = list("banned") + + suicide_act(mob/user) + to_chat(viewers(user), "\red [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/nullrod + name = "null rod" + desc = "A rod of pure obsidian, its very presence disrupts and dampens the powers of paranormal phenomenae." + icon_state = "nullrod" + item_state = "nullrod" + slot_flags = SLOT_BELT + force = 15 + throw_speed = 1 + throw_range = 4 + throwforce = 10 + light_color = "#4c4cff" + light_power = 3 + w_class = 2 + var/last_process = 0 + var/datum/cult/reveal/power + var/static/list/scum + +/obj/item/weapon/nullrod/suicide_act(mob/user) + user.visible_message("[user] is impaling himself with the [name]! It looks like \he's trying to commit suicide.") + return (BRUTELOSS|FIRELOSS) + +/obj/item/weapon/nullrod/atom_init() + . = ..() + if(!scum) + scum = typecacheof(list(/mob/living/simple_animal/construct, /obj/structure/cult, /obj/effect/rune, /mob/dead/observer)) + power = new(src) + +/obj/item/weapon/nullrod/equipped(mob/user, slot) + if(user.mind && user.mind.assigned_role == "Chaplain") + START_PROCESSING(SSobj, src) + ..() + +/obj/item/weapon/nullrod/Destroy() + STOP_PROCESSING(SSobj, src) + QDEL_NULL(power) + return ..() + +/obj/item/weapon/nullrod/dropped(mob/user) + if(isprocessing) + STOP_PROCESSING(SSobj, src) + ..() + +/obj/item/weapon/nullrod/process() + if(last_process + 60 >= world.time) + return + last_process = world.time + var/turf/turf = get_turf(loc) + for(var/A in range(6, turf)) + if(iscultist(A) || is_type_in_typecache(A, scum)) + set_light(3) + addtimer(CALLBACK(src, .atom/proc/set_light, 0), 20) + return + +/obj/item/weapon/nullrod/attack(mob/M, mob/living/user) //Paste from old-code to decult with a null rod. + if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") + to_chat(user, " You don't have the dexterity to do this!") + return + + 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]) ([ADMIN_JMP(user)]) ([ADMIN_FLW(user)])") + + if ((CLUMSY in user.mutations) && prob(50)) + to_chat(user, "The rod slips out of your hand and hits your head.") + user.adjustBruteLoss(10) + user.Paralyse(20) + return + + if (M.stat != DEAD) + if((M.mind in ticker.mode.cult) && user.mind && user.mind.assigned_role == "Chaplain" && prob(33)) + to_chat(M, "The power of [src] clears your mind of the cult's influence!") + to_chat(user, "You wave [src] over [M]'s head and see their eyes become clear, their mind returning to normal.") + ticker.mode.remove_cultist(M.mind) + else + to_chat(user, "The rod appears to do nothing.") + M.visible_message("[user] waves [src] over [M.name]'s head") + +/obj/item/weapon/nullrod/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if (proximity_flag && istype(target, /turf/simulated/floor) && user.mind && user.mind.assigned_role == "Chaplain") + to_chat(user, "You hit the floor with the [src].") + power.action(user, 1) + +/obj/item/weapon/sord/attack(mob/living/carbon/M, mob/living/carbon/user) + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + 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" + flags = CONDUCT + slot_flags = SLOT_BELT + force = 40 + throwforce = 10 + sharp = 1 + edge = 1 + w_class = 3 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + + Get_shield_chance() + return 50 + + suicide_act(mob/user) + to_chat(viewers(user), "\red [user] is falling on the [src.name]! It looks like \he's trying to commit suicide.") + return(BRUTELOSS) + +/obj/item/weapon/claymore/light + force = 20 + can_embed = 0 + +/obj/item/weapon/claymore/attack(mob/living/carbon/M, mob/living/carbon/user) + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return ..() + +/obj/item/weapon/katana + name = "katana" + desc = "Woefully underpowered in D20." + icon_state = "katana" + item_state = "katana" + flags = CONDUCT + slot_flags = SLOT_BELT | SLOT_BACK + force = 40 + throwforce = 10 + sharp = 1 + edge = 1 + w_class = 3 + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + + suicide_act(mob/user) + to_chat(viewers(user), "\red [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/Get_shield_chance() + return 50 + +/obj/item/weapon/katana/attack(mob/living/carbon/M, mob/living/carbon/user) + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return ..() + +/obj/item/weapon/harpoon + name = "harpoon" + sharp = 1 + edge = 0 + desc = "Tharr she blows!" + icon_state = "harpoon" + item_state = "harpoon" + force = 20 + throwforce = 15 + w_class = 3 + attack_verb = list("jabbed","stabbed","ripped") + +/obj/item/weapon/switchblade + name = "switchblade" + icon_state = "switchblade" + desc = "A sharp, concealable, spring-loaded knife." + flags = CONDUCT + force = 20 + w_class = 2 + throwforce = 15 + throw_speed = 3 + throw_range = 6 + m_amt = 12000 + origin_tech = "materials=1" + hitsound = 'sound/weapons/Genhit.ogg' + attack_verb = list("stubbed", "poked") + var/extended + +/obj/item/weapon/switchblade/attack_self(mob/user) + extended = !extended + playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) + if(extended) + force = 20 + w_class = 3 + throwforce = 15 + icon_state = "switchblade_ext" + attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + hitsound = 'sound/weapons/bladeslice.ogg' + else + force = 1 + w_class = 2 + throwforce = 5 + icon_state = "switchblade" + attack_verb = list("stubbed", "poked") + hitsound = 'sound/weapons/Genhit.ogg' + +/obj/item/weapon/switchblade/suicide_act(mob/user) + user.visible_message("[user] is slitting \his own throat with the [src.name]! It looks like \he's trying to commit suicide.") + return (BRUTELOSS) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 45fb5f7fed77..6ea57aede4a1 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -1,243 +1,243 @@ -/obj - //var/datum/module/mod //not used - var/m_amt = 0 // metal - var/g_amt = 0 // glass - var/w_amt = 0 // waster amounts - 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/list/attack_verb = list() //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]" - var/sharp = 0 // whether this object cuts - var/edge = 0 // whether this object is more likely to dismember - 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 - var/icon_custom = null //Default Bay12 sprite or not - - var/being_shocked = 0 - -/obj/item/proc/is_used_on(obj/O, mob/user) - -/obj/process() - STOP_PROCESSING(SSobj, src) - return 0 - -/obj/Destroy() - if(!istype(src, /obj/machinery)) - STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists - nanomanager.close_uis(src) - return ..() - -/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/singularity_act() - ex_act(1.0) - if(src && !QDELETED(src)) - qdel(src) - return 2 - -/obj/singularity_pull(S, current_size) - if(anchored) - if(current_size >= STAGE_FIVE) - anchored = 0 - step_towards(src,S) - else - step_towards(src,S) - -// the obj is deconstructed into pieces, whether through careful disassembly or when destroyed. -/obj/proc/deconstruct(disassembled = TRUE) - qdel(src) - -/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 - -/obj/proc/updateUsrDialog() - if(in_use) - var/is_in_use = FALSE - var/list/nearby = viewers(1, src) - for(var/mob/M in nearby) - if ((M.client && M.machine == src)) - is_in_use = TRUE - if(ishuman(M)) //most users is humans, so check this first - attack_hand(M) - continue - if(isobserver(M)) //ghosts and synths must use their own attack_ procs - attack_ghost(M) - continue - if(isAI(M) || isrobot(M)) //VERY rare AI can be placed near to something - //with custom attack_ai - attack_ai(M) - continue - attack_hand(M) - if (isAI(usr) || isrobot(usr)) - if (!(usr in nearby)) - if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh. - is_in_use = TRUE - attack_ai(usr) - - if (isobserver(usr)) - if (!(usr in nearby)) - if (usr.client && usr.machine==src) - is_in_use = TRUE - attack_ghost(usr) - - // check for TK users - - if (ishuman(usr)) - if(istype(usr.l_hand, /obj/item/tk_grab) || istype(usr.r_hand, /obj/item/tk_grab/)) - if(!(usr in nearby)) - if(usr.client && usr.machine==src) - is_in_use = 1 - attack_hand(usr) - 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 = FALSE - for(var/mob/M in nearby) - if ((M.client && M.machine == src)) - is_in_use = TRUE - src.interact(M) - var/ai_in_use = AutoUpdateAI(src) - - in_use = is_in_use|ai_in_use - -/obj/attack_ghost(mob/dead/observer/user) - if(user.client.machine_interactive_ghost && ui_interact(user) != -1) - return - ..() - -/obj/proc/damage_flags() - . = 0 - if(has_edge(src)) - . |= DAM_EDGE - if(is_sharp(src)) - . |= DAM_SHARP - if(damtype == BURN) - . |= DAM_LASER - -/obj/proc/interact(mob/user) - return - -/obj/proc/container_resist() - return - -/obj/proc/update_icon() - return - -/mob/proc/unset_machine(obj/O) - if(O && O == src.machine) - src.machine = null - else - src.machine = null - -/mob/proc/set_machine(obj/O) - if(src.machine) - unset_machine(src.machine) - src.machine = O - if(istype(O)) - O.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/hides_under_flooring() - return level == 1 - -/obj/proc/hear_talk(mob/M, text, verb, datum/language/speaking) - if(talking_atom) - talking_atom.catchMessage(text, M) -/* - var/mob/mo = locate(/mob) in src - if(mo) - var/rendered = "[M.name]: [text]" - mo.show_message(rendered, 2) - */ - return - -/obj/proc/tesla_act(power) - being_shocked = 1 - var/power_bounced = power / 2 - tesla_zap(src, 3, power_bounced) - spawn(10) - reset_shocked() - -/obj/proc/reset_shocked() - being_shocked = 0 - -//mob - who is being feed -//user - who is feeding -//food - whai is feeded -//eatverb - take/drink/eat method -/proc/CanEat(user, mob, food, eatverb = "consume") - if(ishuman(mob)) - var/mob/living/carbon/human/Feeded = mob - if(Feeded.head) - var/obj/item/Head = Feeded.head - if(Head.flags & HEADCOVERSMOUTH) - if (Feeded == user) - to_chat(user, "You can't [eatverb] [food] through [Head]") - else - to_chat(user, "You can't feed [Feeded] with [food] through [Head]") - return FALSE - if(Feeded.wear_mask) - var/obj/item/Mask = Feeded.wear_mask - if(Mask.flags & MASKCOVERSMOUTH) - if (Feeded == user) - to_chat(user, "You can't [eatverb] [food] through [Mask]") - else - to_chat(user, "You can't feed [Feeded] with [food] through [Mask]") - return FALSE - return TRUE - if(isIAN(mob)) - var/mob/living/carbon/ian/dumdum = mob - if(dumdum.head) - var/obj/item/Head = dumdum.head - if(Head.flags & HEADCOVERSMOUTH) - if (dumdum == user) - to_chat(user, "You can't [eatverb] [food] through [Head]") - else - to_chat(user, "You can't feed [dumdum] with [food] through [Head]") - return FALSE - return TRUE - -/obj/proc/CanAStarPass(obj/item/weapon/card/id/ID, to_dir, caller) - return !density +/obj + //var/datum/module/mod //not used + var/m_amt = 0 // metal + var/g_amt = 0 // glass + var/w_amt = 0 // waster amounts + 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/list/attack_verb = list() //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]" + var/sharp = 0 // whether this object cuts + var/edge = 0 // whether this object is more likely to dismember + 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 + var/icon_custom = null //Default Bay12 sprite or not + + var/being_shocked = 0 + +/obj/item/proc/is_used_on(obj/O, mob/user) + +/obj/process() + STOP_PROCESSING(SSobj, src) + return 0 + +/obj/Destroy() + if(!istype(src, /obj/machinery)) + STOP_PROCESSING(SSobj, src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists + nanomanager.close_uis(src) + return ..() + +/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/singularity_act() + ex_act(1.0) + if(src && !QDELETED(src)) + qdel(src) + return 2 + +/obj/singularity_pull(S, current_size) + if(anchored) + if(current_size >= STAGE_FIVE) + anchored = 0 + step_towards(src,S) + else + step_towards(src,S) + +// the obj is deconstructed into pieces, whether through careful disassembly or when destroyed. +/obj/proc/deconstruct(disassembled = TRUE) + qdel(src) + +/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 + +/obj/proc/updateUsrDialog() + if(in_use) + var/is_in_use = FALSE + var/list/nearby = viewers(1, src) + for(var/mob/M in nearby) + if ((M.client && M.machine == src)) + is_in_use = TRUE + if(ishuman(M)) //most users is humans, so check this first + attack_hand(M) + continue + if(isobserver(M)) //ghosts and synths must use their own attack_ procs + attack_ghost(M) + continue + if(isAI(M) || isrobot(M)) //VERY rare AI can be placed near to something + //with custom attack_ai + attack_ai(M) + continue + attack_hand(M) + if (isAI(usr) || isrobot(usr)) + if (!(usr in nearby)) + if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh. + is_in_use = TRUE + attack_ai(usr) + + if (isobserver(usr)) + if (!(usr in nearby)) + if (usr.client && usr.machine==src) + is_in_use = TRUE + attack_ghost(usr) + + // check for TK users + + if (ishuman(usr)) + if(istype(usr.l_hand, /obj/item/tk_grab) || istype(usr.r_hand, /obj/item/tk_grab/)) + if(!(usr in nearby)) + if(usr.client && usr.machine==src) + is_in_use = 1 + attack_hand(usr) + 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 = FALSE + for(var/mob/M in nearby) + if ((M.client && M.machine == src)) + is_in_use = TRUE + src.interact(M) + var/ai_in_use = AutoUpdateAI(src) + + in_use = is_in_use|ai_in_use + +/obj/attack_ghost(mob/dead/observer/user) + if(user.client.machine_interactive_ghost && ui_interact(user) != -1) + return + ..() + +/obj/proc/damage_flags() + . = 0 + if(has_edge(src)) + . |= DAM_EDGE + if(is_sharp(src)) + . |= DAM_SHARP + if(damtype == BURN) + . |= DAM_LASER + +/obj/proc/interact(mob/user) + return + +/obj/proc/container_resist() + return + +/obj/proc/update_icon() + return + +/mob/proc/unset_machine(obj/O) + if(O && O == src.machine) + src.machine = null + else + src.machine = null + +/mob/proc/set_machine(obj/O) + if(src.machine) + unset_machine(src.machine) + src.machine = O + if(istype(O)) + O.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/hides_under_flooring() + return level == 1 + +/obj/proc/hear_talk(mob/M, text, verb, datum/language/speaking) + if(talking_atom) + talking_atom.catchMessage(text, M) +/* + var/mob/mo = locate(/mob) in src + if(mo) + var/rendered = "[M.name]: [text]" + mo.show_message(rendered, 2) + */ + return + +/obj/proc/tesla_act(power) + being_shocked = 1 + var/power_bounced = power / 2 + tesla_zap(src, 3, power_bounced) + spawn(10) + reset_shocked() + +/obj/proc/reset_shocked() + being_shocked = 0 + +//mob - who is being feed +//user - who is feeding +//food - whai is feeded +//eatverb - take/drink/eat method +/proc/CanEat(user, mob, food, eatverb = "consume") + if(ishuman(mob)) + var/mob/living/carbon/human/Feeded = mob + if(Feeded.head) + var/obj/item/Head = Feeded.head + if(Head.flags & HEADCOVERSMOUTH) + if (Feeded == user) + to_chat(user, "You can't [eatverb] [food] through [Head]") + else + to_chat(user, "You can't feed [Feeded] with [food] through [Head]") + return FALSE + if(Feeded.wear_mask) + var/obj/item/Mask = Feeded.wear_mask + if(Mask.flags & MASKCOVERSMOUTH) + if (Feeded == user) + to_chat(user, "You can't [eatverb] [food] through [Mask]") + else + to_chat(user, "You can't feed [Feeded] with [food] through [Mask]") + return FALSE + return TRUE + if(isIAN(mob)) + var/mob/living/carbon/ian/dumdum = mob + if(dumdum.head) + var/obj/item/Head = dumdum.head + if(Head.flags & HEADCOVERSMOUTH) + if (dumdum == user) + to_chat(user, "You can't [eatverb] [food] through [Head]") + else + to_chat(user, "You can't feed [dumdum] with [food] through [Head]") + return FALSE + return TRUE + +/obj/proc/CanAStarPass(obj/item/weapon/card/id/ID, to_dir, caller) + return !density diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 45274954130d..3d6b356499c6 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -1,170 +1,170 @@ -/obj/structure - icon = 'icons/obj/structures.dmi' - var/climbable - var/list/climbers = list() - -/obj/structure/blob_act() - if(prob(50)) - qdel(src) - -/obj/structure/ex_act(severity) - switch(severity) - if(1.0) - for(var/atom/movable/AM in contents) - AM.forceMove(loc) - AM.ex_act(severity++) - qdel(src) - return - if(2.0) - if(prob(50)) - for(var/atom/movable/AM in contents) - AM.forceMove(loc) - AM.ex_act(severity++) - qdel(src) - return - if(3.0) - return - -/obj/structure/meteorhit(obj/O) - qdel(src) - -/obj/structure/atom_init() - . = ..() - if(climbable) - verbs += /obj/structure/proc/climb_on - -/obj/structure/proc/climb_on() - - set name = "Climb structure" - set desc = "Climbs onto a structure." - set category = "Object" - set src in oview(1) - - do_climb(usr) - -/obj/structure/MouseDrop_T(mob/target, mob/user) - if(isessence(user)) - return - var/mob/living/H = user - if(can_climb(H) && target == user) - do_climb(target) - else - return ..() - -/obj/structure/proc/can_climb(mob/living/user, post_climb_check=0) - if (!can_touch(user) || !climbable || (!post_climb_check && (user in climbers))) - return 0 - - if (!user.Adjacent(src)) - to_chat(user, "You can't climb there, the way is blocked.") - return 0 - - if(user.is_busy()) - return 0 - - var/obj/occupied = turf_is_crowded() - if(occupied) - to_chat(user, "There's \a [occupied] in the way.") - return 0 - return 1 - -/obj/structure/proc/turf_is_crowded() - var/turf/T = get_turf(src) - if(!T || !istype(T)) - return 0 - for(var/obj/O in T.contents) - if(istype(O,/obj/structure)) - var/obj/structure/S = O - if(S.climbable) continue - if(O && O.density) - return O - return 0 - -/obj/structure/proc/do_climb(mob/living/user) - if (!can_climb(user)) - return - usr.visible_message("[user] starts climbing onto \the [src]!") - climbers |= user - - var/adjusted_climb_time = 50 - if(user.restrained()) //climbing takes twice as long when restrained. - adjusted_climb_time *= 2 - if(isalien(user)) - adjusted_climb_time *= 0.25 //aliens are terrifyingly fast - - if(!do_after(user, adjusted_climb_time, target = user)) - climbers -= user - return - - if (!can_climb(user, post_climb_check=1)) - climbers -= user - return - - on_climb(user) - climbers -= user - -/obj/structure/proc/on_climb(mob/living/user) - usr.forceMove(get_turf(src)) - - if (get_turf(user) == get_turf(src)) - usr.visible_message("[user] climbs onto \the [src]!") - -/obj/structure/proc/structure_shaken() - for(var/mob/living/M in climbers) - M.Weaken(2) - to_chat(M, "You topple as you are shaken off \the [src]!") - climbers.Cut(1,2) - - for(var/mob/living/M in get_turf(src)) - if(M.lying) return //No spamming this on people. - M.Weaken(5) - to_chat(M, "You topple as \the [src] moves under you!") - - if(prob(25)) - - var/damage = rand(15,30) - var/mob/living/carbon/human/H = M - if(!istype(M)) - to_chat(H, "You land heavily!") - M.adjustBruteLoss(damage) - return - - var/obj/item/organ/external/BP - - switch(pick(list("knee","head","elbow"))) - if("knee") - BP = H.bodyparts_by_name[pick(BP_L_LEG , BP_R_LEG)] - if("elbow") - BP = H.bodyparts_by_name[pick(BP_L_ARM , BP_R_ARM)] - if("head") - BP = H.bodyparts_by_name[BP_HEAD] - - if(BP) - to_chat(M, "You land heavily on your [BP.name]!") - BP.take_damage(damage, 0) - if(BP.parent) - BP.parent.add_autopsy_data("Misadventure", damage) - else - to_chat(H, "You land heavily!") - H.adjustBruteLoss(damage) - - H.updatehealth() - return - -/obj/structure/proc/can_touch(mob/user) - if(!user) - return 0 - if(!Adjacent(user)) - return 0 - if(user.buckled) - to_chat(user, "You need your hands and legs free for this.") - return 0 - if(user.stat || user.paralysis || user.sleeping || user.lying || user.weakened) - return 0 - if(issilicon(user)) - to_chat(user, "You need hands for this.") - return 0 - for(var/obj/O in src.loc) - if((O.density && O.opacity) > 0) - return 0 - return 1 +/obj/structure + icon = 'icons/obj/structures.dmi' + var/climbable + var/list/climbers = list() + +/obj/structure/blob_act() + if(prob(50)) + qdel(src) + +/obj/structure/ex_act(severity) + switch(severity) + if(1.0) + for(var/atom/movable/AM in contents) + AM.forceMove(loc) + AM.ex_act(severity++) + qdel(src) + return + if(2.0) + if(prob(50)) + for(var/atom/movable/AM in contents) + AM.forceMove(loc) + AM.ex_act(severity++) + qdel(src) + return + if(3.0) + return + +/obj/structure/meteorhit(obj/O) + qdel(src) + +/obj/structure/atom_init() + . = ..() + if(climbable) + verbs += /obj/structure/proc/climb_on + +/obj/structure/proc/climb_on() + + set name = "Climb structure" + set desc = "Climbs onto a structure." + set category = "Object" + set src in oview(1) + + do_climb(usr) + +/obj/structure/MouseDrop_T(mob/target, mob/user) + if(isessence(user)) + return + var/mob/living/H = user + if(can_climb(H) && target == user) + do_climb(target) + else + return ..() + +/obj/structure/proc/can_climb(mob/living/user, post_climb_check=0) + if (!can_touch(user) || !climbable || (!post_climb_check && (user in climbers))) + return 0 + + if (!user.Adjacent(src)) + to_chat(user, "You can't climb there, the way is blocked.") + return 0 + + if(user.is_busy()) + return 0 + + var/obj/occupied = turf_is_crowded() + if(occupied) + to_chat(user, "There's \a [occupied] in the way.") + return 0 + return 1 + +/obj/structure/proc/turf_is_crowded() + var/turf/T = get_turf(src) + if(!T || !istype(T)) + return 0 + for(var/obj/O in T.contents) + if(istype(O,/obj/structure)) + var/obj/structure/S = O + if(S.climbable) continue + if(O && O.density) + return O + return 0 + +/obj/structure/proc/do_climb(mob/living/user) + if (!can_climb(user)) + return + usr.visible_message("[user] starts climbing onto \the [src]!") + climbers |= user + + var/adjusted_climb_time = 50 + if(user.restrained()) //climbing takes twice as long when restrained. + adjusted_climb_time *= 2 + if(isalien(user)) + adjusted_climb_time *= 0.25 //aliens are terrifyingly fast + + if(!do_after(user, adjusted_climb_time, target = user)) + climbers -= user + return + + if (!can_climb(user, post_climb_check=1)) + climbers -= user + return + + on_climb(user) + climbers -= user + +/obj/structure/proc/on_climb(mob/living/user) + usr.forceMove(get_turf(src)) + + if (get_turf(user) == get_turf(src)) + usr.visible_message("[user] climbs onto \the [src]!") + +/obj/structure/proc/structure_shaken() + for(var/mob/living/M in climbers) + M.Weaken(2) + to_chat(M, "You topple as you are shaken off \the [src]!") + climbers.Cut(1,2) + + for(var/mob/living/M in get_turf(src)) + if(M.lying) return //No spamming this on people. + M.Weaken(5) + to_chat(M, "You topple as \the [src] moves under you!") + + if(prob(25)) + + var/damage = rand(15,30) + var/mob/living/carbon/human/H = M + if(!istype(M)) + to_chat(H, "You land heavily!") + M.adjustBruteLoss(damage) + return + + var/obj/item/organ/external/BP + + switch(pick(list("knee","head","elbow"))) + if("knee") + BP = H.bodyparts_by_name[pick(BP_L_LEG , BP_R_LEG)] + if("elbow") + BP = H.bodyparts_by_name[pick(BP_L_ARM , BP_R_ARM)] + if("head") + BP = H.bodyparts_by_name[BP_HEAD] + + if(BP) + to_chat(M, "You land heavily on your [BP.name]!") + BP.take_damage(damage, 0) + if(BP.parent) + BP.parent.add_autopsy_data("Misadventure", damage) + else + to_chat(H, "You land heavily!") + H.adjustBruteLoss(damage) + + H.updatehealth() + return + +/obj/structure/proc/can_touch(mob/user) + if(!user) + return 0 + if(!Adjacent(user)) + return 0 + if(user.buckled) + to_chat(user, "You need your hands and legs free for this.") + return 0 + if(user.stat || user.paralysis || user.sleeping || user.lying || user.weakened) + return 0 + if(issilicon(user)) + to_chat(user, "You need hands for this.") + return 0 + for(var/obj/O in src.loc) + if((O.density && O.opacity) > 0) + return 0 + return 1 diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index c9ab3938704e..42bedd409934 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -1,244 +1,244 @@ -/* -CONTAINS: -BEDSHEETS -LINEN BINS -*/ - -/obj/item/weapon/bedsheet - name = "bedsheet" - desc = "A surprisingly soft linen bedsheet." - icon = 'icons/obj/bedsheets.dmi' - icon_state = "sheet" - item_state = "bedsheet" - slot_flags = SLOT_BACK - layer = 4.0 - throwforce = 1 - throw_speed = 1 - throw_range = 2 - w_class = 2.0 - item_color = "white" - - -/obj/item/weapon/bedsheet/attack_self(mob/user) - user.drop_item() - if(layer == initial(layer)) - layer = 5 - else - layer = initial(layer) - add_fingerprint(user) - return - - -/obj/item/weapon/bedsheet/blue - icon_state = "sheetblue" - item_color = "blue" - -/obj/item/weapon/bedsheet/green - icon_state = "sheetgreen" - item_color = "green" - -/obj/item/weapon/bedsheet/orange - icon_state = "sheetorange" - item_color = "orange" - -/obj/item/weapon/bedsheet/purple - icon_state = "sheetpurple" - item_color = "purple" - -/obj/item/weapon/bedsheet/rainbow - name = "rainbow bedsheet" - desc = "A multicolored blanket. It's actually several different sheets cut up and sewn together." - icon_state = "sheetrainbow" - item_color = "rainbow" - -/obj/item/weapon/bedsheet/red - icon_state = "sheetred" - item_color = "red" - -/obj/item/weapon/bedsheet/yellow - icon_state = "sheetyellow" - item_color = "yellow" - -/obj/item/weapon/bedsheet/mime - name = "mime's blanket" - desc = "A very soothing striped blanket. All the noise just seems to fade out when you're under the covers in this." - icon_state = "sheetmime" - item_color = "mime" - -/obj/item/weapon/bedsheet/clown - name = "clown's blanket" - desc = "A rainbow blanket with a clown mask woven in. It smells faintly of bananas." - icon_state = "sheetclown" - item_color = "clown" - -/obj/item/weapon/bedsheet/captain - name = "captain's bedsheet" - desc = "It has a Nanotrasen symbol on it, and was woven with a revolutionary new kind of thread guaranteed to have 0.01% permeability for most non-chemical substances, popular among most modern captains." - icon_state = "sheetcaptain" - item_color = "captain" - -/obj/item/weapon/bedsheet/rd - name = "research director's bedsheet" - desc = "It appears to have a beaker emblem, and is made out of fire-resistant material, although it probably won't protect you in the event of fires you're familiar with every day." - icon_state = "sheetrd" - item_color = "director" - -/obj/item/weapon/bedsheet/medical - name = "medical blanket" - desc = "It's a sterilized* blanket commonly used in the Medbay. *Sterilization is voided if a virologist is present onboard the station." - icon_state = "sheetmedical" - item_color = "medical" - -/obj/item/weapon/bedsheet/hos - name = "head of security's bedsheet" - desc = "It is decorated with a shield emblem. While crime doesn't sleep, you do, but you are still THE LAW!" - icon_state = "sheethos" - item_color = "hosred" - -/obj/item/weapon/bedsheet/hop - name = "head of personnel's bedsheet" - desc = "It is decorated with a key emblem. For those rare moments when you can rest and cuddle with Ian without someone screaming for you over the radio." - icon_state = "sheethop" - item_color = "hop" - -/obj/item/weapon/bedsheet/ce - name = "chief engineer's bedsheet" - desc = "It is decorated with a wrench emblem. It's highly reflective and stain resistant, so you don't need to worry about ruining it with oil." - icon_state = "sheetce" - item_color = "chief" - -/obj/item/weapon/bedsheet/brown - icon_state = "sheetbrown" - item_color = "brown" - -/obj/item/weapon/bedsheet/psych - icon = 'icons/obj/items.dmi' - icon_state = "sheetbrown" - item_color = "brown" - -/obj/item/weapon/bedsheet/centcom - name = "\improper Centcom bedsheet" - desc = "Woven with advanced nanothread for warmth as well as being very decorated, essential for all officials." - icon_state = "sheetcentcom" - item_color = "centcom" - -/obj/item/weapon/bedsheet/syndie - name = "syndicate bedsheet" - desc = "It has a syndicate emblem and it has an aura of evil." - icon_state = "sheetsyndie" - item_color = "syndie" - -/obj/item/weapon/bedsheet/cult - name = "cultist's bedsheet" - desc = "You might dream of Nar'Sie if you sleep with this. It seems rather tattered and glows of an eldritch presence." - icon_state = "sheetcult" - item_color = "cult" - -/obj/item/weapon/bedsheet/wiz - name = "wizard's bedsheet" - desc = "A special fabric enchanted with magic so you can have an enchanted night. It even glows!" - icon_state = "sheetwiz" - item_color = "wiz" - -/obj/item/weapon/bedsheet/gar - name = "gar bedsheet" - desc = "A surprisingly soft gar bedsheet." - icon_state = "sheetgurren" - item_state = "bedsheet" - item_color = "gurren" - - -/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 < 1) - to_chat(user, "There are no bed sheets in the bin.") - return - if(amount == 1) - to_chat(user, "There is one bed sheet in the bin.") - return - 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, mob/user) - if(istype(I, /obj/item/weapon/bedsheet)) - user.drop_item() - I.loc = src - sheets.Add(I) - amount++ - to_chat(user, "You put [I] in [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. - user.drop_item() - I.loc = src - hidden = I - to_chat(user, "You hide [I] among the sheets.") - - - -/obj/structure/bedsheetbin/attack_paw(mob/user) - return attack_hand(user) - - -/obj/structure/bedsheetbin/attack_hand(mob/user) - 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) - 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/bedsheets.dmi' + icon_state = "sheet" + item_state = "bedsheet" + slot_flags = SLOT_BACK + layer = 4.0 + throwforce = 1 + throw_speed = 1 + throw_range = 2 + w_class = 2.0 + item_color = "white" + + +/obj/item/weapon/bedsheet/attack_self(mob/user) + user.drop_item() + if(layer == initial(layer)) + layer = 5 + else + layer = initial(layer) + add_fingerprint(user) + return + + +/obj/item/weapon/bedsheet/blue + icon_state = "sheetblue" + item_color = "blue" + +/obj/item/weapon/bedsheet/green + icon_state = "sheetgreen" + item_color = "green" + +/obj/item/weapon/bedsheet/orange + icon_state = "sheetorange" + item_color = "orange" + +/obj/item/weapon/bedsheet/purple + icon_state = "sheetpurple" + item_color = "purple" + +/obj/item/weapon/bedsheet/rainbow + name = "rainbow bedsheet" + desc = "A multicolored blanket. It's actually several different sheets cut up and sewn together." + icon_state = "sheetrainbow" + item_color = "rainbow" + +/obj/item/weapon/bedsheet/red + icon_state = "sheetred" + item_color = "red" + +/obj/item/weapon/bedsheet/yellow + icon_state = "sheetyellow" + item_color = "yellow" + +/obj/item/weapon/bedsheet/mime + name = "mime's blanket" + desc = "A very soothing striped blanket. All the noise just seems to fade out when you're under the covers in this." + icon_state = "sheetmime" + item_color = "mime" + +/obj/item/weapon/bedsheet/clown + name = "clown's blanket" + desc = "A rainbow blanket with a clown mask woven in. It smells faintly of bananas." + icon_state = "sheetclown" + item_color = "clown" + +/obj/item/weapon/bedsheet/captain + name = "captain's bedsheet" + desc = "It has a Nanotrasen symbol on it, and was woven with a revolutionary new kind of thread guaranteed to have 0.01% permeability for most non-chemical substances, popular among most modern captains." + icon_state = "sheetcaptain" + item_color = "captain" + +/obj/item/weapon/bedsheet/rd + name = "research director's bedsheet" + desc = "It appears to have a beaker emblem, and is made out of fire-resistant material, although it probably won't protect you in the event of fires you're familiar with every day." + icon_state = "sheetrd" + item_color = "director" + +/obj/item/weapon/bedsheet/medical + name = "medical blanket" + desc = "It's a sterilized* blanket commonly used in the Medbay. *Sterilization is voided if a virologist is present onboard the station." + icon_state = "sheetmedical" + item_color = "medical" + +/obj/item/weapon/bedsheet/hos + name = "head of security's bedsheet" + desc = "It is decorated with a shield emblem. While crime doesn't sleep, you do, but you are still THE LAW!" + icon_state = "sheethos" + item_color = "hosred" + +/obj/item/weapon/bedsheet/hop + name = "head of personnel's bedsheet" + desc = "It is decorated with a key emblem. For those rare moments when you can rest and cuddle with Ian without someone screaming for you over the radio." + icon_state = "sheethop" + item_color = "hop" + +/obj/item/weapon/bedsheet/ce + name = "chief engineer's bedsheet" + desc = "It is decorated with a wrench emblem. It's highly reflective and stain resistant, so you don't need to worry about ruining it with oil." + icon_state = "sheetce" + item_color = "chief" + +/obj/item/weapon/bedsheet/brown + icon_state = "sheetbrown" + item_color = "brown" + +/obj/item/weapon/bedsheet/psych + icon = 'icons/obj/items.dmi' + icon_state = "sheetbrown" + item_color = "brown" + +/obj/item/weapon/bedsheet/centcom + name = "\improper Centcom bedsheet" + desc = "Woven with advanced nanothread for warmth as well as being very decorated, essential for all officials." + icon_state = "sheetcentcom" + item_color = "centcom" + +/obj/item/weapon/bedsheet/syndie + name = "syndicate bedsheet" + desc = "It has a syndicate emblem and it has an aura of evil." + icon_state = "sheetsyndie" + item_color = "syndie" + +/obj/item/weapon/bedsheet/cult + name = "cultist's bedsheet" + desc = "You might dream of Nar'Sie if you sleep with this. It seems rather tattered and glows of an eldritch presence." + icon_state = "sheetcult" + item_color = "cult" + +/obj/item/weapon/bedsheet/wiz + name = "wizard's bedsheet" + desc = "A special fabric enchanted with magic so you can have an enchanted night. It even glows!" + icon_state = "sheetwiz" + item_color = "wiz" + +/obj/item/weapon/bedsheet/gar + name = "gar bedsheet" + desc = "A surprisingly soft gar bedsheet." + icon_state = "sheetgurren" + item_state = "bedsheet" + item_color = "gurren" + + +/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 < 1) + to_chat(user, "There are no bed sheets in the bin.") + return + if(amount == 1) + to_chat(user, "There is one bed sheet in the bin.") + return + 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, mob/user) + if(istype(I, /obj/item/weapon/bedsheet)) + user.drop_item() + I.loc = src + sheets.Add(I) + amount++ + to_chat(user, "You put [I] in [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. + user.drop_item() + I.loc = src + hidden = I + to_chat(user, "You hide [I] among the sheets.") + + + +/obj/structure/bedsheetbin/attack_paw(mob/user) + return attack_hand(user) + + +/obj/structure/bedsheetbin/attack_hand(mob/user) + 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) + 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/bobross.dm b/code/game/objects/structures/bobross.dm index c9bf9631e5ae..30f66c70f056 100644 --- a/code/game/objects/structures/bobross.dm +++ b/code/game/objects/structures/bobross.dm @@ -1,25 +1,25 @@ -/obj/structure/bobross - name = "masterpiece" - desc = "Just a beautiful painting. You can see a man with afro haircut and a painting with happy little trees on it. There are no mistakes, only happy accidents." - icon = 'icons/obj/decals.dmi' - icon_state = "bobross" - anchored = TRUE - opacity = FALSE - density = FALSE - layer = SIGN_LAYER - -/obj/structure/bobross/attack_hand(mob/user) - if(icon_state == "bobross") - playsound(src, 'sound/effects/doorcreaky.ogg', 50, 1) - to_chat(user, "You gently open the picture.") - icon_state = "bobross_opened" - desc = "Back of the painting. It is written here: 'r.i.p. Bob Ross'" - pixel_x = pixel_x - 6 - return - if(icon_state == "bobross_opened") - playsound(src, 'sound/effects/doorcreaky.ogg', 50, 1) - to_chat(user, "You gently close the picture.") - icon_state = "bobross" - desc = "Just a beautiful painting. You can see a man with afro haircut and a painting with happy little trees on it. There are no mistakes, only happy accidents." - pixel_x = pixel_x + 6 - return +/obj/structure/bobross + name = "masterpiece" + desc = "Just a beautiful painting. You can see a man with afro haircut and a painting with happy little trees on it. There are no mistakes, only happy accidents." + icon = 'icons/obj/decals.dmi' + icon_state = "bobross" + anchored = TRUE + opacity = FALSE + density = FALSE + layer = SIGN_LAYER + +/obj/structure/bobross/attack_hand(mob/user) + if(icon_state == "bobross") + playsound(src, 'sound/effects/doorcreaky.ogg', 50, 1) + to_chat(user, "You gently open the picture.") + icon_state = "bobross_opened" + desc = "Back of the painting. It is written here: 'r.i.p. Bob Ross'" + pixel_x = pixel_x - 6 + return + if(icon_state == "bobross_opened") + playsound(src, 'sound/effects/doorcreaky.ogg', 50, 1) + to_chat(user, "You gently close the picture.") + icon_state = "bobross" + desc = "Just a beautiful painting. You can see a man with afro haircut and a painting with happy little trees on it. There are no mistakes, only happy accidents." + pixel_x = pixel_x + 6 + return diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 1ea5cea1dace..c88eec274c9e 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -1,336 +1,336 @@ -/obj/structure/closet - name = "closet" - desc = "It's a basic storage unit." - icon = 'icons/obj/closet.dmi' - icon_state = "closed" - density = 1 - layer = CONTAINER_STRUCTURE_LAYER - var/icon_closed = "closed" - var/icon_opened = "open" - var/opened = 0 - var/welded = 0 - var/locked = 0 - var/broken = 0 - 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. - -/obj/structure/closet/atom_init(mapload) - . = ..() - closet_list += src - if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents - for(var/obj/item/I in src.loc) - if(I.density || I.anchored || I == src) - continue - I.forceMove(src) - PopulateContents() - update_icon() - -/obj/structure/closet/Destroy() - closet_list -= src - return ..() - -//USE THIS TO FILL IT, NOT INITIALIZE OR NEW -/obj/structure/closet/proc/PopulateContents() - return - -/obj/structure/closet/alter_health() - return get_turf(src) - -/obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=0, 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() - //Cham Projector Exception - for(var/obj/effect/dummy/chameleon/AD in src) - AD.forceMove(src.loc) - - for(var/obj/I in src) - I.forceMove(src.loc) - - for(var/mob/M in src) - M.forceMove(src.loc) - M.instant_vision_update(0) - -/obj/structure/closet/proc/open() - if(src.opened) - return 0 - - if(!src.can_open()) - return 0 - - src.dump_contents() - - src.icon_state = src.icon_opened - src.opened = 1 - if(istype(src, /obj/structure/closet/body_bag)) - playsound(src.loc, 'sound/items/zip.ogg', 15, 1, -3) - else - playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) - density = 0 - return 1 - -/obj/structure/closet/proc/close() - if(!src.opened) - return 0 - if(!src.can_close()) - return 0 - - var/itemcount = 0 - - //Cham Projector Exception - for(var/obj/effect/dummy/chameleon/AD in src.loc) - if(itemcount >= storage_capacity) - break - AD.forceMove(src) - itemcount++ - - for(var/obj/item/I in src.loc) - if(itemcount >= storage_capacity) - break - if(!I.anchored) - I.forceMove(src) - itemcount++ - - for(var/mob/M in src.loc) - if(itemcount >= storage_capacity) - break - if(istype (M, /mob/dead/observer)) - continue - if(M.buckled) - continue - - M.forceMove(src) - M.instant_vision_update(1,src) - itemcount++ - - src.icon_state = src.icon_closed - src.opened = 0 - if(istype(src, /obj/structure/closet/body_bag)) - playsound(src.loc, 'sound/items/zip.ogg', 15, 1, -3) - else - playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) - density = 1 - return 1 - -/obj/structure/closet/proc/toggle(mob/user) - if(!(src.opened ? src.close() : src.open())) - to_chat(user, "It won't budge!") - return - -// 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.forceMove(src.loc) - A.ex_act(severity++) - qdel(src) - if(2) - if(prob(50)) - for (var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) - A.ex_act(severity++) - qdel(src) - if(3) - if(prob(5)) - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) - A.ex_act(severity++) - qdel(src) - -/obj/structure/closet/bullet_act(obj/item/projectile/Proj) - health -= Proj.damage - ..() - if(health <= 0) - for(var/atom/movable/A as mob|obj in src) - A.forceMove(src.loc) - qdel(src) - - return - -/obj/structure/closet/attack_animal(mob/living/simple_animal/user) - if(user.environment_smash) - ..() - playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) - visible_message("\red [user] destroys the [src]. ") - open() - qdel(src) - -// this should probably use dump_contents() -/obj/structure/closet/blob_act() - if(prob(75)) - open() - qdel(src) - -/obj/structure/closet/meteorhit(obj/O) - if(O.icon_state == "flaming") - for(var/mob/M in src) - M.meteorhit(O) - src.dump_contents() - qdel(src) - -/obj/structure/closet/attackby(obj/item/weapon/W, mob/user) - if(src.opened) - if(istype(W, /obj/item/weapon/grab)) - src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet - 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 - new /obj/item/stack/sheet/metal(loc) - visible_message("\The [src] has been cut apart by [user] with \the [WT].", "You hear welding.") - qdel(src) - return - if(isrobot(user)) - return - if(!W.canremove || W.flags & NODROP) - return - usr.drop_item() - if(W) - W.forceMove(src.loc) - - else if(istype(W, /obj/item/weapon/packageWrap) || istype(W, /obj/item/weapon/extraction_pack)) - return - - else if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - user.SetNextMove(CLICK_CD_INTERACT) - 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() - visible_message("[src] has been [welded?"welded shut":"unwelded"] by [user.name].", "You hear welding.") - else - attack_hand(user) - -/obj/structure/closet/MouseDrop_T(atom/movable/O, mob/user) - if(istype(O, /obj/screen)) //fix for HUD elements making their way into the world -Pete - return - if(O.loc == user) - return - if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis) - return - if((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src))) - 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)) // are you in a container/closet/pod/etc? - return - if(!src.opened) - return - if(istype(O, /obj/structure/closet)) - return - user.SetNextMove(CLICK_CD_INTERACT) - step_towards(O, src.loc) - if(user != O) - user.show_viewers("[user] stuffs [O] into [src]!") - src.add_fingerprint(user) - return - -/obj/structure/closet/attack_ai(mob/user) - if(isrobot(user) && Adjacent(user)) //Robots can open/close it, but not the AI - attack_hand(user) - -/obj/structure/closet/relaymove(mob/user) - 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) - return src.attack_hand(user) - -/obj/structure/closet/attack_hand(mob/user) - src.add_fingerprint(user) - user.SetNextMove(CLICK_CD_RAPID) - src.toggle(user) - -// tk grab then use on self -/obj/structure/closet/attack_self_tk(mob/user) - 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.stat || usr.restrained()) - return - - if(ishuman(usr)) - src.add_fingerprint(usr) - src.toggle(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.Cut() - if(!opened) - icon_state = icon_closed - if(welded) - overlays += "welded" - else - icon_state = icon_opened - -/obj/structure/closet/hear_talk(mob/M, text, verb, datum/language/speaking) - for (var/atom/A in src) - if(istype(A,/obj/)) - var/obj/O = A - O.hear_talk(M, text, verb, speaking) - -/obj/structure/closet/container_resist() - var/mob/living/user = usr - var/breakout_time = 2 //2 minutes by default - //if(istype(user.loc, /obj/structure/closet/critter) && !welded) - // breakout_time = 0.75 //45 seconds if it's an unwelded critter crate - - 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.SetNextMove(100) - user.last_special = world.time + 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!") - - if(do_after(user,(breakout_time*60*10),target=src)) //minutes * 60seconds * 10deciseconds - if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded)) - 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 + layer = CONTAINER_STRUCTURE_LAYER + var/icon_closed = "closed" + var/icon_opened = "open" + var/opened = 0 + var/welded = 0 + var/locked = 0 + var/broken = 0 + 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. + +/obj/structure/closet/atom_init(mapload) + . = ..() + closet_list += src + if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents + for(var/obj/item/I in src.loc) + if(I.density || I.anchored || I == src) + continue + I.forceMove(src) + PopulateContents() + update_icon() + +/obj/structure/closet/Destroy() + closet_list -= src + return ..() + +//USE THIS TO FILL IT, NOT INITIALIZE OR NEW +/obj/structure/closet/proc/PopulateContents() + return + +/obj/structure/closet/alter_health() + return get_turf(src) + +/obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=0, 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() + //Cham Projector Exception + for(var/obj/effect/dummy/chameleon/AD in src) + AD.forceMove(src.loc) + + for(var/obj/I in src) + I.forceMove(src.loc) + + for(var/mob/M in src) + M.forceMove(src.loc) + M.instant_vision_update(0) + +/obj/structure/closet/proc/open() + if(src.opened) + return 0 + + if(!src.can_open()) + return 0 + + src.dump_contents() + + src.icon_state = src.icon_opened + src.opened = 1 + if(istype(src, /obj/structure/closet/body_bag)) + playsound(src.loc, 'sound/items/zip.ogg', 15, 1, -3) + else + playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) + density = 0 + return 1 + +/obj/structure/closet/proc/close() + if(!src.opened) + return 0 + if(!src.can_close()) + return 0 + + var/itemcount = 0 + + //Cham Projector Exception + for(var/obj/effect/dummy/chameleon/AD in src.loc) + if(itemcount >= storage_capacity) + break + AD.forceMove(src) + itemcount++ + + for(var/obj/item/I in src.loc) + if(itemcount >= storage_capacity) + break + if(!I.anchored) + I.forceMove(src) + itemcount++ + + for(var/mob/M in src.loc) + if(itemcount >= storage_capacity) + break + if(istype (M, /mob/dead/observer)) + continue + if(M.buckled) + continue + + M.forceMove(src) + M.instant_vision_update(1,src) + itemcount++ + + src.icon_state = src.icon_closed + src.opened = 0 + if(istype(src, /obj/structure/closet/body_bag)) + playsound(src.loc, 'sound/items/zip.ogg', 15, 1, -3) + else + playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) + density = 1 + return 1 + +/obj/structure/closet/proc/toggle(mob/user) + if(!(src.opened ? src.close() : src.open())) + to_chat(user, "It won't budge!") + return + +// 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.forceMove(src.loc) + A.ex_act(severity++) + qdel(src) + if(2) + if(prob(50)) + for (var/atom/movable/A as mob|obj in src) + A.forceMove(src.loc) + A.ex_act(severity++) + qdel(src) + if(3) + if(prob(5)) + for(var/atom/movable/A as mob|obj in src) + A.forceMove(src.loc) + A.ex_act(severity++) + qdel(src) + +/obj/structure/closet/bullet_act(obj/item/projectile/Proj) + health -= Proj.damage + ..() + if(health <= 0) + for(var/atom/movable/A as mob|obj in src) + A.forceMove(src.loc) + qdel(src) + + return + +/obj/structure/closet/attack_animal(mob/living/simple_animal/user) + if(user.environment_smash) + ..() + playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) + visible_message("\red [user] destroys the [src]. ") + open() + qdel(src) + +// this should probably use dump_contents() +/obj/structure/closet/blob_act() + if(prob(75)) + open() + qdel(src) + +/obj/structure/closet/meteorhit(obj/O) + if(O.icon_state == "flaming") + for(var/mob/M in src) + M.meteorhit(O) + src.dump_contents() + qdel(src) + +/obj/structure/closet/attackby(obj/item/weapon/W, mob/user) + if(src.opened) + if(istype(W, /obj/item/weapon/grab)) + src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet + 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 + new /obj/item/stack/sheet/metal(loc) + visible_message("\The [src] has been cut apart by [user] with \the [WT].", "You hear welding.") + qdel(src) + return + if(isrobot(user)) + return + if(!W.canremove || W.flags & NODROP) + return + usr.drop_item() + if(W) + W.forceMove(src.loc) + + else if(istype(W, /obj/item/weapon/packageWrap) || istype(W, /obj/item/weapon/extraction_pack)) + return + + else if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + user.SetNextMove(CLICK_CD_INTERACT) + 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() + visible_message("[src] has been [welded?"welded shut":"unwelded"] by [user.name].", "You hear welding.") + else + attack_hand(user) + +/obj/structure/closet/MouseDrop_T(atom/movable/O, mob/user) + if(istype(O, /obj/screen)) //fix for HUD elements making their way into the world -Pete + return + if(O.loc == user) + return + if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis) + return + if((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src))) + 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)) // are you in a container/closet/pod/etc? + return + if(!src.opened) + return + if(istype(O, /obj/structure/closet)) + return + user.SetNextMove(CLICK_CD_INTERACT) + step_towards(O, src.loc) + if(user != O) + user.show_viewers("[user] stuffs [O] into [src]!") + src.add_fingerprint(user) + return + +/obj/structure/closet/attack_ai(mob/user) + if(isrobot(user) && Adjacent(user)) //Robots can open/close it, but not the AI + attack_hand(user) + +/obj/structure/closet/relaymove(mob/user) + 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) + return src.attack_hand(user) + +/obj/structure/closet/attack_hand(mob/user) + src.add_fingerprint(user) + user.SetNextMove(CLICK_CD_RAPID) + src.toggle(user) + +// tk grab then use on self +/obj/structure/closet/attack_self_tk(mob/user) + 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.stat || usr.restrained()) + return + + if(ishuman(usr)) + src.add_fingerprint(usr) + src.toggle(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.Cut() + if(!opened) + icon_state = icon_closed + if(welded) + overlays += "welded" + else + icon_state = icon_opened + +/obj/structure/closet/hear_talk(mob/M, text, verb, datum/language/speaking) + for (var/atom/A in src) + if(istype(A,/obj/)) + var/obj/O = A + O.hear_talk(M, text, verb, speaking) + +/obj/structure/closet/container_resist() + var/mob/living/user = usr + var/breakout_time = 2 //2 minutes by default + //if(istype(user.loc, /obj/structure/closet/critter) && !welded) + // breakout_time = 0.75 //45 seconds if it's an unwelded critter crate + + 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.SetNextMove(100) + user.last_special = world.time + 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!") + + if(do_after(user,(breakout_time*60*10),target=src)) //minutes * 60seconds * 10deciseconds + if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded)) + 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 67de5d38b9d7..b1bf05f73c4c 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 - icon_state = icon_opened +/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 diff --git a/code/game/objects/structures/crates_lockers/closets/crittercrate.dm b/code/game/objects/structures/crates_lockers/closets/crittercrate.dm index 0c02825fcad5..91cc11ddf8a1 100644 --- a/code/game/objects/structures/crates_lockers/closets/crittercrate.dm +++ b/code/game/objects/structures/crates_lockers/closets/crittercrate.dm @@ -1,105 +1,105 @@ -/obj/structure/closet/critter - name = "critter crate" - desc = "A crate designed for safe transport of animals. Only openable from the the outside." - icon_state = "critter" - icon_opened = "critteropen" - icon_closed = "critter" - var/already_opened = 0 - var/content_mob = null - -/obj/structure/closet/critter/can_open() - if(locked || welded) - return 0 - return 1 - -/obj/structure/closet/critter/open() - if(!can_open()) - return 0 - - if(content_mob == null) //making sure we don't spawn anything too eldritch - already_opened = 1 - return ..() - var/mob/living/to_die - if(content_mob != null && already_opened == 0) - if(content_mob == /mob/living/simple_animal/shiba) - new/obj/item/weapon/bikehorn/dogtoy(src) - if(content_mob == /mob/living/simple_animal/chick) - var/num = rand(4, 6) - for(var/i = 0, i < num, i++) - to_die = new content_mob(loc) - to_die.health = to_die.health * (!crit_fail) - else if(content_mob == /mob/living/simple_animal/corgi) - var/num = rand(0, 1) - if(num) //No more matriarchy for cargo - content_mob = /mob/living/simple_animal/corgi/Lisa - to_die = new content_mob(loc) - to_die.health = to_die.health * (!crit_fail) - else - to_die = new content_mob(loc) - to_die.health = to_die.health * (!crit_fail) - already_opened = 1 - ..() - -/obj/structure/closet/critter/close() - ..() - locked = 1 - return 1 - -/obj/structure/closet/critter/attack_hand(mob/user) - src.add_fingerprint(user) - user.SetNextMove(CLICK_CD_RAPID) - - if(src.loc == user.loc) - to_chat(user, "It won't budge!") - toggle() - else - locked = 0 - toggle() - -/obj/structure/closet/critter/corgi - name = "corgi crate" - content_mob = /mob/living/simple_animal/corgi //This statement is (not) false. See above. - -/obj/structure/closet/critter/cow - name = "cow crate" - content_mob = /mob/living/simple_animal/cow - -/obj/structure/closet/critter/goat - name = "goat crate" - content_mob = /mob/living/simple_animal/hostile/retaliate/goat - -/obj/structure/closet/critter/chick - name = "chicken crate" - content_mob = /mob/living/simple_animal/chick - -/obj/structure/closet/critter/cat - name = "cat crate" - content_mob = /mob/living/simple_animal/cat - -/obj/structure/closet/critter/pug - name = "pug crate" - content_mob = /mob/living/simple_animal/pug - -/obj/structure/closet/critter/shiba - name = "shiba crate" - content_mob = /mob/living/simple_animal/shiba - -/obj/structure/closet/critter/pig - name = "pig crate" - content_mob = /mob/living/simple_animal/pig - -/obj/structure/closet/critter/turkey - name = "turkey crate" - content_mob = /mob/living/simple_animal/turkey - -/obj/structure/closet/critter/goose - name = "goose crate" - content_mob = /mob/living/simple_animal/goose - -/obj/structure/closet/critter/seal - name = "seal crate" - content_mob = /mob/living/simple_animal/seal - -/obj/structure/closet/critter/walrus - name = "walrus crate" +/obj/structure/closet/critter + name = "critter crate" + desc = "A crate designed for safe transport of animals. Only openable from the the outside." + icon_state = "critter" + icon_opened = "critteropen" + icon_closed = "critter" + var/already_opened = 0 + var/content_mob = null + +/obj/structure/closet/critter/can_open() + if(locked || welded) + return 0 + return 1 + +/obj/structure/closet/critter/open() + if(!can_open()) + return 0 + + if(content_mob == null) //making sure we don't spawn anything too eldritch + already_opened = 1 + return ..() + var/mob/living/to_die + if(content_mob != null && already_opened == 0) + if(content_mob == /mob/living/simple_animal/shiba) + new/obj/item/weapon/bikehorn/dogtoy(src) + if(content_mob == /mob/living/simple_animal/chick) + var/num = rand(4, 6) + for(var/i = 0, i < num, i++) + to_die = new content_mob(loc) + to_die.health = to_die.health * (!crit_fail) + else if(content_mob == /mob/living/simple_animal/corgi) + var/num = rand(0, 1) + if(num) //No more matriarchy for cargo + content_mob = /mob/living/simple_animal/corgi/Lisa + to_die = new content_mob(loc) + to_die.health = to_die.health * (!crit_fail) + else + to_die = new content_mob(loc) + to_die.health = to_die.health * (!crit_fail) + already_opened = 1 + ..() + +/obj/structure/closet/critter/close() + ..() + locked = 1 + return 1 + +/obj/structure/closet/critter/attack_hand(mob/user) + src.add_fingerprint(user) + user.SetNextMove(CLICK_CD_RAPID) + + if(src.loc == user.loc) + to_chat(user, "It won't budge!") + toggle() + else + locked = 0 + toggle() + +/obj/structure/closet/critter/corgi + name = "corgi crate" + content_mob = /mob/living/simple_animal/corgi //This statement is (not) false. See above. + +/obj/structure/closet/critter/cow + name = "cow crate" + content_mob = /mob/living/simple_animal/cow + +/obj/structure/closet/critter/goat + name = "goat crate" + content_mob = /mob/living/simple_animal/hostile/retaliate/goat + +/obj/structure/closet/critter/chick + name = "chicken crate" + content_mob = /mob/living/simple_animal/chick + +/obj/structure/closet/critter/cat + name = "cat crate" + content_mob = /mob/living/simple_animal/cat + +/obj/structure/closet/critter/pug + name = "pug crate" + content_mob = /mob/living/simple_animal/pug + +/obj/structure/closet/critter/shiba + name = "shiba crate" + content_mob = /mob/living/simple_animal/shiba + +/obj/structure/closet/critter/pig + name = "pig crate" + content_mob = /mob/living/simple_animal/pig + +/obj/structure/closet/critter/turkey + name = "turkey crate" + content_mob = /mob/living/simple_animal/turkey + +/obj/structure/closet/critter/goose + name = "goose crate" + content_mob = /mob/living/simple_animal/goose + +/obj/structure/closet/critter/seal + name = "seal crate" + content_mob = /mob/living/simple_animal/seal + +/obj/structure/closet/critter/walrus + name = "walrus crate" content_mob = /mob/living/simple_animal/walrus \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/fitness.dm b/code/game/objects/structures/crates_lockers/closets/fitness.dm index e4a764049a64..d8085d003af7 100644 --- a/code/game/objects/structures/crates_lockers/closets/fitness.dm +++ b/code/game/objects/structures/crates_lockers/closets/fitness.dm @@ -1,66 +1,66 @@ -/obj/structure/closet/athletic_mixed - name = "athletic wardrobe" - desc = "It's a storage unit for athletic wear." - icon_state = "mixed" - icon_closed = "mixed" - -/obj/structure/closet/athletic_mixed/PopulateContents() - new /obj/item/clothing/under/shorts/grey(src) - new /obj/item/clothing/under/shorts/black(src) - new /obj/item/clothing/under/shorts/red(src) - new /obj/item/clothing/under/shorts/blue(src) - new /obj/item/clothing/under/shorts/green(src) - new /obj/item/clothing/under/swimsuit/red(src) - new /obj/item/clothing/under/swimsuit/black(src) - new /obj/item/clothing/under/swimsuit/blue(src) - new /obj/item/clothing/under/swimsuit/green(src) - new /obj/item/clothing/under/swimsuit/purple(src) - for (var/i in 1 to 2) - new /obj/item/clothing/mask/snorkel(src) - new /obj/item/clothing/shoes/swimmingfins(src) - - - -/obj/structure/closet/boxinggloves - name = "boxing gloves" - desc = "It's a storage unit for gloves for use in the boxing ring." - -/obj/structure/closet/boxinggloves/PopulateContents() - new /obj/item/clothing/gloves/boxing/blue(src) - new /obj/item/clothing/gloves/boxing/green(src) - new /obj/item/clothing/gloves/boxing/yellow(src) - new /obj/item/clothing/gloves/boxing(src) - - -/obj/structure/closet/masks - name = "mask closet" - desc = "IT'S A STORAGE UNIT FOR FIGHTER MASKS OLE!" - -/obj/structure/closet/masks/PopulateContents() - new /obj/item/clothing/mask/luchador(src) - new /obj/item/clothing/mask/luchador/rudos(src) - new /obj/item/clothing/mask/luchador/tecnicos(src) - - -/obj/structure/closet/lasertag/red - name = "red laser tag equipment" - desc = "It's a storage unit for laser tag equipment." - icon_state = "red" - icon_closed = "red" - -/obj/structure/closet/lasertag/red/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/weapon/gun/energy/laser/redtag(src) - new /obj/item/clothing/suit/redtag(src) - - -/obj/structure/closet/lasertag/blue - name = "blue laser tag equipment" - desc = "It's a storage unit for laser tag equipment." - icon_state = "blue" - icon_closed = "blue" - -/obj/structure/closet/lasertag/blue/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/weapon/gun/energy/laser/bluetag(src) - new /obj/item/clothing/suit/bluetag(src) +/obj/structure/closet/athletic_mixed + name = "athletic wardrobe" + desc = "It's a storage unit for athletic wear." + icon_state = "mixed" + icon_closed = "mixed" + +/obj/structure/closet/athletic_mixed/PopulateContents() + new /obj/item/clothing/under/shorts/grey(src) + new /obj/item/clothing/under/shorts/black(src) + new /obj/item/clothing/under/shorts/red(src) + new /obj/item/clothing/under/shorts/blue(src) + new /obj/item/clothing/under/shorts/green(src) + new /obj/item/clothing/under/swimsuit/red(src) + new /obj/item/clothing/under/swimsuit/black(src) + new /obj/item/clothing/under/swimsuit/blue(src) + new /obj/item/clothing/under/swimsuit/green(src) + new /obj/item/clothing/under/swimsuit/purple(src) + for (var/i in 1 to 2) + new /obj/item/clothing/mask/snorkel(src) + new /obj/item/clothing/shoes/swimmingfins(src) + + + +/obj/structure/closet/boxinggloves + name = "boxing gloves" + desc = "It's a storage unit for gloves for use in the boxing ring." + +/obj/structure/closet/boxinggloves/PopulateContents() + new /obj/item/clothing/gloves/boxing/blue(src) + new /obj/item/clothing/gloves/boxing/green(src) + new /obj/item/clothing/gloves/boxing/yellow(src) + new /obj/item/clothing/gloves/boxing(src) + + +/obj/structure/closet/masks + name = "mask closet" + desc = "IT'S A STORAGE UNIT FOR FIGHTER MASKS OLE!" + +/obj/structure/closet/masks/PopulateContents() + new /obj/item/clothing/mask/luchador(src) + new /obj/item/clothing/mask/luchador/rudos(src) + new /obj/item/clothing/mask/luchador/tecnicos(src) + + +/obj/structure/closet/lasertag/red + name = "red laser tag equipment" + desc = "It's a storage unit for laser tag equipment." + icon_state = "red" + icon_closed = "red" + +/obj/structure/closet/lasertag/red/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/weapon/gun/energy/laser/redtag(src) + new /obj/item/clothing/suit/redtag(src) + + +/obj/structure/closet/lasertag/blue + name = "blue laser tag equipment" + desc = "It's a storage unit for laser tag equipment." + icon_state = "blue" + icon_closed = "blue" + +/obj/structure/closet/lasertag/blue/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/weapon/gun/energy/laser/bluetag(src) + new /obj/item/clothing/suit/bluetag(src) diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm index ee2b29d02f18..bc2050222814 100644 --- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm +++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm @@ -1,92 +1,92 @@ -/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" - -/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/PopulateContents() - for (var/i in 1 to 5) - new /obj/item/clothing/head/ushanka(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/PopulateContents() - ..() - new /obj/item/clothing/glasses/eyepatch(src) - new /obj/item/clothing/glasses/sunglasses(src) - for (var/i in 1 to 2) - new /obj/item/clothing/gloves/swat(src) - new /obj/item/clothing/head/helmet/swat(src) - new /obj/item/clothing/mask/gas/coloured(src) - new /obj/item/clothing/shoes/swat(src) - new /obj/item/clothing/suit/armor/swat(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 = TRUE - -/obj/structure/closet/thunderdome/tdred - name = "red-team Thunderdome closet" - -/obj/structure/closet/thunderdome/tdred/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/suit/armor/tdome/red(src) - new /obj/item/weapon/melee/energy/sword(src) - new /obj/item/weapon/gun/energy/laser(src) - new /obj/item/weapon/melee/baton(src) - new /obj/item/weapon/storage/box/flashbangs(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/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/suit/armor/tdome/green(src) - new /obj/item/weapon/melee/energy/sword(src) - new /obj/item/weapon/gun/energy/laser(src) - new /obj/item/weapon/melee/baton(src) - new /obj/item/weapon/storage/box/flashbangs(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" + +/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/PopulateContents() + for (var/i in 1 to 5) + new /obj/item/clothing/head/ushanka(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/PopulateContents() + ..() + new /obj/item/clothing/glasses/eyepatch(src) + new /obj/item/clothing/glasses/sunglasses(src) + for (var/i in 1 to 2) + new /obj/item/clothing/gloves/swat(src) + new /obj/item/clothing/head/helmet/swat(src) + new /obj/item/clothing/mask/gas/coloured(src) + new /obj/item/clothing/shoes/swat(src) + new /obj/item/clothing/suit/armor/swat(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 = TRUE + +/obj/structure/closet/thunderdome/tdred + name = "red-team Thunderdome closet" + +/obj/structure/closet/thunderdome/tdred/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/suit/armor/tdome/red(src) + new /obj/item/weapon/melee/energy/sword(src) + new /obj/item/weapon/gun/energy/laser(src) + new /obj/item/weapon/melee/baton(src) + new /obj/item/weapon/storage/box/flashbangs(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/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/suit/armor/tdome/green(src) + new /obj/item/weapon/melee/energy/sword(src) + new /obj/item/weapon/gun/energy/laser(src) + new /obj/item/weapon/melee/baton(src) + new /obj/item/weapon/storage/box/flashbangs(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 9ebca4e20b6f..da1aed39fb7c 100644 --- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm @@ -1,164 +1,164 @@ -/* 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/PopulateContents() - new /obj/item/clothing/head/hairflower(src) - new /obj/item/clothing/under/dress/dress_saloon(src) - for (var/i in 1 to 2) - new /obj/item/clothing/head/that(src) - new /obj/item/clothing/under/sl_suit(src) - new /obj/item/clothing/under/rank/bartender(src) - new /obj/item/clothing/suit/wcoat(src) - new /obj/item/clothing/shoes/black(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/PopulateContents() - new /obj/item/clothing/under/rank/janitor(src) - new /obj/item/weapon/cartridge/janitor(src) - new /obj/item/clothing/gloves/black(src) - new /obj/item/clothing/head/soft/janitor(src) - new /obj/item/device/flashlight(src) - for (var/i in 1 to 4) - new /obj/item/weapon/caution(src) - new /obj/item/device/lightreplacer(src) - new /obj/item/weapon/storage/bag/trash(src) - new /obj/item/clothing/shoes/galoshes(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/PopulateContents() - 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) - -/obj/structure/closet/theatrecloset - name = "Theatre Closet" - desc = "This closet contains basic set of costumes required to preform stage acts and honk outside." - icon_state = "cabinet_closed" - icon_closed = "cabinet_closed" - icon_opened = "cabinet_open" - -/obj/structure/closet/theatrecloset/PopulateContents() - switch (rand(1, 21)) - if (1) - new /obj/item/clothing/suit/chickensuit(src) - new /obj/item/clothing/head/chicken(src) - new /obj/item/weapon/reagent_containers/food/snacks/egg(src) - if (2) - new /obj/item/clothing/under/gladiator(src) - new /obj/item/clothing/head/helmet/gladiator(src) - if (3) - new /obj/item/clothing/mask/gas/sexymime(src) - new /obj/item/clothing/under/sexymime(src) - if (4) - new /obj/item/clothing/under/gimmick/rank/captain/suit(src) - new /obj/item/clothing/head/flatcap(src) - new /obj/item/clothing/mask/cigarette/cigar/havana(src) - new /obj/item/clothing/shoes/jackboots(src) - if (5) - new /obj/item/clothing/under/schoolgirl(src) - new /obj/item/clothing/head/kitty(src) - if (6) - new /obj/item/clothing/under/blackskirt(src) - var/choice = pick( /obj/item/clothing/head/beret , /obj/item/clothing/head/rabbitears ) - new choice(src) - new /obj/item/clothing/glasses/sunglasses/blindfold(src) - if (7) - new /obj/item/clothing/suit/wcoat(src) - new /obj/item/clothing/under/suit_jacket(src) - new /obj/item/clothing/head/that(src) - if (8) - new /obj/item/clothing/gloves/white(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/under/scratch(src) - if (prob(30)) - new /obj/item/clothing/head/cueball(src) - if (9) - new /obj/item/clothing/under/kilt(src) - new /obj/item/clothing/head/beret(src) - if (10) - new /obj/item/clothing/suit/wcoat(src) - new /obj/item/clothing/glasses/monocle(src) - var/choice = pick( /obj/item/clothing/head/bowler, /obj/item/clothing/head/that) - new choice(src) - new /obj/item/clothing/shoes/black(src) - new /obj/item/weapon/cane(src) - new /obj/item/clothing/under/sl_suit(src) - new /obj/item/clothing/mask/fakemoustache(src) - if (11) - new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(src) - new /obj/item/clothing/head/plaguedoctorhat(src) - new /obj/item/clothing/mask/gas/plaguedoctor(src) - if( 12) - new /obj/item/clothing/under/owl(src) - new /obj/item/clothing/mask/gas/owl_mask(src) - if (13) - new /obj/item/clothing/under/waiter(src) - var/choice = pick( /obj/item/clothing/head/kitty, /obj/item/clothing/head/rabbitears) - new choice(src) - new /obj/item/clothing/suit/apron(src) - if (14) - new /obj/item/clothing/under/pirate(src) - new /obj/item/clothing/suit/pirate(src) - var/choice = pick( /obj/item/clothing/head/pirate , /obj/item/clothing/head/bandana ) - new choice(src) - new /obj/item/clothing/glasses/eyepatch(src) - if (15) - new /obj/item/clothing/under/soviet(src) - new /obj/item/clothing/head/ushanka(src) - if (16) - new /obj/item/clothing/suit/imperium_monk(src) - if (prob(25)) - new /obj/item/clothing/mask/gas/cyborg(src) - if (17) - new /obj/item/clothing/suit/holidaypriest(src) - if (18) - new /obj/item/clothing/shoes/sandal/marisa(src) - for (var/i in 1 to 2) - new /obj/item/clothing/head/wizard/marisa/fake(src) - if (19) - new /obj/item/clothing/under/sundress(src) - new /obj/item/clothing/head/witchwig(src) - new /obj/item/weapon/staff/broom(src) - if (20) - new /obj/item/clothing/shoes/sandal(src) - new /obj/item/clothing/suit/wizrobe/fake(src) - new /obj/item/clothing/head/wizard/fake(src) - new /obj/item/weapon/staff/(src) - if (21) - new /obj/item/clothing/mask/gas/sexyclown(src) - new /obj/item/clothing/under/sexyclown(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/PopulateContents() + new /obj/item/clothing/head/hairflower(src) + new /obj/item/clothing/under/dress/dress_saloon(src) + for (var/i in 1 to 2) + new /obj/item/clothing/head/that(src) + new /obj/item/clothing/under/sl_suit(src) + new /obj/item/clothing/under/rank/bartender(src) + new /obj/item/clothing/suit/wcoat(src) + new /obj/item/clothing/shoes/black(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/PopulateContents() + new /obj/item/clothing/under/rank/janitor(src) + new /obj/item/weapon/cartridge/janitor(src) + new /obj/item/clothing/gloves/black(src) + new /obj/item/clothing/head/soft/janitor(src) + new /obj/item/device/flashlight(src) + for (var/i in 1 to 4) + new /obj/item/weapon/caution(src) + new /obj/item/device/lightreplacer(src) + new /obj/item/weapon/storage/bag/trash(src) + new /obj/item/clothing/shoes/galoshes(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/PopulateContents() + 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) + +/obj/structure/closet/theatrecloset + name = "Theatre Closet" + desc = "This closet contains basic set of costumes required to preform stage acts and honk outside." + icon_state = "cabinet_closed" + icon_closed = "cabinet_closed" + icon_opened = "cabinet_open" + +/obj/structure/closet/theatrecloset/PopulateContents() + switch (rand(1, 21)) + if (1) + new /obj/item/clothing/suit/chickensuit(src) + new /obj/item/clothing/head/chicken(src) + new /obj/item/weapon/reagent_containers/food/snacks/egg(src) + if (2) + new /obj/item/clothing/under/gladiator(src) + new /obj/item/clothing/head/helmet/gladiator(src) + if (3) + new /obj/item/clothing/mask/gas/sexymime(src) + new /obj/item/clothing/under/sexymime(src) + if (4) + new /obj/item/clothing/under/gimmick/rank/captain/suit(src) + new /obj/item/clothing/head/flatcap(src) + new /obj/item/clothing/mask/cigarette/cigar/havana(src) + new /obj/item/clothing/shoes/jackboots(src) + if (5) + new /obj/item/clothing/under/schoolgirl(src) + new /obj/item/clothing/head/kitty(src) + if (6) + new /obj/item/clothing/under/blackskirt(src) + var/choice = pick( /obj/item/clothing/head/beret , /obj/item/clothing/head/rabbitears ) + new choice(src) + new /obj/item/clothing/glasses/sunglasses/blindfold(src) + if (7) + new /obj/item/clothing/suit/wcoat(src) + new /obj/item/clothing/under/suit_jacket(src) + new /obj/item/clothing/head/that(src) + if (8) + new /obj/item/clothing/gloves/white(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/under/scratch(src) + if (prob(30)) + new /obj/item/clothing/head/cueball(src) + if (9) + new /obj/item/clothing/under/kilt(src) + new /obj/item/clothing/head/beret(src) + if (10) + new /obj/item/clothing/suit/wcoat(src) + new /obj/item/clothing/glasses/monocle(src) + var/choice = pick( /obj/item/clothing/head/bowler, /obj/item/clothing/head/that) + new choice(src) + new /obj/item/clothing/shoes/black(src) + new /obj/item/weapon/cane(src) + new /obj/item/clothing/under/sl_suit(src) + new /obj/item/clothing/mask/fakemoustache(src) + if (11) + new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(src) + new /obj/item/clothing/head/plaguedoctorhat(src) + new /obj/item/clothing/mask/gas/plaguedoctor(src) + if( 12) + new /obj/item/clothing/under/owl(src) + new /obj/item/clothing/mask/gas/owl_mask(src) + if (13) + new /obj/item/clothing/under/waiter(src) + var/choice = pick( /obj/item/clothing/head/kitty, /obj/item/clothing/head/rabbitears) + new choice(src) + new /obj/item/clothing/suit/apron(src) + if (14) + new /obj/item/clothing/under/pirate(src) + new /obj/item/clothing/suit/pirate(src) + var/choice = pick( /obj/item/clothing/head/pirate , /obj/item/clothing/head/bandana ) + new choice(src) + new /obj/item/clothing/glasses/eyepatch(src) + if (15) + new /obj/item/clothing/under/soviet(src) + new /obj/item/clothing/head/ushanka(src) + if (16) + new /obj/item/clothing/suit/imperium_monk(src) + if (prob(25)) + new /obj/item/clothing/mask/gas/cyborg(src) + if (17) + new /obj/item/clothing/suit/holidaypriest(src) + if (18) + new /obj/item/clothing/shoes/sandal/marisa(src) + for (var/i in 1 to 2) + new /obj/item/clothing/head/wizard/marisa/fake(src) + if (19) + new /obj/item/clothing/under/sundress(src) + new /obj/item/clothing/head/witchwig(src) + new /obj/item/weapon/staff/broom(src) + if (20) + new /obj/item/clothing/shoes/sandal(src) + new /obj/item/clothing/suit/wizrobe/fake(src) + new /obj/item/clothing/head/wizard/fake(src) + new /obj/item/weapon/staff/(src) + if (21) + new /obj/item/clothing/mask/gas/sexyclown(src) + new /obj/item/clothing/under/sexyclown(src) diff --git a/code/game/objects/structures/crates_lockers/closets/l3closet.dm b/code/game/objects/structures/crates_lockers/closets/l3closet.dm index 1c290324e985..73b6b2ee97ef 100644 --- a/code/game/objects/structures/crates_lockers/closets/l3closet.dm +++ b/code/game/objects/structures/crates_lockers/closets/l3closet.dm @@ -1,57 +1,57 @@ -/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/general - icon_state = "bio_general" - icon_closed = "bio_general" - icon_opened = "bio_generalopen" - -/obj/structure/closet/l3closet/general/PopulateContents() - new /obj/item/clothing/suit/bio_suit/new_hazmat/general(src) - new /obj/item/clothing/head/bio_hood/new_hazmat/general(src) - - -/obj/structure/closet/l3closet/virology - icon_state = "bio_virology" - icon_closed = "bio_virology" - icon_opened = "bio_virologyopen" - -/obj/structure/closet/l3closet/virology/PopulateContents() - new /obj/item/clothing/suit/bio_suit/new_hazmat/virology(src) - new /obj/item/clothing/head/bio_hood/new_hazmat/virology(src) - new /obj/item/clothing/mask/breath(src) - new /obj/item/weapon/tank/oxygen(src) - - -/obj/structure/closet/l3closet/security - icon_state = "bio_security" - icon_closed = "bio_security" - icon_opened = "bio_securityopen" - -/obj/structure/closet/l3closet/security/PopulateContents() - new /obj/item/clothing/suit/bio_suit/new_hazmat/security(src) - new /obj/item/clothing/head/bio_hood/new_hazmat/security(src) - - -/obj/structure/closet/l3closet/janitor - icon_state = "bio_janitor" - icon_closed = "bio_janitor" - icon_opened = "bio_janitoropen" - -/obj/structure/closet/l3closet/janitor/PopulateContents() - new /obj/item/clothing/suit/bio_suit/new_hazmat/janitor(src) - new /obj/item/clothing/head/bio_hood/new_hazmat/janitor(src) - - -/obj/structure/closet/l3closet/scientist - icon_state = "bio_scientist" - icon_closed = "bio_scientist" - icon_opened = "bio_scientistopen" - -/obj/structure/closet/l3closet/scientist/PopulateContents() - new /obj/item/clothing/suit/bio_suit/new_hazmat/scientist(src) - new /obj/item/clothing/head/bio_hood/new_hazmat/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/general + icon_state = "bio_general" + icon_closed = "bio_general" + icon_opened = "bio_generalopen" + +/obj/structure/closet/l3closet/general/PopulateContents() + new /obj/item/clothing/suit/bio_suit/new_hazmat/general(src) + new /obj/item/clothing/head/bio_hood/new_hazmat/general(src) + + +/obj/structure/closet/l3closet/virology + icon_state = "bio_virology" + icon_closed = "bio_virology" + icon_opened = "bio_virologyopen" + +/obj/structure/closet/l3closet/virology/PopulateContents() + new /obj/item/clothing/suit/bio_suit/new_hazmat/virology(src) + new /obj/item/clothing/head/bio_hood/new_hazmat/virology(src) + new /obj/item/clothing/mask/breath(src) + new /obj/item/weapon/tank/oxygen(src) + + +/obj/structure/closet/l3closet/security + icon_state = "bio_security" + icon_closed = "bio_security" + icon_opened = "bio_securityopen" + +/obj/structure/closet/l3closet/security/PopulateContents() + new /obj/item/clothing/suit/bio_suit/new_hazmat/security(src) + new /obj/item/clothing/head/bio_hood/new_hazmat/security(src) + + +/obj/structure/closet/l3closet/janitor + icon_state = "bio_janitor" + icon_closed = "bio_janitor" + icon_opened = "bio_janitoropen" + +/obj/structure/closet/l3closet/janitor/PopulateContents() + new /obj/item/clothing/suit/bio_suit/new_hazmat/janitor(src) + new /obj/item/clothing/head/bio_hood/new_hazmat/janitor(src) + + +/obj/structure/closet/l3closet/scientist + icon_state = "bio_scientist" + icon_closed = "bio_scientist" + icon_opened = "bio_scientistopen" + +/obj/structure/closet/l3closet/scientist/PopulateContents() + new /obj/item/clothing/suit/bio_suit/new_hazmat/scientist(src) + new /obj/item/clothing/head/bio_hood/new_hazmat/scientist(src) diff --git a/code/game/objects/structures/crates_lockers/closets/malfunction.dm b/code/game/objects/structures/crates_lockers/closets/malfunction.dm index 80818191cf42..9f2b477da5d4 100644 --- a/code/game/objects/structures/crates_lockers/closets/malfunction.dm +++ b/code/game/objects/structures/crates_lockers/closets/malfunction.dm @@ -1,15 +1,15 @@ - -/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/PopulateContents() - 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/stock_parts/cell(src) - new /obj/item/device/multitool(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/PopulateContents() + 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/stock_parts/cell(src) + new /obj/item/device/multitool(src) 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 38191bc6a071..c87f54383978 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -1,133 +1,133 @@ -/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" - -/obj/structure/closet/secure_closet/engineering_chief/PopulateContents() - if (prob(50)) - new /obj/item/weapon/storage/backpack/industrial(src) - else - new /obj/item/weapon/storage/backpack/satchel/eng(src) - - if (prob(70)) - new /obj/item/clothing/accessory/storage/brown_vest(src) - else - new /obj/item/clothing/accessory/storage/webbing(src) - - new /obj/item/blueprints(src) - new /obj/item/device/remote_device/chief_engineer(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/clothing/suit/storage/hazardvest(src) - new /obj/item/clothing/mask/gas/coloured(src) - new /obj/item/device/multitool(src) - new /obj/item/device/flash(src) - new /obj/item/taperoll/engineering(src) - -/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" - -/obj/structure/closet/secure_closet/engineering_electrical/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/clothing/gloves/yellow(src) - for (var/i in 1 to 3) - new /obj/item/weapon/storage/toolbox/electrical(src) - for (var/i in 1 to 3) - new /obj/item/weapon/module/power_control(src) - for (var/i in 1 to 3) - new /obj/item/device/multitool(src) - -/obj/structure/closet/secure_closet/engineering_welding - name = "Welding Supplies" - req_access = list(access_construction) - icon_state = "secureengweld1" - icon_closed = "secureengweld" - icon_locked = "secureengweld1" - icon_opened = "toolclosetopen" - icon_broken = "secureengweldbroken" - icon_off = "secureengweldoff" - -/obj/structure/closet/secure_closet/engineering_welding/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/head/welding(src) - for (var/i in 1 to 3) - new /obj/item/weapon/weldingtool/largetank(src) - for (var/i in 1 to 3) - new /obj/item/weapon/weldpack(src) - -/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" - -/obj/structure/closet/secure_closet/engineering_personal/PopulateContents() - if (prob(50)) - new /obj/item/weapon/storage/backpack/industrial(src) - else - new /obj/item/weapon/storage/backpack/satchel/eng(src) - - if (prob(70)) - new /obj/item/clothing/accessory/storage/brown_vest(src) - else - new /obj/item/clothing/accessory/storage/webbing(src) - - new /obj/item/weapon/storage/toolbox/mechanical(src) - new /obj/item/device/radio/headset/headset_eng(src) - new /obj/item/clothing/suit/storage/hazardvest(src) - new /obj/item/clothing/mask/gas/coloured(src) - new /obj/item/clothing/glasses/meson(src) - new /obj/item/weapon/cartridge/engineering(src) - new /obj/item/taperoll/engineering(src) - -/obj/structure/closet/secure_closet/atmos_personal - name = "Technician's Locker" - req_access = list(access_atmospherics) - icon_state = "secureatm1" - icon_closed = "secureatm" - icon_locked = "secureatm1" - icon_opened = "secureatmopen" - icon_broken = "secureatmbroken" - icon_off = "secureatmoff" - -/obj/structure/closet/secure_closet/atmos_personal/PopulateContents() - if (prob(50)) - new /obj/item/weapon/storage/backpack/industrial(src) - else - new /obj/item/weapon/storage/backpack/satchel/eng(src) - - if (prob(70)) - new /obj/item/clothing/accessory/storage/brown_vest(src) - else - new /obj/item/clothing/accessory/storage/webbing(src) - - new /obj/item/clothing/suit/fire/firefighter(src) - new /obj/item/device/flashlight(src) - new /obj/item/weapon/extinguisher(src) - new /obj/item/device/radio/headset/headset_eng(src) - new /obj/item/clothing/suit/storage/hazardvest(src) - new /obj/item/clothing/mask/gas/coloured(src) - new /obj/item/weapon/cartridge/atmos(src) - new /obj/item/taperoll/engineering(src) +/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" + +/obj/structure/closet/secure_closet/engineering_chief/PopulateContents() + if (prob(50)) + new /obj/item/weapon/storage/backpack/industrial(src) + else + new /obj/item/weapon/storage/backpack/satchel/eng(src) + + if (prob(70)) + new /obj/item/clothing/accessory/storage/brown_vest(src) + else + new /obj/item/clothing/accessory/storage/webbing(src) + + new /obj/item/blueprints(src) + new /obj/item/device/remote_device/chief_engineer(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/clothing/suit/storage/hazardvest(src) + new /obj/item/clothing/mask/gas/coloured(src) + new /obj/item/device/multitool(src) + new /obj/item/device/flash(src) + new /obj/item/taperoll/engineering(src) + +/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" + +/obj/structure/closet/secure_closet/engineering_electrical/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/clothing/gloves/yellow(src) + for (var/i in 1 to 3) + new /obj/item/weapon/storage/toolbox/electrical(src) + for (var/i in 1 to 3) + new /obj/item/weapon/module/power_control(src) + for (var/i in 1 to 3) + new /obj/item/device/multitool(src) + +/obj/structure/closet/secure_closet/engineering_welding + name = "Welding Supplies" + req_access = list(access_construction) + icon_state = "secureengweld1" + icon_closed = "secureengweld" + icon_locked = "secureengweld1" + icon_opened = "toolclosetopen" + icon_broken = "secureengweldbroken" + icon_off = "secureengweldoff" + +/obj/structure/closet/secure_closet/engineering_welding/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/head/welding(src) + for (var/i in 1 to 3) + new /obj/item/weapon/weldingtool/largetank(src) + for (var/i in 1 to 3) + new /obj/item/weapon/weldpack(src) + +/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" + +/obj/structure/closet/secure_closet/engineering_personal/PopulateContents() + if (prob(50)) + new /obj/item/weapon/storage/backpack/industrial(src) + else + new /obj/item/weapon/storage/backpack/satchel/eng(src) + + if (prob(70)) + new /obj/item/clothing/accessory/storage/brown_vest(src) + else + new /obj/item/clothing/accessory/storage/webbing(src) + + new /obj/item/weapon/storage/toolbox/mechanical(src) + new /obj/item/device/radio/headset/headset_eng(src) + new /obj/item/clothing/suit/storage/hazardvest(src) + new /obj/item/clothing/mask/gas/coloured(src) + new /obj/item/clothing/glasses/meson(src) + new /obj/item/weapon/cartridge/engineering(src) + new /obj/item/taperoll/engineering(src) + +/obj/structure/closet/secure_closet/atmos_personal + name = "Technician's Locker" + req_access = list(access_atmospherics) + icon_state = "secureatm1" + icon_closed = "secureatm" + icon_locked = "secureatm1" + icon_opened = "secureatmopen" + icon_broken = "secureatmbroken" + icon_off = "secureatmoff" + +/obj/structure/closet/secure_closet/atmos_personal/PopulateContents() + if (prob(50)) + new /obj/item/weapon/storage/backpack/industrial(src) + else + new /obj/item/weapon/storage/backpack/satchel/eng(src) + + if (prob(70)) + new /obj/item/clothing/accessory/storage/brown_vest(src) + else + new /obj/item/clothing/accessory/storage/webbing(src) + + new /obj/item/clothing/suit/fire/firefighter(src) + new /obj/item/device/flashlight(src) + new /obj/item/weapon/extinguisher(src) + new /obj/item/device/radio/headset/headset_eng(src) + new /obj/item/clothing/suit/storage/hazardvest(src) + new /obj/item/clothing/mask/gas/coloured(src) + new /obj/item/weapon/cartridge/atmos(src) + new /obj/item/taperoll/engineering(src) 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 259f5eb977f4..4c9aae59093f 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm @@ -1,75 +1,75 @@ -/obj/structure/closet/secure_closet/freezer - -/obj/structure/closet/secure_closet/freezer/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/freezer/kitchen - name = "Kitchen Cabinet" - req_access = list(access_kitchen) - -/obj/structure/closet/secure_closet/freezer/kitchen/PopulateContents() - for (var/i in 1 to 6) - new /obj/item/weapon/reagent_containers/food/condiment/flour(src) - for (var/i in 1 to 3) - new /obj/item/weapon/reagent_containers/food/snacks/meat/monkey(src) - new /obj/item/weapon/reagent_containers/food/condiment/sugar(src) - -/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" - -/obj/structure/closet/secure_closet/freezer/meat/PopulateContents() - for (var/i in 1 to 4) - new /obj/item/weapon/reagent_containers/food/snacks/meat/monkey(src) - -/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" - -/obj/structure/closet/secure_closet/freezer/fridge/PopulateContents() - for (var/i in 1 to 5) - new /obj/item/weapon/reagent_containers/food/drinks/milk(src) - for (var/i in 1 to 3) - new /obj/item/weapon/reagent_containers/food/drinks/soymilk(src) - for (var/i in 1 to 2) - new /obj/item/weapon/storage/fancy/egg_box(src) - -/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) - -/obj/structure/closet/secure_closet/freezer/money/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/weapon/spacecash/c1000(src) - for (var/i in 1 to 5) - new /obj/item/weapon/spacecash/c500(src) - for (var/i in 1 to 6) - new /obj/item/weapon/spacecash/c200(src) +/obj/structure/closet/secure_closet/freezer + +/obj/structure/closet/secure_closet/freezer/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/freezer/kitchen + name = "Kitchen Cabinet" + req_access = list(access_kitchen) + +/obj/structure/closet/secure_closet/freezer/kitchen/PopulateContents() + for (var/i in 1 to 6) + new /obj/item/weapon/reagent_containers/food/condiment/flour(src) + for (var/i in 1 to 3) + new /obj/item/weapon/reagent_containers/food/snacks/meat/monkey(src) + new /obj/item/weapon/reagent_containers/food/condiment/sugar(src) + +/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" + +/obj/structure/closet/secure_closet/freezer/meat/PopulateContents() + for (var/i in 1 to 4) + new /obj/item/weapon/reagent_containers/food/snacks/meat/monkey(src) + +/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" + +/obj/structure/closet/secure_closet/freezer/fridge/PopulateContents() + for (var/i in 1 to 5) + new /obj/item/weapon/reagent_containers/food/drinks/milk(src) + for (var/i in 1 to 3) + new /obj/item/weapon/reagent_containers/food/drinks/soymilk(src) + for (var/i in 1 to 2) + new /obj/item/weapon/storage/fancy/egg_box(src) + +/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) + +/obj/structure/closet/secure_closet/freezer/money/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/weapon/spacecash/c1000(src) + for (var/i in 1 to 5) + new /obj/item/weapon/spacecash/c500(src) + for (var/i in 1 to 6) + new /obj/item/weapon/spacecash/c200(src) 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 41c4daa9ee9f..8c5fae42f6fd 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -1,176 +1,176 @@ -/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) - -/obj/structure/closet/secure_closet/medical1/PopulateContents() - new /obj/item/weapon/storage/box/autoinjectors(src) - new /obj/item/weapon/storage/box/syringes(src) - - for (var/i in 1 to 2) - new /obj/item/weapon/reagent_containers/dropper(src) - for (var/i in 1 to 2) - new /obj/item/weapon/reagent_containers/glass/beaker(src) - for (var/i in 1 to 2) - new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) - for (var/i in 1 to 2) - new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) - -/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) - -/obj/structure/closet/secure_closet/medical2/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/weapon/tank/anesthetic(src) - new /obj/item/clothing/mask/breath/medical(src) - -/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" - -/obj/structure/closet/secure_closet/medical3/PopulateContents() - if(prob(50)) - new /obj/item/weapon/storage/backpack/medic(src) - else - new /obj/item/weapon/storage/backpack/satchel/med(src) - - for (var/i in 1 to 2) - 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/nursesuit (src) - new /obj/item/clothing/head/nursehat (src) - new /obj/item/clothing/under/rank/medical(src) - new /obj/item/clothing/under/rank/medical/skirt(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) - new /obj/item/clothing/gloves/latex/nitrile(src) - new /obj/item/clothing/suit/surgicalapron(src) - -/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" - -/obj/structure/closet/secure_closet/CMO/PopulateContents() - if(prob(50)) - new /obj/item/weapon/storage/backpack/medic(src) - else - new /obj/item/weapon/storage/backpack/satchel/med(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/suit/bio_suit/new_hazmat/cmo(src) - new /obj/item/clothing/head/bio_hood/new_hazmat/cmo(src) - new /obj/item/device/remote_device/chief_medical_officer(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/under/rank/chief_medical_officer(src) - new /obj/item/clothing/under/rank/chief_medical_officer/skirt(src) - new /obj/item/clothing/suit/storage/labcoat/cmo(src) - new /obj/item/weapon/cartridge/cmo(src) - new /obj/item/clothing/gloves/latex/nitrile(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/cmo(src) - new /obj/item/clothing/suit/surgicalapron(src) - new /obj/item/airbag(src) - -/obj/structure/closet/secure_closet/animal - name = "Animal Control" - req_access = list(access_surgery) - -/obj/structure/closet/secure_closet/animal/PopulateContents() - new /obj/item/device/assembly/signaler(src) - for (var/i in 1 to 3) - new /obj/item/device/radio/electropack(src) - -/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) - -/obj/structure/closet/secure_closet/chemical/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/weapon/storage/box/pillbottles(src) - -/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/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) + +/obj/structure/closet/secure_closet/medical1/PopulateContents() + new /obj/item/weapon/storage/box/autoinjectors(src) + new /obj/item/weapon/storage/box/syringes(src) + + for (var/i in 1 to 2) + new /obj/item/weapon/reagent_containers/dropper(src) + for (var/i in 1 to 2) + new /obj/item/weapon/reagent_containers/glass/beaker(src) + for (var/i in 1 to 2) + new /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline(src) + for (var/i in 1 to 2) + new /obj/item/weapon/reagent_containers/glass/bottle/antitoxin(src) + +/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) + +/obj/structure/closet/secure_closet/medical2/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/weapon/tank/anesthetic(src) + new /obj/item/clothing/mask/breath/medical(src) + +/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" + +/obj/structure/closet/secure_closet/medical3/PopulateContents() + if(prob(50)) + new /obj/item/weapon/storage/backpack/medic(src) + else + new /obj/item/weapon/storage/backpack/satchel/med(src) + + for (var/i in 1 to 2) + 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/nursesuit (src) + new /obj/item/clothing/head/nursehat (src) + new /obj/item/clothing/under/rank/medical(src) + new /obj/item/clothing/under/rank/medical/skirt(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) + new /obj/item/clothing/gloves/latex/nitrile(src) + new /obj/item/clothing/suit/surgicalapron(src) + +/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" + +/obj/structure/closet/secure_closet/CMO/PopulateContents() + if(prob(50)) + new /obj/item/weapon/storage/backpack/medic(src) + else + new /obj/item/weapon/storage/backpack/satchel/med(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/suit/bio_suit/new_hazmat/cmo(src) + new /obj/item/clothing/head/bio_hood/new_hazmat/cmo(src) + new /obj/item/device/remote_device/chief_medical_officer(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/under/rank/chief_medical_officer(src) + new /obj/item/clothing/under/rank/chief_medical_officer/skirt(src) + new /obj/item/clothing/suit/storage/labcoat/cmo(src) + new /obj/item/weapon/cartridge/cmo(src) + new /obj/item/clothing/gloves/latex/nitrile(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/cmo(src) + new /obj/item/clothing/suit/surgicalapron(src) + new /obj/item/airbag(src) + +/obj/structure/closet/secure_closet/animal + name = "Animal Control" + req_access = list(access_surgery) + +/obj/structure/closet/secure_closet/animal/PopulateContents() + new /obj/item/device/assembly/signaler(src) + for (var/i in 1 to 3) + new /obj/item/device/radio/electropack(src) + +/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) + +/obj/structure/closet/secure_closet/chemical/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/weapon/storage/box/pillbottles(src) + +/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 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 da27eef704f9..d8bc57b307cc 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm @@ -1,106 +1,106 @@ -/obj/structure/closet/secure_closet/personal - desc = "It's a secure locker for personnel. 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/PopulateContents() - 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) - -/obj/structure/closet/secure_closet/personal/patient - name = "patient's closet" - -/obj/structure/closet/secure_closet/personal/patient/PopulateContents() - new /obj/item/clothing/under/color/white(src) - new /obj/item/clothing/shoes/white(src) - -/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/PopulateContents() - new /obj/item/weapon/storage/backpack/satchel/withwallet(src) - new /obj/item/device/radio/headset(src) - -/obj/structure/closet/secure_closet/personal/attackby(obj/item/weapon/W, mob/user) - if (src.opened) - if (istype(W, /obj/item/weapon/grab)) - src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet - user.drop_item() - if (W) W.forceMove(src.loc) - else 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 - if(src.allowed(user) || !src.registered_name || (istype(I) && (src.registered_name == I.registered_name))) - //they can open all lockers, or nobody owns this, or they own this locker - src.locked = !( src.locked ) - if(src.locked) src.icon_state = src.icon_locked - else src.icon_state = src.icon_closed - - if(!src.registered_name) - src.registered_name = I.registered_name - src.desc = "Owned by [I.registered_name]." - else - to_chat(user, "\red Access Denied") - else if( (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)||istype(W, /obj/item/weapon/twohanded/dualsaber)) && !src.broken) - broken = 1 - locked = 0 - user.SetNextMove(CLICK_CD_MELEE) - desc = "It appears to be broken." - icon_state = src.icon_broken - if(istype(W, /obj/item/weapon/melee/energy/blade)||istype(W, /obj/item/weapon/twohanded/dualsaber)) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(src.loc, "sparks", 50, 1) - for(var/mob/O in viewers(user, 3)) - O.show_message("\blue The locker has been sliced open by [user] with an [W.name]!", 1, "\red You hear metal being sliced and sparks flying.", 2) - else - to_chat(user, "\red Access Denied") - return - -/obj/structure/closet/secure_closet/personal/verb/reset() - set src in oview(1) // One square distance - set category = "Object" - set name = "Reset Lock" - if(!usr.canmove || usr.stat || usr.restrained()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain - return - if(ishuman(usr)) - src.add_fingerprint(usr) - if (src.locked || !src.registered_name) - to_chat(usr, "\red You need to unlock it first.") - else if (src.broken) - to_chat(usr, "\red It appears to be broken.") - else - if (src.opened) - if(!src.close()) - return - src.locked = 1 - src.icon_state = src.icon_locked - src.registered_name = null - src.desc = "It's a secure locker for personnel. The first card swiped gains control." - return +/obj/structure/closet/secure_closet/personal + desc = "It's a secure locker for personnel. 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/PopulateContents() + 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) + +/obj/structure/closet/secure_closet/personal/patient + name = "patient's closet" + +/obj/structure/closet/secure_closet/personal/patient/PopulateContents() + new /obj/item/clothing/under/color/white(src) + new /obj/item/clothing/shoes/white(src) + +/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/PopulateContents() + new /obj/item/weapon/storage/backpack/satchel/withwallet(src) + new /obj/item/device/radio/headset(src) + +/obj/structure/closet/secure_closet/personal/attackby(obj/item/weapon/W, mob/user) + if (src.opened) + if (istype(W, /obj/item/weapon/grab)) + src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet + user.drop_item() + if (W) W.forceMove(src.loc) + else 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 + if(src.allowed(user) || !src.registered_name || (istype(I) && (src.registered_name == I.registered_name))) + //they can open all lockers, or nobody owns this, or they own this locker + src.locked = !( src.locked ) + if(src.locked) src.icon_state = src.icon_locked + else src.icon_state = src.icon_closed + + if(!src.registered_name) + src.registered_name = I.registered_name + src.desc = "Owned by [I.registered_name]." + else + to_chat(user, "\red Access Denied") + else if( (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)||istype(W, /obj/item/weapon/twohanded/dualsaber)) && !src.broken) + broken = 1 + locked = 0 + user.SetNextMove(CLICK_CD_MELEE) + desc = "It appears to be broken." + icon_state = src.icon_broken + if(istype(W, /obj/item/weapon/melee/energy/blade)||istype(W, /obj/item/weapon/twohanded/dualsaber)) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src.loc) + spark_system.start() + playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(src.loc, "sparks", 50, 1) + for(var/mob/O in viewers(user, 3)) + O.show_message("\blue The locker has been sliced open by [user] with an [W.name]!", 1, "\red You hear metal being sliced and sparks flying.", 2) + else + to_chat(user, "\red Access Denied") + return + +/obj/structure/closet/secure_closet/personal/verb/reset() + set src in oview(1) // One square distance + set category = "Object" + set name = "Reset Lock" + if(!usr.canmove || usr.stat || usr.restrained()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain + return + if(ishuman(usr)) + src.add_fingerprint(usr) + if (src.locked || !src.registered_name) + to_chat(usr, "\red You need to unlock it first.") + else if (src.broken) + to_chat(usr, "\red It appears to be broken.") + else + if (src.opened) + if(!src.close()) + return + src.locked = 1 + src.icon_state = src.icon_locked + src.registered_name = null + src.desc = "It's a secure locker for personnel. The first card swiped gains control." + return 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 f4deb33edbbf..47f7f9e32182 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -1,48 +1,48 @@ -/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" - -/obj/structure/closet/secure_closet/scientist/PopulateContents() - 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/science(src) - new /obj/item/device/radio/headset/headset_sci(src) - new /obj/item/weapon/tank/air(src) - new /obj/item/clothing/mask/gas/coloured(src) - -/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" - -/obj/structure/closet/secure_closet/RD/PopulateContents() - - new /obj/item/clothing/suit/bio_suit/new_hazmat/scientist(src) - new /obj/item/clothing/head/bio_hood/new_hazmat/scientist(src) - new /obj/item/clothing/under/rank/research_director(src) - new /obj/item/clothing/under/rank/research_director/rdalt(src) - new /obj/item/clothing/under/rank/research_director/dress_rd(src) - new /obj/item/clothing/suit/storage/labcoat/rd(src) - new /obj/item/weapon/cartridge/rd(src) - new /obj/item/clothing/shoes/white(src) - new /obj/item/clothing/shoes/leather(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/coloured(src) - new /obj/item/device/flash(src) - new /obj/item/device/remote_device/research_director(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" + +/obj/structure/closet/secure_closet/scientist/PopulateContents() + 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/science(src) + new /obj/item/device/radio/headset/headset_sci(src) + new /obj/item/weapon/tank/air(src) + new /obj/item/clothing/mask/gas/coloured(src) + +/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" + +/obj/structure/closet/secure_closet/RD/PopulateContents() + + new /obj/item/clothing/suit/bio_suit/new_hazmat/scientist(src) + new /obj/item/clothing/head/bio_hood/new_hazmat/scientist(src) + new /obj/item/clothing/under/rank/research_director(src) + new /obj/item/clothing/under/rank/research_director/rdalt(src) + new /obj/item/clothing/under/rank/research_director/dress_rd(src) + new /obj/item/clothing/suit/storage/labcoat/rd(src) + new /obj/item/weapon/cartridge/rd(src) + new /obj/item/clothing/shoes/white(src) + new /obj/item/clothing/shoes/leather(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/coloured(src) + new /obj/item/device/flash(src) + new /obj/item/device/remote_device/research_director(src) new /obj/item/airbag(src) \ 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 3d643ed6b071..1b892bbd9bd0 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,135 +1,135 @@ -/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 - locked = 1 - var/large = 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(src.locked || src.welded) - return 0 - return ..() - -/obj/structure/closet/secure_closet/close() - if(..()) - if(broken) - icon_state = src.icon_off - return 1 - else - return 0 - -/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) - if(src.opened) - to_chat(user, "Close the locker first.") - return - if(src.broken) - to_chat(user, "The locker appears to be broken.") - return - if(user.loc == src) - to_chat(user, "You can't reach the lock from inside.") - return - 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].") - update_icon() - else - to_chat(user, "Access Denied") - -/obj/structure/closet/secure_closet/attackby(obj/item/weapon/W, mob/user) - if(src.opened) - if(istype(W, /obj/item/weapon/grab)) - if(src.large) - src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet - else - to_chat(user, "The locker is too small to stuff [W:affecting] into!") - if(isrobot(user)) - return - user.drop_item() - if(W) - W.forceMove(src.loc) - else if((istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)||istype(W, /obj/item/weapon/twohanded/dualsaber)) && !src.broken) - broken = 1 - locked = 0 - user.SetNextMove(CLICK_CD_MELEE) - desc = "It appears to be broken." - icon_state = icon_off - flick(icon_broken, src) - if(istype(W, /obj/item/weapon/melee/energy/blade)||istype(W, /obj/item/weapon/twohanded/dualsaber)) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(src.loc, "sparks", 50, 1) - for(var/mob/O in viewers(user, 3)) - O.show_message("The locker has been sliced open by [user] with an [W.name]!", 1, "You hear metal being sliced and sparks flying.", 2) - else - 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) - else if(istype(W,/obj/item/weapon/packageWrap) || istype(W,/obj/item/weapon/weldingtool)) - return ..(W,user) - else - togglelock(user) - -/obj/structure/closet/secure_closet/attack_hand(mob/user) - src.add_fingerprint(user) - user.SetNextMove(CLICK_CD_RAPID) - if(src.locked) - src.togglelock(user) - else - src.toggle(user) - -/obj/structure/closet/secure_closet/attack_paw(mob/user) - 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.stat || usr.restrained()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain - return - - if(ishuman(usr)) - src.add_fingerprint(usr) - src.togglelock(usr) - else - to_chat(usr, "This mob type can't use this verb.") - -/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.Cut() - 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 + name = "secure locker" + desc = "It's an immobile card-locked storage unit." + icon = 'icons/obj/closet.dmi' + icon_state = "secure1" + density = 1 + opened = 0 + locked = 1 + var/large = 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(src.locked || src.welded) + return 0 + return ..() + +/obj/structure/closet/secure_closet/close() + if(..()) + if(broken) + icon_state = src.icon_off + return 1 + else + return 0 + +/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) + if(src.opened) + to_chat(user, "Close the locker first.") + return + if(src.broken) + to_chat(user, "The locker appears to be broken.") + return + if(user.loc == src) + to_chat(user, "You can't reach the lock from inside.") + return + 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].") + update_icon() + else + to_chat(user, "Access Denied") + +/obj/structure/closet/secure_closet/attackby(obj/item/weapon/W, mob/user) + if(src.opened) + if(istype(W, /obj/item/weapon/grab)) + if(src.large) + src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet + else + to_chat(user, "The locker is too small to stuff [W:affecting] into!") + if(isrobot(user)) + return + user.drop_item() + if(W) + W.forceMove(src.loc) + else if((istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)||istype(W, /obj/item/weapon/twohanded/dualsaber)) && !src.broken) + broken = 1 + locked = 0 + user.SetNextMove(CLICK_CD_MELEE) + desc = "It appears to be broken." + icon_state = icon_off + flick(icon_broken, src) + if(istype(W, /obj/item/weapon/melee/energy/blade)||istype(W, /obj/item/weapon/twohanded/dualsaber)) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src.loc) + spark_system.start() + playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(src.loc, "sparks", 50, 1) + for(var/mob/O in viewers(user, 3)) + O.show_message("The locker has been sliced open by [user] with an [W.name]!", 1, "You hear metal being sliced and sparks flying.", 2) + else + 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) + else if(istype(W,/obj/item/weapon/packageWrap) || istype(W,/obj/item/weapon/weldingtool)) + return ..(W,user) + else + togglelock(user) + +/obj/structure/closet/secure_closet/attack_hand(mob/user) + src.add_fingerprint(user) + user.SetNextMove(CLICK_CD_RAPID) + if(src.locked) + src.togglelock(user) + else + src.toggle(user) + +/obj/structure/closet/secure_closet/attack_paw(mob/user) + 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.stat || usr.restrained()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain + return + + if(ishuman(usr)) + src.add_fingerprint(usr) + src.togglelock(usr) + else + to_chat(usr, "This mob type can't use this verb.") + +/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.Cut() + if(!opened) + if(locked) + icon_state = icon_locked + 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 21e58010bc35..9d5a9dc4e6b7 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -1,369 +1,369 @@ -/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" - -/obj/structure/closet/secure_closet/captains/PopulateContents() - 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/captunic/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/clothing/accessory/holster/waist(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/clothing/under/rank/capcamsole(src) - new /obj/item/device/remote_device/captain(src) - new /obj/item/airbag(src) - #ifdef NEWYEARCONTENT - new /obj/item/clothing/suit/wintercoat/captain(src) - new /obj/item/clothing/head/santa(src) - new /obj/item/clothing/shoes/winterboots(src) - #endif - -/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" - -/obj/structure/closet/secure_closet/hop/PopulateContents() - new /obj/item/device/remote_device/head_of_personal(src) - new /obj/item/clothing/glasses/sunglasses(src) - new /obj/item/clothing/suit/armor/vest(src) - new /obj/item/clothing/head/helmet(src) - new /obj/item/weapon/cartridge/hop(src) - new /obj/item/device/radio/headset/heads/hop(src) - - for (var/i in 1 to 2) - new /obj/item/weapon/storage/box/ids(src) - - new /obj/item/clothing/accessory/holster/waist(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/device/flash(src) - new /obj/item/airbag(src) - -/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" - -/obj/structure/closet/secure_closet/hop2/PopulateContents() - new /obj/item/clothing/head/fez(src) - 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) - new /obj/item/clothing/under/rank/head_of_personnel_whimsy(src) - new /obj/item/clothing/under/rank/goodman_shirt(src) - new /obj/item/clothing/suit/goodman_jacket(src) - new /obj/item/airbag(src) - -/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" - -/obj/structure/closet/secure_closet/hos/PopulateContents() - 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/head/helmet/HoS/dermal(src) - new /obj/item/clothing/head/beret/sec/hos(src) - new /obj/item/device/remote_device/head_of_security(src) - new /obj/item/clothing/under/rank/head_of_security_fem(src) - new /obj/item/clothing/suit/armor/hos(src) - new /obj/item/clothing/under/rank/head_of_security(src) - new /obj/item/weapon/storage/belt/security(src) - new /obj/item/clothing/mask/gas/sechailer(src) - new /obj/item/weapon/cartridge/hos(src) - new /obj/item/device/radio/headset/heads/hos(src) - new /obj/item/taperoll/police(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/gloves/black/hos(src) - new /obj/item/clothing/glasses/thermal/hos_thermals(src) - new /obj/item/weapon/shield/riot/tele(src) - new /obj/item/weapon/storage/lockbox/loyalty(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/device/flash(src) - new /obj/item/weapon/reagent_containers/spray/pepper(src) - new /obj/item/weapon/melee/baton(src) - new /obj/item/clothing/accessory/holster/waist(src) - new /obj/item/weapon/melee/telebaton(src) - new /obj/item/weapon/gun/energy/gun(src) - new /obj/item/device/flashlight/flare(src) - new /obj/item/clothing/under/rank/head_of_security/turtleneck(src) - new /obj/item/device/flashlight/seclite(src) - new /obj/item/airbag(src) - #ifdef NEWYEARCONTENT - new /obj/item/clothing/suit/wintercoat/security(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/santa(src) - #endif - -/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" - -/obj/structure/closet/secure_closet/warden/PopulateContents() - 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/warden(src) - new /obj/item/clothing/head/beret/sec/warden(src) - new /obj/item/clothing/under/rank/warden(src) - new /obj/item/clothing/under/rank/warden_fem(src) - new /obj/item/clothing/suit/storage/flak(src) - new /obj/item/clothing/suit/storage/flak/warden(src) - new /obj/item/clothing/accessory/holster/armpit(src) - new /obj/item/weapon/gun/energy/taser(src) - new /obj/item/weapon/storage/belt/security(src) - new /obj/item/clothing/mask/gas/sechailer(src) - new /obj/item/device/radio/headset/headset_sec(src) - new /obj/item/clothing/glasses/sunglasses/sechud(src) - new /obj/item/taperoll/police(src) - new /obj/item/weapon/storage/box/flashbangs(src) - new /obj/item/device/flash(src) - new /obj/item/weapon/reagent_containers/spray/pepper(src) - new /obj/item/weapon/melee/baton(src) - new /obj/item/weapon/storage/box/holobadge(src) - new /obj/item/device/flashlight/seclite(src) - #ifdef NEWYEARCONTENT - new /obj/item/clothing/suit/wintercoat/security(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/santa(src) - #endif - -/obj/structure/closet/secure_closet/security - name = "Security Officer's Locker" - req_access = list(access_brig) - icon_state = "sec1" - icon_closed = "sec" - icon_locked = "sec1" - icon_opened = "secopen" - icon_broken = "secbroken" - icon_off = "secoff" - -/obj/structure/closet/secure_closet/security/PopulateContents() - 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/gloves/security(src) - new /obj/item/clothing/suit/storage/flak(src) - new /obj/item/clothing/head/helmet(src) - new /obj/item/weapon/storage/belt/security(src) - new /obj/item/clothing/accessory/holster/armpit(src) - new /obj/item/weapon/gun/energy/taser(src) - new /obj/item/device/radio/headset/headset_sec(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(src) - new /obj/item/clothing/glasses/sunglasses/sechud(src) - new /obj/item/taperoll/police(src) - new /obj/item/device/hailer(src) - new /obj/item/device/flashlight/flare(src) - new /obj/item/device/flashlight/seclite(src) - #ifdef NEWYEARCONTENT - new /obj/item/clothing/suit/wintercoat/security(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/ushanka(src) - #endif - -/obj/structure/closet/secure_closet/security/cargo - -/obj/structure/closet/secure_closet/security/cargo/PopulateContents() - new /obj/item/clothing/accessory/armband/cargo(src) - new /obj/item/device/encryptionkey/headset_cargo(src) - -/obj/structure/closet/secure_closet/security/engine - -/obj/structure/closet/secure_closet/security/engine/PopulateContents() - new /obj/item/clothing/accessory/armband/engine(src) - new /obj/item/device/encryptionkey/headset_eng(src) - -/obj/structure/closet/secure_closet/security/science - -/obj/structure/closet/secure_closet/security/science/PopulateContents() - new /obj/item/clothing/accessory/armband/science(src) - new /obj/item/device/encryptionkey/headset_sci(src) - -/obj/structure/closet/secure_closet/security/med - -/obj/structure/closet/secure_closet/security/med/PopulateContents() - new /obj/item/clothing/accessory/armband/medgreen(src) - new /obj/item/device/encryptionkey/headset_med(src) - -/obj/structure/closet/secure_closet/detective - name = "Detective's Cabinet" - req_access = list(access_detective) - 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/detective/PopulateContents() - new /obj/item/clothing/under/det(src) - new /obj/item/clothing/under/det/black(src) - new /obj/item/clothing/under/det/slob(src) - new /obj/item/clothing/under/det/max_payne(src) - new /obj/item/clothing/suit/storage/det_suit(src) - new /obj/item/clothing/suit/storage/det_suit/black(src) - new /obj/item/clothing/suit/storage/det_suit/max_payne(src) - new /obj/item/clothing/gloves/black(src) - new /obj/item/clothing/head/det_hat(src) - new /obj/item/clothing/head/det_hat/black(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) - for (var/i in 1 to 2) - new /obj/item/ammo_box/magazine/c45r(src) - new /obj/item/taperoll/police(src) - new /obj/item/weapon/gun/projectile/automatic/colt1911(src) - new /obj/item/clothing/accessory/holster/armpit(src) - -/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) - -/obj/structure/closet/secure_closet/injection/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/weapon/reagent_containers/ld50_syringe/choral(src) - -/obj/structure/closet/secure_closet/brig - name = "Brig Locker" - req_access = list(access_brig) - anchored = 1 - var/id = null - -/obj/structure/closet/secure_closet/brig/PopulateContents() - new /obj/item/clothing/under/color/orange(src) - new /obj/item/clothing/shoes/orange(src) - -/obj/structure/closet/secure_closet/courtroom - name = "Courtroom Locker" - req_access = list(access_court) - -/obj/structure/closet/secure_closet/courtroom/PopulateContents() - new /obj/item/clothing/shoes/brown(src) - for (var/i in 1 to 3) - 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) - -/obj/structure/closet/secure_closet/wall - name = "wall locker" - req_access = list(access_brig) - 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/forensics - name = "Forensics'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" - -/obj/structure/closet/secure_closet/forensics/PopulateContents() - new /obj/item/clothing/under/rank/forensic_technician(src) - new /obj/item/clothing/suit/storage/labcoat(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/shoes/red(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/taperoll/police(src) +/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" + +/obj/structure/closet/secure_closet/captains/PopulateContents() + 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/captunic/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/clothing/accessory/holster/waist(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/clothing/under/rank/capcamsole(src) + new /obj/item/device/remote_device/captain(src) + new /obj/item/airbag(src) + #ifdef NEWYEARCONTENT + new /obj/item/clothing/suit/wintercoat/captain(src) + new /obj/item/clothing/head/santa(src) + new /obj/item/clothing/shoes/winterboots(src) + #endif + +/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" + +/obj/structure/closet/secure_closet/hop/PopulateContents() + new /obj/item/device/remote_device/head_of_personal(src) + new /obj/item/clothing/glasses/sunglasses(src) + new /obj/item/clothing/suit/armor/vest(src) + new /obj/item/clothing/head/helmet(src) + new /obj/item/weapon/cartridge/hop(src) + new /obj/item/device/radio/headset/heads/hop(src) + + for (var/i in 1 to 2) + new /obj/item/weapon/storage/box/ids(src) + + new /obj/item/clothing/accessory/holster/waist(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/device/flash(src) + new /obj/item/airbag(src) + +/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" + +/obj/structure/closet/secure_closet/hop2/PopulateContents() + new /obj/item/clothing/head/fez(src) + 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) + new /obj/item/clothing/under/rank/head_of_personnel_whimsy(src) + new /obj/item/clothing/under/rank/goodman_shirt(src) + new /obj/item/clothing/suit/goodman_jacket(src) + new /obj/item/airbag(src) + +/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" + +/obj/structure/closet/secure_closet/hos/PopulateContents() + 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/head/helmet/HoS/dermal(src) + new /obj/item/clothing/head/beret/sec/hos(src) + new /obj/item/device/remote_device/head_of_security(src) + new /obj/item/clothing/under/rank/head_of_security_fem(src) + new /obj/item/clothing/suit/armor/hos(src) + new /obj/item/clothing/under/rank/head_of_security(src) + new /obj/item/weapon/storage/belt/security(src) + new /obj/item/clothing/mask/gas/sechailer(src) + new /obj/item/weapon/cartridge/hos(src) + new /obj/item/device/radio/headset/heads/hos(src) + new /obj/item/taperoll/police(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/gloves/black/hos(src) + new /obj/item/clothing/glasses/thermal/hos_thermals(src) + new /obj/item/weapon/shield/riot/tele(src) + new /obj/item/weapon/storage/lockbox/loyalty(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/device/flash(src) + new /obj/item/weapon/reagent_containers/spray/pepper(src) + new /obj/item/weapon/melee/baton(src) + new /obj/item/clothing/accessory/holster/waist(src) + new /obj/item/weapon/melee/telebaton(src) + new /obj/item/weapon/gun/energy/gun(src) + new /obj/item/device/flashlight/flare(src) + new /obj/item/clothing/under/rank/head_of_security/turtleneck(src) + new /obj/item/device/flashlight/seclite(src) + new /obj/item/airbag(src) + #ifdef NEWYEARCONTENT + new /obj/item/clothing/suit/wintercoat/security(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/santa(src) + #endif + +/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" + +/obj/structure/closet/secure_closet/warden/PopulateContents() + 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/warden(src) + new /obj/item/clothing/head/beret/sec/warden(src) + new /obj/item/clothing/under/rank/warden(src) + new /obj/item/clothing/under/rank/warden_fem(src) + new /obj/item/clothing/suit/storage/flak(src) + new /obj/item/clothing/suit/storage/flak/warden(src) + new /obj/item/clothing/accessory/holster/armpit(src) + new /obj/item/weapon/gun/energy/taser(src) + new /obj/item/weapon/storage/belt/security(src) + new /obj/item/clothing/mask/gas/sechailer(src) + new /obj/item/device/radio/headset/headset_sec(src) + new /obj/item/clothing/glasses/sunglasses/sechud(src) + new /obj/item/taperoll/police(src) + new /obj/item/weapon/storage/box/flashbangs(src) + new /obj/item/device/flash(src) + new /obj/item/weapon/reagent_containers/spray/pepper(src) + new /obj/item/weapon/melee/baton(src) + new /obj/item/weapon/storage/box/holobadge(src) + new /obj/item/device/flashlight/seclite(src) + #ifdef NEWYEARCONTENT + new /obj/item/clothing/suit/wintercoat/security(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/santa(src) + #endif + +/obj/structure/closet/secure_closet/security + name = "Security Officer's Locker" + req_access = list(access_brig) + icon_state = "sec1" + icon_closed = "sec" + icon_locked = "sec1" + icon_opened = "secopen" + icon_broken = "secbroken" + icon_off = "secoff" + +/obj/structure/closet/secure_closet/security/PopulateContents() + 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/gloves/security(src) + new /obj/item/clothing/suit/storage/flak(src) + new /obj/item/clothing/head/helmet(src) + new /obj/item/weapon/storage/belt/security(src) + new /obj/item/clothing/accessory/holster/armpit(src) + new /obj/item/weapon/gun/energy/taser(src) + new /obj/item/device/radio/headset/headset_sec(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(src) + new /obj/item/clothing/glasses/sunglasses/sechud(src) + new /obj/item/taperoll/police(src) + new /obj/item/device/hailer(src) + new /obj/item/device/flashlight/flare(src) + new /obj/item/device/flashlight/seclite(src) + #ifdef NEWYEARCONTENT + new /obj/item/clothing/suit/wintercoat/security(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/ushanka(src) + #endif + +/obj/structure/closet/secure_closet/security/cargo + +/obj/structure/closet/secure_closet/security/cargo/PopulateContents() + new /obj/item/clothing/accessory/armband/cargo(src) + new /obj/item/device/encryptionkey/headset_cargo(src) + +/obj/structure/closet/secure_closet/security/engine + +/obj/structure/closet/secure_closet/security/engine/PopulateContents() + new /obj/item/clothing/accessory/armband/engine(src) + new /obj/item/device/encryptionkey/headset_eng(src) + +/obj/structure/closet/secure_closet/security/science + +/obj/structure/closet/secure_closet/security/science/PopulateContents() + new /obj/item/clothing/accessory/armband/science(src) + new /obj/item/device/encryptionkey/headset_sci(src) + +/obj/structure/closet/secure_closet/security/med + +/obj/structure/closet/secure_closet/security/med/PopulateContents() + new /obj/item/clothing/accessory/armband/medgreen(src) + new /obj/item/device/encryptionkey/headset_med(src) + +/obj/structure/closet/secure_closet/detective + name = "Detective's Cabinet" + req_access = list(access_detective) + 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/detective/PopulateContents() + new /obj/item/clothing/under/det(src) + new /obj/item/clothing/under/det/black(src) + new /obj/item/clothing/under/det/slob(src) + new /obj/item/clothing/under/det/max_payne(src) + new /obj/item/clothing/suit/storage/det_suit(src) + new /obj/item/clothing/suit/storage/det_suit/black(src) + new /obj/item/clothing/suit/storage/det_suit/max_payne(src) + new /obj/item/clothing/gloves/black(src) + new /obj/item/clothing/head/det_hat(src) + new /obj/item/clothing/head/det_hat/black(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) + for (var/i in 1 to 2) + new /obj/item/ammo_box/magazine/c45r(src) + new /obj/item/taperoll/police(src) + new /obj/item/weapon/gun/projectile/automatic/colt1911(src) + new /obj/item/clothing/accessory/holster/armpit(src) + +/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) + +/obj/structure/closet/secure_closet/injection/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/weapon/reagent_containers/ld50_syringe/choral(src) + +/obj/structure/closet/secure_closet/brig + name = "Brig Locker" + req_access = list(access_brig) + anchored = 1 + var/id = null + +/obj/structure/closet/secure_closet/brig/PopulateContents() + new /obj/item/clothing/under/color/orange(src) + new /obj/item/clothing/shoes/orange(src) + +/obj/structure/closet/secure_closet/courtroom + name = "Courtroom Locker" + req_access = list(access_court) + +/obj/structure/closet/secure_closet/courtroom/PopulateContents() + new /obj/item/clothing/shoes/brown(src) + for (var/i in 1 to 3) + 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) + +/obj/structure/closet/secure_closet/wall + name = "wall locker" + req_access = list(access_brig) + 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/forensics + name = "Forensics'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" + +/obj/structure/closet/secure_closet/forensics/PopulateContents() + new /obj/item/clothing/under/rank/forensic_technician(src) + new /obj/item/clothing/suit/storage/labcoat(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/shoes/red(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/taperoll/police(src) diff --git a/code/game/objects/structures/crates_lockers/closets/syndicate.dm b/code/game/objects/structures/crates_lockers/closets/syndicate.dm index e372671c7fb0..a3d00d9a7a0e 100644 --- a/code/game/objects/structures/crates_lockers/closets/syndicate.dm +++ b/code/game/objects/structures/crates_lockers/closets/syndicate.dm @@ -1,106 +1,106 @@ -/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/PopulateContents() - new /obj/item/clothing/glasses/night(src) - new /obj/item/clothing/under/syndicate(src) - new /obj/item/weapon/crowbar/red(src) - new /obj/item/weapon/storage/belt/military(src) - new /obj/item/clothing/gloves/combat(src) - new /obj/item/clothing/accessory/storage/syndi_vest(src) - new /obj/item/clothing/mask/gas/syndicate(src) - - -/obj/structure/closet/syndicate/nuclear - desc = "It's a storage unit for nuclear-operative gear." - -/obj/structure/closet/syndicate/nuclear/PopulateContents() - new /obj/item/weapon/storage/box/handcuffs(src) - new /obj/item/weapon/storage/box/flashbangs(src) - for (var/i in 1 to 6) - new /obj/item/weapon/pinpointer/nukeop(src) - new /obj/item/device/pda/syndicate(src) - -/obj/structure/closet/syndicate/resources - desc = "An old, dusty locker." - -/obj/structure/closet/syndicate/resources/PopulateContents() - 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 - - var/pickednum = rand(1, 50) - - //Sad trombone - if(pickednum == 1) - var/obj/item/weapon/paper/P = new(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) // WEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE~ - new /obj/item/stack/sheet/metal(src, rand(common_min, common_max)) - - //Glass (common ore) - if(pickednum >= 5) - new /obj/item/stack/sheet/glass(src, rand(common_min, common_max)) - - //Plasteel (common ore) Because it has a million more uses then phoron - if(pickednum >= 10) - new /obj/item/stack/sheet/plasteel(src, rand(common_min, common_max)) - - //Phoron (rare ore) - if(pickednum >= 15) - new /obj/item/stack/sheet/mineral/phoron(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) - -/obj/structure/closet/syndicate/resources/everything - desc = "It's an emergency storage closet for repairs." - -/obj/structure/closet/syndicate/resources/everything/PopulateContents() - var/list/resources = list( - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/glass, - /obj/item/stack/sheet/mineral/gold, - /obj/item/stack/sheet/mineral/silver, - /obj/item/stack/sheet/mineral/phoron, - /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/cable_coil, - /obj/item/stack/rods - ) - - for(var/i in 1 to 2) - for(var/res in resources) - var/obj/item/stack/R = new res(src) - R.set_amount(R.max_amount) +/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/PopulateContents() + new /obj/item/clothing/glasses/night(src) + new /obj/item/clothing/under/syndicate(src) + new /obj/item/weapon/crowbar/red(src) + new /obj/item/weapon/storage/belt/military(src) + new /obj/item/clothing/gloves/combat(src) + new /obj/item/clothing/accessory/storage/syndi_vest(src) + new /obj/item/clothing/mask/gas/syndicate(src) + + +/obj/structure/closet/syndicate/nuclear + desc = "It's a storage unit for nuclear-operative gear." + +/obj/structure/closet/syndicate/nuclear/PopulateContents() + new /obj/item/weapon/storage/box/handcuffs(src) + new /obj/item/weapon/storage/box/flashbangs(src) + for (var/i in 1 to 6) + new /obj/item/weapon/pinpointer/nukeop(src) + new /obj/item/device/pda/syndicate(src) + +/obj/structure/closet/syndicate/resources + desc = "An old, dusty locker." + +/obj/structure/closet/syndicate/resources/PopulateContents() + 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 + + var/pickednum = rand(1, 50) + + //Sad trombone + if(pickednum == 1) + var/obj/item/weapon/paper/P = new(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) // WEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE~ + new /obj/item/stack/sheet/metal(src, rand(common_min, common_max)) + + //Glass (common ore) + if(pickednum >= 5) + new /obj/item/stack/sheet/glass(src, rand(common_min, common_max)) + + //Plasteel (common ore) Because it has a million more uses then phoron + if(pickednum >= 10) + new /obj/item/stack/sheet/plasteel(src, rand(common_min, common_max)) + + //Phoron (rare ore) + if(pickednum >= 15) + new /obj/item/stack/sheet/mineral/phoron(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) + +/obj/structure/closet/syndicate/resources/everything + desc = "It's an emergency storage closet for repairs." + +/obj/structure/closet/syndicate/resources/everything/PopulateContents() + var/list/resources = list( + /obj/item/stack/sheet/metal, + /obj/item/stack/sheet/glass, + /obj/item/stack/sheet/mineral/gold, + /obj/item/stack/sheet/mineral/silver, + /obj/item/stack/sheet/mineral/phoron, + /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/cable_coil, + /obj/item/stack/rods + ) + + for(var/i in 1 to 2) + for(var/res in resources) + var/obj/item/stack/R = new res(src) + R.set_amount(R.max_amount) 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 e817aebe6981..42fb22d9b4bd 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -1,216 +1,216 @@ -/* 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 tanks." - icon_state = "emergency" - icon_closed = "emergency" - icon_opened = "emergencyopen" - -/obj/structure/closet/emcloset/PopulateContents() - new /obj/item/clothing/head/helmet/space/sk(src) - new /obj/item/clothing/suit/space/sk(src) - - switch (pickweight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10, "nothing" = 4))) - if ("small") - for (var/i in 1 to 2) - new /obj/item/weapon/tank/emergency_oxygen(src) - new /obj/item/clothing/mask/breath(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") - for (var/i in 1 to 2) - new /obj/item/weapon/tank/emergency_oxygen/engi(src) - new /obj/item/clothing/mask/breath(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 you want to re-add fire, just add "fire" = 15 to the pick list. - /*if ("fire") - new /obj/structure/closet/firecloset(src.loc) - qdel(src)*/ - -/obj/structure/closet/emcloset/legacy/PopulateContents() - ..() - new /obj/item/weapon/tank/oxygen(src) - new /obj/item/clothing/mask/gas/coloured(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/PopulateContents() - new /obj/item/clothing/suit/fire/firefighter(src) - new /obj/item/clothing/mask/gas/coloured(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/PopulateContents() - new /obj/item/clothing/suit/fire/firefighter(src) - new /obj/item/clothing/mask/gas/coloured(src) - new /obj/item/device/flashlight(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/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/PopulateContents() - 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) - for (var/i in 1 to 3) - 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)) - if(prob(75)) - new /obj/item/clothing/head/hardhat/yellow(src) - else - new /obj/item/clothing/head/hardhat/yellow/visor(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/PopulateContents() - for (var/i in 1 to 2) - 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/PopulateContents() - 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/PopulateContents() - 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 = TRUE - density = FALSE - wall_mounted = TRUE - -/obj/structure/closet/hydrant/PopulateContents() - new /obj/item/clothing/suit/fire/firefighter(src) - new /obj/item/clothing/mask/gas/coloured(src) - new /obj/item/device/flashlight(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 = TRUE - density = FALSE - wall_mounted = TRUE - -/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 tanks." + icon_state = "emergency" + icon_closed = "emergency" + icon_opened = "emergencyopen" + +/obj/structure/closet/emcloset/PopulateContents() + new /obj/item/clothing/head/helmet/space/sk(src) + new /obj/item/clothing/suit/space/sk(src) + + switch (pickweight(list("small" = 55, "aid" = 25, "tank" = 10, "both" = 10, "nothing" = 4))) + if ("small") + for (var/i in 1 to 2) + new /obj/item/weapon/tank/emergency_oxygen(src) + new /obj/item/clothing/mask/breath(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") + for (var/i in 1 to 2) + new /obj/item/weapon/tank/emergency_oxygen/engi(src) + new /obj/item/clothing/mask/breath(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 you want to re-add fire, just add "fire" = 15 to the pick list. + /*if ("fire") + new /obj/structure/closet/firecloset(src.loc) + qdel(src)*/ + +/obj/structure/closet/emcloset/legacy/PopulateContents() + ..() + new /obj/item/weapon/tank/oxygen(src) + new /obj/item/clothing/mask/gas/coloured(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/PopulateContents() + new /obj/item/clothing/suit/fire/firefighter(src) + new /obj/item/clothing/mask/gas/coloured(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/PopulateContents() + new /obj/item/clothing/suit/fire/firefighter(src) + new /obj/item/clothing/mask/gas/coloured(src) + new /obj/item/device/flashlight(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/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/PopulateContents() + 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) + for (var/i in 1 to 3) + 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)) + if(prob(75)) + new /obj/item/clothing/head/hardhat/yellow(src) + else + new /obj/item/clothing/head/hardhat/yellow/visor(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/PopulateContents() + for (var/i in 1 to 2) + 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/PopulateContents() + 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/PopulateContents() + 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 = TRUE + density = FALSE + wall_mounted = TRUE + +/obj/structure/closet/hydrant/PopulateContents() + new /obj/item/clothing/suit/fire/firefighter(src) + new /obj/item/clothing/mask/gas/coloured(src) + new /obj/item/device/flashlight(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 = TRUE + density = FALSE + wall_mounted = TRUE + +/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 c45f4297c7d4..e4be75d443ec 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -1,416 +1,416 @@ -/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/red - name = "security wardrobe" - icon_state = "red" - icon_closed = "red" - -/obj/structure/closet/wardrobe/red/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/rank/security(src) - for (var/i in 1 to 3) - new /obj/item/clothing/shoes/jackboots(src) - for (var/i in 1 to 3) - new /obj/item/clothing/head/soft/sec(src) - for (var/i in 1 to 2) - new /obj/item/clothing/mask/bandana/red(src) - for (var/i in 1 to 3) - new /obj/item/clothing/head/beret/sec(src) - #ifdef NEWYEARCONTENT - for (var/i in 1 to 3) - new /obj/item/clothing/head/santa(src) - new /obj/item/clothing/suit/wintercoat/security(src) - new /obj/item/clothing/shoes/winterboots(src) - #endif - - -/obj/structure/closet/wardrobe/pink - name = "pink wardrobe" - icon_state = "pink" - icon_closed = "pink" - -/obj/structure/closet/wardrobe/pink/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/color/pink(src) - new /obj/item/clothing/shoes/brown(src) - -/obj/structure/closet/wardrobe/black - name = "black wardrobe" - icon_state = "black" - icon_closed = "black" - -/obj/structure/closet/wardrobe/black/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/color/black(src) - if(prob(25)) - new /obj/item/clothing/suit/jacket/leather(src) - if(prob(20)) - new /obj/item/clothing/suit/jacket/leather/overcoat(src) - for (var/i in 1 to 3) - new /obj/item/clothing/shoes/black(src) - #ifdef NEWYEARCONTENT - for (var/i in 1 to 3) - new /obj/item/clothing/suit/wintercoat(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/santa(src) - #endif - - -/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/PopulateContents() - 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/game_kit/chaplain(src) - new /obj/item/weapon/reagent_containers/spray/thurible(src) - for (var/i in 1 to 2) - new /obj/item/weapon/storage/fancy/candle_box(src) - - -/obj/structure/closet/wardrobe/green - name = "green wardrobe" - icon_state = "green" - icon_closed = "green" - -/obj/structure/closet/wardrobe/green/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/color/green(src) - for (var/i in 1 to 3) - new /obj/item/clothing/shoes/black(src) - //for (var/i in 1 to 2) - // new /obj/item/clothing/mask/bandana/green(src) - - -/obj/structure/closet/wardrobe/xenos - name = "xenos wardrobe" - icon_state = "green" - icon_closed = "green" - -/obj/structure/closet/wardrobe/xenos/PopulateContents() - new /obj/item/clothing/suit/unathi/mantle(src) - new /obj/item/clothing/suit/unathi/robe(src) - for (var/i in 1 to 3) - new /obj/item/clothing/shoes/sandal(src) - - -/obj/structure/closet/wardrobe/orange - name = "prison wardrobe" - desc = "It's a storage unit for Nanotrasen-regulation prisoner attire." - icon_state = "orange" - icon_closed = "orange" - -/obj/structure/closet/wardrobe/orange/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/color/orange(src) - new /obj/item/clothing/shoes/orange(src) - - -/obj/structure/closet/wardrobe/yellow - name = "yellow wardrobe" - icon_state = "wardrobe-y" - icon_closed = "wardrobe-y" - -/obj/structure/closet/wardrobe/yellow/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/color/yellow(src) - new /obj/item/clothing/shoes/orange(src) - //for (var/i in 1 to 2) - // new /obj/item/clothing/mask/bandana/gold(src) - - -/obj/structure/closet/wardrobe/atmospherics_yellow - name = "atmospherics wardrobe" - icon_state = "yellow" - icon_closed = "yellow" - -/obj/structure/closet/wardrobe/atmospherics_yellow/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/rank/atmospheric_technician(src) - for (var/i in 1 to 3) - new /obj/item/clothing/shoes/black(src) - for (var/i in 1 to 3) - new /obj/item/clothing/head/hardhat/red(src) - for (var/i in 1 to 3) - new /obj/item/clothing/head/beret/eng(src) - #ifdef NEWYEARCONTENT - for (var/i in 1 to 3) - new /obj/item/clothing/suit/wintercoat/engineering/atmos(src) - new /obj/item/clothing/shoes/winterboots(src) - #endif - - - -/obj/structure/closet/wardrobe/engineering_yellow - name = "engineering wardrobe" - icon_state = "yellow" - icon_closed = "yellow" - -/obj/structure/closet/wardrobe/engineering_yellow/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/rank/engineer(src) - for (var/i in 1 to 3) - new /obj/item/clothing/shoes/workboots(src) - for(var/i = 1 to 3) - if(prob(75)) - new /obj/item/clothing/head/hardhat/yellow(src) - else - new /obj/item/clothing/head/hardhat/yellow/visor(src) - for (var/i in 1 to 3) - new /obj/item/clothing/head/beret/eng(src) - #ifdef NEWYEARCONTENT - for (var/i in 1 to 3) - new /obj/item/clothing/suit/wintercoat/engineering(src) - new /obj/item/clothing/shoes/winterboots(src) - #endif - - -/obj/structure/closet/wardrobe/white - name = "white wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/white/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/color/white(src) - new /obj/item/clothing/shoes/white(src) - - -/obj/structure/closet/wardrobe/pjs - name = "Pajama wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/pjs/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/clothing/under/pj/red(src) - for (var/i in 1 to 2) - new /obj/item/clothing/under/pj/blue(src) - for (var/i in 1 to 2) - new /obj/item/clothing/shoes/white(src) - for (var/i in 1 to 2) - new /obj/item/clothing/shoes/slippers(src) - - -/obj/structure/closet/wardrobe/science_white - name = "science wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/toxins_white/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/rank/scientist(src) - for (var/i in 1 to 3) - new /obj/item/clothing/suit/storage/labcoat(src) - for (var/i in 1 to 3) - new /obj/item/clothing/shoes/white(src) - for (var/i in 1 to 3) - new /obj/item/clothing/shoes/slippers(src) - - -/obj/structure/closet/wardrobe/robotics_black - name = "robotics wardrobe" - icon_state = "black" - icon_closed = "black" - -/obj/structure/closet/wardrobe/robotics_black/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/clothing/under/rank/roboticist(src) - for (var/i in 1 to 2) - new /obj/item/clothing/suit/storage/labcoat(src) - for (var/i in 1 to 2) - new /obj/item/clothing/shoes/black(src) - for (var/i in 1 to 2) - new /obj/item/clothing/gloves/black(src) - #ifdef NEWYEARCONTENT - for (var/i in 1 to 2) - new /obj/item/clothing/suit/wintercoat/science(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/santa(src) - #endif - - -/obj/structure/closet/wardrobe/chemistry_white - name = "chemistry wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/chemistry_white/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/clothing/under/rank/chemist(src) - for (var/i in 1 to 2) - new /obj/item/clothing/under/rank/chemist/skirt(src) - for (var/i in 1 to 2) - new /obj/item/clothing/shoes/white(src) - for (var/i in 1 to 2) - new /obj/item/clothing/suit/storage/labcoat/chemist(src) - - -/obj/structure/closet/wardrobe/genetics_white - name = "genetics wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/genetics_white/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/clothing/under/rank/geneticist(src) - for (var/i in 1 to 2) - new /obj/item/clothing/under/rank/geneticist/skirt(src) - for (var/i in 1 to 2) - new /obj/item/clothing/shoes/white(src) - for (var/i in 1 to 2) - new /obj/item/clothing/suit/storage/labcoat/genetics(src) - #ifdef NEWYEARCONTENT - for (var/i in 1 to 2) - new /obj/item/clothing/suit/wintercoat/science(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/santa(src) - #endif - - -/obj/structure/closet/wardrobe/virology_white - name = "virology wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/virology_white/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/clothing/under/rank/virologist(src) - for (var/i in 1 to 2) - new /obj/item/clothing/under/rank/virologist/skirt(src) - for (var/i in 1 to 2) - new /obj/item/clothing/shoes/white(src) - for (var/i in 1 to 2) - new /obj/item/clothing/suit/storage/labcoat/virologist(src) - for (var/i in 1 to 2) - new /obj/item/clothing/mask/surgical(src) - #ifdef NEWYEARCONTENT - new /obj/item/clothing/suit/wintercoat/medical(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/santa(src) - #endif - - -/obj/structure/closet/wardrobe/medic_white - name = "medical wardrobe" - icon_state = "white" - icon_closed = "white" - -/obj/structure/closet/wardrobe/medic_white/PopulateContents() - for (var/i in 1 to 2) - new /obj/item/clothing/under/rank/medical(src) - for (var/i in 1 to 2) - new /obj/item/clothing/under/rank/medical/skirt(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) - for (var/i in 1 to 2) - new /obj/item/clothing/shoes/white(src) - for (var/i in 1 to 2) - new /obj/item/clothing/suit/storage/labcoat(src) - for (var/i in 1 to 2) - new /obj/item/clothing/mask/surgical(src) - #ifdef NEWYEARCONTENT - new /obj/item/clothing/suit/wintercoat/medical(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/santa(src) - new /obj/item/clothing/suit/storage/labcoat/winterlabcoat(src) - #endif - - -/obj/structure/closet/wardrobe/grey - name = "grey wardrobe" - icon_state = "grey" - icon_closed = "grey" - -/obj/structure/closet/wardrobe/grey/PopulateContents() - for (var/i in 1 to 3) - new /obj/item/clothing/under/color/grey(src) - for (var/i in 1 to 3) - new /obj/item/clothing/shoes/black(src) - for (var/i in 1 to 3) - new /obj/item/clothing/head/soft/grey(src) - #ifdef NEWYEARCONTENT - for (var/i in 1 to 2) - new /obj/item/clothing/suit/wintercoat(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/santa(src) - #endif - - -/obj/structure/closet/wardrobe/mixed - name = "mixed wardrobe" - icon_state = "mixed" - icon_closed = "mixed" - -/obj/structure/closet/wardrobe/mixed/PopulateContents() - for (var/i in 1 to 2) - if(prob(25)) - new /obj/item/clothing/suit/jacket(src) - 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/color/red(src) - //new /obj/item/clothing/under/color/lightblue(src) - //new /obj/item/clothing/under/color/aqua(src) - //new /obj/item/clothing/under/color/purple(src) - //new /obj/item/clothing/under/color/lightpurple(src) - //new /obj/item/clothing/under/color/lightgreen(src) - //new /obj/item/clothing/under/color/darkblue(src) - //new /obj/item/clothing/under/color/darkred(src) - //new /obj/item/clothing/under/color/lightred(src) - //new /obj/item/clothing/mask/bandana/red(src) - //new /obj/item/clothing/mask/bandana/red(src) - //new /obj/item/clothing/mask/bandana/blue(src) - //new /obj/item/clothing/mask/bandana/blue(src) - //new /obj/item/clothing/mask/bandana/gold(src) - //new /obj/item/clothing/mask/bandana/gold(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/red(src) - new /obj/item/clothing/shoes/leather(src) - #ifdef NEWYEARCONTENT - new /obj/item/clothing/suit/wintercoat(src) - new /obj/item/clothing/shoes/winterboots(src) - new /obj/item/clothing/head/santa(src) - #endif - -/obj/structure/closet/wardrobe/tactical - name = "tactical equipment" - icon_state = "syndicate1" - icon_closed = "syndicate1" - icon_opened = "syndicate1open" - -/obj/structure/closet/wardrobe/tactical/PopulateContents() - new /obj/item/device/radio/headset/headset_sec/marinad(src) - new /obj/item/weapon/storage/backpack/dufflebag/marinad(src) - new /obj/item/clothing/gloves/security/marinad(src) - new /obj/item/clothing/head/helmet/tactical/marinad(src) - new /obj/item/clothing/suit/storage/flak/marinad(src) - new /obj/item/clothing/under/tactical/marinad(src) - new /obj/item/clothing/mask/balaclava(src) - new /obj/item/clothing/glasses/sunglasses/sechud/tactical(src) - new /obj/item/weapon/storage/belt/security/tactical(src) - new /obj/item/clothing/shoes/workboots(src) +/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/red + name = "security wardrobe" + icon_state = "red" + icon_closed = "red" + +/obj/structure/closet/wardrobe/red/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/rank/security(src) + for (var/i in 1 to 3) + new /obj/item/clothing/shoes/jackboots(src) + for (var/i in 1 to 3) + new /obj/item/clothing/head/soft/sec(src) + for (var/i in 1 to 2) + new /obj/item/clothing/mask/bandana/red(src) + for (var/i in 1 to 3) + new /obj/item/clothing/head/beret/sec(src) + #ifdef NEWYEARCONTENT + for (var/i in 1 to 3) + new /obj/item/clothing/head/santa(src) + new /obj/item/clothing/suit/wintercoat/security(src) + new /obj/item/clothing/shoes/winterboots(src) + #endif + + +/obj/structure/closet/wardrobe/pink + name = "pink wardrobe" + icon_state = "pink" + icon_closed = "pink" + +/obj/structure/closet/wardrobe/pink/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/color/pink(src) + new /obj/item/clothing/shoes/brown(src) + +/obj/structure/closet/wardrobe/black + name = "black wardrobe" + icon_state = "black" + icon_closed = "black" + +/obj/structure/closet/wardrobe/black/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/color/black(src) + if(prob(25)) + new /obj/item/clothing/suit/jacket/leather(src) + if(prob(20)) + new /obj/item/clothing/suit/jacket/leather/overcoat(src) + for (var/i in 1 to 3) + new /obj/item/clothing/shoes/black(src) + #ifdef NEWYEARCONTENT + for (var/i in 1 to 3) + new /obj/item/clothing/suit/wintercoat(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/santa(src) + #endif + + +/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/PopulateContents() + 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/game_kit/chaplain(src) + new /obj/item/weapon/reagent_containers/spray/thurible(src) + for (var/i in 1 to 2) + new /obj/item/weapon/storage/fancy/candle_box(src) + + +/obj/structure/closet/wardrobe/green + name = "green wardrobe" + icon_state = "green" + icon_closed = "green" + +/obj/structure/closet/wardrobe/green/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/color/green(src) + for (var/i in 1 to 3) + new /obj/item/clothing/shoes/black(src) + //for (var/i in 1 to 2) + // new /obj/item/clothing/mask/bandana/green(src) + + +/obj/structure/closet/wardrobe/xenos + name = "xenos wardrobe" + icon_state = "green" + icon_closed = "green" + +/obj/structure/closet/wardrobe/xenos/PopulateContents() + new /obj/item/clothing/suit/unathi/mantle(src) + new /obj/item/clothing/suit/unathi/robe(src) + for (var/i in 1 to 3) + new /obj/item/clothing/shoes/sandal(src) + + +/obj/structure/closet/wardrobe/orange + name = "prison wardrobe" + desc = "It's a storage unit for Nanotrasen-regulation prisoner attire." + icon_state = "orange" + icon_closed = "orange" + +/obj/structure/closet/wardrobe/orange/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/color/orange(src) + new /obj/item/clothing/shoes/orange(src) + + +/obj/structure/closet/wardrobe/yellow + name = "yellow wardrobe" + icon_state = "wardrobe-y" + icon_closed = "wardrobe-y" + +/obj/structure/closet/wardrobe/yellow/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/color/yellow(src) + new /obj/item/clothing/shoes/orange(src) + //for (var/i in 1 to 2) + // new /obj/item/clothing/mask/bandana/gold(src) + + +/obj/structure/closet/wardrobe/atmospherics_yellow + name = "atmospherics wardrobe" + icon_state = "yellow" + icon_closed = "yellow" + +/obj/structure/closet/wardrobe/atmospherics_yellow/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/rank/atmospheric_technician(src) + for (var/i in 1 to 3) + new /obj/item/clothing/shoes/black(src) + for (var/i in 1 to 3) + new /obj/item/clothing/head/hardhat/red(src) + for (var/i in 1 to 3) + new /obj/item/clothing/head/beret/eng(src) + #ifdef NEWYEARCONTENT + for (var/i in 1 to 3) + new /obj/item/clothing/suit/wintercoat/engineering/atmos(src) + new /obj/item/clothing/shoes/winterboots(src) + #endif + + + +/obj/structure/closet/wardrobe/engineering_yellow + name = "engineering wardrobe" + icon_state = "yellow" + icon_closed = "yellow" + +/obj/structure/closet/wardrobe/engineering_yellow/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/rank/engineer(src) + for (var/i in 1 to 3) + new /obj/item/clothing/shoes/workboots(src) + for(var/i = 1 to 3) + if(prob(75)) + new /obj/item/clothing/head/hardhat/yellow(src) + else + new /obj/item/clothing/head/hardhat/yellow/visor(src) + for (var/i in 1 to 3) + new /obj/item/clothing/head/beret/eng(src) + #ifdef NEWYEARCONTENT + for (var/i in 1 to 3) + new /obj/item/clothing/suit/wintercoat/engineering(src) + new /obj/item/clothing/shoes/winterboots(src) + #endif + + +/obj/structure/closet/wardrobe/white + name = "white wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/white/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/color/white(src) + new /obj/item/clothing/shoes/white(src) + + +/obj/structure/closet/wardrobe/pjs + name = "Pajama wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/pjs/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/clothing/under/pj/red(src) + for (var/i in 1 to 2) + new /obj/item/clothing/under/pj/blue(src) + for (var/i in 1 to 2) + new /obj/item/clothing/shoes/white(src) + for (var/i in 1 to 2) + new /obj/item/clothing/shoes/slippers(src) + + +/obj/structure/closet/wardrobe/science_white + name = "science wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/toxins_white/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/rank/scientist(src) + for (var/i in 1 to 3) + new /obj/item/clothing/suit/storage/labcoat(src) + for (var/i in 1 to 3) + new /obj/item/clothing/shoes/white(src) + for (var/i in 1 to 3) + new /obj/item/clothing/shoes/slippers(src) + + +/obj/structure/closet/wardrobe/robotics_black + name = "robotics wardrobe" + icon_state = "black" + icon_closed = "black" + +/obj/structure/closet/wardrobe/robotics_black/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/clothing/under/rank/roboticist(src) + for (var/i in 1 to 2) + new /obj/item/clothing/suit/storage/labcoat(src) + for (var/i in 1 to 2) + new /obj/item/clothing/shoes/black(src) + for (var/i in 1 to 2) + new /obj/item/clothing/gloves/black(src) + #ifdef NEWYEARCONTENT + for (var/i in 1 to 2) + new /obj/item/clothing/suit/wintercoat/science(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/santa(src) + #endif + + +/obj/structure/closet/wardrobe/chemistry_white + name = "chemistry wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/chemistry_white/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/clothing/under/rank/chemist(src) + for (var/i in 1 to 2) + new /obj/item/clothing/under/rank/chemist/skirt(src) + for (var/i in 1 to 2) + new /obj/item/clothing/shoes/white(src) + for (var/i in 1 to 2) + new /obj/item/clothing/suit/storage/labcoat/chemist(src) + + +/obj/structure/closet/wardrobe/genetics_white + name = "genetics wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/genetics_white/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/clothing/under/rank/geneticist(src) + for (var/i in 1 to 2) + new /obj/item/clothing/under/rank/geneticist/skirt(src) + for (var/i in 1 to 2) + new /obj/item/clothing/shoes/white(src) + for (var/i in 1 to 2) + new /obj/item/clothing/suit/storage/labcoat/genetics(src) + #ifdef NEWYEARCONTENT + for (var/i in 1 to 2) + new /obj/item/clothing/suit/wintercoat/science(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/santa(src) + #endif + + +/obj/structure/closet/wardrobe/virology_white + name = "virology wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/virology_white/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/clothing/under/rank/virologist(src) + for (var/i in 1 to 2) + new /obj/item/clothing/under/rank/virologist/skirt(src) + for (var/i in 1 to 2) + new /obj/item/clothing/shoes/white(src) + for (var/i in 1 to 2) + new /obj/item/clothing/suit/storage/labcoat/virologist(src) + for (var/i in 1 to 2) + new /obj/item/clothing/mask/surgical(src) + #ifdef NEWYEARCONTENT + new /obj/item/clothing/suit/wintercoat/medical(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/santa(src) + #endif + + +/obj/structure/closet/wardrobe/medic_white + name = "medical wardrobe" + icon_state = "white" + icon_closed = "white" + +/obj/structure/closet/wardrobe/medic_white/PopulateContents() + for (var/i in 1 to 2) + new /obj/item/clothing/under/rank/medical(src) + for (var/i in 1 to 2) + new /obj/item/clothing/under/rank/medical/skirt(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) + for (var/i in 1 to 2) + new /obj/item/clothing/shoes/white(src) + for (var/i in 1 to 2) + new /obj/item/clothing/suit/storage/labcoat(src) + for (var/i in 1 to 2) + new /obj/item/clothing/mask/surgical(src) + #ifdef NEWYEARCONTENT + new /obj/item/clothing/suit/wintercoat/medical(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/santa(src) + new /obj/item/clothing/suit/storage/labcoat/winterlabcoat(src) + #endif + + +/obj/structure/closet/wardrobe/grey + name = "grey wardrobe" + icon_state = "grey" + icon_closed = "grey" + +/obj/structure/closet/wardrobe/grey/PopulateContents() + for (var/i in 1 to 3) + new /obj/item/clothing/under/color/grey(src) + for (var/i in 1 to 3) + new /obj/item/clothing/shoes/black(src) + for (var/i in 1 to 3) + new /obj/item/clothing/head/soft/grey(src) + #ifdef NEWYEARCONTENT + for (var/i in 1 to 2) + new /obj/item/clothing/suit/wintercoat(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/santa(src) + #endif + + +/obj/structure/closet/wardrobe/mixed + name = "mixed wardrobe" + icon_state = "mixed" + icon_closed = "mixed" + +/obj/structure/closet/wardrobe/mixed/PopulateContents() + for (var/i in 1 to 2) + if(prob(25)) + new /obj/item/clothing/suit/jacket(src) + 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/color/red(src) + //new /obj/item/clothing/under/color/lightblue(src) + //new /obj/item/clothing/under/color/aqua(src) + //new /obj/item/clothing/under/color/purple(src) + //new /obj/item/clothing/under/color/lightpurple(src) + //new /obj/item/clothing/under/color/lightgreen(src) + //new /obj/item/clothing/under/color/darkblue(src) + //new /obj/item/clothing/under/color/darkred(src) + //new /obj/item/clothing/under/color/lightred(src) + //new /obj/item/clothing/mask/bandana/red(src) + //new /obj/item/clothing/mask/bandana/red(src) + //new /obj/item/clothing/mask/bandana/blue(src) + //new /obj/item/clothing/mask/bandana/blue(src) + //new /obj/item/clothing/mask/bandana/gold(src) + //new /obj/item/clothing/mask/bandana/gold(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/red(src) + new /obj/item/clothing/shoes/leather(src) + #ifdef NEWYEARCONTENT + new /obj/item/clothing/suit/wintercoat(src) + new /obj/item/clothing/shoes/winterboots(src) + new /obj/item/clothing/head/santa(src) + #endif + +/obj/structure/closet/wardrobe/tactical + name = "tactical equipment" + icon_state = "syndicate1" + icon_closed = "syndicate1" + icon_opened = "syndicate1open" + +/obj/structure/closet/wardrobe/tactical/PopulateContents() + new /obj/item/device/radio/headset/headset_sec/marinad(src) + new /obj/item/weapon/storage/backpack/dufflebag/marinad(src) + new /obj/item/clothing/gloves/security/marinad(src) + new /obj/item/clothing/head/helmet/tactical/marinad(src) + new /obj/item/clothing/suit/storage/flak/marinad(src) + new /obj/item/clothing/under/tactical/marinad(src) + new /obj/item/clothing/mask/balaclava(src) + new /obj/item/clothing/glasses/sunglasses/sechud/tactical(src) + new /obj/item/weapon/storage/belt/security/tactical(src) + new /obj/item/clothing/shoes/workboots(src) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 8d77a88577e6..df1550393962 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -1,520 +1,520 @@ -//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" - icon_opened = "crateopen" - icon_closed = "crate" - climbable = 1 -// mouse_drag_pointer = MOUSE_ACTIVE_POINTER //??? - var/rigged = 0 - -/obj/structure/closet/crate/can_open() - return 1 - -/obj/structure/closet/crate/can_close() - return 1 - -/obj/structure/closet/crate/open() - if(src.opened) - return 0 - if(!src.can_open()) - return 0 - - if(rigged && locate(/obj/item/device/radio/electropack) in src) - if(isliving(usr)) - var/mob/living/L = usr - 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 2 - - playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) - for(var/obj/O in src) - O.forceMove(get_turf(src)) - icon_state = icon_opened - src.opened = 1 - - if(climbable) - structure_shaken() - - return 1 - -/obj/structure/closet/crate/close() - if(!src.opened) - return 0 - if(!src.can_close()) - return 0 - - playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) - var/itemcount = 0 - for(var/obj/O in get_turf(src)) - if(itemcount >= storage_capacity) - break - if(O.density || O.anchored || istype(O,/obj/structure/closet)) - continue - if(istype(O, /obj/structure/stool/bed)) //This is only necessary because of rollerbeds and swivel chairs. - var/obj/structure/stool/bed/B = O - if(B.buckled_mob) - continue - O.forceMove(src) - itemcount++ - - icon_state = icon_closed - src.opened = 0 - return 1 - -/obj/structure/closet/crate/attackby(obj/item/weapon/W, mob/user) - if(opened) - if(isrobot(user)) - return - if(!W.canremove || W.flags & NODROP) - return - user.drop_item() - if(W) - W.forceMove(src.loc) - else if(istype(W, /obj/item/weapon/packageWrap) || istype(W, /obj/item/weapon/extraction_pack)) //OOP? Doesn't heard. - return - else if(istype(W, /obj/item/stack/cable_coil)) - if(rigged) - to_chat(user, "[src] is already rigged!") - return - - var/obj/item/stack/cable_coil/C = W - if(!C.use(1)) - return - - to_chat(user, "You rig [src].") - rigged = 1 - else if(istype(W, /obj/item/device/radio/electropack)) - if(rigged) - to_chat(user, "You attach [W] to [src].") - user.drop_item() - W.forceMove(src) - 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 - else - return attack_hand(user) - -/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 - 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 - -/obj/structure/closet/crate/secure/atom_init() - . = ..() - if(locked) - overlays.Cut() - overlays += redlight - else - overlays.Cut() - overlays += greenlight - -/obj/structure/closet/crate/secure/can_open() - return !locked - -/obj/structure/closet/crate/secure/proc/togglelock(mob/user) - if(src.opened) - to_chat(user, "Close the crate first.") - return - if(src.broken) - to_chat(user, "The crate appears to be broken.") - return - 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 crate has been [locked ? null : "un"]locked by [user].") - overlays.Cut() - overlays += locked ? redlight : greenlight - else - to_chat(user, "Access Denied") - -/obj/structure/closet/crate/secure/verb/verb_togglelock() - set src in oview(1) // One square distance - set category = "Object" - set name = "Toggle Lock" - - if(!usr.canmove || usr.stat || usr.restrained()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain - return - - if(ishuman(usr)) - src.add_fingerprint(usr) - src.togglelock(usr) - else - to_chat(usr, "This mob type can't use this verb.") - -/obj/structure/closet/crate/secure/attack_hand(mob/user) - src.add_fingerprint(user) - user.SetNextMove(CLICK_CD_RAPID) - if(locked) - src.togglelock(user) - else - src.toggle(user) - -/obj/structure/closet/crate/secure/attackby(obj/item/weapon/W, mob/user) - if(is_type_in_list(W, list(/obj/item/weapon/packageWrap, /obj/item/stack/cable_coil, /obj/item/device/radio/electropack, /obj/item/weapon/wirecutters))) - return ..() - if(locked && (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade))) - user.SetNextMove(CLICK_CD_MELEE) - overlays.Cut() - overlays += emag - overlays += sparks - spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* - playsound(src.loc, "sparks", 60, 1) - src.locked = 0 - src.broken = 1 - to_chat(user, "You unlock \the [src].") - return - if(!opened) - src.togglelock(user) - return - return ..() - -/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.Cut() - overlays += redlight - else - overlays.Cut() - overlays += emag - overlays += sparks - spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* - playsound(src.loc, '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/plastic - name = "plastic crate" - desc = "A rectangular plastic crate." - icon_state = "plasticcrate" - icon_opened = "plasticcrateopen" - icon_closed = "plasticcrate" - -/obj/structure/closet/crate/internals - desc = "A internals crate." - name = "Internals crate" - icon_state = "o2crate" - icon_opened = "o2crateopen" - icon_closed = "o2crate" - -/obj/structure/closet/crate/trashcart - desc = "A heavy, metal trashcart with wheels." - name = "Trash Cart" - icon_state = "trashcart" - icon_opened = "trashcartopen" - icon_closed = "trashcart" - -/*these aren't needed anymore -/obj/structure/closet/crate/hat - desc = "A crate filled with Valuable Collector's Hats!." - name = "Hat Crate" - icon_state = "crate" - 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_state = "crate" - icon_opened = "crateopen" - icon_closed = "crate" -*/ - -/obj/structure/closet/crate/engi - desc = "A engineer crate." - name = "Engineer crate" - icon_state = "engicrate" - icon_opened = "engicrateopen" - icon_closed = "engicrate" - -/obj/structure/closet/crate/secure/engisec - desc = "A crate with a lock on it." - name = "Secured engineer crate" - icon_state = "engicrateopensec" - icon_opened = "engiseccrateopensec" - icon_closed = "engicrateopensec" - -/obj/structure/closet/crate/medical - desc = "A medical crate." - name = "Medical crate" - icon_state = "medicalcrate" - icon_opened = "medicalcrateopen" - icon_closed = "medicalcrate" - -/obj/structure/closet/crate/secure/medical - desc = "A crate with a lock on it" - name = "Secured medical crate" - icon_state = "medicalseccrate" - icon_opened = "medicalseccrateopen" - icon_closed = "medicalseccrate" - -/obj/structure/closet/crate/rcd - desc = "A crate for the storage of the RCD." - name = "RCD crate" - icon_state = "crate" - icon_opened = "crateopen" - icon_closed = "crate" - -/obj/structure/closet/crate/rcd/PopulateContents() - for(var/i in 1 to 3) - new /obj/item/weapon/rcd_ammo(src) - new /obj/item/weapon/rcd(src) - -/obj/structure/closet/crate/solar - name = "Solar Pack crate" - -/obj/structure/closet/crate/solar/PopulateContents() - for(var/i in 1 to 21) - new /obj/item/solar_assembly(src) - new /obj/item/weapon/circuitboard/solar_control(src) - new /obj/item/weapon/tracker_electronics(src) - new /obj/item/weapon/paper/solar(src) - -/obj/structure/closet/crate/freezer - desc = "A freezer." - name = "Freezer" - icon_state = "freezer" - icon_opened = "freezeropen" - icon_closed = "freezer" - var/target_temp = T0C - 40 - var/cooling_power = 40 - -/obj/structure/closet/crate/freezer/return_air() - var/datum/gas_mixture/gas = (..()) - if(!gas) - return null - var/datum/gas_mixture/newgas = new/datum/gas_mixture() - newgas.copy_from(gas) - 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/freezer/rations //Fpr use in the escape shuttle - desc = "A crate of emergency rations." - name = "Emergency Rations" - - -/obj/structure/closet/crate/freezer/rations/PopulateContents() - for(var/i in 1 to 2) - new /obj/item/weapon/storage/box/donkpockets(src) - -/obj/structure/closet/crate/bin - desc = "A large bin." - name = "Large bin" - icon_state = "largebin" - 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_state = "radiation" - icon_opened = "radiationopen" - icon_closed = "radiation" - -/obj/structure/closet/crate/radiation/PopulateContents() - for(var/i in 1 to 4) - new /obj/item/clothing/suit/radiation(src) - for(var/i in 1 to 4) - new /obj/item/clothing/head/radiation(src) - -/obj/structure/closet/crate/secure/weapon - desc = "A secure weapons crate." - name = "Weapons crate" - icon_state = "weaponcrate" - icon_opened = "weaponcrateopen" - icon_closed = "weaponcrate" - -/obj/structure/closet/crate/scicrate - desc = "A science crate." - name = "Science crate" - icon_state = "scicrate" - icon_opened = "scicrateopen" - icon_closed = "scicrate" - -/obj/structure/closet/crate/secure/scisecurecrate - desc = "A secure science crate." - name = "Science crate" - icon_state = "scisecurecrate" - icon_opened = "scisecurecrateopen" - icon_closed = "scisecurecrate" - -/obj/structure/closet/crate/secure/gear - desc = "A secure gear crate." - name = "Gear crate" - icon_state = "secgearcrate" - 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_state = "hydrosecurecrate" - icon_opened = "hydrosecurecrateopen" - icon_closed = "hydrosecurecrate" - -/obj/structure/closet/crate/secure/woodseccrate - desc = "A secure wooden crate." - name = "Secure wooden crate" - icon_state = "woodseccrate" - icon_opened = "woodseccrateopen" - icon_closed = "woodseccrate" - -/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/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() - . = ..() - if (.)//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.forceMove(src) - break - if(!found) - for(var/obj/machinery/M in src.loc) - if(!M.anchored) - M.forceMove(src) - break - return - -/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() - . = ..() - if (.)//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.forceMove(src) - break - if(!found) - for(var/obj/machinery/M in src.loc) - if(!M.anchored) - M.forceMove(src) - break - return - -//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/hydroponics - name = "Hydroponics crate" - desc = "All you need to destroy those pesky weeds and pests." - icon_state = "hydrocrate" - icon_opened = "hydrocrateopen" - icon_closed = "hydrocrate" - -/obj/structure/closet/crate/hydroponics/prespawned - //This exists so the prespawned hydro crates spawn with their contents. - -/obj/structure/closet/crate/hydroponics/prespawned/PopulateContents() - for(var/i in 1 to 2) - new /obj/item/weapon/reagent_containers/spray/plantbgone(src) - new /obj/item/weapon/minihoe(src) -// new /obj/item/weapon/weedspray(src) -// new /obj/item/weapon/weedspray(src) -// new /obj/item/weapon/pestspray(src) -// new /obj/item/weapon/pestspray(src) -// new /obj/item/weapon/pestspray(src) - -/obj/structure/closet/crate/dwarf_agriculture - -/obj/structure/closet/crate/dwarf_agriculture/PopulateContents() - new /obj/item/weapon/storage/bag/plants(src) - new /obj/item/device/plant_analyzer(src) - new /obj/item/weapon/minihoe(src) - new /obj/item/weapon/hatchet(src) - new /obj/item/seeds/reishimycelium(src) - new /obj/item/seeds/glowshroom(src) - new /obj/item/seeds/amanitamycelium(src) - new /obj/item/seeds/angelmycelium(src) - new /obj/item/seeds/libertymycelium(src) - new /obj/item/seeds/plastiseed(src) - new /obj/item/seeds/plumpmycelium(src) - new /obj/item/seeds/chantermycelium(src) +//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" + icon_opened = "crateopen" + icon_closed = "crate" + climbable = 1 +// mouse_drag_pointer = MOUSE_ACTIVE_POINTER //??? + var/rigged = 0 + +/obj/structure/closet/crate/can_open() + return 1 + +/obj/structure/closet/crate/can_close() + return 1 + +/obj/structure/closet/crate/open() + if(src.opened) + return 0 + if(!src.can_open()) + return 0 + + if(rigged && locate(/obj/item/device/radio/electropack) in src) + if(isliving(usr)) + var/mob/living/L = usr + 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 2 + + playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) + for(var/obj/O in src) + O.forceMove(get_turf(src)) + icon_state = icon_opened + src.opened = 1 + + if(climbable) + structure_shaken() + + return 1 + +/obj/structure/closet/crate/close() + if(!src.opened) + return 0 + if(!src.can_close()) + return 0 + + playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) + var/itemcount = 0 + for(var/obj/O in get_turf(src)) + if(itemcount >= storage_capacity) + break + if(O.density || O.anchored || istype(O,/obj/structure/closet)) + continue + if(istype(O, /obj/structure/stool/bed)) //This is only necessary because of rollerbeds and swivel chairs. + var/obj/structure/stool/bed/B = O + if(B.buckled_mob) + continue + O.forceMove(src) + itemcount++ + + icon_state = icon_closed + src.opened = 0 + return 1 + +/obj/structure/closet/crate/attackby(obj/item/weapon/W, mob/user) + if(opened) + if(isrobot(user)) + return + if(!W.canremove || W.flags & NODROP) + return + user.drop_item() + if(W) + W.forceMove(src.loc) + else if(istype(W, /obj/item/weapon/packageWrap) || istype(W, /obj/item/weapon/extraction_pack)) //OOP? Doesn't heard. + return + else if(istype(W, /obj/item/stack/cable_coil)) + if(rigged) + to_chat(user, "[src] is already rigged!") + return + + var/obj/item/stack/cable_coil/C = W + if(!C.use(1)) + return + + to_chat(user, "You rig [src].") + rigged = 1 + else if(istype(W, /obj/item/device/radio/electropack)) + if(rigged) + to_chat(user, "You attach [W] to [src].") + user.drop_item() + W.forceMove(src) + 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 + else + return attack_hand(user) + +/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 + 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 + +/obj/structure/closet/crate/secure/atom_init() + . = ..() + if(locked) + overlays.Cut() + overlays += redlight + else + overlays.Cut() + overlays += greenlight + +/obj/structure/closet/crate/secure/can_open() + return !locked + +/obj/structure/closet/crate/secure/proc/togglelock(mob/user) + if(src.opened) + to_chat(user, "Close the crate first.") + return + if(src.broken) + to_chat(user, "The crate appears to be broken.") + return + 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 crate has been [locked ? null : "un"]locked by [user].") + overlays.Cut() + overlays += locked ? redlight : greenlight + else + to_chat(user, "Access Denied") + +/obj/structure/closet/crate/secure/verb/verb_togglelock() + set src in oview(1) // One square distance + set category = "Object" + set name = "Toggle Lock" + + if(!usr.canmove || usr.stat || usr.restrained()) // Don't use it if you're not able to! Checks for stuns, ghost and restrain + return + + if(ishuman(usr)) + src.add_fingerprint(usr) + src.togglelock(usr) + else + to_chat(usr, "This mob type can't use this verb.") + +/obj/structure/closet/crate/secure/attack_hand(mob/user) + src.add_fingerprint(user) + user.SetNextMove(CLICK_CD_RAPID) + if(locked) + src.togglelock(user) + else + src.toggle(user) + +/obj/structure/closet/crate/secure/attackby(obj/item/weapon/W, mob/user) + if(is_type_in_list(W, list(/obj/item/weapon/packageWrap, /obj/item/stack/cable_coil, /obj/item/device/radio/electropack, /obj/item/weapon/wirecutters))) + return ..() + if(locked && (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade))) + user.SetNextMove(CLICK_CD_MELEE) + overlays.Cut() + overlays += emag + overlays += sparks + spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* + playsound(src.loc, "sparks", 60, 1) + src.locked = 0 + src.broken = 1 + to_chat(user, "You unlock \the [src].") + return + if(!opened) + src.togglelock(user) + return + return ..() + +/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.Cut() + overlays += redlight + else + overlays.Cut() + overlays += emag + overlays += sparks + spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface* + playsound(src.loc, '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/plastic + name = "plastic crate" + desc = "A rectangular plastic crate." + icon_state = "plasticcrate" + icon_opened = "plasticcrateopen" + icon_closed = "plasticcrate" + +/obj/structure/closet/crate/internals + desc = "A internals crate." + name = "Internals crate" + icon_state = "o2crate" + icon_opened = "o2crateopen" + icon_closed = "o2crate" + +/obj/structure/closet/crate/trashcart + desc = "A heavy, metal trashcart with wheels." + name = "Trash Cart" + icon_state = "trashcart" + icon_opened = "trashcartopen" + icon_closed = "trashcart" + +/*these aren't needed anymore +/obj/structure/closet/crate/hat + desc = "A crate filled with Valuable Collector's Hats!." + name = "Hat Crate" + icon_state = "crate" + 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_state = "crate" + icon_opened = "crateopen" + icon_closed = "crate" +*/ + +/obj/structure/closet/crate/engi + desc = "A engineer crate." + name = "Engineer crate" + icon_state = "engicrate" + icon_opened = "engicrateopen" + icon_closed = "engicrate" + +/obj/structure/closet/crate/secure/engisec + desc = "A crate with a lock on it." + name = "Secured engineer crate" + icon_state = "engicrateopensec" + icon_opened = "engiseccrateopensec" + icon_closed = "engicrateopensec" + +/obj/structure/closet/crate/medical + desc = "A medical crate." + name = "Medical crate" + icon_state = "medicalcrate" + icon_opened = "medicalcrateopen" + icon_closed = "medicalcrate" + +/obj/structure/closet/crate/secure/medical + desc = "A crate with a lock on it" + name = "Secured medical crate" + icon_state = "medicalseccrate" + icon_opened = "medicalseccrateopen" + icon_closed = "medicalseccrate" + +/obj/structure/closet/crate/rcd + desc = "A crate for the storage of the RCD." + name = "RCD crate" + icon_state = "crate" + icon_opened = "crateopen" + icon_closed = "crate" + +/obj/structure/closet/crate/rcd/PopulateContents() + for(var/i in 1 to 3) + new /obj/item/weapon/rcd_ammo(src) + new /obj/item/weapon/rcd(src) + +/obj/structure/closet/crate/solar + name = "Solar Pack crate" + +/obj/structure/closet/crate/solar/PopulateContents() + for(var/i in 1 to 21) + new /obj/item/solar_assembly(src) + new /obj/item/weapon/circuitboard/solar_control(src) + new /obj/item/weapon/tracker_electronics(src) + new /obj/item/weapon/paper/solar(src) + +/obj/structure/closet/crate/freezer + desc = "A freezer." + name = "Freezer" + icon_state = "freezer" + icon_opened = "freezeropen" + icon_closed = "freezer" + var/target_temp = T0C - 40 + var/cooling_power = 40 + +/obj/structure/closet/crate/freezer/return_air() + var/datum/gas_mixture/gas = (..()) + if(!gas) + return null + var/datum/gas_mixture/newgas = new/datum/gas_mixture() + newgas.copy_from(gas) + 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/freezer/rations //Fpr use in the escape shuttle + desc = "A crate of emergency rations." + name = "Emergency Rations" + + +/obj/structure/closet/crate/freezer/rations/PopulateContents() + for(var/i in 1 to 2) + new /obj/item/weapon/storage/box/donkpockets(src) + +/obj/structure/closet/crate/bin + desc = "A large bin." + name = "Large bin" + icon_state = "largebin" + 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_state = "radiation" + icon_opened = "radiationopen" + icon_closed = "radiation" + +/obj/structure/closet/crate/radiation/PopulateContents() + for(var/i in 1 to 4) + new /obj/item/clothing/suit/radiation(src) + for(var/i in 1 to 4) + new /obj/item/clothing/head/radiation(src) + +/obj/structure/closet/crate/secure/weapon + desc = "A secure weapons crate." + name = "Weapons crate" + icon_state = "weaponcrate" + icon_opened = "weaponcrateopen" + icon_closed = "weaponcrate" + +/obj/structure/closet/crate/scicrate + desc = "A science crate." + name = "Science crate" + icon_state = "scicrate" + icon_opened = "scicrateopen" + icon_closed = "scicrate" + +/obj/structure/closet/crate/secure/scisecurecrate + desc = "A secure science crate." + name = "Science crate" + icon_state = "scisecurecrate" + icon_opened = "scisecurecrateopen" + icon_closed = "scisecurecrate" + +/obj/structure/closet/crate/secure/gear + desc = "A secure gear crate." + name = "Gear crate" + icon_state = "secgearcrate" + 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_state = "hydrosecurecrate" + icon_opened = "hydrosecurecrateopen" + icon_closed = "hydrosecurecrate" + +/obj/structure/closet/crate/secure/woodseccrate + desc = "A secure wooden crate." + name = "Secure wooden crate" + icon_state = "woodseccrate" + icon_opened = "woodseccrateopen" + icon_closed = "woodseccrate" + +/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/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() + . = ..() + if (.)//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.forceMove(src) + break + if(!found) + for(var/obj/machinery/M in src.loc) + if(!M.anchored) + M.forceMove(src) + break + return + +/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() + . = ..() + if (.)//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.forceMove(src) + break + if(!found) + for(var/obj/machinery/M in src.loc) + if(!M.anchored) + M.forceMove(src) + break + return + +//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/hydroponics + name = "Hydroponics crate" + desc = "All you need to destroy those pesky weeds and pests." + icon_state = "hydrocrate" + icon_opened = "hydrocrateopen" + icon_closed = "hydrocrate" + +/obj/structure/closet/crate/hydroponics/prespawned + //This exists so the prespawned hydro crates spawn with their contents. + +/obj/structure/closet/crate/hydroponics/prespawned/PopulateContents() + for(var/i in 1 to 2) + new /obj/item/weapon/reagent_containers/spray/plantbgone(src) + new /obj/item/weapon/minihoe(src) +// new /obj/item/weapon/weedspray(src) +// new /obj/item/weapon/weedspray(src) +// new /obj/item/weapon/pestspray(src) +// new /obj/item/weapon/pestspray(src) +// new /obj/item/weapon/pestspray(src) + +/obj/structure/closet/crate/dwarf_agriculture + +/obj/structure/closet/crate/dwarf_agriculture/PopulateContents() + new /obj/item/weapon/storage/bag/plants(src) + new /obj/item/device/plant_analyzer(src) + new /obj/item/weapon/minihoe(src) + new /obj/item/weapon/hatchet(src) + new /obj/item/seeds/reishimycelium(src) + new /obj/item/seeds/glowshroom(src) + new /obj/item/seeds/amanitamycelium(src) + new /obj/item/seeds/angelmycelium(src) + new /obj/item/seeds/libertymycelium(src) + new /obj/item/seeds/plastiseed(src) + new /obj/item/seeds/plumpmycelium(src) + new /obj/item/seeds/chantermycelium(src) diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm index 279d928ca895..c44f82cd511f 100644 --- a/code/game/objects/structures/crates_lockers/largecrate.dm +++ b/code/game/objects/structures/crates_lockers/largecrate.dm @@ -1,26 +1,26 @@ -/obj/structure/largecrate - name = "large crate" - desc = "A hefty wooden crate." - icon = 'icons/obj/storage.dmi' - icon_state = "densecrate" - density = 1 - -/obj/structure/largecrate/attack_hand(mob/user) - to_chat(user, "You need a crowbar to pry this open!") - return - -/obj/structure/largecrate/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/crowbar)) - new /obj/item/stack/sheet/wood(src) - var/turf/T = get_turf(src) - for(var/atom/movable/M in contents) - M.forceMove(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 + name = "large crate" + desc = "A hefty wooden crate." + icon = 'icons/obj/storage.dmi' + icon_state = "densecrate" + density = 1 + +/obj/structure/largecrate/attack_hand(mob/user) + to_chat(user, "You need a crowbar to pry this open!") + return + +/obj/structure/largecrate/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/crowbar)) + new /obj/item/stack/sheet/wood(src) + var/turf/T = get_turf(src) + for(var/atom/movable/M in contents) + M.forceMove(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" diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index c78d38242284..020a2135cf97 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -1,98 +1,98 @@ -/obj/structure/displaycase - name = "display case" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "glassbox1" - desc = "A display case for prized possessions. It taunts you to kick it." - density = 1 - anchored = 1 - unacidable = 1//Dissolving the case would also delete the gun. - var/health = 30 - var/occupied = 1 - var/destroyed = 0 - -/obj/structure/displaycase/ex_act(severity) - switch(severity) - if (1) - new /obj/item/weapon/shard( src.loc ) - if (occupied) - new /obj/item/weapon/gun/energy/laser/selfcharging/captain( src.loc ) - occupied = 0 - 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(obj/item/projectile/Proj) - health -= Proj.damage - ..() - src.healthcheck() - return - - -/obj/structure/displaycase/blob_act() - if (prob(75)) - new /obj/item/weapon/shard( src.loc ) - if (occupied) - new /obj/item/weapon/gun/energy/laser/selfcharging/captain( src.loc ) - occupied = 0 - qdel(src) - - -/obj/structure/displaycase/meteorhit(obj/O) - new /obj/item/weapon/shard( src.loc ) - new /obj/item/weapon/gun/energy/laser/selfcharging/captain( src.loc ) - qdel(src) - - -/obj/structure/displaycase/proc/healthcheck() - if (src.health <= 0) - if (!( src.destroyed )) - src.density = 0 - src.destroyed = 1 - new /obj/item/weapon/shard( src.loc ) - playsound(src, "shatter", 70, 1) - update_icon() - else - playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) - return - -/obj/structure/displaycase/update_icon() - if(src.destroyed) - src.icon_state = "glassboxb[src.occupied]" - else - src.icon_state = "glassbox[src.occupied]" - return - - -/obj/structure/displaycase/attackby(obj/item/weapon/W, mob/user) - user.SetNextMove(CLICK_CD_MELEE) - src.health -= W.force - src.healthcheck() - ..() - return - -/obj/structure/displaycase/attack_paw(mob/user) - return src.attack_hand(user) - -/obj/structure/displaycase/attack_hand(mob/user) - if (src.destroyed && src.occupied) - new /obj/item/weapon/gun/energy/laser/selfcharging/captain( src.loc ) - to_chat(user, "\b You deactivate the hover field built into the case.") - src.occupied = 0 - src.add_fingerprint(user) - update_icon() - return - else - user.SetNextMove(CLICK_CD_MELEE) - visible_message("[user] kicks the display case.") - src.health -= 2 - healthcheck() - return - - +/obj/structure/displaycase + name = "display case" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "glassbox1" + desc = "A display case for prized possessions. It taunts you to kick it." + density = 1 + anchored = 1 + unacidable = 1//Dissolving the case would also delete the gun. + var/health = 30 + var/occupied = 1 + var/destroyed = 0 + +/obj/structure/displaycase/ex_act(severity) + switch(severity) + if (1) + new /obj/item/weapon/shard( src.loc ) + if (occupied) + new /obj/item/weapon/gun/energy/laser/selfcharging/captain( src.loc ) + occupied = 0 + 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(obj/item/projectile/Proj) + health -= Proj.damage + ..() + src.healthcheck() + return + + +/obj/structure/displaycase/blob_act() + if (prob(75)) + new /obj/item/weapon/shard( src.loc ) + if (occupied) + new /obj/item/weapon/gun/energy/laser/selfcharging/captain( src.loc ) + occupied = 0 + qdel(src) + + +/obj/structure/displaycase/meteorhit(obj/O) + new /obj/item/weapon/shard( src.loc ) + new /obj/item/weapon/gun/energy/laser/selfcharging/captain( src.loc ) + qdel(src) + + +/obj/structure/displaycase/proc/healthcheck() + if (src.health <= 0) + if (!( src.destroyed )) + src.density = 0 + src.destroyed = 1 + new /obj/item/weapon/shard( src.loc ) + playsound(src, "shatter", 70, 1) + update_icon() + else + playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) + return + +/obj/structure/displaycase/update_icon() + if(src.destroyed) + src.icon_state = "glassboxb[src.occupied]" + else + src.icon_state = "glassbox[src.occupied]" + return + + +/obj/structure/displaycase/attackby(obj/item/weapon/W, mob/user) + user.SetNextMove(CLICK_CD_MELEE) + src.health -= W.force + src.healthcheck() + ..() + return + +/obj/structure/displaycase/attack_paw(mob/user) + return src.attack_hand(user) + +/obj/structure/displaycase/attack_hand(mob/user) + if (src.destroyed && src.occupied) + new /obj/item/weapon/gun/energy/laser/selfcharging/captain( src.loc ) + to_chat(user, "\b You deactivate the hover field built into the case.") + src.occupied = 0 + src.add_fingerprint(user) + update_icon() + return + else + user.SetNextMove(CLICK_CD_MELEE) + visible_message("[user] kicks the display case.") + src.health -= 2 + healthcheck() + return + + diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 76badfde7916..985b9ec15431 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -1,277 +1,277 @@ -/obj/structure/door_assembly - name = "airlock assembly" - - icon = 'icons/obj/doors/airlocks/station/public.dmi' - icon_state = "construction" - var/overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' - - anchored = FALSE - density = TRUE - var/state = ASSEMBLY_SECURED - var/obj/item/weapon/airlock_electronics/electronics = null - - var/airlock_type = /obj/machinery/door/airlock - var/glass_type = /obj/machinery/door/airlock/glass - - var/glass_material = null // Icon logic. - var/mineral = null // Door mineral type. - var/can_insert_glass = TRUE - var/glass_only = FALSE // For something like multitile airlock, where there is only one type. - var/created_name = null - -/obj/structure/door_assembly/atom_init() - . = ..() - update_state() - -/obj/structure/door_assembly/Destroy() - if(electronics) - qdel(electronics) - electronics = null - return ..() - -/obj/structure/door_assembly/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/weapon/pen)) - var/t = sanitize_safe(input(user, "Enter the name for the door.", name, input_default(created_name)), MAX_LNAME_LEN) - if(!t) - return - if(!in_range(src, usr) && src.loc != usr) - return - created_name = t - return - - if(istype(W, /obj/item/weapon/weldingtool) && ((glass_material && !glass_only) || mineral || !anchored)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - if(user.is_busy()) return - playsound(src, 'sound/items/Welder2.ogg', 50, 1) - if(glass_material) - 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, 40, target = src)) - if(!src || !WT.isOn()) - return - to_chat(user, "You welded the glass panel out!") - new /obj/item/stack/sheet/rglass(loc) - set_glass(FALSE) - - else if(mineral) - user.visible_message("[user] welds the [mineral] plating off the airlock assembly.", "You start to weld the [mineral] plating off the airlock assembly.") - if(do_after(user, 40, target = src)) - if(!src || !WT.isOn()) - return - to_chat(user, "You welded the [mineral] plating off!") - var/M = text2path("/obj/item/stack/sheet/mineral/[mineral]") - new M(loc, 2) - change_mineral_airlock_type() - - else if(!anchored) - user.visible_message("[user] dissassembles the airlock assembly.", "You start to dissassemble the airlock assembly.") - if(do_after(user, 40, target = src)) - if(!src || !WT.isOn()) - return - to_chat(user, "You dissasembled the airlock assembly!") - new /obj/item/stack/sheet/metal(loc, 4) - qdel (src) - else - to_chat(user, "You need more welding fuel.") - return - - else if(istype(W, /obj/item/weapon/wrench) && state == ASSEMBLY_SECURED) - playsound(src, 'sound/items/Ratchet.ogg', 100, 1) - if(user.is_busy()) return - 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, 40, target = src)) - if(!src) - return - to_chat(user, "You [anchored ? "un" : ""]secured the airlock assembly!") - anchored = !anchored - - else if(istype(W, /obj/item/stack/cable_coil) && state == ASSEMBLY_SECURED && anchored ) - if(user.is_busy()) return - 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, 40, target = src)) - if(!src) - return - if(!coil.use(1)) - return - state = ASSEMBLY_WIRED - to_chat(user, "You wire the airlock!") - - else if(istype(W, /obj/item/weapon/wirecutters) && state == ASSEMBLY_WIRED) - if(user.is_busy()) return - playsound(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, 40, target = src)) - if(!src) - return - to_chat(user, "You cut the airlock wires!") - new /obj/item/stack/cable_coil/random(loc, 1) - state = ASSEMBLY_SECURED - - else if(istype(W, /obj/item/weapon/airlock_electronics) && state == ASSEMBLY_WIRED) - var/obj/item/weapon/airlock_electronics/AE = W - if(!AE.broken && !user.is_busy()) - playsound(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.") - - if(do_after(user, 40, target = src)) - if(!src) - return - user.drop_item() - AE.loc = src - to_chat(user, "You installed the airlock electronics!") - state = ASSEMBLY_NEAR_FINISHED - electronics = AE - - else if(istype(W, /obj/item/weapon/crowbar) && state == ASSEMBLY_NEAR_FINISHED) - if(user.is_busy()) return - playsound(src, 'sound/items/Crowbar.ogg', 100, 1) - user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove the electronics from the airlock assembly.") - - if(do_after(user, 40, target = src)) - if(!src) - return - to_chat(user, "You removed the airlock electronics!") - state = ASSEMBLY_WIRED - var/obj/item/weapon/airlock_electronics/AE - if (!electronics) - AE = new /obj/item/weapon/airlock_electronics(loc) - else - AE = electronics - electronics = null - AE.loc = loc - - else if(istype(W, /obj/item/stack/sheet)) - var/obj/item/stack/sheet/S = W - if(S.get_amount() >= 1) - if(istype(S, /obj/item/stack/sheet/rglass)) - if(glass_material) - to_chat(user, "There is already glass in the [src].") - else if(can_insert_glass) - if(user.is_busy()) return - playsound(src, 'sound/items/Crowbar.ogg', 100, 1) - user.visible_message("[user] adds [S.name] to the [src].", "You start to install [S.name] into the [src].") - if(do_after(user, 40, target = src)) - to_chat(user, "You installed reinforced glass windows into the [src]!") - if(!S.use(1)) - return - set_glass(TRUE) - else - to_chat(user, "You can't insert glass into [src].") - - else if(istype(S, /obj/item/stack/sheet/mineral) && S.sheettype) - if(can_insert_mineral()) - var/M = S.sheettype - if(S.get_amount() >= 2) - if(user.is_busy()) return - playsound(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, 40, target = src)) - if(!S.use(2)) - return - to_chat(user, "You installed [M] plating into the airlock assembly!") - change_mineral_airlock_type(M) - else - to_chat(user, "There is not enough [S].") - else - to_chat(user, "You can't add [S] to the [src].") - - else if(istype(W, /obj/item/weapon/screwdriver) && state == ASSEMBLY_NEAR_FINISHED ) - if(user.is_busy()) return - playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) - to_chat(user, "Now finishing the airlock.") - - if(do_after(user, 40, target = src)) - if(!src) - return - to_chat(user, "You finish the airlock!") - var/obj/machinery/door/airlock/door = null - if(glass_material && !glass_only) - door = new glass_type(loc, dir) - else - door = new airlock_type(loc, dir) - door.assembly_type = type - door.electronics = electronics - if(electronics.one_access) - door.req_access = null - door.req_one_access = electronics.conf_access - else - door.req_access = electronics.conf_access - if(created_name) - door.name = created_name - electronics.loc = door - qdel(src) - else - ..() - update_state() - -/obj/structure/door_assembly/proc/set_glass(has_glass, glass_material = "glass") - if(has_glass) - src.glass_material = glass_material - can_insert_glass = FALSE - else - src.glass_material = null - can_insert_glass = TRUE - -/obj/structure/door_assembly/proc/can_insert_mineral() - return type == /obj/structure/door_assembly && !mineral - -/obj/structure/door_assembly/proc/change_mineral_airlock_type(mineral = null) - if(mineral) - var/normal_airlock_type = text2path("/obj/machinery/door/airlock/[mineral]") - var/glass_airlock_type = text2path("/obj/machinery/door/airlock/[mineral]/glass") - - airlock_type = normal_airlock_type - glass_type = glass_airlock_type - src.mineral = mineral - - switch(mineral) - if("gold") - icon = 'icons/obj/doors/airlocks/station/gold.dmi' - if("silver") - icon = 'icons/obj/doors/airlocks/station/silver.dmi' - if("diamond") - icon = 'icons/obj/doors/airlocks/station/diamond.dmi' - if("uranium") - icon = 'icons/obj/doors/airlocks/station/uranium.dmi' - if("phoron") - icon = 'icons/obj/doors/airlocks/station/phoron.dmi' - if("clown") - icon = 'icons/obj/doors/airlocks/station/bananium.dmi' - if("sandstone") - icon = 'icons/obj/doors/airlocks/station/sandstone.dmi' - else - airlock_type = initial(airlock_type) - glass_type = initial(glass_type) - icon = initial(icon) - src.mineral = null - - -/obj/structure/door_assembly/proc/update_state() - update_icon() - var/general_state_text - switch(state) - if(ASSEMBLY_SECURED) - general_state_text = "[anchored ? "secured " : ""]" - if(ASSEMBLY_WIRED) - general_state_text = "wired " - if(ASSEMBLY_NEAR_FINISHED) - general_state_text = "near finished " - - var/glass_state_text = "[glass_material ? "[glass_material] " : ""]" - var/mineral_state_text = "[mineral ? "[mineral] " : ""]" - - name = general_state_text + glass_state_text + mineral_state_text + initial(name) - -/obj/structure/door_assembly/update_icon() - overlays.Cut() - if(!glass_material) - overlays += get_airlock_overlay("fill_construction", icon) - else - overlays += get_airlock_overlay("[glass_material]_construction", overlays_file) - overlays += get_airlock_overlay("panel_c[state + 1]", overlays_file) +/obj/structure/door_assembly + name = "airlock assembly" + + icon = 'icons/obj/doors/airlocks/station/public.dmi' + icon_state = "construction" + var/overlays_file = 'icons/obj/doors/airlocks/station/overlays.dmi' + + anchored = FALSE + density = TRUE + var/state = ASSEMBLY_SECURED + var/obj/item/weapon/airlock_electronics/electronics = null + + var/airlock_type = /obj/machinery/door/airlock + var/glass_type = /obj/machinery/door/airlock/glass + + var/glass_material = null // Icon logic. + var/mineral = null // Door mineral type. + var/can_insert_glass = TRUE + var/glass_only = FALSE // For something like multitile airlock, where there is only one type. + var/created_name = null + +/obj/structure/door_assembly/atom_init() + . = ..() + update_state() + +/obj/structure/door_assembly/Destroy() + if(electronics) + qdel(electronics) + electronics = null + return ..() + +/obj/structure/door_assembly/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/weapon/pen)) + var/t = sanitize_safe(input(user, "Enter the name for the door.", name, input_default(created_name)), MAX_LNAME_LEN) + if(!t) + return + if(!in_range(src, usr) && src.loc != usr) + return + created_name = t + return + + if(istype(W, /obj/item/weapon/weldingtool) && ((glass_material && !glass_only) || mineral || !anchored)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + if(user.is_busy()) return + playsound(src, 'sound/items/Welder2.ogg', 50, 1) + if(glass_material) + 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, 40, target = src)) + if(!src || !WT.isOn()) + return + to_chat(user, "You welded the glass panel out!") + new /obj/item/stack/sheet/rglass(loc) + set_glass(FALSE) + + else if(mineral) + user.visible_message("[user] welds the [mineral] plating off the airlock assembly.", "You start to weld the [mineral] plating off the airlock assembly.") + if(do_after(user, 40, target = src)) + if(!src || !WT.isOn()) + return + to_chat(user, "You welded the [mineral] plating off!") + var/M = text2path("/obj/item/stack/sheet/mineral/[mineral]") + new M(loc, 2) + change_mineral_airlock_type() + + else if(!anchored) + user.visible_message("[user] dissassembles the airlock assembly.", "You start to dissassemble the airlock assembly.") + if(do_after(user, 40, target = src)) + if(!src || !WT.isOn()) + return + to_chat(user, "You dissasembled the airlock assembly!") + new /obj/item/stack/sheet/metal(loc, 4) + qdel (src) + else + to_chat(user, "You need more welding fuel.") + return + + else if(istype(W, /obj/item/weapon/wrench) && state == ASSEMBLY_SECURED) + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) + if(user.is_busy()) return + 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, 40, target = src)) + if(!src) + return + to_chat(user, "You [anchored ? "un" : ""]secured the airlock assembly!") + anchored = !anchored + + else if(istype(W, /obj/item/stack/cable_coil) && state == ASSEMBLY_SECURED && anchored ) + if(user.is_busy()) return + 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, 40, target = src)) + if(!src) + return + if(!coil.use(1)) + return + state = ASSEMBLY_WIRED + to_chat(user, "You wire the airlock!") + + else if(istype(W, /obj/item/weapon/wirecutters) && state == ASSEMBLY_WIRED) + if(user.is_busy()) return + playsound(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, 40, target = src)) + if(!src) + return + to_chat(user, "You cut the airlock wires!") + new /obj/item/stack/cable_coil/random(loc, 1) + state = ASSEMBLY_SECURED + + else if(istype(W, /obj/item/weapon/airlock_electronics) && state == ASSEMBLY_WIRED) + var/obj/item/weapon/airlock_electronics/AE = W + if(!AE.broken && !user.is_busy()) + playsound(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.") + + if(do_after(user, 40, target = src)) + if(!src) + return + user.drop_item() + AE.loc = src + to_chat(user, "You installed the airlock electronics!") + state = ASSEMBLY_NEAR_FINISHED + electronics = AE + + else if(istype(W, /obj/item/weapon/crowbar) && state == ASSEMBLY_NEAR_FINISHED) + if(user.is_busy()) return + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) + user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove the electronics from the airlock assembly.") + + if(do_after(user, 40, target = src)) + if(!src) + return + to_chat(user, "You removed the airlock electronics!") + state = ASSEMBLY_WIRED + var/obj/item/weapon/airlock_electronics/AE + if (!electronics) + AE = new /obj/item/weapon/airlock_electronics(loc) + else + AE = electronics + electronics = null + AE.loc = loc + + else if(istype(W, /obj/item/stack/sheet)) + var/obj/item/stack/sheet/S = W + if(S.get_amount() >= 1) + if(istype(S, /obj/item/stack/sheet/rglass)) + if(glass_material) + to_chat(user, "There is already glass in the [src].") + else if(can_insert_glass) + if(user.is_busy()) return + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) + user.visible_message("[user] adds [S.name] to the [src].", "You start to install [S.name] into the [src].") + if(do_after(user, 40, target = src)) + to_chat(user, "You installed reinforced glass windows into the [src]!") + if(!S.use(1)) + return + set_glass(TRUE) + else + to_chat(user, "You can't insert glass into [src].") + + else if(istype(S, /obj/item/stack/sheet/mineral) && S.sheettype) + if(can_insert_mineral()) + var/M = S.sheettype + if(S.get_amount() >= 2) + if(user.is_busy()) return + playsound(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, 40, target = src)) + if(!S.use(2)) + return + to_chat(user, "You installed [M] plating into the airlock assembly!") + change_mineral_airlock_type(M) + else + to_chat(user, "There is not enough [S].") + else + to_chat(user, "You can't add [S] to the [src].") + + else if(istype(W, /obj/item/weapon/screwdriver) && state == ASSEMBLY_NEAR_FINISHED ) + if(user.is_busy()) return + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) + to_chat(user, "Now finishing the airlock.") + + if(do_after(user, 40, target = src)) + if(!src) + return + to_chat(user, "You finish the airlock!") + var/obj/machinery/door/airlock/door = null + if(glass_material && !glass_only) + door = new glass_type(loc, dir) + else + door = new airlock_type(loc, dir) + door.assembly_type = type + door.electronics = electronics + if(electronics.one_access) + door.req_access = null + door.req_one_access = electronics.conf_access + else + door.req_access = electronics.conf_access + if(created_name) + door.name = created_name + electronics.loc = door + qdel(src) + else + ..() + update_state() + +/obj/structure/door_assembly/proc/set_glass(has_glass, glass_material = "glass") + if(has_glass) + src.glass_material = glass_material + can_insert_glass = FALSE + else + src.glass_material = null + can_insert_glass = TRUE + +/obj/structure/door_assembly/proc/can_insert_mineral() + return type == /obj/structure/door_assembly && !mineral + +/obj/structure/door_assembly/proc/change_mineral_airlock_type(mineral = null) + if(mineral) + var/normal_airlock_type = text2path("/obj/machinery/door/airlock/[mineral]") + var/glass_airlock_type = text2path("/obj/machinery/door/airlock/[mineral]/glass") + + airlock_type = normal_airlock_type + glass_type = glass_airlock_type + src.mineral = mineral + + switch(mineral) + if("gold") + icon = 'icons/obj/doors/airlocks/station/gold.dmi' + if("silver") + icon = 'icons/obj/doors/airlocks/station/silver.dmi' + if("diamond") + icon = 'icons/obj/doors/airlocks/station/diamond.dmi' + if("uranium") + icon = 'icons/obj/doors/airlocks/station/uranium.dmi' + if("phoron") + icon = 'icons/obj/doors/airlocks/station/phoron.dmi' + if("clown") + icon = 'icons/obj/doors/airlocks/station/bananium.dmi' + if("sandstone") + icon = 'icons/obj/doors/airlocks/station/sandstone.dmi' + else + airlock_type = initial(airlock_type) + glass_type = initial(glass_type) + icon = initial(icon) + src.mineral = null + + +/obj/structure/door_assembly/proc/update_state() + update_icon() + var/general_state_text + switch(state) + if(ASSEMBLY_SECURED) + general_state_text = "[anchored ? "secured " : ""]" + if(ASSEMBLY_WIRED) + general_state_text = "wired " + if(ASSEMBLY_NEAR_FINISHED) + general_state_text = "near finished " + + var/glass_state_text = "[glass_material ? "[glass_material] " : ""]" + var/mineral_state_text = "[mineral ? "[mineral] " : ""]" + + name = general_state_text + glass_state_text + mineral_state_text + initial(name) + +/obj/structure/door_assembly/update_icon() + overlays.Cut() + if(!glass_material) + overlays += get_airlock_overlay("fill_construction", icon) + else + overlays += get_airlock_overlay("[glass_material]_construction", overlays_file) + overlays += get_airlock_overlay("panel_c[state + 1]", overlays_file) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index 76354fd16a1c..e880b7f64d16 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -1,352 +1,352 @@ -/* - * False Walls - */ -/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 - var/block_air_zones = 1 -/obj/structure/falsewall/atom_init() - 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() - return ..() - -/obj/structure/falsewall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group) return !block_air_zones - if(istype(mover, /obj/effect/beam)) - return !opacity - return !density - -/obj/structure/falsewall/relativewall() - - if(!density) - icon_state = "[mineral]fwall_open" - return - - var/junction = 0 //will be used to determine from which side the wall is connected to other walls - - for(var/turf/simulated/wall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - if(src.mineral == W.mineral)//Only 'like' walls connect -Sieve - junction |= get_dir(src,W) - for(var/obj/structure/falsewall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - if(src.mineral == W.mineral) - junction |= get_dir(src,W) - for(var/obj/structure/falserwall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - if(src.mineral == W.mineral) - junction |= get_dir(src,W) - icon_state = "[mineral][junction]" - return - -/obj/structure/falsewall/attack_hand(mob/user) - if(opening) - return - user.SetNextMove(CLICK_CD_MELEE) - if(density) - opening = 1 - icon_state = "[mineral]fwall_open" - flick("[mineral]fwall_opening", src) - sleep(15) - src.density = 0 - set_opacity(0) - opening = 0 - update_nearby_tiles() - else - opening = 1 - flick("[mineral]fwall_closing", src) - icon_state = "[mineral]0" - density = 1 - sleep(15) - set_opacity(1) - src.relativewall() - opening = 0 - update_nearby_tiles() - -/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, mob/user) - if(opening) - to_chat(user, "\red You must wait until the door has stopped moving.") - return - user.SetNextMove(CLICK_CD_INTERACT) - - if(density) - var/turf/T = get_turf(src) - if(T.density) - to_chat(user, "\red 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 != "phoron")//Stupid shit keeps me from pushing the attackby() to phoron walls -Sieve - T = get_turf(src) - T.attackby(W,user) - qdel(src) - else - to_chat(user, "\blue You can't reach, close it first!") - - if( istype(W, /obj/item/weapon/pickaxe/plasmacutter) ) - var/turf/T = get_turf(src) - if(!mineral) - T.ChangeTurf(/turf/simulated/wall) - else - T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) - if(mineral != "phoron") - T = get_turf(src) - T.attackby(W,user) - qdel(src) - - //DRILLING - else if (istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) - var/turf/T = get_turf(src) - if(!mineral) - T.ChangeTurf(/turf/simulated/wall) - else - T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) - T = get_turf(src) - T.attackby(W,user) - qdel(src) - - else if( istype(W, /obj/item/weapon/melee/energy/blade) ) - var/turf/T = get_turf(src) - if(!mineral) - T.ChangeTurf(/turf/simulated/wall) - else - T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) - if(mineral != "phoron") - 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 - -/obj/structure/falserwall/atom_init() - relativewall_neighbours() - . = ..() - - -/obj/structure/falserwall/attack_hand(mob/user) - if(opening) - return - user.SetNextMove(CLICK_CD_MELEE) - if(density) - opening = 1 - // Open wall - icon_state = "frwall_open" - flick("frwall_opening", src) - sleep(15) - density = 0 - set_opacity(0) - opening = 0 - update_nearby_tiles() - else - opening = 1 - icon_state = "r_wall" - flick("frwall_closing", src) - density = 1 - sleep(15) - set_opacity(1) - relativewall() - opening = 0 - update_nearby_tiles() - -/obj/structure/falserwall/relativewall() - - if(!density) - icon_state = "frwall_open" - return - - var/junction = 0 //will be used to determine from which side the wall is connected to other walls - - for(var/turf/simulated/wall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - if(src.mineral == W.mineral)//Only 'like' walls connect -Sieve - junction |= get_dir(src,W) - for(var/obj/structure/falsewall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - if(src.mineral == W.mineral) - junction |= get_dir(src,W) - for(var/obj/structure/falserwall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - if(src.mineral == W.mineral) - junction |= get_dir(src,W) - icon_state = "rwall[junction]" - return - - - -/obj/structure/falserwall/attackby(obj/item/weapon/W, mob/user) - if(opening) - to_chat(user, "\red You must wait until the door has stopped moving.") - return - user.SetNextMove(CLICK_CD_INTERACT) - - 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) - 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/r_wall) - T = get_turf(src) - T.attackby(W,user) - qdel(src) - - else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - var/turf/T = get_turf(src) - T.ChangeTurf(/turf/simulated/wall/r_wall) - T = get_turf(src) - T.attackby(W,user) - qdel(src) - - //DRILLING - else if (istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) - var/turf/T = get_turf(src) - T.ChangeTurf(/turf/simulated/wall/r_wall) - T = get_turf(src) - T.attackby(W,user) - qdel(src) - - else if( istype(W, /obj/item/weapon/melee/energy/blade) ) - var/turf/T = get_turf(src) - T.ChangeTurf(/turf/simulated/wall/r_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, mob/user) - radiate() - ..() - -/obj/structure/falsewall/uranium/attack_hand(mob/user) - 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/phoron - name = "phoron wall" - desc = "A wall with phoron plating. This is definately a bad idea." - icon_state = "" - mineral = "phoron" - -//-----------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 +/* + * False Walls + */ +/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 + var/block_air_zones = 1 +/obj/structure/falsewall/atom_init() + 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() + return ..() + +/obj/structure/falsewall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group) return !block_air_zones + if(istype(mover, /obj/effect/beam)) + return !opacity + return !density + +/obj/structure/falsewall/relativewall() + + if(!density) + icon_state = "[mineral]fwall_open" + return + + var/junction = 0 //will be used to determine from which side the wall is connected to other walls + + for(var/turf/simulated/wall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + if(src.mineral == W.mineral)//Only 'like' walls connect -Sieve + junction |= get_dir(src,W) + for(var/obj/structure/falsewall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + if(src.mineral == W.mineral) + junction |= get_dir(src,W) + for(var/obj/structure/falserwall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + if(src.mineral == W.mineral) + junction |= get_dir(src,W) + icon_state = "[mineral][junction]" + return + +/obj/structure/falsewall/attack_hand(mob/user) + if(opening) + return + user.SetNextMove(CLICK_CD_MELEE) + if(density) + opening = 1 + icon_state = "[mineral]fwall_open" + flick("[mineral]fwall_opening", src) + sleep(15) + src.density = 0 + set_opacity(0) + opening = 0 + update_nearby_tiles() + else + opening = 1 + flick("[mineral]fwall_closing", src) + icon_state = "[mineral]0" + density = 1 + sleep(15) + set_opacity(1) + src.relativewall() + opening = 0 + update_nearby_tiles() + +/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, mob/user) + if(opening) + to_chat(user, "\red You must wait until the door has stopped moving.") + return + user.SetNextMove(CLICK_CD_INTERACT) + + if(density) + var/turf/T = get_turf(src) + if(T.density) + to_chat(user, "\red 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 != "phoron")//Stupid shit keeps me from pushing the attackby() to phoron walls -Sieve + T = get_turf(src) + T.attackby(W,user) + qdel(src) + else + to_chat(user, "\blue You can't reach, close it first!") + + if( istype(W, /obj/item/weapon/pickaxe/plasmacutter) ) + var/turf/T = get_turf(src) + if(!mineral) + T.ChangeTurf(/turf/simulated/wall) + else + T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) + if(mineral != "phoron") + T = get_turf(src) + T.attackby(W,user) + qdel(src) + + //DRILLING + else if (istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) + var/turf/T = get_turf(src) + if(!mineral) + T.ChangeTurf(/turf/simulated/wall) + else + T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) + T = get_turf(src) + T.attackby(W,user) + qdel(src) + + else if( istype(W, /obj/item/weapon/melee/energy/blade) ) + var/turf/T = get_turf(src) + if(!mineral) + T.ChangeTurf(/turf/simulated/wall) + else + T.ChangeTurf(text2path("/turf/simulated/wall/mineral/[mineral]")) + if(mineral != "phoron") + 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 + +/obj/structure/falserwall/atom_init() + relativewall_neighbours() + . = ..() + + +/obj/structure/falserwall/attack_hand(mob/user) + if(opening) + return + user.SetNextMove(CLICK_CD_MELEE) + if(density) + opening = 1 + // Open wall + icon_state = "frwall_open" + flick("frwall_opening", src) + sleep(15) + density = 0 + set_opacity(0) + opening = 0 + update_nearby_tiles() + else + opening = 1 + icon_state = "r_wall" + flick("frwall_closing", src) + density = 1 + sleep(15) + set_opacity(1) + relativewall() + opening = 0 + update_nearby_tiles() + +/obj/structure/falserwall/relativewall() + + if(!density) + icon_state = "frwall_open" + return + + var/junction = 0 //will be used to determine from which side the wall is connected to other walls + + for(var/turf/simulated/wall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + if(src.mineral == W.mineral)//Only 'like' walls connect -Sieve + junction |= get_dir(src,W) + for(var/obj/structure/falsewall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + if(src.mineral == W.mineral) + junction |= get_dir(src,W) + for(var/obj/structure/falserwall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + if(src.mineral == W.mineral) + junction |= get_dir(src,W) + icon_state = "rwall[junction]" + return + + + +/obj/structure/falserwall/attackby(obj/item/weapon/W, mob/user) + if(opening) + to_chat(user, "\red You must wait until the door has stopped moving.") + return + user.SetNextMove(CLICK_CD_INTERACT) + + 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) + 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/r_wall) + T = get_turf(src) + T.attackby(W,user) + qdel(src) + + else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + var/turf/T = get_turf(src) + T.ChangeTurf(/turf/simulated/wall/r_wall) + T = get_turf(src) + T.attackby(W,user) + qdel(src) + + //DRILLING + else if (istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) + var/turf/T = get_turf(src) + T.ChangeTurf(/turf/simulated/wall/r_wall) + T = get_turf(src) + T.attackby(W,user) + qdel(src) + + else if( istype(W, /obj/item/weapon/melee/energy/blade) ) + var/turf/T = get_turf(src) + T.ChangeTurf(/turf/simulated/wall/r_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, mob/user) + radiate() + ..() + +/obj/structure/falsewall/uranium/attack_hand(mob/user) + 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/phoron + name = "phoron wall" + desc = "A wall with phoron plating. This is definately a bad idea." + icon_state = "" + mineral = "phoron" + +//-----------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 1844dd2a4573..d9ed012d5cb0 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -1,505 +1,505 @@ -// random plants - -/obj/structure/flora - name = "bush" - icon = 'icons/obj/flora/plants.dmi' - icon_state = "plant-10" - var/can_be_cut = FALSE - var/health_flora = 40 - var/damage_threshhold = 5 - var/cutting_sound = 'sound/weapons/bladeslice.ogg' - var/list/drop_on_destroy = list() - -/obj/structure/flora/attackby(obj/item/weapon/W, mob/user) - . = ..() - if(can_be_cut && is_sharp(W) && W.force >= damage_threshhold) - playsound(src, cutting_sound, 50, 1) - health_flora -= W.force - if(health_flora <= 0) - visible_message("[src] is hacked into pieces!") - if(drop_on_destroy.len) - for(var/type_drop in drop_on_destroy) - new type_drop(get_turf(src)) - qdel(src) - return - -/obj/structure/flora/plant - name = "marvelous potted plant" - icon = 'icons/obj/flora/plants.dmi' - icon_state = "plant-10" - -/obj/structure/flora/plant/random/atom_init() - . = ..() - var/newtype = pick(subtypesof(/obj/structure/flora/pottedplant)) - new newtype(get_turf(src)) - return INITIALIZE_HINT_QDEL - -/obj/structure/flora/pottedplant - name = "potted plant" - desc = "Really brings the room together." - icon = 'icons/obj/flora/plants.dmi' - icon_state = "plant-1" - -/obj/structure/flora/pottedplant/fern - name = "potted fern" - desc = "This is an ordinary looking fern. It looks like it could do with some water." - icon_state = "plant-2" - -/obj/structure/flora/pottedplant/overgrown - name = "overgrown potted plants" - desc = "This is an assortment of colourful plants. Some parts are overgrown." - icon_state = "plant-3" - -/obj/structure/flora/pottedplant/bamboo - name = "potted bamboo" - desc = "These are bamboo shoots. The tops looks like they've been cut short." - icon_state = "plant-4" - -/obj/structure/flora/pottedplant/largebush - name = "large potted bush" - desc = "This is a large bush. The leaves stick upwards in an odd fashion." - icon_state = "plant-5" - -/obj/structure/flora/pottedplant/thinbush - name = "thin potted bush" - desc = "This is a thin bush. It appears to be flowering." - icon_state = "plant-6" - -/obj/structure/flora/pottedplant/mysterious - name = "mysterious potted bulbs" - desc = "This is a mysterious looking plant. Touching the bulbs cause them to shrink." - icon_state = "plant-7" - -/obj/structure/flora/pottedplant/smalltree - name = "small potted tree" - desc = "This is a small tree. It is rather pleasant." - icon_state = "plant-8" - -/obj/structure/flora/pottedplant/unusual - name = "unusual potted plant" - desc = "This is an unusual plant. It's bulbous ends emit a soft blue light." - icon_state = "plant-9" - -/obj/structure/flora/pottedplant/unusual/atom_init() - . = ..() - set_light(2, 0.5, "#007fff") - -/obj/structure/flora/pottedplant/orientaltree - name = "potted oriental tree" - desc = "This is a rather oriental style tree. It's flowers are bright pink." - icon_state = "plant-10" - -/obj/structure/flora/pottedplant/smallcactus - name = "small potted cactus" - desc = "This is a small cactus. Its needles are sharp." - icon_state = "plant-11" - -/obj/structure/flora/pottedplant/tall - name = "tall potted plant" - desc = "This is a tall plant. Tiny pores line its surface." - icon_state = "plant-12" - -/obj/structure/flora/pottedplant/sticky - name = "sticky potted plant" - desc = "This is an odd plant. Its sticky leaves trap insects." - icon_state = "plant-13" - -/obj/structure/flora/pottedplant/smelly - name = "smelly potted plant" - desc = "This is some kind of tropical plant. It reeks of rotten eggs." - icon_state = "plant-14" - -/obj/structure/flora/pottedplant/small - name = "small potted plant" - desc = "This is a pot of assorted small flora. Some look familiar." - icon_state = "plant-15" - -/obj/structure/flora/pottedplant/aquatic - name = "aquatic potted plant" - desc = "This is apparently an aquatic plant. It's probably fake." - icon_state = "plant-16" - -/obj/structure/flora/pottedplant/shoot - name = "small potted shoot" - desc = "This is a small shoot. It still needs time to grow." - icon_state = "plant-17" - -/obj/structure/flora/pottedplant/flower - name = "potted flower" - desc = "This is a slim plant. Sweet smelling flowers are supported by spindly stems." - icon_state = "plant-18" - -/obj/structure/flora/pottedplant/crystal - name = "crystalline potted plant" - desc = "These are rather cubic plants. Odd crystal formations grow on the end." - icon_state = "plant-19" - -/obj/structure/flora/pottedplant/subterranean - name = "subterranean potted plant" - desc = "This is a subterranean plant. It's bulbous ends glow faintly." - icon_state = "plant-20" - -/obj/structure/flora/pottedplant/subterranean/atom_init() - . = ..() - set_light(2, 0.5, "#ff6633") - -/obj/structure/flora/pottedplant/minitree - name = "potted tree" - desc = "This is a miniature tree. Apparently it was grown to 1/5 scale." - icon_state = "plant-21" - -/obj/structure/flora/pottedplant/stoutbush - name = "stout potted bush" - desc = "This is a stout bush. Its leaves point up and outwards." - icon_state = "plant-22" - -/obj/structure/flora/pottedplant/drooping - name = "drooping potted plant" - desc = "This is a small plant. The drooping leaves make it look like its wilted." - icon_state = "plant-23" - -/obj/structure/flora/pottedplant/tropical_1 - name = "tropical potted plant" - desc = "This is some kind of tropical plant. It hasn't begun to flower yet." - icon_state = "plant-24" - -/obj/structure/flora/pottedplant/dead - name = "dead potted plant" - desc = "This is the dried up remains of a dead plant. Someone should replace it." - icon_state = "plant-25" - -/obj/structure/flora/pottedplant/large - name = "large potted plant" - desc = "This is a large plant. Three branches support pairs of waxy leaves." - icon_state = "plant-26" - -/obj/structure/flora/pottedplant/tropicalfern - name = "tropical fern" - desc = "This is a tropical fern. It looks like it could do with some water" - icon_state = "plant-27" - -/obj/structure/flora/pottedplant/palm - name = "palm potted plant" - desc = "This is some kind of tropical palm. It is unlikely that you'll find coconuts under it." - icon_state = "plant-28" - -/obj/structure/flora/pottedplant/ficus - name = "ficus plant" - desc = "This is a ficus. Also known as fig tree." - icon_state = "plant-29" - -/obj/structure/flora/pottedplant/tropical_2 - name = "tropical potted plant" - desc = "This is some kind of tropical plant. It has large smelly leaves without flowers." - icon_state = "plant-30" - -/obj/structure/flora/pottedplant/decorative - name = "decorative potted plant" - desc = "This is a decorative shrub. It's been trimmed into the shape of an apple." - icon_state = "applebush" - -/obj/structure/flora/plant/monkey - name = "monkeyplant" - desc = "This is a monkey plant. Made by one mad scientist." - icon_state = "monkeyplant" - -/obj/structure/flora/plant/deskfern - name = "fancy ferny potted plant" - desc = "This leafy desk fern could do with a trim." - icon_state = "plant-31" - -/obj/structure/flora/plant/floorleaf - name = "fancy leafy floor plant" - desc = "This plant has remarkably waxy leaves." - icon_state = "plant-32" - -/obj/structure/flora/plant/deskleaf - name = "fancy leafy potted desk plant" - desc = "A tiny waxy leafed plant specimen." - icon_state = "plant-33" - -/obj/structure/flora/plant/deskferntrim - name = "fancy trimmed ferny potted plant" - desc = "This leafy desk fern seems to have been trimmed too much." - icon_state = "plant-34" - -// trees -/obj/structure/flora/tree - name = "tree" - anchored = 1 - density = 1 - pixel_x = -16 - layer = 9 - health_flora = 150 - damage_threshhold = 15 - can_be_cut = TRUE - cutting_sound = 'sound/items/Axe.ogg' - drop_on_destroy = list(/obj/item/weapon/grown/log, /obj/item/weapon/grown/log, /obj/item/weapon/grown/log, /obj/item/weapon/grown/log) - - -/obj/structure/flora/tree/pine - name = "pine tree" - icon = 'icons/obj/flora/pinetrees.dmi' - icon_state = "pine_1" - -/obj/structure/flora/tree/pine/atom_init() - . = ..() - 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/atom_init() - . = ..() - tree_xmas_list += src - icon_state = "pine_c" - -/obj/structure/flora/tree/pine/xmas/Destroy() - tree_xmas_list -= src - return ..() - -/obj/structure/flora/tree/dead - icon = 'icons/obj/flora/deadtrees.dmi' - icon_state = "tree_1" - -/obj/structure/flora/tree/dead/atom_init() - . = ..() - icon_state = "tree_[rand(1, 6)]" - -/obj/structure/flora/tree/jungle - name = "tree" - icon_state = "tree" - desc = "It's seriously hampering your view of the jungle." - icon = 'icons/obj/flora/jungletrees.dmi' - pixel_x = -48 - pixel_y = -20 - -/obj/structure/flora/tree/jungle/atom_init() - . = ..() - icon_state = pick(icon_states(icon)) - -/obj/structure/flora/tree/jungle/small - pixel_y = 0 - pixel_x = -32 - icon = 'icons/obj/flora/jungletreesmall.dmi' - -// grass - -/obj/structure/flora/grass - name = "grass" - icon = 'icons/obj/flora/snowflora.dmi' - anchored = 1 - can_be_cut = TRUE - health_flora = 60 - -/obj/structure/flora/grass/brown - icon_state = "snowgrass1bb" - -/obj/structure/flora/grass/brown/atom_init() - . = ..() - icon_state = "snowgrass[rand(1, 3)]bb" - - -/obj/structure/flora/grass/green - icon_state = "snowgrass1gb" - -/obj/structure/flora/grass/green/atom_init() - . = ..() - icon_state = "snowgrass[rand(1, 3)]gb" - -/obj/structure/flora/grass/both - icon_state = "snowgrassall1" - -/obj/structure/flora/grass/both/atom_init() - . = ..() - icon_state = "snowgrassall[rand(1, 3)]" - -// bushes - -/obj/structure/flora/bush - name = "bush" - icon = 'icons/obj/flora/snowflora.dmi' - icon_state = "snowbush1" - anchored = 1 - can_be_cut = TRUE - health_flora = 50 - -/obj/structure/flora/bush/atom_init() - . = ..() - icon_state = "snowbush[rand(1, 6)]" - -// newbushes - -/obj/structure/flora/ausbushes - name = "bush" - icon = 'icons/obj/flora/ausflora.dmi' - icon_state = "firstbush_1" - anchored = 1 - can_be_cut = TRUE - health_flora = 50 - -/obj/structure/flora/ausbushes/atom_init() - . = ..() - icon_state = "firstbush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/reedbush - icon_state = "reedbush_1" - -/obj/structure/flora/ausbushes/reedbush/atom_init() - . = ..() - icon_state = "reedbush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/leafybush - icon_state = "leafybush_1" - -/obj/structure/flora/ausbushes/leafybush/atom_init() - . = ..() - icon_state = "leafybush_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/palebush - icon_state = "palebush_1" - -/obj/structure/flora/ausbushes/palebush/atom_init() - . = ..() - icon_state = "palebush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/stalkybush - icon_state = "stalkybush_1" - -/obj/structure/flora/ausbushes/stalkybush/atom_init() - . = ..() - icon_state = "stalkybush_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/grassybush - icon_state = "grassybush_1" - -/obj/structure/flora/ausbushes/grassybush/atom_init() - . = ..() - icon_state = "grassybush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/fernybush - icon_state = "fernybush_1" - -/obj/structure/flora/ausbushes/fernybush/atom_init() - . = ..() - icon_state = "fernybush_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/sunnybush - icon_state = "sunnybush_1" - -/obj/structure/flora/ausbushes/sunnybush/atom_init() - . = ..() - icon_state = "sunnybush_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/genericbush - icon_state = "genericbush_1" - -/obj/structure/flora/ausbushes/genericbush/atom_init() - . = ..() - icon_state = "genericbush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/pointybush - icon_state = "pointybush_1" - -/obj/structure/flora/ausbushes/pointybush/atom_init() - . = ..() - icon_state = "pointybush_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/lavendergrass - icon_state = "lavendergrass_1" - -/obj/structure/flora/ausbushes/lavendergrass/atom_init() - . = ..() - icon_state = "lavendergrass_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/ywflowers - icon_state = "ywflowers_1" - -/obj/structure/flora/ausbushes/ywflowers/atom_init() - . = ..() - icon_state = "ywflowers_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/brflowers - icon_state = "brflowers_1" - -/obj/structure/flora/ausbushes/brflowers/atom_init() - . = ..() - icon_state = "brflowers_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/ppflowers - icon_state = "ppflowers_1" - -/obj/structure/flora/ausbushes/ppflowers/atom_init() - . = ..() - icon_state = "ppflowers_[rand(1, 4)]" - -/obj/structure/flora/ausbushes/sparsegrass - icon_state = "sparsegrass_1" - -/obj/structure/flora/ausbushes/sparsegrass/atom_init() - . = ..() - icon_state = "sparsegrass_[rand(1, 3)]" - -/obj/structure/flora/ausbushes/fullgrass - icon_state = "fullgrass_1" - -/obj/structure/flora/ausbushes/fullgrass/atom_init() - . = ..() - icon_state = "fullgrass_[rand(1, 3)]" - -// Jungle rocks - -/obj/structure/flora/rock/jungle - icon_state = "pile of rocks" - desc = "A pile of rocks." - icon_state = "rock" - icon = 'icons/obj/flora/jungleflora.dmi' - density = FALSE - can_be_cut = TRUE - health_flora = 50 - -/obj/structure/flora/rock/jungle/atom_init() - . = ..() - icon_state = "[initial(icon_state)][rand(1,5)]" - -// Jungle bushes - -/obj/structure/flora/junglebush - name = "bush" - desc = "A wild plant that is found in jungles." - icon = 'icons/obj/flora/jungleflora.dmi' - icon_state = "busha" - anchored = 1 - can_be_cut = TRUE - health_flora = 40 - -/obj/structure/flora/junglebush/atom_init() - . = ..() - icon_state = "[icon_state][rand(1, 3)]" - -/obj/structure/flora/junglebush/b - icon_state = "bushb" - -/obj/structure/flora/junglebush/c - icon_state = "bushc" - -/obj/structure/flora/junglebush/large - icon_state = "bush" - icon = 'icons/obj/flora/largejungleflora.dmi' - pixel_x = -16 - pixel_y = -12 - layer = 9 - -/obj/structure/flora/rock/pile/largejungle - name = "rocks" - icon_state = "rocks" - icon = 'icons/obj/flora/largejungleflora.dmi' - density = 1 - pixel_x = -16 - pixel_y = -16 - -/obj/structure/flora/rock/pile/largejungle/atom_init() - . = ..() - icon_state = "[initial(icon_state)][rand(1,3)]" +// random plants + +/obj/structure/flora + name = "bush" + icon = 'icons/obj/flora/plants.dmi' + icon_state = "plant-10" + var/can_be_cut = FALSE + var/health_flora = 40 + var/damage_threshhold = 5 + var/cutting_sound = 'sound/weapons/bladeslice.ogg' + var/list/drop_on_destroy = list() + +/obj/structure/flora/attackby(obj/item/weapon/W, mob/user) + . = ..() + if(can_be_cut && is_sharp(W) && W.force >= damage_threshhold) + playsound(src, cutting_sound, 50, 1) + health_flora -= W.force + if(health_flora <= 0) + visible_message("[src] is hacked into pieces!") + if(drop_on_destroy.len) + for(var/type_drop in drop_on_destroy) + new type_drop(get_turf(src)) + qdel(src) + return + +/obj/structure/flora/plant + name = "marvelous potted plant" + icon = 'icons/obj/flora/plants.dmi' + icon_state = "plant-10" + +/obj/structure/flora/plant/random/atom_init() + . = ..() + var/newtype = pick(subtypesof(/obj/structure/flora/pottedplant)) + new newtype(get_turf(src)) + return INITIALIZE_HINT_QDEL + +/obj/structure/flora/pottedplant + name = "potted plant" + desc = "Really brings the room together." + icon = 'icons/obj/flora/plants.dmi' + icon_state = "plant-1" + +/obj/structure/flora/pottedplant/fern + name = "potted fern" + desc = "This is an ordinary looking fern. It looks like it could do with some water." + icon_state = "plant-2" + +/obj/structure/flora/pottedplant/overgrown + name = "overgrown potted plants" + desc = "This is an assortment of colourful plants. Some parts are overgrown." + icon_state = "plant-3" + +/obj/structure/flora/pottedplant/bamboo + name = "potted bamboo" + desc = "These are bamboo shoots. The tops looks like they've been cut short." + icon_state = "plant-4" + +/obj/structure/flora/pottedplant/largebush + name = "large potted bush" + desc = "This is a large bush. The leaves stick upwards in an odd fashion." + icon_state = "plant-5" + +/obj/structure/flora/pottedplant/thinbush + name = "thin potted bush" + desc = "This is a thin bush. It appears to be flowering." + icon_state = "plant-6" + +/obj/structure/flora/pottedplant/mysterious + name = "mysterious potted bulbs" + desc = "This is a mysterious looking plant. Touching the bulbs cause them to shrink." + icon_state = "plant-7" + +/obj/structure/flora/pottedplant/smalltree + name = "small potted tree" + desc = "This is a small tree. It is rather pleasant." + icon_state = "plant-8" + +/obj/structure/flora/pottedplant/unusual + name = "unusual potted plant" + desc = "This is an unusual plant. It's bulbous ends emit a soft blue light." + icon_state = "plant-9" + +/obj/structure/flora/pottedplant/unusual/atom_init() + . = ..() + set_light(2, 0.5, "#007fff") + +/obj/structure/flora/pottedplant/orientaltree + name = "potted oriental tree" + desc = "This is a rather oriental style tree. It's flowers are bright pink." + icon_state = "plant-10" + +/obj/structure/flora/pottedplant/smallcactus + name = "small potted cactus" + desc = "This is a small cactus. Its needles are sharp." + icon_state = "plant-11" + +/obj/structure/flora/pottedplant/tall + name = "tall potted plant" + desc = "This is a tall plant. Tiny pores line its surface." + icon_state = "plant-12" + +/obj/structure/flora/pottedplant/sticky + name = "sticky potted plant" + desc = "This is an odd plant. Its sticky leaves trap insects." + icon_state = "plant-13" + +/obj/structure/flora/pottedplant/smelly + name = "smelly potted plant" + desc = "This is some kind of tropical plant. It reeks of rotten eggs." + icon_state = "plant-14" + +/obj/structure/flora/pottedplant/small + name = "small potted plant" + desc = "This is a pot of assorted small flora. Some look familiar." + icon_state = "plant-15" + +/obj/structure/flora/pottedplant/aquatic + name = "aquatic potted plant" + desc = "This is apparently an aquatic plant. It's probably fake." + icon_state = "plant-16" + +/obj/structure/flora/pottedplant/shoot + name = "small potted shoot" + desc = "This is a small shoot. It still needs time to grow." + icon_state = "plant-17" + +/obj/structure/flora/pottedplant/flower + name = "potted flower" + desc = "This is a slim plant. Sweet smelling flowers are supported by spindly stems." + icon_state = "plant-18" + +/obj/structure/flora/pottedplant/crystal + name = "crystalline potted plant" + desc = "These are rather cubic plants. Odd crystal formations grow on the end." + icon_state = "plant-19" + +/obj/structure/flora/pottedplant/subterranean + name = "subterranean potted plant" + desc = "This is a subterranean plant. It's bulbous ends glow faintly." + icon_state = "plant-20" + +/obj/structure/flora/pottedplant/subterranean/atom_init() + . = ..() + set_light(2, 0.5, "#ff6633") + +/obj/structure/flora/pottedplant/minitree + name = "potted tree" + desc = "This is a miniature tree. Apparently it was grown to 1/5 scale." + icon_state = "plant-21" + +/obj/structure/flora/pottedplant/stoutbush + name = "stout potted bush" + desc = "This is a stout bush. Its leaves point up and outwards." + icon_state = "plant-22" + +/obj/structure/flora/pottedplant/drooping + name = "drooping potted plant" + desc = "This is a small plant. The drooping leaves make it look like its wilted." + icon_state = "plant-23" + +/obj/structure/flora/pottedplant/tropical_1 + name = "tropical potted plant" + desc = "This is some kind of tropical plant. It hasn't begun to flower yet." + icon_state = "plant-24" + +/obj/structure/flora/pottedplant/dead + name = "dead potted plant" + desc = "This is the dried up remains of a dead plant. Someone should replace it." + icon_state = "plant-25" + +/obj/structure/flora/pottedplant/large + name = "large potted plant" + desc = "This is a large plant. Three branches support pairs of waxy leaves." + icon_state = "plant-26" + +/obj/structure/flora/pottedplant/tropicalfern + name = "tropical fern" + desc = "This is a tropical fern. It looks like it could do with some water" + icon_state = "plant-27" + +/obj/structure/flora/pottedplant/palm + name = "palm potted plant" + desc = "This is some kind of tropical palm. It is unlikely that you'll find coconuts under it." + icon_state = "plant-28" + +/obj/structure/flora/pottedplant/ficus + name = "ficus plant" + desc = "This is a ficus. Also known as fig tree." + icon_state = "plant-29" + +/obj/structure/flora/pottedplant/tropical_2 + name = "tropical potted plant" + desc = "This is some kind of tropical plant. It has large smelly leaves without flowers." + icon_state = "plant-30" + +/obj/structure/flora/pottedplant/decorative + name = "decorative potted plant" + desc = "This is a decorative shrub. It's been trimmed into the shape of an apple." + icon_state = "applebush" + +/obj/structure/flora/plant/monkey + name = "monkeyplant" + desc = "This is a monkey plant. Made by one mad scientist." + icon_state = "monkeyplant" + +/obj/structure/flora/plant/deskfern + name = "fancy ferny potted plant" + desc = "This leafy desk fern could do with a trim." + icon_state = "plant-31" + +/obj/structure/flora/plant/floorleaf + name = "fancy leafy floor plant" + desc = "This plant has remarkably waxy leaves." + icon_state = "plant-32" + +/obj/structure/flora/plant/deskleaf + name = "fancy leafy potted desk plant" + desc = "A tiny waxy leafed plant specimen." + icon_state = "plant-33" + +/obj/structure/flora/plant/deskferntrim + name = "fancy trimmed ferny potted plant" + desc = "This leafy desk fern seems to have been trimmed too much." + icon_state = "plant-34" + +// trees +/obj/structure/flora/tree + name = "tree" + anchored = 1 + density = 1 + pixel_x = -16 + layer = 9 + health_flora = 150 + damage_threshhold = 15 + can_be_cut = TRUE + cutting_sound = 'sound/items/Axe.ogg' + drop_on_destroy = list(/obj/item/weapon/grown/log, /obj/item/weapon/grown/log, /obj/item/weapon/grown/log, /obj/item/weapon/grown/log) + + +/obj/structure/flora/tree/pine + name = "pine tree" + icon = 'icons/obj/flora/pinetrees.dmi' + icon_state = "pine_1" + +/obj/structure/flora/tree/pine/atom_init() + . = ..() + 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/atom_init() + . = ..() + tree_xmas_list += src + icon_state = "pine_c" + +/obj/structure/flora/tree/pine/xmas/Destroy() + tree_xmas_list -= src + return ..() + +/obj/structure/flora/tree/dead + icon = 'icons/obj/flora/deadtrees.dmi' + icon_state = "tree_1" + +/obj/structure/flora/tree/dead/atom_init() + . = ..() + icon_state = "tree_[rand(1, 6)]" + +/obj/structure/flora/tree/jungle + name = "tree" + icon_state = "tree" + desc = "It's seriously hampering your view of the jungle." + icon = 'icons/obj/flora/jungletrees.dmi' + pixel_x = -48 + pixel_y = -20 + +/obj/structure/flora/tree/jungle/atom_init() + . = ..() + icon_state = pick(icon_states(icon)) + +/obj/structure/flora/tree/jungle/small + pixel_y = 0 + pixel_x = -32 + icon = 'icons/obj/flora/jungletreesmall.dmi' + +// grass + +/obj/structure/flora/grass + name = "grass" + icon = 'icons/obj/flora/snowflora.dmi' + anchored = 1 + can_be_cut = TRUE + health_flora = 60 + +/obj/structure/flora/grass/brown + icon_state = "snowgrass1bb" + +/obj/structure/flora/grass/brown/atom_init() + . = ..() + icon_state = "snowgrass[rand(1, 3)]bb" + + +/obj/structure/flora/grass/green + icon_state = "snowgrass1gb" + +/obj/structure/flora/grass/green/atom_init() + . = ..() + icon_state = "snowgrass[rand(1, 3)]gb" + +/obj/structure/flora/grass/both + icon_state = "snowgrassall1" + +/obj/structure/flora/grass/both/atom_init() + . = ..() + icon_state = "snowgrassall[rand(1, 3)]" + +// bushes + +/obj/structure/flora/bush + name = "bush" + icon = 'icons/obj/flora/snowflora.dmi' + icon_state = "snowbush1" + anchored = 1 + can_be_cut = TRUE + health_flora = 50 + +/obj/structure/flora/bush/atom_init() + . = ..() + icon_state = "snowbush[rand(1, 6)]" + +// newbushes + +/obj/structure/flora/ausbushes + name = "bush" + icon = 'icons/obj/flora/ausflora.dmi' + icon_state = "firstbush_1" + anchored = 1 + can_be_cut = TRUE + health_flora = 50 + +/obj/structure/flora/ausbushes/atom_init() + . = ..() + icon_state = "firstbush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/reedbush + icon_state = "reedbush_1" + +/obj/structure/flora/ausbushes/reedbush/atom_init() + . = ..() + icon_state = "reedbush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/leafybush + icon_state = "leafybush_1" + +/obj/structure/flora/ausbushes/leafybush/atom_init() + . = ..() + icon_state = "leafybush_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/palebush + icon_state = "palebush_1" + +/obj/structure/flora/ausbushes/palebush/atom_init() + . = ..() + icon_state = "palebush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/stalkybush + icon_state = "stalkybush_1" + +/obj/structure/flora/ausbushes/stalkybush/atom_init() + . = ..() + icon_state = "stalkybush_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/grassybush + icon_state = "grassybush_1" + +/obj/structure/flora/ausbushes/grassybush/atom_init() + . = ..() + icon_state = "grassybush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/fernybush + icon_state = "fernybush_1" + +/obj/structure/flora/ausbushes/fernybush/atom_init() + . = ..() + icon_state = "fernybush_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/sunnybush + icon_state = "sunnybush_1" + +/obj/structure/flora/ausbushes/sunnybush/atom_init() + . = ..() + icon_state = "sunnybush_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/genericbush + icon_state = "genericbush_1" + +/obj/structure/flora/ausbushes/genericbush/atom_init() + . = ..() + icon_state = "genericbush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/pointybush + icon_state = "pointybush_1" + +/obj/structure/flora/ausbushes/pointybush/atom_init() + . = ..() + icon_state = "pointybush_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/lavendergrass + icon_state = "lavendergrass_1" + +/obj/structure/flora/ausbushes/lavendergrass/atom_init() + . = ..() + icon_state = "lavendergrass_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/ywflowers + icon_state = "ywflowers_1" + +/obj/structure/flora/ausbushes/ywflowers/atom_init() + . = ..() + icon_state = "ywflowers_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/brflowers + icon_state = "brflowers_1" + +/obj/structure/flora/ausbushes/brflowers/atom_init() + . = ..() + icon_state = "brflowers_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/ppflowers + icon_state = "ppflowers_1" + +/obj/structure/flora/ausbushes/ppflowers/atom_init() + . = ..() + icon_state = "ppflowers_[rand(1, 4)]" + +/obj/structure/flora/ausbushes/sparsegrass + icon_state = "sparsegrass_1" + +/obj/structure/flora/ausbushes/sparsegrass/atom_init() + . = ..() + icon_state = "sparsegrass_[rand(1, 3)]" + +/obj/structure/flora/ausbushes/fullgrass + icon_state = "fullgrass_1" + +/obj/structure/flora/ausbushes/fullgrass/atom_init() + . = ..() + icon_state = "fullgrass_[rand(1, 3)]" + +// Jungle rocks + +/obj/structure/flora/rock/jungle + icon_state = "pile of rocks" + desc = "A pile of rocks." + icon_state = "rock" + icon = 'icons/obj/flora/jungleflora.dmi' + density = FALSE + can_be_cut = TRUE + health_flora = 50 + +/obj/structure/flora/rock/jungle/atom_init() + . = ..() + icon_state = "[initial(icon_state)][rand(1,5)]" + +// Jungle bushes + +/obj/structure/flora/junglebush + name = "bush" + desc = "A wild plant that is found in jungles." + icon = 'icons/obj/flora/jungleflora.dmi' + icon_state = "busha" + anchored = 1 + can_be_cut = TRUE + health_flora = 40 + +/obj/structure/flora/junglebush/atom_init() + . = ..() + icon_state = "[icon_state][rand(1, 3)]" + +/obj/structure/flora/junglebush/b + icon_state = "bushb" + +/obj/structure/flora/junglebush/c + icon_state = "bushc" + +/obj/structure/flora/junglebush/large + icon_state = "bush" + icon = 'icons/obj/flora/largejungleflora.dmi' + pixel_x = -16 + pixel_y = -12 + layer = 9 + +/obj/structure/flora/rock/pile/largejungle + name = "rocks" + icon_state = "rocks" + icon = 'icons/obj/flora/largejungleflora.dmi' + density = 1 + pixel_x = -16 + pixel_y = -16 + +/obj/structure/flora/rock/pile/largejungle/atom_init() + . = ..() + icon_state = "[initial(icon_state)][rand(1,3)]" diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 1935ba07f0cb..b2401fd16f43 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -1,289 +1,289 @@ -/obj/structure/girder - icon_state = "girder" - anchored = 1 - density = 1 - layer = 2.9 - var/state = 0 - var/health = 200 - - - bullet_act(obj/item/projectile/Proj) - if(istype(Proj, /obj/item/projectile/beam)) - health -= Proj.damage - ..() - if(health <= 0) - new /obj/item/stack/sheet/metal(get_turf(src)) - qdel(src) - - return - - attackby(obj/item/W, mob/user) - if(user.is_busy()) return - if(istype (W,/obj/item/weapon/changeling_hammer)) - var/obj/item/weapon/changeling_hammer/C = W - visible_message("\red [user] has punched \the [src]!") - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - if(C.use_charge(user, 1) && prob(40)) - playsound(loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) - qdel(src) - else if(istype(W, /obj/item/weapon/wrench) && state == 0) - if(anchored && !istype(src,/obj/structure/girder/displaced)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - to_chat(user, "\blue Now disassembling the girder") - if(do_after(user,40,target = src)) - if(!src) return - to_chat(user, "\blue You dissasembled the girder!") - new /obj/item/stack/sheet/metal(get_turf(src)) - qdel(src) - else if(!anchored) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - to_chat(user, "\blue Now securing the girder") - if(do_after(user,40, target = src)) - to_chat(user, "\blue You secured the girder!") - new/obj/structure/girder( src.loc ) - qdel(src) - - else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - to_chat(user, "\blue Now slicing apart the girder") - if(do_after(user,30,target = src)) - if(!src) return - to_chat(user, "\blue You slice apart the girder!") - new /obj/item/stack/sheet/metal(get_turf(src)) - qdel(src) - - else if(istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) - to_chat(user, "\blue You drill through the girder!") - new /obj/item/stack/sheet/metal(get_turf(src)) - qdel(src) - - else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 && istype(src,/obj/structure/girder/reinforced)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) - to_chat(user, "\blue Now unsecuring support struts") - if(do_after(user,40,target = src)) - if(!src) return - to_chat(user, "\blue You unsecured the support struts!") - state = 1 - - else if(istype(W, /obj/item/weapon/wirecutters) && istype(src,/obj/structure/girder/reinforced) && state == 1) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) - to_chat(user, "\blue Now removing support struts") - if(do_after(user,40,target = src)) - if(!src) return - to_chat(user, "\blue You removed the support struts!") - new/obj/structure/girder( src.loc ) - qdel(src) - - else if(istype(W, /obj/item/weapon/crowbar) && state == 0 && anchored ) - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) - to_chat(user, "\blue Now dislodging the girder") - if(do_after(user, 40,target = src)) - if(!src) return - to_chat(user, "\blue You dislodged the girder!") - new/obj/structure/girder/displaced( src.loc ) - qdel(src) - - 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(!anchored) - if(!S.use(2)) - return - to_chat(user, "\blue You create a false wall! Push on it to open or close the passage.") - new /obj/structure/falsewall (src.loc) - qdel(src) - else - if(S.get_amount() < 2) - return ..() - to_chat(user, "\blue Now adding plating...") - if (do_after(user, 40, target = src)) - if(QDELETED(src) || QDELETED(S) || !S.use(2)) - return - to_chat(user, "\blue You added the plating!") - var/turf/Tsrc = get_turf(src) - Tsrc.ChangeTurf(/turf/simulated/wall) - for(var/turf/simulated/wall/X in Tsrc.loc) - X.add_hiddenprint(usr) - qdel(src) - return - - if(/obj/item/stack/sheet/plasteel) - if(!anchored) - if(!S.use(2)) - return - to_chat(user, "\blue You create a false wall! Push on it to open or close the passage.") - new /obj/structure/falserwall (src.loc) - qdel(src) - else - if (src.icon_state == "reinforced") //I cant believe someone would actually write this line of code... - if(S.get_amount() < 1) - return ..() - to_chat(user, "\blue Now finalising reinforced wall.") - if(do_after(user, 50, target = src)) - if(QDELETED(src) || QDELETED(S) || !S.use(1)) - return - to_chat(user, "\blue Wall fully reinforced!") - var/turf/Tsrc = get_turf(src) - Tsrc.ChangeTurf(/turf/simulated/wall/r_wall) - for(var/turf/simulated/wall/r_wall/X in Tsrc.loc) - X.add_hiddenprint(usr) - qdel(src) - return - else - if(S.get_amount() < 1) - return ..() - to_chat(user, "\blue Now reinforcing girders") - if (do_after(user, 60, target = src)) - if(QDELETED(src) || QDELETED(S) || !S.use(1)) - return - to_chat(user, "\blue Girders reinforced!") - new/obj/structure/girder/reinforced( src.loc ) - qdel(src) - return - - if(S.sheettype) - var/M = S.sheettype - if(!anchored) - if(!S.use(2)) - return - to_chat(user, "\blue You create a false wall! Push on it to open or close the passage.") - var/F = text2path("/obj/structure/falsewall/[M]") - new F (src.loc) - qdel(src) - else - if(S.get_amount() < 2) - return ..() - to_chat(user, "\blue Now adding plating...") - if (do_after(user, 40, target = src)) - if(QDELETED(src) || QDELETED(S) || !S.use(2)) - return - to_chat(user, "\blue You added the plating!") - var/turf/Tsrc = get_turf(src) - Tsrc.ChangeTurf(text2path("/turf/simulated/wall/mineral/[M]")) - for(var/turf/simulated/wall/mineral/X in Tsrc.loc) - X.add_hiddenprint(usr) - qdel(src) - return - - add_hiddenprint(usr) - - 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. - user.drop_item() - P.loc = src.loc - to_chat(user, "\blue You fit the pipe into the [src]!") - else - ..() - - - blob_act() - if(prob(40)) - qdel(src) - - - ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - if (prob(30)) - var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal) - new remains(loc) - qdel(src) - return - if(3.0) - if (prob(5)) - var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal) - new remains(loc) - qdel(src) - return - else - return - -/obj/structure/girder/attack_animal(mob/living/simple_animal/M) - if(M.environment_smash) - ..() - M.visible_message("[M] smashes against [src].", \ - "You smash against [src].", \ - "You hear twisting metal.") - playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - health -= M.melee_damage_upper - if(health <= 0) - new /obj/item/stack/sheet/metal(get_turf(src)) - qdel(src) - -/obj/structure/girder/displaced - icon_state = "displaced" - anchored = 0 - health = 50 - -/obj/structure/girder/reinforced - icon_state = "reinforced" - state = 2 - health = 500 - -/obj/structure/cultgirder - icon= 'icons/obj/cult.dmi' - icon_state= "cultgirder" - anchored = 1 - density = 1 - layer = 2.9 - var/health = 250 - - attackby(obj/item/W, mob/user) - if(user.is_busy()) return - if(istype(W, /obj/item/weapon/wrench)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - to_chat(user, "\blue Now disassembling the girder") - if(do_after(user,40,target = src)) - to_chat(user, "\blue You dissasembled the girder!") - new /obj/effect/decal/remains/human(get_turf(src)) - qdel(src) - - else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - to_chat(user, "\blue Now slicing apart the girder") - if(do_after(user,30,target = src)) - to_chat(user, "\blue You slice apart the girder!") - new /obj/effect/decal/remains/human(get_turf(src)) - qdel(src) - - else if(istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) - to_chat(user, "\blue You drill through the girder!") - new /obj/effect/decal/remains/human(get_turf(src)) - qdel(src) - - blob_act() - if(prob(40)) - qdel(src) - - bullet_act(obj/item/projectile/Proj) //No beam check- How else will you destroy the cult girder with silver bullets????? - health -= Proj.damage - ..() - if(health <= 0) - new /obj/item/stack/sheet/metal(get_turf(src)) - qdel(src) - - return - - 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 - else - return +/obj/structure/girder + icon_state = "girder" + anchored = 1 + density = 1 + layer = 2.9 + var/state = 0 + var/health = 200 + + + bullet_act(obj/item/projectile/Proj) + if(istype(Proj, /obj/item/projectile/beam)) + health -= Proj.damage + ..() + if(health <= 0) + new /obj/item/stack/sheet/metal(get_turf(src)) + qdel(src) + + return + + attackby(obj/item/W, mob/user) + if(user.is_busy()) return + if(istype (W,/obj/item/weapon/changeling_hammer)) + var/obj/item/weapon/changeling_hammer/C = W + visible_message("\red [user] has punched \the [src]!") + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + if(C.use_charge(user, 1) && prob(40)) + playsound(loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) + qdel(src) + else if(istype(W, /obj/item/weapon/wrench) && state == 0) + if(anchored && !istype(src,/obj/structure/girder/displaced)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + to_chat(user, "\blue Now disassembling the girder") + if(do_after(user,40,target = src)) + if(!src) return + to_chat(user, "\blue You dissasembled the girder!") + new /obj/item/stack/sheet/metal(get_turf(src)) + qdel(src) + else if(!anchored) + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + to_chat(user, "\blue Now securing the girder") + if(do_after(user,40, target = src)) + to_chat(user, "\blue You secured the girder!") + new/obj/structure/girder( src.loc ) + qdel(src) + + else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + to_chat(user, "\blue Now slicing apart the girder") + if(do_after(user,30,target = src)) + if(!src) return + to_chat(user, "\blue You slice apart the girder!") + new /obj/item/stack/sheet/metal(get_turf(src)) + qdel(src) + + else if(istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) + to_chat(user, "\blue You drill through the girder!") + new /obj/item/stack/sheet/metal(get_turf(src)) + qdel(src) + + else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 && istype(src,/obj/structure/girder/reinforced)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + to_chat(user, "\blue Now unsecuring support struts") + if(do_after(user,40,target = src)) + if(!src) return + to_chat(user, "\blue You unsecured the support struts!") + state = 1 + + else if(istype(W, /obj/item/weapon/wirecutters) && istype(src,/obj/structure/girder/reinforced) && state == 1) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + to_chat(user, "\blue Now removing support struts") + if(do_after(user,40,target = src)) + if(!src) return + to_chat(user, "\blue You removed the support struts!") + new/obj/structure/girder( src.loc ) + qdel(src) + + else if(istype(W, /obj/item/weapon/crowbar) && state == 0 && anchored ) + playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + to_chat(user, "\blue Now dislodging the girder") + if(do_after(user, 40,target = src)) + if(!src) return + to_chat(user, "\blue You dislodged the girder!") + new/obj/structure/girder/displaced( src.loc ) + qdel(src) + + 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(!anchored) + if(!S.use(2)) + return + to_chat(user, "\blue You create a false wall! Push on it to open or close the passage.") + new /obj/structure/falsewall (src.loc) + qdel(src) + else + if(S.get_amount() < 2) + return ..() + to_chat(user, "\blue Now adding plating...") + if (do_after(user, 40, target = src)) + if(QDELETED(src) || QDELETED(S) || !S.use(2)) + return + to_chat(user, "\blue You added the plating!") + var/turf/Tsrc = get_turf(src) + Tsrc.ChangeTurf(/turf/simulated/wall) + for(var/turf/simulated/wall/X in Tsrc.loc) + X.add_hiddenprint(usr) + qdel(src) + return + + if(/obj/item/stack/sheet/plasteel) + if(!anchored) + if(!S.use(2)) + return + to_chat(user, "\blue You create a false wall! Push on it to open or close the passage.") + new /obj/structure/falserwall (src.loc) + qdel(src) + else + if (src.icon_state == "reinforced") //I cant believe someone would actually write this line of code... + if(S.get_amount() < 1) + return ..() + to_chat(user, "\blue Now finalising reinforced wall.") + if(do_after(user, 50, target = src)) + if(QDELETED(src) || QDELETED(S) || !S.use(1)) + return + to_chat(user, "\blue Wall fully reinforced!") + var/turf/Tsrc = get_turf(src) + Tsrc.ChangeTurf(/turf/simulated/wall/r_wall) + for(var/turf/simulated/wall/r_wall/X in Tsrc.loc) + X.add_hiddenprint(usr) + qdel(src) + return + else + if(S.get_amount() < 1) + return ..() + to_chat(user, "\blue Now reinforcing girders") + if (do_after(user, 60, target = src)) + if(QDELETED(src) || QDELETED(S) || !S.use(1)) + return + to_chat(user, "\blue Girders reinforced!") + new/obj/structure/girder/reinforced( src.loc ) + qdel(src) + return + + if(S.sheettype) + var/M = S.sheettype + if(!anchored) + if(!S.use(2)) + return + to_chat(user, "\blue You create a false wall! Push on it to open or close the passage.") + var/F = text2path("/obj/structure/falsewall/[M]") + new F (src.loc) + qdel(src) + else + if(S.get_amount() < 2) + return ..() + to_chat(user, "\blue Now adding plating...") + if (do_after(user, 40, target = src)) + if(QDELETED(src) || QDELETED(S) || !S.use(2)) + return + to_chat(user, "\blue You added the plating!") + var/turf/Tsrc = get_turf(src) + Tsrc.ChangeTurf(text2path("/turf/simulated/wall/mineral/[M]")) + for(var/turf/simulated/wall/mineral/X in Tsrc.loc) + X.add_hiddenprint(usr) + qdel(src) + return + + add_hiddenprint(usr) + + 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. + user.drop_item() + P.loc = src.loc + to_chat(user, "\blue You fit the pipe into the [src]!") + else + ..() + + + blob_act() + if(prob(40)) + qdel(src) + + + ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + if (prob(30)) + var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal) + new remains(loc) + qdel(src) + return + if(3.0) + if (prob(5)) + var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal) + new remains(loc) + qdel(src) + return + else + return + +/obj/structure/girder/attack_animal(mob/living/simple_animal/M) + if(M.environment_smash) + ..() + M.visible_message("[M] smashes against [src].", \ + "You smash against [src].", \ + "You hear twisting metal.") + playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) + health -= M.melee_damage_upper + if(health <= 0) + new /obj/item/stack/sheet/metal(get_turf(src)) + qdel(src) + +/obj/structure/girder/displaced + icon_state = "displaced" + anchored = 0 + health = 50 + +/obj/structure/girder/reinforced + icon_state = "reinforced" + state = 2 + health = 500 + +/obj/structure/cultgirder + icon= 'icons/obj/cult.dmi' + icon_state= "cultgirder" + anchored = 1 + density = 1 + layer = 2.9 + var/health = 250 + + attackby(obj/item/W, mob/user) + if(user.is_busy()) return + if(istype(W, /obj/item/weapon/wrench)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + to_chat(user, "\blue Now disassembling the girder") + if(do_after(user,40,target = src)) + to_chat(user, "\blue You dissasembled the girder!") + new /obj/effect/decal/remains/human(get_turf(src)) + qdel(src) + + else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + to_chat(user, "\blue Now slicing apart the girder") + if(do_after(user,30,target = src)) + to_chat(user, "\blue You slice apart the girder!") + new /obj/effect/decal/remains/human(get_turf(src)) + qdel(src) + + else if(istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) + to_chat(user, "\blue You drill through the girder!") + new /obj/effect/decal/remains/human(get_turf(src)) + qdel(src) + + blob_act() + if(prob(40)) + qdel(src) + + bullet_act(obj/item/projectile/Proj) //No beam check- How else will you destroy the cult girder with silver bullets????? + health -= Proj.damage + ..() + if(health <= 0) + new /obj/item/stack/sheet/metal(get_turf(src)) + qdel(src) + + return + + 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 + else + return diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index eeceb5138694..f8594bc49a9e 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -1,238 +1,238 @@ -/obj/structure/grille - desc = "A flimsy lattice of metal rods, with screws to secure it to the floor." - name = "grille" - icon = 'icons/obj/structures.dmi' - icon_state = "grille" - density = 1 - anchored = 1 - flags = CONDUCT - layer = BELOW_MACHINERY_LAYER - explosion_resistance = 5 - var/health = 10 - var/destroyed = 0 - var/damaged = FALSE - -/obj/structure/grille/ex_act(severity) - qdel(src) - -/obj/structure/grille/blob_act() - qdel(src) - -/obj/structure/grille/meteorhit(obj/M) - qdel(src) - - -/obj/structure/grille/Bumped(atom/user) - if(ismob(user)) shock(user, 70) - - -/obj/structure/grille/attack_paw(mob/user) - attack_hand(user) - -/obj/structure/grille/attack_hand(mob/user) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - user.visible_message("[user] kicks [src].", \ - "You kick [src].", \ - "You hear twisting metal.") - - if(shock(user, 70)) - return - if(HULK in user.mutations) - health -= 5 - else - health -= 1 - healthcheck() - -/obj/structure/grille/attack_alien(mob/user) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - if(istype(user, /mob/living/carbon/alien/larva)) return - - playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - user.visible_message("[user] mangles [src].", \ - "You mangle [src].", \ - "You hear twisting metal.") - - if(!shock(user, 70)) - health -= 5 - healthcheck() - return - -/obj/structure/grille/attack_slime(mob/user) - if(!istype(user, /mob/living/carbon/slime/adult)) return - user.SetNextMove(CLICK_CD_MELEE) - user.do_attack_animation(src) - playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - user.visible_message("[user] smashes against [src].", \ - "You smash against [src].", \ - "You hear twisting metal.") - - health -= rand(2,3) - healthcheck() - return - -/obj/structure/grille/attack_animal(mob/living/simple_animal/M) - if(M.melee_damage_upper == 0) - return - ..() - playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - M.visible_message("[M] smashes against [src].", \ - "You smash against [src].", \ - "You hear twisting metal.") - health -= M.melee_damage_upper - healthcheck() - return - - -/obj/structure/grille/CanPass(atom/movable/mover, turf/target, height=0, 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(30) - else - return !density - -/obj/structure/grille/bullet_act(obj/item/projectile/Proj) - - if(!Proj) return - - //Tasers and the like should not damage grilles. - if(Proj.damage_type == HALLOSS) - return - - src.health -= Proj.damage*0.2 - healthcheck() - return 0 - -/obj/structure/grille/attackby(obj/item/weapon/W, mob/user) - user.SetNextMove(CLICK_CD_INTERACT) - if(iswirecutter(W)) - if(!shock(user, 100)) - playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) - new /obj/item/stack/rods(get_turf(src), 2) - qdel(src) - 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.", \ - "You have [anchored ? "fastened the grille to" : "unfastened the grill from"] the floor.") - return - -//window placing begin - else if( istype(W,/obj/item/stack/sheet/rglass) || istype(W,/obj/item/stack/sheet/glass) ) - var/obj/item/stack/ST = W - if(ST.get_amount() < 1) - return - var/dir_to_set = 1 - if(loc == user.loc) - dir_to_set = user.dir - else - if( ( x == user.x ) || (y == user.y) ) //Only supposed to work for cardinal directions. - if( x == user.x ) - if( y > user.y ) - dir_to_set = 2 - else - dir_to_set = 1 - else if( y == user.y ) - if( x > user.x ) - dir_to_set = 8 - else - dir_to_set = 4 - else - to_chat(user, "You can't reach.") - return //Only works for cardinal direcitons, diagonals aren't supposed to work like this. - for(var/obj/structure/window/WINDOW in loc) - if(WINDOW.dir == dir_to_set) - to_chat(user, "There is already a window facing this way there.") - return - if(user.is_busy()) return - to_chat(user, "You start placing the window.") - if(do_after(user,20,target = src)) - if(QDELETED(src)) - return //Grille destroyed while waiting - for(var/obj/structure/window/WINDOW in loc) - if(WINDOW.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 is already a window facing this way there.") - return - if(!ST.use(1)) - return - var/obj/structure/window/WD - if(istype(W,/obj/item/stack/sheet/rglass)) - WD = new/obj/structure/window/reinforced(loc) //reinforced window - else - WD = new/obj/structure/window/basic(loc) //normal window - WD.dir = dir_to_set - WD.ini_dir = dir_to_set - WD.anchored = 0 - WD.state = 0 - to_chat(user, "You place the [WD] on [src].") - WD.update_icon() - return -//window placing end - - else if(istype(W, /obj/item/weapon/shard)) - health -= W.force * 0.1 - else if(!shock(user, 70)) - playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - switch(W.damtype) - if("fire") - health -= W.force - if("brute") - health -= W.force * 0.1 - healthcheck() - ..() - return - - -/obj/structure/grille/proc/healthcheck() - if(health <= 5) - if(!destroyed && !damaged) - icon_state = "grille_damaged_[rand(1, 4)]" - damaged = 1 - if(health <= 0) - if(!destroyed) - icon_state = "brokengrille" - density = 0 - destroyed = 1 - new /obj/item/stack/rods(get_turf(src)) - - else - if(health <= -6) - new /obj/item/stack/rods(get_turf(src)) - qdel(src) - return - 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, prb) - if(!anchored || destroyed) // anchored/destroyed grilles are never connected - return 0 - if(!prob(prb)) - return 0 - if(!in_range(src, user))//To prevent TK and mech users from getting shocked - return 0 - 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(!destroyed) - if(exposed_temperature > T0C + 1500) - health -= 1 - healthcheck() - ..() +/obj/structure/grille + desc = "A flimsy lattice of metal rods, with screws to secure it to the floor." + name = "grille" + icon = 'icons/obj/structures.dmi' + icon_state = "grille" + density = 1 + anchored = 1 + flags = CONDUCT + layer = BELOW_MACHINERY_LAYER + explosion_resistance = 5 + var/health = 10 + var/destroyed = 0 + var/damaged = FALSE + +/obj/structure/grille/ex_act(severity) + qdel(src) + +/obj/structure/grille/blob_act() + qdel(src) + +/obj/structure/grille/meteorhit(obj/M) + qdel(src) + + +/obj/structure/grille/Bumped(atom/user) + if(ismob(user)) shock(user, 70) + + +/obj/structure/grille/attack_paw(mob/user) + attack_hand(user) + +/obj/structure/grille/attack_hand(mob/user) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) + user.visible_message("[user] kicks [src].", \ + "You kick [src].", \ + "You hear twisting metal.") + + if(shock(user, 70)) + return + if(HULK in user.mutations) + health -= 5 + else + health -= 1 + healthcheck() + +/obj/structure/grille/attack_alien(mob/user) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + if(istype(user, /mob/living/carbon/alien/larva)) return + + playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) + user.visible_message("[user] mangles [src].", \ + "You mangle [src].", \ + "You hear twisting metal.") + + if(!shock(user, 70)) + health -= 5 + healthcheck() + return + +/obj/structure/grille/attack_slime(mob/user) + if(!istype(user, /mob/living/carbon/slime/adult)) return + user.SetNextMove(CLICK_CD_MELEE) + user.do_attack_animation(src) + playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) + user.visible_message("[user] smashes against [src].", \ + "You smash against [src].", \ + "You hear twisting metal.") + + health -= rand(2,3) + healthcheck() + return + +/obj/structure/grille/attack_animal(mob/living/simple_animal/M) + if(M.melee_damage_upper == 0) + return + ..() + playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) + M.visible_message("[M] smashes against [src].", \ + "You smash against [src].", \ + "You hear twisting metal.") + health -= M.melee_damage_upper + healthcheck() + return + + +/obj/structure/grille/CanPass(atom/movable/mover, turf/target, height=0, 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(30) + else + return !density + +/obj/structure/grille/bullet_act(obj/item/projectile/Proj) + + if(!Proj) return + + //Tasers and the like should not damage grilles. + if(Proj.damage_type == HALLOSS) + return + + src.health -= Proj.damage*0.2 + healthcheck() + return 0 + +/obj/structure/grille/attackby(obj/item/weapon/W, mob/user) + user.SetNextMove(CLICK_CD_INTERACT) + if(iswirecutter(W)) + if(!shock(user, 100)) + playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) + new /obj/item/stack/rods(get_turf(src), 2) + qdel(src) + 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.", \ + "You have [anchored ? "fastened the grille to" : "unfastened the grill from"] the floor.") + return + +//window placing begin + else if( istype(W,/obj/item/stack/sheet/rglass) || istype(W,/obj/item/stack/sheet/glass) ) + var/obj/item/stack/ST = W + if(ST.get_amount() < 1) + return + var/dir_to_set = 1 + if(loc == user.loc) + dir_to_set = user.dir + else + if( ( x == user.x ) || (y == user.y) ) //Only supposed to work for cardinal directions. + if( x == user.x ) + if( y > user.y ) + dir_to_set = 2 + else + dir_to_set = 1 + else if( y == user.y ) + if( x > user.x ) + dir_to_set = 8 + else + dir_to_set = 4 + else + to_chat(user, "You can't reach.") + return //Only works for cardinal direcitons, diagonals aren't supposed to work like this. + for(var/obj/structure/window/WINDOW in loc) + if(WINDOW.dir == dir_to_set) + to_chat(user, "There is already a window facing this way there.") + return + if(user.is_busy()) return + to_chat(user, "You start placing the window.") + if(do_after(user,20,target = src)) + if(QDELETED(src)) + return //Grille destroyed while waiting + for(var/obj/structure/window/WINDOW in loc) + if(WINDOW.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 is already a window facing this way there.") + return + if(!ST.use(1)) + return + var/obj/structure/window/WD + if(istype(W,/obj/item/stack/sheet/rglass)) + WD = new/obj/structure/window/reinforced(loc) //reinforced window + else + WD = new/obj/structure/window/basic(loc) //normal window + WD.dir = dir_to_set + WD.ini_dir = dir_to_set + WD.anchored = 0 + WD.state = 0 + to_chat(user, "You place the [WD] on [src].") + WD.update_icon() + return +//window placing end + + else if(istype(W, /obj/item/weapon/shard)) + health -= W.force * 0.1 + else if(!shock(user, 70)) + playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) + switch(W.damtype) + if("fire") + health -= W.force + if("brute") + health -= W.force * 0.1 + healthcheck() + ..() + return + + +/obj/structure/grille/proc/healthcheck() + if(health <= 5) + if(!destroyed && !damaged) + icon_state = "grille_damaged_[rand(1, 4)]" + damaged = 1 + if(health <= 0) + if(!destroyed) + icon_state = "brokengrille" + density = 0 + destroyed = 1 + new /obj/item/stack/rods(get_turf(src)) + + else + if(health <= -6) + new /obj/item/stack/rods(get_turf(src)) + qdel(src) + return + 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, prb) + if(!anchored || destroyed) // anchored/destroyed grilles are never connected + return 0 + if(!prob(prb)) + return 0 + if(!in_range(src, user))//To prevent TK and mech users from getting shocked + return 0 + 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(!destroyed) + if(exposed_temperature > T0C + 1500) + health -= 1 + healthcheck() + ..() diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index ffa23f2d8aa6..092b154471d9 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -1,296 +1,296 @@ -/obj/structure/janitorialcart - name = "janitorial cart" - desc = "The ultimate in janitorial carts! Has space for water, mops, signs, trash bags, and more!" - icon = 'icons/obj/janitor.dmi' - icon_state = "cart" - anchored = 0 - density = 1 - flags = OPENCONTAINER - //copypaste sorry - 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/obj/item/weapon/mop/mymop = null - var/obj/item/weapon/reagent_containers/spray/myspray = null - var/obj/item/device/lightreplacer/myreplacer = null - var/signs = 0 //maximum capacity hardcoded below - - -/obj/structure/janitorialcart/atom_init() - create_reagents(100) - . = ..() - janitorialcart_list += src - - -/obj/structure/janitorialcart/Destroy() - janitorialcart_list -= src - return ..() - -/obj/structure/janitorialcart/examine(mob/user) - ..() - if(src in user) - to_chat(user, "[src] contains [reagents.total_volume] unit\s of liquid!") - -/obj/structure/janitorialcart/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/storage/bag/trash) && !mybag) - user.drop_item() - mybag = I - I.loc = src - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") - - else if(istype(I, /obj/item/weapon/mop)) - if(I.reagents.total_volume < I.reagents.maximum_volume) //if it's not completely soaked we assume they want to wet it, otherwise store it - if(reagents.total_volume < 1) - to_chat(user, "[src] is out of water!") - else - reagents.trans_to(I, 5) // - to_chat(user, "You wet [I] in [src].") - playsound(loc, 'sound/effects/slosh.ogg', 25, 1) - return - if(!mymop) - user.drop_item() - mymop = I - I.loc = src - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") - - else if(istype(I, /obj/item/weapon/reagent_containers/spray) && !myspray) - user.drop_item() - myspray = I - I.loc = src - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") - - else if(istype(I, /obj/item/device/lightreplacer) && !myreplacer) - user.drop_item() - myreplacer = I - I.loc = src - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") - - else if(istype(I, /obj/item/weapon/caution)) - if(signs < 4) - user.drop_item() - I.loc = src - signs++ - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") - else - to_chat(user, "[src] can't hold any more signs.") - - else if(mybag) - mybag.attackby(I, user) - -/obj/structure/janitorialcart/on_reagent_change() - update_icon() - -/obj/structure/janitorialcart/attack_hand(mob/user) - user.set_machine(src) - var/dat - if(mybag) - dat += "[mybag.name]
                    " - if(mymop) - dat += "[mymop.name]
                    " - if(myspray) - dat += "[myspray.name]
                    " - if(myreplacer) - dat += "[myreplacer.name]
                    " - if(signs) - dat += "[signs] sign\s
                    " - var/datum/browser/popup = new(user, "janicart", name, 240, 160) - popup.set_content(dat) - popup.open() - - -/obj/structure/janitorialcart/Topic(href, href_list) - if(!in_range(src, usr)) - return - if(!isliving(usr)) - return - var/mob/living/user = usr - if(href_list["garbage"]) - if(mybag) - user.put_in_hands(mybag) - to_chat(user, "You take [mybag] from [src].") - mybag = null - if(href_list["mop"]) - if(mymop) - user.put_in_hands(mymop) - to_chat(user, "You take [mymop] from [src].") - mymop = null - if(href_list["spray"]) - if(myspray) - user.put_in_hands(myspray) - to_chat(user, "You take [myspray] from [src].") - myspray = null - if(href_list["replacer"]) - if(myreplacer) - user.put_in_hands(myreplacer) - to_chat(user, "You take [myreplacer] from [src].") - myreplacer = null - if(href_list["sign"]) - if(signs) - var/obj/item/weapon/caution/Sign = locate() in src - if(Sign) - user.put_in_hands(Sign) - to_chat(user, "You take \a [Sign] from [src].") - signs-- - else - warning("[src] signs ([signs]) didn't match contents") - signs = 0 - - update_icon() - updateUsrDialog() - - -/obj/structure/janitorialcart/update_icon() - overlays = null - if(mybag) - overlays += "cart_garbage" - if(mymop) - overlays += "cart_mop" - if(myspray) - overlays += "cart_spray" - if(myreplacer) - overlays += "cart_replacer" - if(signs) - overlays += "cart_sign[signs]" - if(reagents.total_volume > 1) - overlays += "cart_water" - - -//old style retardo-cart -/obj/structure/stool/bed/chair/janicart - name = "janicart" - icon = 'icons/obj/vehicles.dmi' - icon_state = "pussywagon" - anchored = 1 - density = 1 - flags = OPENCONTAINER - //copypaste sorry - 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/callme = "pimpin' ride" //how do people refer to it? - - -/obj/structure/stool/bed/chair/janicart/atom_init() - handle_rotation() - create_reagents(100) - . = ..() - - -/obj/structure/stool/bed/chair/janicart/examine(mob/user) - ..() - if(src in user) - to_chat(user, "This [callme] contains [reagents.total_volume] unit\s of water!") - if(mybag) - to_chat(user, "\A [mybag] is hanging on the [callme].") - - -/obj/structure/stool/bed/chair/janicart/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/mop)) - if(reagents.total_volume > 1) - reagents.trans_to(I, 2) - to_chat(user, "You wet [I] in the [callme].") - playsound(loc, 'sound/effects/slosh.ogg', 25, 1) - else - to_chat(user, "This [callme] is out of water!") - else if(istype(I, /obj/item/key)) - to_chat(user, "Hold [I] in one of your hands while you drive this [callme].") - else if(istype(I, /obj/item/weapon/storage/bag/trash)) - to_chat(user, "You hook the trashbag onto the [callme].") - user.drop_item() - I.loc = src - mybag = I - - -/obj/structure/stool/bed/chair/janicart/attack_hand(mob/user) - if(mybag) - mybag.loc = get_turf(user) - user.put_in_hands(mybag) - mybag = null - else - ..() - - -/obj/structure/stool/bed/chair/janicart/relaymove(mob/user, direction) - if(user.stat || user.stunned || user.weakened || user.paralysis) - unbuckle_mob() - if(istype(user.l_hand, /obj/item/key) || istype(user.r_hand, /obj/item/key)) - step(src, direction) - update_mob() - handle_rotation() - else - to_chat(user, "You'll need the keys in one of your hands to drive this [callme].") - - -/obj/structure/stool/bed/chair/janicart/Move() - ..() - if(buckled_mob) - if(buckled_mob.buckled == src) - buckled_mob.loc = loc - - -/obj/structure/stool/bed/chair/janicart/post_buckle_mob(mob/living/M) - update_mob() - return ..() - - -/obj/structure/stool/bed/chair/janicart/unbuckle_mob() - var/mob/living/M = ..() - if(M) - M.pixel_x = 0 - M.pixel_y = 0 - return M - - -/obj/structure/stool/bed/chair/janicart/handle_rotation() - if(dir == SOUTH) - layer = FLY_LAYER - else - layer = OBJ_LAYER - - if(buckled_mob) - if(buckled_mob.loc != loc) - buckled_mob.buckled = null //Temporary, so Move() succeeds. - buckled_mob.buckled = src //Restoring - - update_mob() - - -/obj/structure/stool/bed/chair/janicart/proc/update_mob() - if(buckled_mob) - buckled_mob.dir = dir - switch(dir) - if(SOUTH) - buckled_mob.pixel_x = 0 - buckled_mob.pixel_y = 7 - if(WEST) - buckled_mob.pixel_x = 13 - buckled_mob.pixel_y = 7 - if(NORTH) - buckled_mob.pixel_x = 0 - buckled_mob.pixel_y = 4 - if(EAST) - buckled_mob.pixel_x = -13 - buckled_mob.pixel_y = 7 - - -/obj/structure/stool/bed/chair/janicart/bullet_act(obj/item/projectile/Proj) - if(buckled_mob) - if(prob(85)) - return buckled_mob.bullet_act(Proj) - visible_message("[Proj] ricochets off the [callme]!") - - -/obj/item/key - name = "key" - desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"." - icon = 'icons/obj/vehicles.dmi' - icon_state = "keys" - w_class = 1 +/obj/structure/janitorialcart + name = "janitorial cart" + desc = "The ultimate in janitorial carts! Has space for water, mops, signs, trash bags, and more!" + icon = 'icons/obj/janitor.dmi' + icon_state = "cart" + anchored = 0 + density = 1 + flags = OPENCONTAINER + //copypaste sorry + 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/obj/item/weapon/mop/mymop = null + var/obj/item/weapon/reagent_containers/spray/myspray = null + var/obj/item/device/lightreplacer/myreplacer = null + var/signs = 0 //maximum capacity hardcoded below + + +/obj/structure/janitorialcart/atom_init() + create_reagents(100) + . = ..() + janitorialcart_list += src + + +/obj/structure/janitorialcart/Destroy() + janitorialcart_list -= src + return ..() + +/obj/structure/janitorialcart/examine(mob/user) + ..() + if(src in user) + to_chat(user, "[src] contains [reagents.total_volume] unit\s of liquid!") + +/obj/structure/janitorialcart/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/storage/bag/trash) && !mybag) + user.drop_item() + mybag = I + I.loc = src + update_icon() + updateUsrDialog() + to_chat(user, "You put [I] into [src].") + + else if(istype(I, /obj/item/weapon/mop)) + if(I.reagents.total_volume < I.reagents.maximum_volume) //if it's not completely soaked we assume they want to wet it, otherwise store it + if(reagents.total_volume < 1) + to_chat(user, "[src] is out of water!
                    ") + else + reagents.trans_to(I, 5) // + to_chat(user, "You wet [I] in [src].") + playsound(loc, 'sound/effects/slosh.ogg', 25, 1) + return + if(!mymop) + user.drop_item() + mymop = I + I.loc = src + update_icon() + updateUsrDialog() + to_chat(user, "You put [I] into [src].") + + else if(istype(I, /obj/item/weapon/reagent_containers/spray) && !myspray) + user.drop_item() + myspray = I + I.loc = src + update_icon() + updateUsrDialog() + to_chat(user, "You put [I] into [src].") + + else if(istype(I, /obj/item/device/lightreplacer) && !myreplacer) + user.drop_item() + myreplacer = I + I.loc = src + update_icon() + updateUsrDialog() + to_chat(user, "You put [I] into [src].") + + else if(istype(I, /obj/item/weapon/caution)) + if(signs < 4) + user.drop_item() + I.loc = src + signs++ + update_icon() + updateUsrDialog() + to_chat(user, "You put [I] into [src].") + else + to_chat(user, "[src] can't hold any more signs.") + + else if(mybag) + mybag.attackby(I, user) + +/obj/structure/janitorialcart/on_reagent_change() + update_icon() + +/obj/structure/janitorialcart/attack_hand(mob/user) + user.set_machine(src) + var/dat + if(mybag) + dat += "[mybag.name]
                    " + if(mymop) + dat += "[mymop.name]
                    " + if(myspray) + dat += "[myspray.name]
                    " + if(myreplacer) + dat += "[myreplacer.name]
                    " + if(signs) + dat += "[signs] sign\s
                    " + var/datum/browser/popup = new(user, "janicart", name, 240, 160) + popup.set_content(dat) + popup.open() + + +/obj/structure/janitorialcart/Topic(href, href_list) + if(!in_range(src, usr)) + return + if(!isliving(usr)) + return + var/mob/living/user = usr + if(href_list["garbage"]) + if(mybag) + user.put_in_hands(mybag) + to_chat(user, "You take [mybag] from [src].") + mybag = null + if(href_list["mop"]) + if(mymop) + user.put_in_hands(mymop) + to_chat(user, "You take [mymop] from [src].") + mymop = null + if(href_list["spray"]) + if(myspray) + user.put_in_hands(myspray) + to_chat(user, "You take [myspray] from [src].") + myspray = null + if(href_list["replacer"]) + if(myreplacer) + user.put_in_hands(myreplacer) + to_chat(user, "You take [myreplacer] from [src].") + myreplacer = null + if(href_list["sign"]) + if(signs) + var/obj/item/weapon/caution/Sign = locate() in src + if(Sign) + user.put_in_hands(Sign) + to_chat(user, "You take \a [Sign] from [src].") + signs-- + else + warning("[src] signs ([signs]) didn't match contents") + signs = 0 + + update_icon() + updateUsrDialog() + + +/obj/structure/janitorialcart/update_icon() + overlays = null + if(mybag) + overlays += "cart_garbage" + if(mymop) + overlays += "cart_mop" + if(myspray) + overlays += "cart_spray" + if(myreplacer) + overlays += "cart_replacer" + if(signs) + overlays += "cart_sign[signs]" + if(reagents.total_volume > 1) + overlays += "cart_water" + + +//old style retardo-cart +/obj/structure/stool/bed/chair/janicart + name = "janicart" + icon = 'icons/obj/vehicles.dmi' + icon_state = "pussywagon" + anchored = 1 + density = 1 + flags = OPENCONTAINER + //copypaste sorry + 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/callme = "pimpin' ride" //how do people refer to it? + + +/obj/structure/stool/bed/chair/janicart/atom_init() + handle_rotation() + create_reagents(100) + . = ..() + + +/obj/structure/stool/bed/chair/janicart/examine(mob/user) + ..() + if(src in user) + to_chat(user, "This [callme] contains [reagents.total_volume] unit\s of water!") + if(mybag) + to_chat(user, "\A [mybag] is hanging on the [callme].") + + +/obj/structure/stool/bed/chair/janicart/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/mop)) + if(reagents.total_volume > 1) + reagents.trans_to(I, 2) + to_chat(user, "You wet [I] in the [callme].") + playsound(loc, 'sound/effects/slosh.ogg', 25, 1) + else + to_chat(user, "This [callme] is out of water!") + else if(istype(I, /obj/item/key)) + to_chat(user, "Hold [I] in one of your hands while you drive this [callme].") + else if(istype(I, /obj/item/weapon/storage/bag/trash)) + to_chat(user, "You hook the trashbag onto the [callme].") + user.drop_item() + I.loc = src + mybag = I + + +/obj/structure/stool/bed/chair/janicart/attack_hand(mob/user) + if(mybag) + mybag.loc = get_turf(user) + user.put_in_hands(mybag) + mybag = null + else + ..() + + +/obj/structure/stool/bed/chair/janicart/relaymove(mob/user, direction) + if(user.stat || user.stunned || user.weakened || user.paralysis) + unbuckle_mob() + if(istype(user.l_hand, /obj/item/key) || istype(user.r_hand, /obj/item/key)) + step(src, direction) + update_mob() + handle_rotation() + else + to_chat(user, "You'll need the keys in one of your hands to drive this [callme].") + + +/obj/structure/stool/bed/chair/janicart/Move() + ..() + if(buckled_mob) + if(buckled_mob.buckled == src) + buckled_mob.loc = loc + + +/obj/structure/stool/bed/chair/janicart/post_buckle_mob(mob/living/M) + update_mob() + return ..() + + +/obj/structure/stool/bed/chair/janicart/unbuckle_mob() + var/mob/living/M = ..() + if(M) + M.pixel_x = 0 + M.pixel_y = 0 + return M + + +/obj/structure/stool/bed/chair/janicart/handle_rotation() + if(dir == SOUTH) + layer = FLY_LAYER + else + layer = OBJ_LAYER + + if(buckled_mob) + if(buckled_mob.loc != loc) + buckled_mob.buckled = null //Temporary, so Move() succeeds. + buckled_mob.buckled = src //Restoring + + update_mob() + + +/obj/structure/stool/bed/chair/janicart/proc/update_mob() + if(buckled_mob) + buckled_mob.dir = dir + switch(dir) + if(SOUTH) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 7 + if(WEST) + buckled_mob.pixel_x = 13 + buckled_mob.pixel_y = 7 + if(NORTH) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 4 + if(EAST) + buckled_mob.pixel_x = -13 + buckled_mob.pixel_y = 7 + + +/obj/structure/stool/bed/chair/janicart/bullet_act(obj/item/projectile/Proj) + if(buckled_mob) + if(prob(85)) + return buckled_mob.bullet_act(Proj) + visible_message("[Proj] ricochets off the [callme]!") + + +/obj/item/key + name = "key" + desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"." + icon = 'icons/obj/vehicles.dmi' + icon_state = "keys" + w_class = 1 diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index 258650e86f78..7baaaeac9c96 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -1,125 +1,125 @@ -//////Kitchen Spike - -/obj/structure/kitchenspike_frame - name = "meatspike frame" - icon = 'icons/obj/kitchen.dmi' - icon_state = "spikeframe" - desc = "The frame of a meat spike." - density = TRUE - anchored = FALSE - -/obj/structure/kitchenspike_frame/attackby(obj/item/I, mob/user) - add_fingerprint(user) - if(default_unfasten_wrench(user, I)) - return - else if(anchored && istype(I, /obj/item/stack/rods)) - var/obj/item/stack/rods/R = I - if(R.use(4)) - to_chat(user, "You add spikes to the frame.") - var/obj/F = new /obj/structure/kitchenspike(src.loc) - transfer_fingerprints_to(F) - qdel(src) - else - ..() - -/obj/structure/kitchenspike - name = "meatspike" - icon = 'icons/obj/kitchen.dmi' - icon_state = "spike" - desc = "A spike for collecting meat from animals." - density = FALSE - anchored = TRUE - can_buckle = TRUE - buckle_lying = FALSE - -/obj/structure/kitchenspike/attack_paw(mob/user) - return attack_hand(user) - -/obj/structure/kitchenspike/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/crowbar)) - if(!src.buckled_mob) - if(user.is_busy()) return - playsound(loc, 'sound/items/Crowbar.ogg', 100, 1) - if(do_after(user, 20, target = src)) - to_chat(user, "You pry the spikes out of the frame.") - new /obj/item/stack/rods(loc, 4) - var/obj/F = new /obj/structure/kitchenspike_frame(src.loc,) - transfer_fingerprints_to(F) - qdel(src) - else - to_chat(user, "You can't do that while something's on the spike!") - else if(istype(I, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = I - if(istype(G.affecting, /mob/living)) - if(!buckled_mob) - if(do_mob(user, src, 120)) - if(buckled_mob) //to prevent spam/queing up attacks - return - if(G.affecting.buckled) - return - var/mob/living/H = G.affecting - playsound(src.loc, "sound/effects/splat.ogg", 25, 1) - H.visible_message("[user] slams [G.affecting] onto the meat spike!", \ - "[user] slams you onto the meat spike!", \ - "You hear a squishy wet noise.") - H.forceMove(src.loc) - H.emote("scream") - if(istype(H, /mob/living/carbon)) //So you don't get human blood when you spike a giant spidere - var/turf/simulated/pos = get_turf(H) - pos.add_blood_floor(H) - H.adjustBruteLoss(30) - H.buckled = src - H.dir = 2 - buckled_mob = H - var/matrix/m = matrix(H.transform) - m.Turn(180) - animate(H, transform = m, time = 3) - H.pixel_y = H.get_standard_pixel_y_offset() - qdel(G) - else - to_chat(user, "You can't use that on the spike!") - else - ..() - -/obj/structure/kitchenspike/user_buckle_mob(mob/living/M, mob/living/user) //Don't want them getting put on the rack other than by spiking - return - -/obj/structure/kitchenspike/user_unbuckle_mob(mob/living/carbon/human/user) - if(buckled_mob) - var/mob/living/L = buckled_mob - if(L != user) - if(user.is_busy()) return - L.visible_message(\ - "[user.name] tries to pull [L.name] free of the [src]!",\ - "[user.name] is trying to pull you off the [src], opening up fresh wounds!",\ - "You hear a squishy wet noise.") - if(!do_after(user, 300, target = user)) - if(L && L.buckled) - L.visible_message(\ - "[user.name] fails to free [L.name]!",\ - "[user.name] fails to pull you off of the [src].") - return - - else - L.visible_message(\ - "[L.name] struggles to break free from the [src]!",\ - "You struggle to break free from the [src], exacerbating your wounds! (Stay still for two minutes.)",\ - "You hear a wet squishing noise..") - L.adjustBruteLoss(15) - if(!do_after(L, 1200, target = src)) - if(L && L.buckled) - to_chat(L, "You fail to free yourself!") - return - - if(!L.buckled) - return - - var/matrix/m = matrix(L.transform) - m.Turn(180) - animate(L, transform = m, time = 3) - L.pixel_y = L.get_standard_pixel_y_offset() - L.adjustBruteLoss(15) - visible_message(text("[L] falls free of the [src]!")) - unbuckle_mob() - L.emote("scream") - L.AdjustWeakened(10) +//////Kitchen Spike + +/obj/structure/kitchenspike_frame + name = "meatspike frame" + icon = 'icons/obj/kitchen.dmi' + icon_state = "spikeframe" + desc = "The frame of a meat spike." + density = TRUE + anchored = FALSE + +/obj/structure/kitchenspike_frame/attackby(obj/item/I, mob/user) + add_fingerprint(user) + if(default_unfasten_wrench(user, I)) + return + else if(anchored && istype(I, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = I + if(R.use(4)) + to_chat(user, "You add spikes to the frame.") + var/obj/F = new /obj/structure/kitchenspike(src.loc) + transfer_fingerprints_to(F) + qdel(src) + else + ..() + +/obj/structure/kitchenspike + name = "meatspike" + icon = 'icons/obj/kitchen.dmi' + icon_state = "spike" + desc = "A spike for collecting meat from animals." + density = FALSE + anchored = TRUE + can_buckle = TRUE + buckle_lying = FALSE + +/obj/structure/kitchenspike/attack_paw(mob/user) + return attack_hand(user) + +/obj/structure/kitchenspike/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/crowbar)) + if(!src.buckled_mob) + if(user.is_busy()) return + playsound(loc, 'sound/items/Crowbar.ogg', 100, 1) + if(do_after(user, 20, target = src)) + to_chat(user, "You pry the spikes out of the frame.") + new /obj/item/stack/rods(loc, 4) + var/obj/F = new /obj/structure/kitchenspike_frame(src.loc,) + transfer_fingerprints_to(F) + qdel(src) + else + to_chat(user, "You can't do that while something's on the spike!") + else if(istype(I, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = I + if(istype(G.affecting, /mob/living)) + if(!buckled_mob) + if(do_mob(user, src, 120)) + if(buckled_mob) //to prevent spam/queing up attacks + return + if(G.affecting.buckled) + return + var/mob/living/H = G.affecting + playsound(src.loc, "sound/effects/splat.ogg", 25, 1) + H.visible_message("[user] slams [G.affecting] onto the meat spike!", \ + "[user] slams you onto the meat spike!", \ + "You hear a squishy wet noise.") + H.forceMove(src.loc) + H.emote("scream") + if(istype(H, /mob/living/carbon)) //So you don't get human blood when you spike a giant spidere + var/turf/simulated/pos = get_turf(H) + pos.add_blood_floor(H) + H.adjustBruteLoss(30) + H.buckled = src + H.dir = 2 + buckled_mob = H + var/matrix/m = matrix(H.transform) + m.Turn(180) + animate(H, transform = m, time = 3) + H.pixel_y = H.get_standard_pixel_y_offset() + qdel(G) + else + to_chat(user, "You can't use that on the spike!") + else + ..() + +/obj/structure/kitchenspike/user_buckle_mob(mob/living/M, mob/living/user) //Don't want them getting put on the rack other than by spiking + return + +/obj/structure/kitchenspike/user_unbuckle_mob(mob/living/carbon/human/user) + if(buckled_mob) + var/mob/living/L = buckled_mob + if(L != user) + if(user.is_busy()) return + L.visible_message(\ + "[user.name] tries to pull [L.name] free of the [src]!",\ + "[user.name] is trying to pull you off the [src], opening up fresh wounds!",\ + "You hear a squishy wet noise.") + if(!do_after(user, 300, target = user)) + if(L && L.buckled) + L.visible_message(\ + "[user.name] fails to free [L.name]!",\ + "[user.name] fails to pull you off of the [src].") + return + + else + L.visible_message(\ + "[L.name] struggles to break free from the [src]!",\ + "You struggle to break free from the [src], exacerbating your wounds! (Stay still for two minutes.)",\ + "You hear a wet squishing noise..") + L.adjustBruteLoss(15) + if(!do_after(L, 1200, target = src)) + if(L && L.buckled) + to_chat(L, "You fail to free yourself!") + return + + if(!L.buckled) + return + + var/matrix/m = matrix(L.transform) + m.Turn(180) + animate(L, transform = m, time = 3) + L.pixel_y = L.get_standard_pixel_y_offset() + L.adjustBruteLoss(15) + visible_message(text("[L] falls free of the [src]!")) + unbuckle_mob() + L.emote("scream") + L.AdjustWeakened(10) diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index 75c58d32f3c6..18af4081a6e3 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -1,81 +1,81 @@ -/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/atom_init() - ladder_list += src - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/structure/ladder/atom_init_late() - for(var/obj/structure/ladder/L in ladder_list) - 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/Destroy() - ladder_list -= src - return ..() - -/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) - 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) - return attack_hand(user) - -/obj/structure/ladder/attackby(obj/item/weapon/W, mob/user) - return attack_hand(user) +/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/atom_init() + ladder_list += src + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/structure/ladder/atom_init_late() + for(var/obj/structure/ladder/L in ladder_list) + 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/Destroy() + ladder_list -= src + return ..() + +/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) + 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) + return attack_hand(user) + +/obj/structure/ladder/attackby(obj/item/weapon/W, mob/user) + return attack_hand(user) diff --git a/code/game/objects/structures/lamarr_cage.dm b/code/game/objects/structures/lamarr_cage.dm index 5e5e2e6c4881..1a499228c023 100644 --- a/code/game/objects/structures/lamarr_cage.dm +++ b/code/game/objects/structures/lamarr_cage.dm @@ -1,101 +1,101 @@ -/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) - new /obj/item/weapon/shard( src.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(obj/item/projectile/Proj) - health -= Proj.damage - ..() - src.healthcheck() - return - - -/obj/structure/lamarr/blob_act() - if (prob(75)) - new /obj/item/weapon/shard( src.loc ) - Break() - qdel(src) - - -/obj/structure/lamarr/meteorhit(obj/O) - new /obj/item/weapon/shard( src.loc ) - Break() - qdel(src) - - -/obj/structure/lamarr/proc/healthcheck() - if (src.health <= 0) - if (!( src.destroyed )) - src.density = 0 - src.destroyed = 1 - new /obj/item/weapon/shard( src.loc ) - playsound(src, "shatter", 70, 1) - Break() - else - playsound(src.loc, '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, mob/user) - src.health -= W.force - src.healthcheck() - ..() - -/obj/structure/lamarr/attack_paw(mob/user) - return src.attack_hand(user) - -/obj/structure/lamarr/attack_hand(mob/user) - if (src.destroyed) - return - else - user.SetNextMove(CLICK_CD_MELEE) - visible_message("[user] kicks the lab cage.") - 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 - gender = FEMALE - -/obj/item/clothing/mask/facehugger/lamarr/atom_init_late()//to prevent deleting it if aliums are disabled - return +/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) + new /obj/item/weapon/shard( src.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(obj/item/projectile/Proj) + health -= Proj.damage + ..() + src.healthcheck() + return + + +/obj/structure/lamarr/blob_act() + if (prob(75)) + new /obj/item/weapon/shard( src.loc ) + Break() + qdel(src) + + +/obj/structure/lamarr/meteorhit(obj/O) + new /obj/item/weapon/shard( src.loc ) + Break() + qdel(src) + + +/obj/structure/lamarr/proc/healthcheck() + if (src.health <= 0) + if (!( src.destroyed )) + src.density = 0 + src.destroyed = 1 + new /obj/item/weapon/shard( src.loc ) + playsound(src, "shatter", 70, 1) + Break() + else + playsound(src.loc, '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, mob/user) + src.health -= W.force + src.healthcheck() + ..() + +/obj/structure/lamarr/attack_paw(mob/user) + return src.attack_hand(user) + +/obj/structure/lamarr/attack_hand(mob/user) + if (src.destroyed) + return + else + user.SetNextMove(CLICK_CD_MELEE) + visible_message("[user] kicks the lab cage.") + 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 + gender = FEMALE + +/obj/item/clothing/mask/facehugger/lamarr/atom_init_late()//to prevent deleting it if aliums are disabled + return diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index b464e994a059..dddde1fc54fc 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -1,82 +1,82 @@ -/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 - plane = FLOOR_PLANE - // flags = CONDUCT - -/obj/structure/lattice/atom_init() - . = ..() - if(!istype(loc, /turf/space)) - return INITIALIZE_HINT_QDEL - for(var/obj/structure/lattice/LAT in loc) - if(LAT != src) - qdel(LAT) - icon = 'icons/obj/smoothlattice.dmi' - icon_state = "latticeblank" - updateOverlays() - for (var/dir in cardinal) - var/obj/structure/lattice/L = locate(/obj/structure/lattice, get_step(src, dir)) - if(L) - L.updateOverlays() - -/obj/structure/lattice/Destroy() - for (var/dir in cardinal) - var/obj/structure/lattice/L = locate(/obj/structure/lattice, get_step(src, dir)) - if(L) - L.updateOverlays(loc) - return ..() - -/obj/structure/lattice/blob_act() - qdel(src) - return - -/obj/structure/lattice/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - qdel(src) - return - if(3.0) - return - else - return - -/obj/structure/lattice/attackby(obj/item/C, mob/user) - - if(istype(C, /obj/item/stack/tile/plasteel) || istype(C, /obj/item/stack/rods)) - var/turf/T = get_turf(src) - T.attackby(C, user) //BubbleWrap - hand this off to the underlying turf instead - return - if (istype(C, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = C - if(WT.remove_fuel(0, user)) - to_chat(user, "\blue Slicing lattice joints ...") - new /obj/item/stack/rods(loc) - qdel(src) - - return - -/obj/structure/lattice/proc/updateOverlays() - //if(!(istype(src.loc, /turf/space))) - // qdel(src) - spawn(1) - overlays = list() - - var/dir_sum = 0 - - for (var/direction in cardinal) - if(locate(/obj/structure/lattice, get_step(src, direction))) - dir_sum += direction - else - if(!(istype(get_step(src, direction), /turf/space))) - dir_sum += direction - - icon_state = "lattice[dir_sum]" - return +/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 + plane = FLOOR_PLANE + // flags = CONDUCT + +/obj/structure/lattice/atom_init() + . = ..() + if(!istype(loc, /turf/space)) + return INITIALIZE_HINT_QDEL + for(var/obj/structure/lattice/LAT in loc) + if(LAT != src) + qdel(LAT) + icon = 'icons/obj/smoothlattice.dmi' + icon_state = "latticeblank" + updateOverlays() + for (var/dir in cardinal) + var/obj/structure/lattice/L = locate(/obj/structure/lattice, get_step(src, dir)) + if(L) + L.updateOverlays() + +/obj/structure/lattice/Destroy() + for (var/dir in cardinal) + var/obj/structure/lattice/L = locate(/obj/structure/lattice, get_step(src, dir)) + if(L) + L.updateOverlays(loc) + return ..() + +/obj/structure/lattice/blob_act() + qdel(src) + return + +/obj/structure/lattice/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + qdel(src) + return + if(3.0) + return + else + return + +/obj/structure/lattice/attackby(obj/item/C, mob/user) + + if(istype(C, /obj/item/stack/tile/plasteel) || istype(C, /obj/item/stack/rods)) + var/turf/T = get_turf(src) + T.attackby(C, user) //BubbleWrap - hand this off to the underlying turf instead + return + if (istype(C, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = C + if(WT.remove_fuel(0, user)) + to_chat(user, "\blue Slicing lattice joints ...") + new /obj/item/stack/rods(loc) + qdel(src) + + return + +/obj/structure/lattice/proc/updateOverlays() + //if(!(istype(src.loc, /turf/space))) + // qdel(src) + spawn(1) + overlays = list() + + var/dir_sum = 0 + + for (var/direction in cardinal) + if(locate(/obj/structure/lattice, get_step(src, direction))) + dir_sum += direction + else + if(!(istype(get_step(src, direction), /turf/space))) + dir_sum += direction + + icon_state = "lattice[dir_sum]" + return diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index 04f734ad74da..304bc001fdf6 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -1,335 +1,335 @@ -/obj/structure/mineral_door - desc = "It opens and closes. What a surprise!" - density = TRUE - anchored = TRUE - opacity = TRUE - - icon = 'icons/obj/doors/mineral_doors.dmi' - - var/operating_sound = 'sound/effects/stonedoor_openclose.ogg' - var/close_state = TRUE - var/isSwitchingStates = FALSE - var/sheetAmount = 7 - var/health = 100 - - var/sheetType - -/obj/structure/mineral_door/atom_init() - . = ..() - update_nearby_tiles(need_rebuild = TRUE) - -/obj/structure/mineral_door/Destroy() - update_nearby_tiles() - return ..() - -/obj/structure/mineral_door/Bumped(atom/M) - if(close_state) - if(ismob(M)) - var/mob/user = M - if(DoorChecks() && MobChecks(user)) - add_fingerprint(user) - Open() - else if(istype(M, /obj/mecha) && DoorChecks()) - Open() - -/obj/structure/mineral_door/attack_ai(mob/user) - if(isrobot(user) && get_dist(user, src) <= 1) - return attack_hand(user) - -/obj/structure/mineral_door/attack_paw(mob/user) - return attack_hand(user) - -/obj/structure/mineral_door/attack_hand(mob/user) - if(DoorChecks() && MobChecks(user)) - add_fingerprint(user) - SwitchState() - -/obj/structure/mineral_door/CanPass(atom/movable/mover, turf/target, height = 0, air_group = 0) - if(air_group) - return FALSE - if(istype(mover, /obj/effect/beam)) - return !opacity - return !density - -/obj/structure/mineral_door/proc/DoorChecks() - return (!isSwitchingStates && anchored) - -/obj/structure/mineral_door/proc/MobChecks(mob/user) - if(!user.small) - if(iscarbon(user)) - var/mob/living/carbon/C = user - if(!C.handcuffed) - return TRUE - else - return TRUE - return FALSE - -/obj/structure/mineral_door/proc/SwitchState() - if(close_state) - Open() - else - Close() - -/obj/structure/mineral_door/proc/Open() - isSwitchingStates = TRUE - playsound(src, operating_sound, 100, 1) - flick("[initial(icon_state)]_opening", src) - sleep(10) - density = FALSE - set_opacity(FALSE) - close_state = FALSE - update_icon() - isSwitchingStates = FALSE - update_nearby_tiles() - -/obj/structure/mineral_door/proc/Close() - isSwitchingStates = TRUE - playsound(src, operating_sound, 100, 1) - flick("[initial(icon_state)]_closing", src) - sleep(10) - density = TRUE - set_opacity(TRUE) - close_state = TRUE - update_icon() - isSwitchingStates = FALSE - update_nearby_tiles() - -/obj/structure/mineral_door/update_icon() - if(close_state) - icon_state = initial(icon_state) - else - icon_state = "[initial(icon_state)]_open" - -/obj/structure/mineral_door/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/pickaxe) && !(istype(src, /obj/structure/mineral_door/wood) || istype(src, /obj/structure/mineral_door/metal))) - if(user.is_busy()) - return - var/obj/item/weapon/pickaxe/digTool = W - to_chat(user, "You start digging the [name].") - if(do_after(user, digTool.digspeed, target = src)) - to_chat(user, "You finished digging!") - Dismantle() - - else if(istype(W, /obj/item/weapon/wrench) && !istype(src, /obj/structure/mineral_door/resin)) - if(user.is_busy()) - return - playsound(src, 'sound/items/Ratchet.ogg', 100, 1) - if(anchored) - to_chat(user, "You start dissassembling the [name].") - if(do_after(user, 40, target = src)) - to_chat(user, "You dissassembled the [name]!") - anchored = FALSE - name = "disassembled [name]" - desc = "Needs assembly." - icon_state = "[initial(icon_state)]_disassembled" - density = FALSE - set_opacity(FALSE) - else - to_chat(user, "You start assembling the [name]!") - if(do_after(user, 40, target = src)) - to_chat(user, "You assembled the [name]!") - anchored = TRUE - name = initial(name) - desc = initial(desc) - density = TRUE - icon_state = initial(icon_state) - if(!istype(src, /obj/structure/mineral_door/transparent)) - set_opacity(TRUE) - - else - health -= W.force - CheckHealth() - return ..() - -/obj/structure/mineral_door/proc/CheckHealth() - if(health <= 0) - Dismantle(TRUE) - -/obj/structure/mineral_door/proc/Dismantle(devastated = FALSE) - var/turf/T = get_turf(src) - if(!devastated) - for(var/i in 1 to sheetAmount) - new sheetType(T) - else - for(var/i in 3 to sheetAmount) - new sheetType(T) - qdel(src) - -/obj/structure/mineral_door/ex_act(severity = 1) - switch(severity) - if(1) - Dismantle(TRUE) - if(2) - if(prob(20)) - Dismantle(TRUE) - else - health-- - CheckHealth() - if(3) - health -= 0.1 - CheckHealth() - -/obj/structure/mineral_door/metal - name = "metal door" - icon_state = "metal" - health = 300 - sheetType = /obj/item/stack/sheet/metal - -/obj/structure/mineral_door/metal/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/weldingtool)) - if(user.is_busy()) - return - var/obj/item/weapon/weldingtool/WT = W - if(!WT.isOn()) - to_chat(user, "The welding tool needs to be on to start this task!") - return - if(WT.remove_fuel(0, user)) - playsound(src, 'sound/items/Welder2.ogg', 100, 1) - to_chat(user, "You start dissassembling the [name] to the metal sheets.") - if(do_after(user, 60, target = src)) - to_chat(user, "You dissassembled the [name] to the metal sheets!") - Dismantle() - else - to_chat(user, "You need more welding fuel!") - return - ..() - -/obj/structure/mineral_door/silver - name = "silver door" - icon_state = "silver" - health = 300 - sheetType = /obj/item/stack/sheet/mineral/silver - -/obj/structure/mineral_door/gold - name = "golden door" - icon_state = "gold" - sheetType = /obj/item/stack/sheet/mineral/gold - -/obj/structure/mineral_door/uranium - name = "uranium door" - icon_state = "uranium" - health = 300 - light_range = 2 - sheetType = /obj/item/stack/sheet/mineral/uranium - -/obj/structure/mineral_door/sandstone - name = "sandstone door" - icon_state = "sandstone" - health = 50 - sheetType = /obj/item/stack/sheet/mineral/sandstone - -/obj/structure/mineral_door/transparent - opacity = FALSE - -/obj/structure/mineral_door/transparent/Close() - ..() - opacity = FALSE - -/obj/structure/mineral_door/transparent/phoron - name = "phoron door" - icon_state = "phoron" - sheetType = /obj/item/stack/sheet/mineral/phoron - -/obj/structure/mineral_door/transparent/phoron/attackby(obj/item/weapon/W, mob/user) - if(istype(W,/obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - TemperatureAct(100) - ..() - -/obj/structure/mineral_door/transparent/phoron/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 300) - TemperatureAct(exposed_temperature) - -/obj/structure/mineral_door/transparent/phoron/proc/TemperatureAct(temperature) - for(var/turf/simulated/floor/target_tile in range(2, loc)) - - var/phoronToDeduce = temperature * 0.1 - - target_tile.assume_gas("phoron", phoronToDeduce) - target_tile.hotspot_expose(temperature, 400) - - health -= phoronToDeduce * 0.01 - CheckHealth() - -/obj/structure/mineral_door/transparent/diamond - name = "diamond door" - icon_state = "diamond" - health = 1000 - sheetType = /obj/item/stack/sheet/mineral/diamond - -/obj/structure/mineral_door/wood - name = "wooden door" - icon_state = "wood" - sheetType = /obj/item/stack/sheet/wood - operating_sound = 'sound/effects/doorcreaky.ogg' - -/obj/structure/mineral_door/wood/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/twohanded/fireaxe)) - if(user.is_busy()) - return - playsound(src, 'sound/items/Axe.ogg', 100, 1) - to_chat(user, "You start cutting the [name] with the axe.") - if(do_after(user, 40, target = src)) - to_chat(user, "You finished cutting the [name]!") - Dismantle() - return - ..() - -/obj/structure/mineral_door/resin - icon = 'icons/mob/alien.dmi' - operating_sound = 'sound/effects/attackblob.ogg' - icon_state = "resin" - health = 150 - var/close_delay = 100 - -/obj/structure/mineral_door/resin/atom_init() - var/turf/T = get_turf(loc) - if(T) - T.blocks_air = TRUE - . = ..() - -/obj/structure/mineral_door/resin/Destroy() - var/turf/T = get_turf(loc) - if(T) - T.blocks_air = FALSE - return ..() - -/obj/structure/mineral_door/resin/Bumped(atom/M) - if(isalien(M) && !isSwitchingStates) - add_fingerprint(M) - Open() - -/obj/structure/mineral_door/resin/Open() - ..() - addtimer(CALLBACK(src, .proc/TryToClose), close_delay) - -/obj/structure/mineral_door/resin/proc/TryToClose() - if(!isSwitchingStates && !close_state) - Close() - -/obj/structure/mineral_door/resin/Dismantle(devastated = FALSE) - qdel(src) - -/obj/structure/mineral_door/resin/CheckHealth() - playsound(src, 'sound/effects/attackblob.ogg', 100, 1) - ..() - -/obj/structure/mineral_door/resin/bullet_act(obj/item/projectile/Proj) - health -= Proj.damage - ..() - CheckHealth() - -/obj/structure/mineral_door/resin/attack_hand(mob/user) - if(isalienadult(user) && user.a_intent == "hurt") - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - health -= rand(40, 60) - if(health <= 0) - user.visible_message("[user] slices the [name] to pieces!") - else - user.visible_message("[user] claws at the resin!") - CheckHealth() - else if(isalien(user) && !isSwitchingStates) - add_fingerprint(user) +/obj/structure/mineral_door + desc = "It opens and closes. What a surprise!" + density = TRUE + anchored = TRUE + opacity = TRUE + + icon = 'icons/obj/doors/mineral_doors.dmi' + + var/operating_sound = 'sound/effects/stonedoor_openclose.ogg' + var/close_state = TRUE + var/isSwitchingStates = FALSE + var/sheetAmount = 7 + var/health = 100 + + var/sheetType + +/obj/structure/mineral_door/atom_init() + . = ..() + update_nearby_tiles(need_rebuild = TRUE) + +/obj/structure/mineral_door/Destroy() + update_nearby_tiles() + return ..() + +/obj/structure/mineral_door/Bumped(atom/M) + if(close_state) + if(ismob(M)) + var/mob/user = M + if(DoorChecks() && MobChecks(user)) + add_fingerprint(user) + Open() + else if(istype(M, /obj/mecha) && DoorChecks()) + Open() + +/obj/structure/mineral_door/attack_ai(mob/user) + if(isrobot(user) && get_dist(user, src) <= 1) + return attack_hand(user) + +/obj/structure/mineral_door/attack_paw(mob/user) + return attack_hand(user) + +/obj/structure/mineral_door/attack_hand(mob/user) + if(DoorChecks() && MobChecks(user)) + add_fingerprint(user) + SwitchState() + +/obj/structure/mineral_door/CanPass(atom/movable/mover, turf/target, height = 0, air_group = 0) + if(air_group) + return FALSE + if(istype(mover, /obj/effect/beam)) + return !opacity + return !density + +/obj/structure/mineral_door/proc/DoorChecks() + return (!isSwitchingStates && anchored) + +/obj/structure/mineral_door/proc/MobChecks(mob/user) + if(!user.small) + if(iscarbon(user)) + var/mob/living/carbon/C = user + if(!C.handcuffed) + return TRUE + else + return TRUE + return FALSE + +/obj/structure/mineral_door/proc/SwitchState() + if(close_state) + Open() + else + Close() + +/obj/structure/mineral_door/proc/Open() + isSwitchingStates = TRUE + playsound(src, operating_sound, 100, 1) + flick("[initial(icon_state)]_opening", src) + sleep(10) + density = FALSE + set_opacity(FALSE) + close_state = FALSE + update_icon() + isSwitchingStates = FALSE + update_nearby_tiles() + +/obj/structure/mineral_door/proc/Close() + isSwitchingStates = TRUE + playsound(src, operating_sound, 100, 1) + flick("[initial(icon_state)]_closing", src) + sleep(10) + density = TRUE + set_opacity(TRUE) + close_state = TRUE + update_icon() + isSwitchingStates = FALSE + update_nearby_tiles() + +/obj/structure/mineral_door/update_icon() + if(close_state) + icon_state = initial(icon_state) + else + icon_state = "[initial(icon_state)]_open" + +/obj/structure/mineral_door/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/pickaxe) && !(istype(src, /obj/structure/mineral_door/wood) || istype(src, /obj/structure/mineral_door/metal))) + if(user.is_busy()) + return + var/obj/item/weapon/pickaxe/digTool = W + to_chat(user, "You start digging the [name].") + if(do_after(user, digTool.digspeed, target = src)) + to_chat(user, "You finished digging!") + Dismantle() + + else if(istype(W, /obj/item/weapon/wrench) && !istype(src, /obj/structure/mineral_door/resin)) + if(user.is_busy()) + return + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) + if(anchored) + to_chat(user, "You start dissassembling the [name].") + if(do_after(user, 40, target = src)) + to_chat(user, "You dissassembled the [name]!") + anchored = FALSE + name = "disassembled [name]" + desc = "Needs assembly." + icon_state = "[initial(icon_state)]_disassembled" + density = FALSE + set_opacity(FALSE) + else + to_chat(user, "You start assembling the [name]!") + if(do_after(user, 40, target = src)) + to_chat(user, "You assembled the [name]!") + anchored = TRUE + name = initial(name) + desc = initial(desc) + density = TRUE + icon_state = initial(icon_state) + if(!istype(src, /obj/structure/mineral_door/transparent)) + set_opacity(TRUE) + + else + health -= W.force + CheckHealth() + return ..() + +/obj/structure/mineral_door/proc/CheckHealth() + if(health <= 0) + Dismantle(TRUE) + +/obj/structure/mineral_door/proc/Dismantle(devastated = FALSE) + var/turf/T = get_turf(src) + if(!devastated) + for(var/i in 1 to sheetAmount) + new sheetType(T) + else + for(var/i in 3 to sheetAmount) + new sheetType(T) + qdel(src) + +/obj/structure/mineral_door/ex_act(severity = 1) + switch(severity) + if(1) + Dismantle(TRUE) + if(2) + if(prob(20)) + Dismantle(TRUE) + else + health-- + CheckHealth() + if(3) + health -= 0.1 + CheckHealth() + +/obj/structure/mineral_door/metal + name = "metal door" + icon_state = "metal" + health = 300 + sheetType = /obj/item/stack/sheet/metal + +/obj/structure/mineral_door/metal/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/weldingtool)) + if(user.is_busy()) + return + var/obj/item/weapon/weldingtool/WT = W + if(!WT.isOn()) + to_chat(user, "The welding tool needs to be on to start this task!") + return + if(WT.remove_fuel(0, user)) + playsound(src, 'sound/items/Welder2.ogg', 100, 1) + to_chat(user, "You start dissassembling the [name] to the metal sheets.") + if(do_after(user, 60, target = src)) + to_chat(user, "You dissassembled the [name] to the metal sheets!") + Dismantle() + else + to_chat(user, "You need more welding fuel!") + return + ..() + +/obj/structure/mineral_door/silver + name = "silver door" + icon_state = "silver" + health = 300 + sheetType = /obj/item/stack/sheet/mineral/silver + +/obj/structure/mineral_door/gold + name = "golden door" + icon_state = "gold" + sheetType = /obj/item/stack/sheet/mineral/gold + +/obj/structure/mineral_door/uranium + name = "uranium door" + icon_state = "uranium" + health = 300 + light_range = 2 + sheetType = /obj/item/stack/sheet/mineral/uranium + +/obj/structure/mineral_door/sandstone + name = "sandstone door" + icon_state = "sandstone" + health = 50 + sheetType = /obj/item/stack/sheet/mineral/sandstone + +/obj/structure/mineral_door/transparent + opacity = FALSE + +/obj/structure/mineral_door/transparent/Close() + ..() + opacity = FALSE + +/obj/structure/mineral_door/transparent/phoron + name = "phoron door" + icon_state = "phoron" + sheetType = /obj/item/stack/sheet/mineral/phoron + +/obj/structure/mineral_door/transparent/phoron/attackby(obj/item/weapon/W, mob/user) + if(istype(W,/obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + TemperatureAct(100) + ..() + +/obj/structure/mineral_door/transparent/phoron/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > 300) + TemperatureAct(exposed_temperature) + +/obj/structure/mineral_door/transparent/phoron/proc/TemperatureAct(temperature) + for(var/turf/simulated/floor/target_tile in range(2, loc)) + + var/phoronToDeduce = temperature * 0.1 + + target_tile.assume_gas("phoron", phoronToDeduce) + target_tile.hotspot_expose(temperature, 400) + + health -= phoronToDeduce * 0.01 + CheckHealth() + +/obj/structure/mineral_door/transparent/diamond + name = "diamond door" + icon_state = "diamond" + health = 1000 + sheetType = /obj/item/stack/sheet/mineral/diamond + +/obj/structure/mineral_door/wood + name = "wooden door" + icon_state = "wood" + sheetType = /obj/item/stack/sheet/wood + operating_sound = 'sound/effects/doorcreaky.ogg' + +/obj/structure/mineral_door/wood/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/twohanded/fireaxe)) + if(user.is_busy()) + return + playsound(src, 'sound/items/Axe.ogg', 100, 1) + to_chat(user, "You start cutting the [name] with the axe.") + if(do_after(user, 40, target = src)) + to_chat(user, "You finished cutting the [name]!") + Dismantle() + return + ..() + +/obj/structure/mineral_door/resin + icon = 'icons/mob/alien.dmi' + operating_sound = 'sound/effects/attackblob.ogg' + icon_state = "resin" + health = 150 + var/close_delay = 100 + +/obj/structure/mineral_door/resin/atom_init() + var/turf/T = get_turf(loc) + if(T) + T.blocks_air = TRUE + . = ..() + +/obj/structure/mineral_door/resin/Destroy() + var/turf/T = get_turf(loc) + if(T) + T.blocks_air = FALSE + return ..() + +/obj/structure/mineral_door/resin/Bumped(atom/M) + if(isalien(M) && !isSwitchingStates) + add_fingerprint(M) + Open() + +/obj/structure/mineral_door/resin/Open() + ..() + addtimer(CALLBACK(src, .proc/TryToClose), close_delay) + +/obj/structure/mineral_door/resin/proc/TryToClose() + if(!isSwitchingStates && !close_state) + Close() + +/obj/structure/mineral_door/resin/Dismantle(devastated = FALSE) + qdel(src) + +/obj/structure/mineral_door/resin/CheckHealth() + playsound(src, 'sound/effects/attackblob.ogg', 100, 1) + ..() + +/obj/structure/mineral_door/resin/bullet_act(obj/item/projectile/Proj) + health -= Proj.damage + ..() + CheckHealth() + +/obj/structure/mineral_door/resin/attack_hand(mob/user) + if(isalienadult(user) && user.a_intent == "hurt") + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + health -= rand(40, 60) + if(health <= 0) + user.visible_message("[user] slices the [name] to pieces!") + else + user.visible_message("[user] claws at the resin!") + CheckHealth() + else if(isalien(user) && !isSwitchingStates) + add_fingerprint(user) SwitchState() \ No newline at end of file diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index e9dea2751782..764ec25d7d1a 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -1,266 +1,266 @@ -//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) - user.SetNextMove(CLICK_CD_MELEE) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.a_intent == "hurt") - H.do_attack_animation(src) - if(!H.gloves) - var/obj/item/organ/external/BP = H.bodyparts_by_name[H.hand ? BP_L_ARM : BP_R_ARM] - BP.take_damage(rand(0, 4)) - if(!shattered && prob(20)) - shatter() - else - playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - else - H.visible_message("[user] stares into \the [src].") - ..() - -/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(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, mob/user) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - if(shattered) - playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return - - if(prob(I.force * 2)) - visible_message("[user] smashes [src] with [I]!") - shatter() - else - visible_message("[user] hits [src] with [I]!") - playsound(src.loc, 'sound/effects/Glasshit.ogg', 70, 1) - - -/obj/structure/mirror/attack_alien(mob/user) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - if(islarva(user) || isfacehugger(user)) - return - if(shattered) - playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return - user.visible_message("[user] smashes [src]!") - shatter() - - -/obj/structure/mirror/attack_animal(mob/user) - if(!isanimal(user)) - return - ..() - - var/mob/living/simple_animal/M = user - if(M.melee_damage_upper <= 0) - return - if(shattered) - playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return - user.visible_message("[user] smashes [src]!") - shatter() - - -/obj/structure/mirror/attack_slime(mob/user) - if(!isslimeadult(user)) - return - user.SetNextMove(CLICK_CD_MELEE) - user.do_attack_animation(src) - if(shattered) - playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return - user.visible_message("[user] smashes [src]!") - shatter() - - - -// Wo-o, some magic goes here -/obj/structure/mirror/magic - name = "magic mirror" - desc = "Turn and face the strange... face." - icon_state = "magic_mirror" -// var/list/choosable_races = list() - -/obj/structure/mirror/magic/attack_hand(mob/user) - if(!ishuman(user)) - return - - var/mob/living/carbon/human/H = user - - var/choice = input(user, "Something to change?", "Magical Grooming") as null|anything in list("name", "skin tone", "xenos skin", "gender", "hair", "eyes") - - switch(choice) - if("name") - var/newname = sanitize_safe(input(H, "Who are we again?", "Name change", H.name) as null|text, MAX_NAME_LEN) - - if(!newname) - return - - H.real_name = newname - H.name = newname - if(H.dna) - H.dna.real_name = newname - if(H.mind) - H.mind.name = newname - - if ("skin tone") - var/new_tone = input(H, "Choose your skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Skin Tone") as num - if(new_tone) - H.s_tone = max(min(round(new_tone), 220), 1) - H.s_tone = -H.s_tone + 35 - H.update_hair() - H.update_body() - H.check_dna(H) - - if("xenos skin") - var/new_skin = input(H, "Please select xeno-body color", "Xenos Skin") as null|color - if(new_skin) - H.r_skin = hex2num(copytext(new_skin, 2, 4)) - H.g_skin = hex2num(copytext(new_skin, 4, 6)) - H.b_skin = hex2num(copytext(new_skin, 6, 8)) - H.update_hair() - H.update_body() - H.check_dna(H) - /* if("race") - var/newrace - var/racechoice = input(H, "What are we again?", "Race change") as null|anything in choosable_races - newrace = species_list[racechoice] - - if(!newrace) - return - - H.set_species(newrace, icon_update=0) - - if(H.dna.species.use_skintones) - var/new_s_tone = input(user, "Choose your skin tone:", "Race change") as null|anything in skin_tones - - if(new_s_tone) - H.skin_tone = new_s_tone - H.dna.update_ui_block(DNA_SKIN_TONE_BLOCK) - - if(MUTCOLORS in H.dna.species.specflags) - var/new_mutantcolor = input(user, "Choose your skin color:", "Race change") as color|null - if(new_mutantcolor) - var/temp_hsv = RGBtoHSV(new_mutantcolor) - - if(ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright - H.dna.features["mcolor"] = sanitize_hexcolor(new_mutantcolor) - - else - to_chat(H, "Invalid color. Your color is not bright enough.") - - H.update_body() - H.update_hair() - H.update_mutcolor() - H.update_mutations_overlay() // no hulk lizard - */ - - if("gender") - if(!(H.gender in list("male", "female"))) //blame the patriarchy - return - - if(H.gender == "male") - if(alert(H, "Become a Witch?", "Confirmation", "Yes", "No") == "Yes") - H.gender = "female" - to_chat(H, "Man, you feel like a woman!") - else - return - - else - if(alert(H, "Become a Warlock?", "Confirmation", "Yes", "No") == "Yes") - H.gender = "male" - to_chat(H, "Whoa man, you feel like a man!") - else - return - H.update_hair() - H.update_body() - H.check_dna(H) - - if("hair") - var/hairchoice = alert(H, "Hair style or hair color?", "Change Hair", "Style", "Color") - - if(hairchoice == "Style") //So you just want to use a mirror then? - var/userloc = H.loc - //see code/modules/mob/dead/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() - else - var/new_hair = input(H, "Choose your hair color", "Hair Color") as null|color - if(new_hair) - H.r_hair = hex2num(copytext(new_hair, 2, 4)) - H.g_hair = hex2num(copytext(new_hair, 4, 6)) - H.b_hair = hex2num(copytext(new_hair, 6, 8)) - - if(H.gender == "male") - var/new_facial = input(H, "Choose your facial hair color", "Hair Color") as null|color - if(new_facial) - H.r_facial = hex2num(copytext(new_facial, 2, 4)) - H.g_facial = hex2num(copytext(new_facial, 4, 6)) - H.b_facial = hex2num(copytext(new_facial, 6, 8)) - H.update_hair() - H.update_body() - H.check_dna(H) - - if("eyes") - var/new_eyes = input(H, "Choose your eye color", "Eye Color") as null|color - if(new_eyes) - H.r_eyes = hex2num(copytext(new_eyes, 2, 4)) - H.g_eyes = hex2num(copytext(new_eyes, 4, 6)) - H.b_eyes = hex2num(copytext(new_eyes, 6, 8)) - H.update_hair() - H.update_body() - H.check_dna(H) +//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) + user.SetNextMove(CLICK_CD_MELEE) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.a_intent == "hurt") + H.do_attack_animation(src) + if(!H.gloves) + var/obj/item/organ/external/BP = H.bodyparts_by_name[H.hand ? BP_L_ARM : BP_R_ARM] + BP.take_damage(rand(0, 4)) + if(!shattered && prob(20)) + shatter() + else + playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + else + H.visible_message("[user] stares into \the [src].") + ..() + +/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(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, mob/user) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + if(shattered) + playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + + if(prob(I.force * 2)) + visible_message("[user] smashes [src] with [I]!") + shatter() + else + visible_message("[user] hits [src] with [I]!") + playsound(src.loc, 'sound/effects/Glasshit.ogg', 70, 1) + + +/obj/structure/mirror/attack_alien(mob/user) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + if(islarva(user) || isfacehugger(user)) + return + if(shattered) + playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + user.visible_message("[user] smashes [src]!") + shatter() + + +/obj/structure/mirror/attack_animal(mob/user) + if(!isanimal(user)) + return + ..() + + var/mob/living/simple_animal/M = user + if(M.melee_damage_upper <= 0) + return + if(shattered) + playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + user.visible_message("[user] smashes [src]!") + shatter() + + +/obj/structure/mirror/attack_slime(mob/user) + if(!isslimeadult(user)) + return + user.SetNextMove(CLICK_CD_MELEE) + user.do_attack_animation(src) + if(shattered) + playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + user.visible_message("[user] smashes [src]!") + shatter() + + + +// Wo-o, some magic goes here +/obj/structure/mirror/magic + name = "magic mirror" + desc = "Turn and face the strange... face." + icon_state = "magic_mirror" +// var/list/choosable_races = list() + +/obj/structure/mirror/magic/attack_hand(mob/user) + if(!ishuman(user)) + return + + var/mob/living/carbon/human/H = user + + var/choice = input(user, "Something to change?", "Magical Grooming") as null|anything in list("name", "skin tone", "xenos skin", "gender", "hair", "eyes") + + switch(choice) + if("name") + var/newname = sanitize_safe(input(H, "Who are we again?", "Name change", H.name) as null|text, MAX_NAME_LEN) + + if(!newname) + return + + H.real_name = newname + H.name = newname + if(H.dna) + H.dna.real_name = newname + if(H.mind) + H.mind.name = newname + + if ("skin tone") + var/new_tone = input(H, "Choose your skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Skin Tone") as num + if(new_tone) + H.s_tone = max(min(round(new_tone), 220), 1) + H.s_tone = -H.s_tone + 35 + H.update_hair() + H.update_body() + H.check_dna(H) + + if("xenos skin") + var/new_skin = input(H, "Please select xeno-body color", "Xenos Skin") as null|color + if(new_skin) + H.r_skin = hex2num(copytext(new_skin, 2, 4)) + H.g_skin = hex2num(copytext(new_skin, 4, 6)) + H.b_skin = hex2num(copytext(new_skin, 6, 8)) + H.update_hair() + H.update_body() + H.check_dna(H) + /* if("race") + var/newrace + var/racechoice = input(H, "What are we again?", "Race change") as null|anything in choosable_races + newrace = species_list[racechoice] + + if(!newrace) + return + + H.set_species(newrace, icon_update=0) + + if(H.dna.species.use_skintones) + var/new_s_tone = input(user, "Choose your skin tone:", "Race change") as null|anything in skin_tones + + if(new_s_tone) + H.skin_tone = new_s_tone + H.dna.update_ui_block(DNA_SKIN_TONE_BLOCK) + + if(MUTCOLORS in H.dna.species.specflags) + var/new_mutantcolor = input(user, "Choose your skin color:", "Race change") as color|null + if(new_mutantcolor) + var/temp_hsv = RGBtoHSV(new_mutantcolor) + + if(ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright + H.dna.features["mcolor"] = sanitize_hexcolor(new_mutantcolor) + + else + to_chat(H, "Invalid color. Your color is not bright enough.") + + H.update_body() + H.update_hair() + H.update_mutcolor() + H.update_mutations_overlay() // no hulk lizard + */ + + if("gender") + if(!(H.gender in list("male", "female"))) //blame the patriarchy + return + + if(H.gender == "male") + if(alert(H, "Become a Witch?", "Confirmation", "Yes", "No") == "Yes") + H.gender = "female" + to_chat(H, "Man, you feel like a woman!") + else + return + + else + if(alert(H, "Become a Warlock?", "Confirmation", "Yes", "No") == "Yes") + H.gender = "male" + to_chat(H, "Whoa man, you feel like a man!") + else + return + H.update_hair() + H.update_body() + H.check_dna(H) + + if("hair") + var/hairchoice = alert(H, "Hair style or hair color?", "Change Hair", "Style", "Color") + + if(hairchoice == "Style") //So you just want to use a mirror then? + var/userloc = H.loc + //see code/modules/mob/dead/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() + else + var/new_hair = input(H, "Choose your hair color", "Hair Color") as null|color + if(new_hair) + H.r_hair = hex2num(copytext(new_hair, 2, 4)) + H.g_hair = hex2num(copytext(new_hair, 4, 6)) + H.b_hair = hex2num(copytext(new_hair, 6, 8)) + + if(H.gender == "male") + var/new_facial = input(H, "Choose your facial hair color", "Hair Color") as null|color + if(new_facial) + H.r_facial = hex2num(copytext(new_facial, 2, 4)) + H.g_facial = hex2num(copytext(new_facial, 4, 6)) + H.b_facial = hex2num(copytext(new_facial, 6, 8)) + H.update_hair() + H.update_body() + H.check_dna(H) + + if("eyes") + var/new_eyes = input(H, "Choose your eye color", "Eye Color") as null|color + if(new_eyes) + H.r_eyes = hex2num(copytext(new_eyes, 2, 4)) + H.g_eyes = hex2num(copytext(new_eyes, 4, 6)) + H.b_eyes = hex2num(copytext(new_eyes, 6, 8)) + H.update_hair() + H.update_body() + H.check_dna(H) diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm index b26a9767a41d..7d7b4b9a476a 100644 --- a/code/game/objects/structures/mop_bucket.dm +++ b/code/game/objects/structures/mop_bucket.dm @@ -1,45 +1,45 @@ -/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 - flags = OPENCONTAINER - var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite - - -/obj/structure/mopbucket/atom_init() - create_reagents(100) - . = ..() - mopbucket_list += src - -/obj/structure/mopbucket/Destroy() - mopbucket_list -= src - return ..() - - -/obj/structure/mopbucket/examine(mob/user) - ..() - if(src in user) - to_chat(user, "[src] contains [reagents.total_volume] unit\s of water!") - - -/obj/structure/mopbucket/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/mop)) - if(reagents.total_volume < 1) - to_chat(user, "[src] is out of water!
                    ") - else - reagents.trans_to(I, 5) - user.SetNextMove(CLICK_CD_INTERACT) - to_chat(user, "You wet [I] in [src].") - playsound(loc, 'sound/effects/slosh.ogg', 25, 1) - else - ..() - -/obj/structure/mopbucket/on_reagent_change() - update_icon() - -/obj/structure/mopbucket/update_icon() - overlays.Cut() - if(reagents.total_volume > 1) - overlays += "mopbucket_water" +/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 + flags = OPENCONTAINER + var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite + + +/obj/structure/mopbucket/atom_init() + create_reagents(100) + . = ..() + mopbucket_list += src + +/obj/structure/mopbucket/Destroy() + mopbucket_list -= src + return ..() + + +/obj/structure/mopbucket/examine(mob/user) + ..() + if(src in user) + to_chat(user, "[src] contains [reagents.total_volume] unit\s of water!") + + +/obj/structure/mopbucket/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/mop)) + if(reagents.total_volume < 1) + to_chat(user, "[src] is out of water!
                    ") + else + reagents.trans_to(I, 5) + user.SetNextMove(CLICK_CD_INTERACT) + to_chat(user, "You wet [I] in [src].") + playsound(loc, 'sound/effects/slosh.ogg', 25, 1) + else + ..() + +/obj/structure/mopbucket/on_reagent_change() + update_icon() + +/obj/structure/mopbucket/update_icon() + overlays.Cut() + if(reagents.total_volume > 1) + overlays += "mopbucket_water" diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 35e69471b946..1ee44fbe8d1e 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -1,451 +1,451 @@ -/* Morgue stuff - * Contains: - * Morgue - * Morgue trays - * Creamatorium - * Creamatorium trays - */ - -/* - * Morgue - */ - -/obj/structure/morgue - name = "morgue" - desc = "Used to keep bodies in untill 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 - var/check_delay = 0 - -/obj/structure/morgue/atom_init() - START_PROCESSING(SSobj, src) - -/obj/structure/morgue/Destroy() - STOP_PROCESSING(SSobj, src) - QDEL_NULL(connected) - return ..() - -/obj/structure/morgue/proc/update() - if (connected) - icon_state = "morgue0" - else - if (contents.len) - icon_state = "morgue2" - else - icon_state = "morgue1" - return - -/obj/structure/morgue/ex_act(severity) - var/chance = 0 - switch(severity) - if(1.0) - chance = 100 - if(2.0) - chance = 50 - if(3.0) - chance = 5 - - if (prob(chance)) - for(var/atom/movable/A in src) - A.forceMove(loc) - A.ex_act(severity) - qdel(src) - -/obj/structure/morgue/alter_health() - return loc - -/obj/structure/morgue/attack_paw(mob/user) - return attack_hand(user) - -/obj/structure/morgue/proc/has_clonable_bodies() - var/list/compiled = recursive_mob_check(src, sight_check = FALSE, include_radio = FALSE) // Search for mobs in all contents. - if(!length(compiled)) // No mobs? - return FALSE - - for(var/mob/living/carbon/human/H in compiled) - if((H.brain_op_stage == 4.0) || H.suiciding || !H.ckey) - continue - - return TRUE - return FALSE - -/obj/structure/morgue/process() - if(check_delay > world.time) - return - check_delay = world.time + 10 SECONDS - - if (!contents.len) - update() - return //nothing inside - - if (has_clonable_bodies()) - icon_state = "morgue3" - else - update() - -/obj/structure/morgue/proc/close() - if (connected) - for(var/atom/movable/A in connected.loc) - if(!A.anchored) - A.loc = src - if(ismob(A)) - var/mob/M = A - M.instant_vision_update(1,src) - playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1) - qdel(connected) - connected = null - update() - -/obj/structure/morgue/proc/open() - if (!connected) - playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1) - connected = new /obj/structure/m_tray( loc ) - step(connected, dir) - connected.layer = BELOW_CONTAINERS_LAYER - var/turf/T = get_step(src, dir) - if (T.contents.Find(connected)) - connected.connected = src - icon_state = "morgue0" - for(var/atom/movable/A in src) - A.forceMove(connected.loc) - if(ismob(A)) - var/mob/M = A - M.instant_vision_update(0) - connected.icon_state = "morguet" - connected.dir = dir - else - qdel(connected) - connected = null - update() - -/obj/structure/morgue/proc/toggle() - if (connected) - close() - else - open() - -/obj/structure/morgue/attack_hand(mob/user) - user.SetNextMove(CLICK_CD_INTERACT) - toggle() - add_fingerprint(user) - return - -/obj/structure/morgue/attackby(P, mob/user) - if(istype(P, /obj/item/weapon/pen)) - - var/t = sanitize_safe(input(user, "What would you like the label to be?", src.name, null) as text, MAX_NAME_LEN) - if (user.get_active_hand() != P) - return - if ((!in_range(src, usr) && loc != user)) - return - add_fingerprint(user) - - if (t) - src.name = text("Morgue- '[]'", t) - else - src.name = "Morgue" - else - ..() - -/obj/structure/morgue/relaymove(mob/user) - if (user.stat) - return - connected = new /obj/structure/m_tray( loc ) - step(connected, dir) - connected.layer = BELOW_CONTAINERS_LAYER - var/turf/T = get_step(src, dir) - if (T.contents.Find(connected)) - connected.connected = src - icon_state = "morgue0" - for(var/atom/movable/A in src) - A.loc = connected.loc - connected.icon_state = "morguet" - else - qdel(connected) - connected = null - return - - -/* - * 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 - throwpass = 1 - -/obj/structure/m_tray/Destroy() - if(connected && connected.connected == src) - connected.connected = null - connected = null - return ..() - -/obj/structure/m_tray/attack_paw(mob/user) - return src.attack_hand(user) - -/obj/structure/m_tray/attack_hand(mob/user) - user.SetNextMove(CLICK_CD_INTERACT) - connected.close() - add_fingerprint(user) - -/obj/structure/m_tray/MouseDrop_T(atom/movable/O, mob/user) - if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) - return - if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) - return - if (!ismob(user) || user.stat || user.lying || user.stunned) - return - O.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/atom_init() - . = ..() - crematorium_list += src - -/obj/structure/crematorium/Destroy() - crematorium_list -= src - if(connected) - qdel(connected) - connected = null - return ..() - -/obj/structure/crematorium/proc/update() - if (src.connected) - src.icon_state = "crema0" - else - if (src.contents.len) - src.icon_state = "crema2" - else - src.icon_state = "crema1" - return - -/obj/structure/crematorium/ex_act(severity) - switch(severity) - if(1.0) - for(var/atom/movable/A as mob|obj in src) - A.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) - return src.attack_hand(user) - -/obj/structure/crematorium/attack_hand(mob/user) -// if (cremating) AWW MAN! THIS WOULD BE SO MUCH MORE FUN ... TO WATCH -// user.show_message("\red Uh-oh, that was a bad idea.", 1) -// //usr << "Uh-oh, that was a bad idea." -// src:loc:poison += 20000000 -// src:loc:firelevel = src:loc:poison -// return - user.SetNextMove(CLICK_CD_INTERACT) - if (cremating) - to_chat(user, "It's locked.") - return - if ((src.connected) && (src.locked == 0)) - for(var/atom/movable/A in src.connected.loc) - if(!A.anchored) - A.loc = src - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - qdel(src.connected) - src.connected = null - else if (src.locked == 0) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - src.connected = new /obj/structure/c_tray( src.loc ) - step(src.connected, SOUTH) - src.connected.layer = BELOW_CONTAINERS_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, mob/user) - if(istype(P, /obj/item/weapon/pen)) - var/t = sanitize_safe(input(user, "What would you like the label to be?", src.name, null) as text, MAX_NAME_LEN) - if (user.get_active_hand() != P) - return - if ((!in_range(src, usr) > 1 && src.loc != user)) - return - add_fingerprint(user) - if (t) - src.name = text("Crematorium- '[]'", t) - else - src.name = "Crematorium" - else - ..() - -/obj/structure/crematorium/relaymove(mob/user) - if (user.stat || locked) - return - src.connected = new /obj/structure/c_tray( src.loc ) - step(src.connected, SOUTH) - src.connected.layer = BELOW_CONTAINERS_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 - return - -/obj/structure/crematorium/proc/cremate(atom/A, 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 - if(!isemptylist(src.search_contents_for(/obj/item/weapon/disk/nuclear))) - to_chat(usr, "You get the feeling that you shouldn't cremate one of the items in the cremator.") - return - - for (var/mob/M in viewers(src)) - M.show_message("You hear a roar as the crematorium activates.", 1) - - cremating = 1 - locked = 1 - - for(var/mob/living/M in contents) - 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 deleted - //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(bancheck = TRUE) - qdel(M) - - for(var/obj/O in contents) //obj instead of obj/item so that bodybags and ashes get destroyed. We dont want tons and tons of ash piling up - qdel(O) - - new /obj/effect/decal/cleanable/ash(src) - sleep(30) - cremating = 0 - locked = 0 - playsound(src.loc, '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 - throwpass = 1 - -/obj/structure/c_tray/attack_paw(mob/user) - return src.attack_hand(user) - -/obj/structure/c_tray/attack_hand(mob/user) - user.SetNextMove(CLICK_CD_RAPID) - if (src.connected) - for(var/atom/movable/A in loc) - if (!A.anchored) - A.loc = src.connected - src.connected.connected = null - src.connected.update() - add_fingerprint(user) - qdel(src) - -/obj/structure/c_tray/MouseDrop_T(atom/movable/O, mob/user) - if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) - return - if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) - return - if (!ismob(user) || user.stat || user.lying || user.stunned) - return - O.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) - . = ..() - if(.) - return - user.SetNextMove(CLICK_CD_MELEE) - for (var/obj/structure/crematorium/C in crematorium_list) - if (C.id == id) - if (!C.cremating) - for(var/mob/living/M in C.contents) - user.attack_log += "\[[time_stamp()]\] Cremated [M.name] ([M.ckey])" - message_admins("[user.name] ([user.ckey]) Cremating [M.name] ([M.ckey]). (JMP)") - C.cremate(user) +/* Morgue stuff + * Contains: + * Morgue + * Morgue trays + * Creamatorium + * Creamatorium trays + */ + +/* + * Morgue + */ + +/obj/structure/morgue + name = "morgue" + desc = "Used to keep bodies in untill 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 + var/check_delay = 0 + +/obj/structure/morgue/atom_init() + START_PROCESSING(SSobj, src) + +/obj/structure/morgue/Destroy() + STOP_PROCESSING(SSobj, src) + QDEL_NULL(connected) + return ..() + +/obj/structure/morgue/proc/update() + if (connected) + icon_state = "morgue0" + else + if (contents.len) + icon_state = "morgue2" + else + icon_state = "morgue1" + return + +/obj/structure/morgue/ex_act(severity) + var/chance = 0 + switch(severity) + if(1.0) + chance = 100 + if(2.0) + chance = 50 + if(3.0) + chance = 5 + + if (prob(chance)) + for(var/atom/movable/A in src) + A.forceMove(loc) + A.ex_act(severity) + qdel(src) + +/obj/structure/morgue/alter_health() + return loc + +/obj/structure/morgue/attack_paw(mob/user) + return attack_hand(user) + +/obj/structure/morgue/proc/has_clonable_bodies() + var/list/compiled = recursive_mob_check(src, sight_check = FALSE, include_radio = FALSE) // Search for mobs in all contents. + if(!length(compiled)) // No mobs? + return FALSE + + for(var/mob/living/carbon/human/H in compiled) + if((H.brain_op_stage == 4.0) || H.suiciding || !H.ckey) + continue + + return TRUE + return FALSE + +/obj/structure/morgue/process() + if(check_delay > world.time) + return + check_delay = world.time + 10 SECONDS + + if (!contents.len) + update() + return //nothing inside + + if (has_clonable_bodies()) + icon_state = "morgue3" + else + update() + +/obj/structure/morgue/proc/close() + if (connected) + for(var/atom/movable/A in connected.loc) + if(!A.anchored) + A.loc = src + if(ismob(A)) + var/mob/M = A + M.instant_vision_update(1,src) + playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1) + qdel(connected) + connected = null + update() + +/obj/structure/morgue/proc/open() + if (!connected) + playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1) + connected = new /obj/structure/m_tray( loc ) + step(connected, dir) + connected.layer = BELOW_CONTAINERS_LAYER + var/turf/T = get_step(src, dir) + if (T.contents.Find(connected)) + connected.connected = src + icon_state = "morgue0" + for(var/atom/movable/A in src) + A.forceMove(connected.loc) + if(ismob(A)) + var/mob/M = A + M.instant_vision_update(0) + connected.icon_state = "morguet" + connected.dir = dir + else + qdel(connected) + connected = null + update() + +/obj/structure/morgue/proc/toggle() + if (connected) + close() + else + open() + +/obj/structure/morgue/attack_hand(mob/user) + user.SetNextMove(CLICK_CD_INTERACT) + toggle() + add_fingerprint(user) + return + +/obj/structure/morgue/attackby(P, mob/user) + if(istype(P, /obj/item/weapon/pen)) + + var/t = sanitize_safe(input(user, "What would you like the label to be?", src.name, null) as text, MAX_NAME_LEN) + if (user.get_active_hand() != P) + return + if ((!in_range(src, usr) && loc != user)) + return + add_fingerprint(user) + + if (t) + src.name = text("Morgue- '[]'", t) + else + src.name = "Morgue" + else + ..() + +/obj/structure/morgue/relaymove(mob/user) + if (user.stat) + return + connected = new /obj/structure/m_tray( loc ) + step(connected, dir) + connected.layer = BELOW_CONTAINERS_LAYER + var/turf/T = get_step(src, dir) + if (T.contents.Find(connected)) + connected.connected = src + icon_state = "morgue0" + for(var/atom/movable/A in src) + A.loc = connected.loc + connected.icon_state = "morguet" + else + qdel(connected) + connected = null + return + + +/* + * 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 + throwpass = 1 + +/obj/structure/m_tray/Destroy() + if(connected && connected.connected == src) + connected.connected = null + connected = null + return ..() + +/obj/structure/m_tray/attack_paw(mob/user) + return src.attack_hand(user) + +/obj/structure/m_tray/attack_hand(mob/user) + user.SetNextMove(CLICK_CD_INTERACT) + connected.close() + add_fingerprint(user) + +/obj/structure/m_tray/MouseDrop_T(atom/movable/O, mob/user) + if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) + return + if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) + return + if (!ismob(user) || user.stat || user.lying || user.stunned) + return + O.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/atom_init() + . = ..() + crematorium_list += src + +/obj/structure/crematorium/Destroy() + crematorium_list -= src + if(connected) + qdel(connected) + connected = null + return ..() + +/obj/structure/crematorium/proc/update() + if (src.connected) + src.icon_state = "crema0" + else + if (src.contents.len) + src.icon_state = "crema2" + else + src.icon_state = "crema1" + return + +/obj/structure/crematorium/ex_act(severity) + switch(severity) + if(1.0) + for(var/atom/movable/A as mob|obj in src) + A.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) + return src.attack_hand(user) + +/obj/structure/crematorium/attack_hand(mob/user) +// if (cremating) AWW MAN! THIS WOULD BE SO MUCH MORE FUN ... TO WATCH +// user.show_message("\red Uh-oh, that was a bad idea.", 1) +// //usr << "Uh-oh, that was a bad idea." +// src:loc:poison += 20000000 +// src:loc:firelevel = src:loc:poison +// return + user.SetNextMove(CLICK_CD_INTERACT) + if (cremating) + to_chat(user, "It's locked.") + return + if ((src.connected) && (src.locked == 0)) + for(var/atom/movable/A in src.connected.loc) + if(!A.anchored) + A.loc = src + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + qdel(src.connected) + src.connected = null + else if (src.locked == 0) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + src.connected = new /obj/structure/c_tray( src.loc ) + step(src.connected, SOUTH) + src.connected.layer = BELOW_CONTAINERS_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, mob/user) + if(istype(P, /obj/item/weapon/pen)) + var/t = sanitize_safe(input(user, "What would you like the label to be?", src.name, null) as text, MAX_NAME_LEN) + if (user.get_active_hand() != P) + return + if ((!in_range(src, usr) > 1 && src.loc != user)) + return + add_fingerprint(user) + if (t) + src.name = text("Crematorium- '[]'", t) + else + src.name = "Crematorium" + else + ..() + +/obj/structure/crematorium/relaymove(mob/user) + if (user.stat || locked) + return + src.connected = new /obj/structure/c_tray( src.loc ) + step(src.connected, SOUTH) + src.connected.layer = BELOW_CONTAINERS_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 + return + +/obj/structure/crematorium/proc/cremate(atom/A, 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 + if(!isemptylist(src.search_contents_for(/obj/item/weapon/disk/nuclear))) + to_chat(usr, "You get the feeling that you shouldn't cremate one of the items in the cremator.") + return + + for (var/mob/M in viewers(src)) + M.show_message("You hear a roar as the crematorium activates.", 1) + + cremating = 1 + locked = 1 + + for(var/mob/living/M in contents) + 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 deleted + //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(bancheck = TRUE) + qdel(M) + + for(var/obj/O in contents) //obj instead of obj/item so that bodybags and ashes get destroyed. We dont want tons and tons of ash piling up + qdel(O) + + new /obj/effect/decal/cleanable/ash(src) + sleep(30) + cremating = 0 + locked = 0 + playsound(src.loc, '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 + throwpass = 1 + +/obj/structure/c_tray/attack_paw(mob/user) + return src.attack_hand(user) + +/obj/structure/c_tray/attack_hand(mob/user) + user.SetNextMove(CLICK_CD_RAPID) + if (src.connected) + for(var/atom/movable/A in loc) + if (!A.anchored) + A.loc = src.connected + src.connected.connected = null + src.connected.update() + add_fingerprint(user) + qdel(src) + +/obj/structure/c_tray/MouseDrop_T(atom/movable/O, mob/user) + if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || user.contents.Find(O))) + return + if (!ismob(O) && !istype(O, /obj/structure/closet/body_bag)) + return + if (!ismob(user) || user.stat || user.lying || user.stunned) + return + O.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) + . = ..() + if(.) + return + user.SetNextMove(CLICK_CD_MELEE) + for (var/obj/structure/crematorium/C in crematorium_list) + if (C.id == id) + if (!C.cremating) + for(var/mob/living/M in C.contents) + user.attack_log += "\[[time_stamp()]\] Cremated [M.name] ([M.ckey])" + message_admins("[user.name] ([user.ckey]) Cremating [M.name] ([M.ckey]). (JMP)") + C.cremate(user) diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm index 3dd29fea2528..5eee83fc177d 100644 --- a/code/game/objects/structures/noticeboard.dm +++ b/code/game/objects/structures/noticeboard.dm @@ -1,83 +1,83 @@ -/obj/structure/noticeboard - name = "notice board" - desc = "A board for pinning important notices upon." - icon = 'icons/obj/objects.dmi' - icon_state = "nboard00" - density = 0 - anchored = 1 - var/notices = 0 - -/obj/structure/noticeboard/atom_init() - . = ..() - 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(obj/item/weapon/O, mob/user) - if(istype(O, /obj/item/weapon/paper)) - if(notices < 5) - O.add_fingerprint(user) - add_fingerprint(user) - user.drop_item() - O.loc = src - notices++ - icon_state = "nboard0[notices]" //update sprite - to_chat(user, "You pin the paper to the noticeboard.") - 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.") - else - ..() - -/obj/structure/noticeboard/attack_hand(user) - var/dat = "Noticeboard
                    " - for(var/obj/item/weapon/paper/P in src) - dat += "[P.name] Write Remove
                    " - user << browse("Notices[entity_ja(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][entity_ja(stars(P.info))]", "window=[P.name]") - onclose(usr, "[P.name]") - else - usr << browse("[P.name][entity_ja(P.info)]", "window=[P.name]") - onclose(usr, "[P.name]") - return +/obj/structure/noticeboard + name = "notice board" + desc = "A board for pinning important notices upon." + icon = 'icons/obj/objects.dmi' + icon_state = "nboard00" + density = 0 + anchored = 1 + var/notices = 0 + +/obj/structure/noticeboard/atom_init() + . = ..() + 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(obj/item/weapon/O, mob/user) + if(istype(O, /obj/item/weapon/paper)) + if(notices < 5) + O.add_fingerprint(user) + add_fingerprint(user) + user.drop_item() + O.loc = src + notices++ + icon_state = "nboard0[notices]" //update sprite + to_chat(user, "You pin the paper to the noticeboard.") + 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.") + else + ..() + +/obj/structure/noticeboard/attack_hand(user) + var/dat = "Noticeboard
                    " + for(var/obj/item/weapon/paper/P in src) + dat += "[P.name] Write Remove
                    " + user << browse("Notices[entity_ja(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][entity_ja(stars(P.info))]", "window=[P.name]") + onclose(usr, "[P.name]") + else + usr << browse("[P.name][entity_ja(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 40639c4a8a55..ab86434c4fdb 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -1,192 +1,192 @@ -/* -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/atom_init() - . = ..() - 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/atom_init() - . = ..() - 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, 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) - user.set_machine(src) - var/dat = "
                    " - dat += "[open ? "Close" : "Open"] [src] | - [dial * 5] +" - if(open) - dat += "" - for(var/i = contents.len, i>=1, i--) - var/obj/item/P = contents[i] - dat += "" - dat += "
                    [P.name]
                    " - user << browse("[name][entity_ja(dat)]", "window=safe;size=350x300") - - -/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, mob/user) - user.SetNextMove(CLICK_CD_INTERACT) - add_fingerprint(user) - if(open) - if(I.w_class + space <= maxspace) - space += I.w_class - user.drop_item() - I.loc = src - to_chat(user, "You put [I] in [src].") - updateUsrDialog() - else - to_chat(user, "[I] won't fit in [src].") - else - if(istype(I, /obj/item/clothing/accessory/stethoscope)) - to_chat(user, "Hold [I] in one of your hands while you manipulate the dial.") - - -obj/structure/safe/blob_act() - return - - -obj/structure/safe/ex_act(severity) - return - - -obj/structure/safe/meteorhit(obj/O) - 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/atom_init() - . = ..() - var/turf/T = loc - hide(T.intact) - - -/obj/structure/safe/floor/hide(intact) - invisibility = intact ? 101 : 0 +/* +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/atom_init() + . = ..() + 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/atom_init() + . = ..() + 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, 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) + user.set_machine(src) + var/dat = "
                    " + dat += "[open ? "Close" : "Open"] [src] | - [dial * 5] +" + if(open) + dat += "" + for(var/i = contents.len, i>=1, i--) + var/obj/item/P = contents[i] + dat += "" + dat += "
                    [P.name]
                    " + user << browse("[name][entity_ja(dat)]", "window=safe;size=350x300") + + +/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, mob/user) + user.SetNextMove(CLICK_CD_INTERACT) + add_fingerprint(user) + if(open) + if(I.w_class + space <= maxspace) + space += I.w_class + user.drop_item() + I.loc = src + to_chat(user, "You put [I] in [src].") + updateUsrDialog() + else + to_chat(user, "[I] won't fit in [src].") + else + if(istype(I, /obj/item/clothing/accessory/stethoscope)) + to_chat(user, "Hold [I] in one of your hands while you manipulate the dial.") + + +obj/structure/safe/blob_act() + return + + +obj/structure/safe/ex_act(severity) + return + + +obj/structure/safe/meteorhit(obj/O) + 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/atom_init() + . = ..() + var/turf/T = loc + hide(T.intact) + + +/obj/structure/safe/floor/hide(intact) + invisibility = intact ? 101 : 0 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 410b4bdb0123..125d761d2ced 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,66 +1,66 @@ -//Alium nests. Essentially beds with an unbuckle delay that only aliums can buckle mobs to. - -/obj/structure/stool/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 - layer = 2.55 - -/obj/structure/stool/bed/nest/user_unbuckle_mob(mob/user) - if(buckled_mob) - if(buckled_mob.buckled == src) - if(buckled_mob != user) - buckled_mob.visible_message(\ - "[user.name] pulls [buckled_mob.name] free from the sticky nest!",\ - "[user.name] pulls you free from the gelatinous resin.",\ - "You hear squelching...") - buckled_mob.pixel_y = 0 - unbuckle_mob() - else - if(user.is_busy()) return - buckled_mob.visible_message(\ - "[buckled_mob.name] struggles to break free of the gelatinous resin...",\ - "You struggle to break free from the gelatinous resin...",\ - "You hear squelching...") - if(do_after(buckled_mob, 3000, target = user)) - if(user && buckled_mob && user.buckled == src) - buckled_mob.pixel_y = 0 - unbuckle_mob() - src.add_fingerprint(user) - return - -/obj/structure/stool/bed/nest/user_buckle_mob(mob/M, mob/user) - if ( !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.restrained() || usr.stat || M.buckled || 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 [src]!",\ - "[user.name] drenches you in a foul-smelling resin, trapping you in the [src]!",\ - "You hear squelching...") - buckle_mob(M) - M.pixel_y = 2 - return - -/obj/structure/stool/bed/nest/attackby(obj/item/weapon/W, mob/user) - var/aforce = W.force - health = max(0, health - aforce) - user.SetNextMove(CLICK_CD_MELEE) - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - visible_message("[user] hits [src] with [W]!") - healthcheck() - -/obj/structure/stool/bed/nest/proc/healthcheck() - if(health <=0) - density = 0 - qdel(src) - return +//Alium nests. Essentially beds with an unbuckle delay that only aliums can buckle mobs to. + +/obj/structure/stool/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 + layer = 2.55 + +/obj/structure/stool/bed/nest/user_unbuckle_mob(mob/user) + if(buckled_mob) + if(buckled_mob.buckled == src) + if(buckled_mob != user) + buckled_mob.visible_message(\ + "[user.name] pulls [buckled_mob.name] free from the sticky nest!",\ + "[user.name] pulls you free from the gelatinous resin.",\ + "You hear squelching...") + buckled_mob.pixel_y = 0 + unbuckle_mob() + else + if(user.is_busy()) return + buckled_mob.visible_message(\ + "[buckled_mob.name] struggles to break free of the gelatinous resin...",\ + "You struggle to break free from the gelatinous resin...",\ + "You hear squelching...") + if(do_after(buckled_mob, 3000, target = user)) + if(user && buckled_mob && user.buckled == src) + buckled_mob.pixel_y = 0 + unbuckle_mob() + src.add_fingerprint(user) + return + +/obj/structure/stool/bed/nest/user_buckle_mob(mob/M, mob/user) + if ( !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.restrained() || usr.stat || M.buckled || 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 [src]!",\ + "[user.name] drenches you in a foul-smelling resin, trapping you in the [src]!",\ + "You hear squelching...") + buckle_mob(M) + M.pixel_y = 2 + return + +/obj/structure/stool/bed/nest/attackby(obj/item/weapon/W, mob/user) + var/aforce = W.force + health = max(0, health - aforce) + user.SetNextMove(CLICK_CD_MELEE) + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + visible_message("[user] hits [src] with [W]!") + healthcheck() + +/obj/structure/stool/bed/nest/proc/healthcheck() + if(health <=0) + density = 0 + qdel(src) + return 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 5b72a988a1ad..891e0a0093fc 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/stool/bed - name = "bed" - desc = "This is used to lie in, sleep in or strap on." - icon = 'icons/obj/objects.dmi' - icon_state = "bed" - can_buckle = 1 - buckle_lying = 1 - -/obj/structure/stool/bed/psych - name = "psychiatrists couch" - desc = "For prime comfort during psychiatric evaluations." - icon = 'icons/obj/objects.dmi' - icon_state = "psychbed" - -/obj/structure/stool/bed/alien - name = "resting contraption" - desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?" - icon = 'icons/obj/objects.dmi' - icon_state = "abed" - -/obj/structure/stool/bed/attack_paw(mob/user) - return src.attack_hand(user) - -/obj/structure/stool/bed/CanPass(atom/movable/mover) - if(iscarbon(mover) && mover.checkpass(PASSCRAWL)) - mover.layer = 2.7 - return ..() - -/obj/structure/stool/bed/CheckExit(atom/movable/O as mob|obj) - if(istype(O) && O.checkpass(PASSCRAWL)) - O.layer = 4.0 - return ..() - -/obj/structure/stool/bed/Process_Spacemove(movement_dir = 0) - if(buckled_mob) - return buckled_mob.Process_Spacemove(movement_dir) - return ..() - -/obj/structure/stool/bed/examine(mob/user) - ..() - var/T = get_turf(src) - var/mob/living/carbon/human/H = locate() in T - if(H && H.crawling) - to_chat(user, "Someone is hiding under [src]") - -/* - * Roller beds - */ -/obj/structure/stool/bed/roller - name = "roller bed" - icon = 'icons/obj/rollerbed.dmi' - icon_state = "down" - anchored = 0 - var/type_roller = /obj/item/roller - -/obj/structure/stool/bed/roller/attackby(obj/item/weapon/W, mob/user) - if(istype(W,src) || istype(W, /obj/item/roller_holder)) - user.SetNextMove(CLICK_CD_INTERACT) - if(buckled_mob) - user_unbuckle_mob() - else - visible_message("[user] collapses \the [src.name].") - new type_roller(get_turf(src)) - qdel(src) - else - ..() - -/obj/structure/stool/bed/roller/CanPass(atom/movable/mover) - if(iscarbon(mover) && mover.checkpass(PASSCRAWL)) - return 0 - return ..() - -/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. - var/type_bed = /obj/structure/stool/bed/roller - var/type_holder = /obj/item/roller_holder - - -/obj/item/roller/attack_self(mob/user) - var/obj/structure/stool/bed/roller/R = new type_bed(user.loc) - R.add_fingerprint(user) - qdel(src) - -/obj/item/roller/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/roller_holder)) - var/obj/item/roller_holder/RH = W - if(!RH.held) - to_chat(user, "You collect the roller bed.") - src.loc = RH - RH.held = src - return - ..() - -/obj/item/roller_holder - name = "roller bed rack" - desc = "A rack for carrying a collapsed roller bed." - icon = 'icons/obj/rollerbed.dmi' - icon_state = "folded" - var/held = /obj/item/roller - var/type_bed = /obj/structure/stool/bed/roller - -/obj/item/roller_holder/atom_init() - . = ..() - held = new held(src) - -/obj/item/roller_holder/attack_self(mob/user) - - if(!held) - to_chat(user, "The rack is empty.") - return - - to_chat(user, "You deploy the roller bed.") - var/obj/structure/stool/bed/roller/R = new type_bed(user.loc) - R.add_fingerprint(user) - qdel(held) - held = null - -/obj/structure/stool/bed/roller/post_buckle_mob(mob/living/M) - if(M == buckled_mob) - if(M.crawling) - M.pass_flags &= ~PASSCRAWL - M.crawling = FALSE - M.layer = 4.0 - density = 1 - icon_state = "up" - else - density = 0 - icon_state = "down" - return ..() - -/obj/structure/stool/bed/roller/MouseDrop(over_object, src_location, over_location) - ..() - if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) - if(!ishuman(usr)) - return - if(buckled_mob) - return 0 - visible_message("[usr] collapses \the [src.name].") - new type_roller(get_turf(src)) - qdel(src) - return - -/obj/structure/stool/bed/attackby(obj/item/weapon/W, mob/user) - ..() - if(istype(W, /obj/item/weapon/grab)) - if(user.is_busy()) return - var/obj/item/weapon/grab/G = W - var/mob/living/L = G.affecting - user.visible_message("[user] attempts to buckle [L] into \the [src]!") - if(do_after(user, 20, target = src)) - L.loc = loc - if(buckle_mob(L)) - L.visible_message(\ - "[L.name] is buckled to [src] by [user.name]!",\ - "You are buckled to [src] by [user.name]!",\ +/* Beds... get your mind out of the gutter, they're for sleeping! + * Contains: + * Beds + * Roller beds + */ + +/* + * Beds + */ +/obj/structure/stool/bed + name = "bed" + desc = "This is used to lie in, sleep in or strap on." + icon = 'icons/obj/objects.dmi' + icon_state = "bed" + can_buckle = 1 + buckle_lying = 1 + +/obj/structure/stool/bed/psych + name = "psychiatrists couch" + desc = "For prime comfort during psychiatric evaluations." + icon = 'icons/obj/objects.dmi' + icon_state = "psychbed" + +/obj/structure/stool/bed/alien + name = "resting contraption" + desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?" + icon = 'icons/obj/objects.dmi' + icon_state = "abed" + +/obj/structure/stool/bed/attack_paw(mob/user) + return src.attack_hand(user) + +/obj/structure/stool/bed/CanPass(atom/movable/mover) + if(iscarbon(mover) && mover.checkpass(PASSCRAWL)) + mover.layer = 2.7 + return ..() + +/obj/structure/stool/bed/CheckExit(atom/movable/O as mob|obj) + if(istype(O) && O.checkpass(PASSCRAWL)) + O.layer = 4.0 + return ..() + +/obj/structure/stool/bed/Process_Spacemove(movement_dir = 0) + if(buckled_mob) + return buckled_mob.Process_Spacemove(movement_dir) + return ..() + +/obj/structure/stool/bed/examine(mob/user) + ..() + var/T = get_turf(src) + var/mob/living/carbon/human/H = locate() in T + if(H && H.crawling) + to_chat(user, "Someone is hiding under [src]") + +/* + * Roller beds + */ +/obj/structure/stool/bed/roller + name = "roller bed" + icon = 'icons/obj/rollerbed.dmi' + icon_state = "down" + anchored = 0 + var/type_roller = /obj/item/roller + +/obj/structure/stool/bed/roller/attackby(obj/item/weapon/W, mob/user) + if(istype(W,src) || istype(W, /obj/item/roller_holder)) + user.SetNextMove(CLICK_CD_INTERACT) + if(buckled_mob) + user_unbuckle_mob() + else + visible_message("[user] collapses \the [src.name].") + new type_roller(get_turf(src)) + qdel(src) + else + ..() + +/obj/structure/stool/bed/roller/CanPass(atom/movable/mover) + if(iscarbon(mover) && mover.checkpass(PASSCRAWL)) + return 0 + return ..() + +/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. + var/type_bed = /obj/structure/stool/bed/roller + var/type_holder = /obj/item/roller_holder + + +/obj/item/roller/attack_self(mob/user) + var/obj/structure/stool/bed/roller/R = new type_bed(user.loc) + R.add_fingerprint(user) + qdel(src) + +/obj/item/roller/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/roller_holder)) + var/obj/item/roller_holder/RH = W + if(!RH.held) + to_chat(user, "You collect the roller bed.") + src.loc = RH + RH.held = src + return + ..() + +/obj/item/roller_holder + name = "roller bed rack" + desc = "A rack for carrying a collapsed roller bed." + icon = 'icons/obj/rollerbed.dmi' + icon_state = "folded" + var/held = /obj/item/roller + var/type_bed = /obj/structure/stool/bed/roller + +/obj/item/roller_holder/atom_init() + . = ..() + held = new held(src) + +/obj/item/roller_holder/attack_self(mob/user) + + if(!held) + to_chat(user, "The rack is empty.") + return + + to_chat(user, "You deploy the roller bed.") + var/obj/structure/stool/bed/roller/R = new type_bed(user.loc) + R.add_fingerprint(user) + qdel(held) + held = null + +/obj/structure/stool/bed/roller/post_buckle_mob(mob/living/M) + if(M == buckled_mob) + if(M.crawling) + M.pass_flags &= ~PASSCRAWL + M.crawling = FALSE + M.layer = 4.0 + density = 1 + icon_state = "up" + else + density = 0 + icon_state = "down" + return ..() + +/obj/structure/stool/bed/roller/MouseDrop(over_object, src_location, over_location) + ..() + if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src)))) + if(!ishuman(usr)) + return + if(buckled_mob) + return 0 + visible_message("[usr] collapses \the [src.name].") + new type_roller(get_turf(src)) + qdel(src) + return + +/obj/structure/stool/bed/attackby(obj/item/weapon/W, mob/user) + ..() + if(istype(W, /obj/item/weapon/grab)) + if(user.is_busy()) return + var/obj/item/weapon/grab/G = W + var/mob/living/L = G.affecting + user.visible_message("[user] attempts to buckle [L] into \the [src]!") + if(do_after(user, 20, target = src)) + L.loc = loc + if(buckle_mob(L)) + L.visible_message(\ + "[L.name] is buckled to [src] by [user.name]!",\ + "You are buckled to [src] by [user.name]!",\ "You hear metal clanking.") \ No newline at end of file diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index e664ef84ec45..11f95b5ba967 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -1,314 +1,314 @@ -/obj/structure/stool/bed/chair // YES, chairs are a type of bed, which are a type of stool. This works, believe me. -Pete - name = "chair" - desc = "You sit in this. Either by will or force." - icon = 'icons/obj/objects.dmi' - icon_state = "chair" - buckle_lying = FALSE // force people to sit up in chairs when buckled - var/can_flipped = FALSE - var/flipped = FALSE - var/flip_angle = FALSE - var/propelled = FALSE // Check for fire-extinguisher-driven chairs - - var/behind = null - var/behind_buckled = null - -/obj/structure/stool/bed/chair/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/structure/stool/bed/chair/atom_init_late() - handle_rotation() - -/obj/structure/stool/bed/chair/attackby(obj/item/weapon/W, mob/user) - ..() - 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 - user.drop_item() - var/obj/structure/stool/bed/chair/e_chair/E = new /obj/structure/stool/bed/chair/e_chair(src.loc) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - E.dir = dir - E.part = SK - SK.loc = E - SK.master = E - qdel(src) - -/obj/structure/stool/bed/chair/attack_hand(mob/user) - if(can_flip(user)) - var/flip_time = 20 //2 sec without someone - if(!isnull(buckled_mob)) - flip_time = 60 //6 sec with - user.SetNextMove(CLICK_CD_MELEE) - if(!flipped) - user.visible_message("[usr] flips \the [src] down.","You flips \the [src] down.") - flip() - if(buckled_mob && !buckled_mob.restrained()) - var/mob/living/L = buckled_mob - unbuckle_mob() - L.apply_effect(2, WEAKEN, 0) - L.apply_damage(3, BRUTE, BP_HEAD) - else if(!user.is_busy() && do_after(user, flip_time, target = usr)) - user.visible_message("[user] flips \the [src] up.","You flips \the [src] up.") - flip() - else - ..() - -/obj/structure/stool/bed/chair/user_buckle_mob(mob/living/M, mob/user) - if(dir == NORTH && !istype(src, /obj/structure/stool/bed/chair/schair/wagon/bench)) - layer = FLY_LAYER - else - layer = OBJ_LAYER - if(flipped) - to_chat(usr, "You can't do it, while \the [src] is flipped.") - if(usr != M) - to_chat(M, "Tried buckle you to \the [src].") - else - ..() - -/obj/structure/stool/bed/chair/attack_tk(mob/user) - if(buckled_mob) - ..() - else - rotate() - return - -/obj/structure/stool/bed/chair/handle_rotation() // making this into a seperate proc so office chairs can call it on Move() - if(dir == NORTH && buckled_mob) - layer = FLY_LAYER - else - layer = OBJ_LAYER - - if(buckled_mob) - buckled_mob.dir = dir - buckled_mob.update_canmove() - -/obj/structure/stool/bed/chair/verb/rotate() - set name = "Rotate Chair" - set category = "Object" - set src in oview(1) - - if(config.ghost_interaction) - src.dir = turn(src.dir, 90) - handle_rotation() - return - else - if(ismouse(usr)) - return - if(!usr || !isturf(usr.loc)) - return - if(usr.incapacitated()) - return - - src.dir = turn(src.dir, 90) - handle_rotation() - return - -/obj/structure/stool/bed/chair/post_buckle_mob(mob/living/M) - . = ..() - if(buckled_mob && behind) - icon_state = behind - else - icon_state = initial(icon_state) - if(dir == NORTH && buckled_mob && !istype(src, /obj/structure/stool/bed/chair/schair/wagon/bench)) - layer = FLY_LAYER - else - layer = OBJ_LAYER - -/obj/structure/stool/bed/chair/proc/can_flip(mob/living/carbon/human/user) - if(!user || !isturf(user.loc) || user.incapacitated() || user.lying || user.a_intent != "hurt"|| !can_flipped) - return 0 - return 1 - -/obj/structure/stool/bed/chair/proc/flip() - var/matrix/M = matrix(transform) - var/offset_y = 0 - var/offset_x = 0 - var/new_angle = pick(90, 270) - - if(!flipped) - M.TurnTo(0,new_angle) - flip_angle = new_angle // save our angle for future flip - if(new_angle==90) - offset_y = -4 - offset_x = 2 - else - offset_y = -4 - offset_x = -2 - flipped = 1 - anchored = 0 // can be pulled - buckle_movable = 0 - playsound(src.loc, 'sound/items/chair_fall.ogg', 25, 1) - else - M.TurnTo(flip_angle,0) - flipped = 0 - anchored = initial(anchored) - buckle_movable = initial(buckle_movable) - - animate(src, transform = M, pixel_y = offset_y, pixel_x = offset_x, time = 2, easing = EASE_IN|EASE_OUT) - handle_rotation() - -/obj/structure/stool/bed/chair/Move(atom/newloc, direct) - ..() - handle_rotation() - -/obj/structure/stool/bed/chair/barber - icon_state = "barber_chair" - -/obj/structure/stool/bed/chair/metal - icon_state = "chair_gray" - can_flipped = 1 - behind = "chair_behind_gray" - -/obj/structure/stool/bed/chair/metal/blue - icon_state = "chair_blue" - behind = "chair_behind_blue" - -/obj/structure/stool/bed/chair/metal/yellow - icon_state = "chair_yellow" - behind = "chair_behind_yellow" - -/obj/structure/stool/bed/chair/metal/red - icon_state = "chair_red" - behind = "chair_behind_red" - -/obj/structure/stool/bed/chair/metal/green - icon_state = "chair_green" - behind = "chair_behind_green" - -/obj/structure/stool/bed/chair/metal/white - icon_state = "chair_white" - behind = "chair_behind_white" - -/obj/structure/stool/bed/chair/metal/black - icon_state = "chair_black" - behind = "chair_behind_black" - -/obj/structure/stool/bed/chair/schair - name = "shuttle chair" - desc = "You sit in this. Either by will or force." - icon = 'icons/obj/objects.dmi' - icon_state = "schair" - var/sarmrest = null - -/obj/structure/stool/bed/chair/schair/atom_init() - sarmrest = image("icons/obj/objects.dmi", "schair_armrest", layer = FLY_LAYER) - . = ..() - -/obj/structure/stool/bed/chair/schair/post_buckle_mob(mob/living/M) - if(buckled_mob) - overlays += sarmrest - else - overlays -= sarmrest - -// Chair types -/obj/structure/stool/bed/chair/wood/normal - icon_state = "wooden_chair" - name = "wooden chair" - desc = "Old is never too old to not be in fashion." - -/obj/structure/stool/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/stool/bed/chair/wood/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/wrench)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - user.SetNextMove(CLICK_CD_RAPID) - new /obj/item/stack/sheet/wood(loc) - qdel(src) - return - else if(istype(W, /obj/item/weapon/melee/energy/blade)) - var/obj/item/weapon/melee/energy/blade/B = W - if(B.active) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(loc, "sparks", 50, 1) - visible_message("[src] was sliced apart by [user]!", "You hear [src] coming apart.") - new /obj/item/stack/sheet/wood(loc) - qdel(src) - return - ..() - -/obj/structure/stool/bed/chair/comfy - name = "comfy chair" - desc = "It looks comfy." - icon_state = "comfychair" - color = rgb(255,255,255) - var/armrest = null - -/obj/structure/stool/bed/chair/comfy/atom_init() - armrest = image("icons/obj/objects.dmi", "comfychair_armrest", layer = FLY_LAYER) - . = ..() - -/obj/structure/stool/bed/chair/comfy/post_buckle_mob(mob/living/M) - if(buckled_mob) - overlays += armrest - else - overlays -= armrest - -/obj/structure/stool/bed/chair/comfy/brown - color = rgb(255,113,0) - -/obj/structure/stool/bed/chair/comfy/beige - color = rgb(255,253,195) - -/obj/structure/stool/bed/chair/comfy/teal - color = rgb(0,255,255) - -/obj/structure/stool/bed/chair/comfy/black - color = rgb(167,164,153) - -/obj/structure/stool/bed/chair/comfy/lime - color = rgb(255,251,0) - -/obj/structure/stool/bed/chair/office - anchored = 0 - buckle_movable = 1 - can_flipped = 1 - -/obj/structure/stool/bed/chair/office/Move() - ..() - if(buckled_mob) - var/mob/living/occupant = buckled_mob - if (occupant && (src.loc != occupant.loc)) - if (propelled) - for (var/mob/O in src.loc) - if (O != occupant) - Bump(O) - else - unbuckle_mob() - handle_rotation() - -/obj/structure/stool/bed/chair/office/Bump(atom/A) - ..() - if(!buckled_mob) return - - if(propelled) - var/mob/living/occupant = unbuckle_mob() - occupant.throw_at(A, 3, propelled) - occupant.apply_effect(6, STUN, 0) - occupant.apply_effect(6, WEAKEN, 0) - occupant.apply_effect(6, STUTTER, 0) - playsound(src.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) - if(istype(A, /mob/living)) - var/mob/living/victim = A - victim.apply_effect(6, STUN, 0) - victim.apply_effect(6, WEAKEN, 0) - victim.apply_effect(6, STUTTER, 0) - victim.take_bodypart_damage(10) - occupant.visible_message("[occupant] crashed into \the [A]!") - -/obj/structure/stool/bed/chair/office/light - icon_state = "officechair_white" - behind = "officechair_white_behind" - -/obj/structure/stool/bed/chair/office/dark - icon_state = "officechair_dark" - behind = "officechair_dark_behind" +/obj/structure/stool/bed/chair // YES, chairs are a type of bed, which are a type of stool. This works, believe me. -Pete + name = "chair" + desc = "You sit in this. Either by will or force." + icon = 'icons/obj/objects.dmi' + icon_state = "chair" + buckle_lying = FALSE // force people to sit up in chairs when buckled + var/can_flipped = FALSE + var/flipped = FALSE + var/flip_angle = FALSE + var/propelled = FALSE // Check for fire-extinguisher-driven chairs + + var/behind = null + var/behind_buckled = null + +/obj/structure/stool/bed/chair/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/structure/stool/bed/chair/atom_init_late() + handle_rotation() + +/obj/structure/stool/bed/chair/attackby(obj/item/weapon/W, mob/user) + ..() + 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 + user.drop_item() + var/obj/structure/stool/bed/chair/e_chair/E = new /obj/structure/stool/bed/chair/e_chair(src.loc) + playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) + E.dir = dir + E.part = SK + SK.loc = E + SK.master = E + qdel(src) + +/obj/structure/stool/bed/chair/attack_hand(mob/user) + if(can_flip(user)) + var/flip_time = 20 //2 sec without someone + if(!isnull(buckled_mob)) + flip_time = 60 //6 sec with + user.SetNextMove(CLICK_CD_MELEE) + if(!flipped) + user.visible_message("[usr] flips \the [src] down.","You flips \the [src] down.") + flip() + if(buckled_mob && !buckled_mob.restrained()) + var/mob/living/L = buckled_mob + unbuckle_mob() + L.apply_effect(2, WEAKEN, 0) + L.apply_damage(3, BRUTE, BP_HEAD) + else if(!user.is_busy() && do_after(user, flip_time, target = usr)) + user.visible_message("[user] flips \the [src] up.","You flips \the [src] up.") + flip() + else + ..() + +/obj/structure/stool/bed/chair/user_buckle_mob(mob/living/M, mob/user) + if(dir == NORTH && !istype(src, /obj/structure/stool/bed/chair/schair/wagon/bench)) + layer = FLY_LAYER + else + layer = OBJ_LAYER + if(flipped) + to_chat(usr, "You can't do it, while \the [src] is flipped.") + if(usr != M) + to_chat(M, "Tried buckle you to \the [src].") + else + ..() + +/obj/structure/stool/bed/chair/attack_tk(mob/user) + if(buckled_mob) + ..() + else + rotate() + return + +/obj/structure/stool/bed/chair/handle_rotation() // making this into a seperate proc so office chairs can call it on Move() + if(dir == NORTH && buckled_mob) + layer = FLY_LAYER + else + layer = OBJ_LAYER + + if(buckled_mob) + buckled_mob.dir = dir + buckled_mob.update_canmove() + +/obj/structure/stool/bed/chair/verb/rotate() + set name = "Rotate Chair" + set category = "Object" + set src in oview(1) + + if(config.ghost_interaction) + src.dir = turn(src.dir, 90) + handle_rotation() + return + else + if(ismouse(usr)) + return + if(!usr || !isturf(usr.loc)) + return + if(usr.incapacitated()) + return + + src.dir = turn(src.dir, 90) + handle_rotation() + return + +/obj/structure/stool/bed/chair/post_buckle_mob(mob/living/M) + . = ..() + if(buckled_mob && behind) + icon_state = behind + else + icon_state = initial(icon_state) + if(dir == NORTH && buckled_mob && !istype(src, /obj/structure/stool/bed/chair/schair/wagon/bench)) + layer = FLY_LAYER + else + layer = OBJ_LAYER + +/obj/structure/stool/bed/chair/proc/can_flip(mob/living/carbon/human/user) + if(!user || !isturf(user.loc) || user.incapacitated() || user.lying || user.a_intent != "hurt"|| !can_flipped) + return 0 + return 1 + +/obj/structure/stool/bed/chair/proc/flip() + var/matrix/M = matrix(transform) + var/offset_y = 0 + var/offset_x = 0 + var/new_angle = pick(90, 270) + + if(!flipped) + M.TurnTo(0,new_angle) + flip_angle = new_angle // save our angle for future flip + if(new_angle==90) + offset_y = -4 + offset_x = 2 + else + offset_y = -4 + offset_x = -2 + flipped = 1 + anchored = 0 // can be pulled + buckle_movable = 0 + playsound(src.loc, 'sound/items/chair_fall.ogg', 25, 1) + else + M.TurnTo(flip_angle,0) + flipped = 0 + anchored = initial(anchored) + buckle_movable = initial(buckle_movable) + + animate(src, transform = M, pixel_y = offset_y, pixel_x = offset_x, time = 2, easing = EASE_IN|EASE_OUT) + handle_rotation() + +/obj/structure/stool/bed/chair/Move(atom/newloc, direct) + ..() + handle_rotation() + +/obj/structure/stool/bed/chair/barber + icon_state = "barber_chair" + +/obj/structure/stool/bed/chair/metal + icon_state = "chair_gray" + can_flipped = 1 + behind = "chair_behind_gray" + +/obj/structure/stool/bed/chair/metal/blue + icon_state = "chair_blue" + behind = "chair_behind_blue" + +/obj/structure/stool/bed/chair/metal/yellow + icon_state = "chair_yellow" + behind = "chair_behind_yellow" + +/obj/structure/stool/bed/chair/metal/red + icon_state = "chair_red" + behind = "chair_behind_red" + +/obj/structure/stool/bed/chair/metal/green + icon_state = "chair_green" + behind = "chair_behind_green" + +/obj/structure/stool/bed/chair/metal/white + icon_state = "chair_white" + behind = "chair_behind_white" + +/obj/structure/stool/bed/chair/metal/black + icon_state = "chair_black" + behind = "chair_behind_black" + +/obj/structure/stool/bed/chair/schair + name = "shuttle chair" + desc = "You sit in this. Either by will or force." + icon = 'icons/obj/objects.dmi' + icon_state = "schair" + var/sarmrest = null + +/obj/structure/stool/bed/chair/schair/atom_init() + sarmrest = image("icons/obj/objects.dmi", "schair_armrest", layer = FLY_LAYER) + . = ..() + +/obj/structure/stool/bed/chair/schair/post_buckle_mob(mob/living/M) + if(buckled_mob) + overlays += sarmrest + else + overlays -= sarmrest + +// Chair types +/obj/structure/stool/bed/chair/wood/normal + icon_state = "wooden_chair" + name = "wooden chair" + desc = "Old is never too old to not be in fashion." + +/obj/structure/stool/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/stool/bed/chair/wood/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/wrench)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + user.SetNextMove(CLICK_CD_RAPID) + new /obj/item/stack/sheet/wood(loc) + qdel(src) + return + else if(istype(W, /obj/item/weapon/melee/energy/blade)) + var/obj/item/weapon/melee/energy/blade/B = W + if(B.active) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src.loc) + spark_system.start() + playsound(loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(loc, "sparks", 50, 1) + visible_message("[src] was sliced apart by [user]!", "You hear [src] coming apart.") + new /obj/item/stack/sheet/wood(loc) + qdel(src) + return + ..() + +/obj/structure/stool/bed/chair/comfy + name = "comfy chair" + desc = "It looks comfy." + icon_state = "comfychair" + color = rgb(255,255,255) + var/armrest = null + +/obj/structure/stool/bed/chair/comfy/atom_init() + armrest = image("icons/obj/objects.dmi", "comfychair_armrest", layer = FLY_LAYER) + . = ..() + +/obj/structure/stool/bed/chair/comfy/post_buckle_mob(mob/living/M) + if(buckled_mob) + overlays += armrest + else + overlays -= armrest + +/obj/structure/stool/bed/chair/comfy/brown + color = rgb(255,113,0) + +/obj/structure/stool/bed/chair/comfy/beige + color = rgb(255,253,195) + +/obj/structure/stool/bed/chair/comfy/teal + color = rgb(0,255,255) + +/obj/structure/stool/bed/chair/comfy/black + color = rgb(167,164,153) + +/obj/structure/stool/bed/chair/comfy/lime + color = rgb(255,251,0) + +/obj/structure/stool/bed/chair/office + anchored = 0 + buckle_movable = 1 + can_flipped = 1 + +/obj/structure/stool/bed/chair/office/Move() + ..() + if(buckled_mob) + var/mob/living/occupant = buckled_mob + if (occupant && (src.loc != occupant.loc)) + if (propelled) + for (var/mob/O in src.loc) + if (O != occupant) + Bump(O) + else + unbuckle_mob() + handle_rotation() + +/obj/structure/stool/bed/chair/office/Bump(atom/A) + ..() + if(!buckled_mob) return + + if(propelled) + var/mob/living/occupant = unbuckle_mob() + occupant.throw_at(A, 3, propelled) + occupant.apply_effect(6, STUN, 0) + occupant.apply_effect(6, WEAKEN, 0) + occupant.apply_effect(6, STUTTER, 0) + playsound(src.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) + if(istype(A, /mob/living)) + var/mob/living/victim = A + victim.apply_effect(6, STUN, 0) + victim.apply_effect(6, WEAKEN, 0) + victim.apply_effect(6, STUTTER, 0) + victim.take_bodypart_damage(10) + occupant.visible_message("[occupant] crashed into \the [A]!") + +/obj/structure/stool/bed/chair/office/light + icon_state = "officechair_white" + behind = "officechair_white_behind" + +/obj/structure/stool/bed/chair/office/dark + icon_state = "officechair_dark" + behind = "officechair_dark_behind" 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 6dd044d67f5c..e3bd60e0687f 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm @@ -1,105 +1,105 @@ -/obj/structure/stool - name = "stool" - desc = "Apply butt." - icon = 'icons/obj/objects.dmi' - icon_state = "stool" - anchored = 1.0 - -/obj/structure/stool/bar - name = "bar stool" - icon = 'icons/obj/objects.dmi' - icon_state = "bar_chair" - -/obj/structure/stool/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 - -/obj/structure/stool/blob_act() - if(prob(75)) - new /obj/item/stack/sheet/metal(loc) - qdel(src) - -/obj/structure/stool/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/wrench) && !(flags & NODECONSTRUCT)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - new /obj/item/stack/sheet/metal(loc) - qdel(src) - return - else if(istype(W, /obj/item/weapon/melee/energy/blade)) - var/obj/item/weapon/melee/energy/blade/B = W - if(B.active) - user.do_attack_animation(src) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(src.loc, "sparks", 50, 1) - visible_message("[src] was sliced apart by [user]!", "You hear [src] coming apart.") - if(!(flags & NODECONSTRUCT)) - new /obj/item/stack/sheet/metal(loc) - qdel(src) - return - ..() - -/obj/structure/stool/MouseDrop(atom/over_object) - if(ishuman(over_object) && type == /obj/structure/stool) - var/mob/living/carbon/human/H = over_object - if(H == usr && !H.restrained() && !H.stat && in_range(src, over_object)) - var/obj/item/weapon/stool/S = new - S.origin_stool = src - src.loc = S - H.put_in_hands(S) - H.visible_message("[H] grabs [src] from the floor!", "You grab [src] from the floor!") - return - return ..() - -/obj/item/weapon/stool - name = "stool" - desc = "Uh-hoh, bar is heating up." - icon = 'icons/obj/objects.dmi' - icon_state = "stool" - force = 10 - throwforce = 10 - w_class = 5.0 - var/obj/structure/stool/origin_stool = null - -/obj/item/weapon/stool/throw_at() - return - -/obj/item/weapon/stool/Destroy() - if(origin_stool) - qdel(origin_stool) - origin_stool = null - return ..() - -/obj/item/weapon/stool/attack_self(mob/user) - user.drop_from_inventory(src) - user.visible_message("[user] dropped [src].", "You dropped [src].") - -/obj/item/weapon/stool/dropped(mob/user) - if(origin_stool) - origin_stool.loc = src.loc - origin_stool = null - qdel(src) - -/obj/item/weapon/stool/attack(mob/M, mob/user) - if (prob(5) && isliving(M)) - user.visible_message("[user] breaks [src] over [M]'s back!") - new /obj/item/stack/sheet/metal(get_turf(src)) - qdel(src) - var/mob/living/T = M - T.Weaken(10) - T.apply_damage(20) - return - ..() +/obj/structure/stool + name = "stool" + desc = "Apply butt." + icon = 'icons/obj/objects.dmi' + icon_state = "stool" + anchored = 1.0 + +/obj/structure/stool/bar + name = "bar stool" + icon = 'icons/obj/objects.dmi' + icon_state = "bar_chair" + +/obj/structure/stool/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 + +/obj/structure/stool/blob_act() + if(prob(75)) + new /obj/item/stack/sheet/metal(loc) + qdel(src) + +/obj/structure/stool/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/wrench) && !(flags & NODECONSTRUCT)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + new /obj/item/stack/sheet/metal(loc) + qdel(src) + return + else if(istype(W, /obj/item/weapon/melee/energy/blade)) + var/obj/item/weapon/melee/energy/blade/B = W + if(B.active) + user.do_attack_animation(src) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src.loc) + spark_system.start() + playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(src.loc, "sparks", 50, 1) + visible_message("[src] was sliced apart by [user]!", "You hear [src] coming apart.") + if(!(flags & NODECONSTRUCT)) + new /obj/item/stack/sheet/metal(loc) + qdel(src) + return + ..() + +/obj/structure/stool/MouseDrop(atom/over_object) + if(ishuman(over_object) && type == /obj/structure/stool) + var/mob/living/carbon/human/H = over_object + if(H == usr && !H.restrained() && !H.stat && in_range(src, over_object)) + var/obj/item/weapon/stool/S = new + S.origin_stool = src + src.loc = S + H.put_in_hands(S) + H.visible_message("[H] grabs [src] from the floor!", "You grab [src] from the floor!") + return + return ..() + +/obj/item/weapon/stool + name = "stool" + desc = "Uh-hoh, bar is heating up." + icon = 'icons/obj/objects.dmi' + icon_state = "stool" + force = 10 + throwforce = 10 + w_class = 5.0 + var/obj/structure/stool/origin_stool = null + +/obj/item/weapon/stool/throw_at() + return + +/obj/item/weapon/stool/Destroy() + if(origin_stool) + qdel(origin_stool) + origin_stool = null + return ..() + +/obj/item/weapon/stool/attack_self(mob/user) + user.drop_from_inventory(src) + user.visible_message("[user] dropped [src].", "You dropped [src].") + +/obj/item/weapon/stool/dropped(mob/user) + if(origin_stool) + origin_stool.loc = src.loc + origin_stool = null + qdel(src) + +/obj/item/weapon/stool/attack(mob/M, mob/user) + if (prob(5) && isliving(M)) + user.visible_message("[user] breaks [src] over [M]'s back!") + new /obj/item/stack/sheet/metal(get_turf(src)) + qdel(src) + var/mob/living/T = M + T.Weaken(10) + T.apply_damage(20) + return + ..() diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index c976e5092f3a..78c7e89e4655 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -1,836 +1,836 @@ -/* 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/tables.dmi' - icon_state = "table" - density = 1 - anchored = 1.0 - layer = CONTAINER_STRUCTURE_LAYER - throwpass = 1 //You can throw objects over this, despite it's density.") - climbable = 1 - - var/parts = /obj/item/weapon/table_parts - var/flipped = 0 - var/health = 100 - var/canconnect = TRUE - -/obj/structure/table/proc/update_adjacent() - for(var/direction in list(1,2,4,8,5,6,9,10)) - 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/atom_init() - . = ..() - for(var/obj/structure/table/T in src.loc) - if(T != src) - qdel(T) - update_icon() - update_adjacent() - -/obj/structure/table/Destroy() - update_adjacent() - return ..() - -/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/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 (canconnect && T && T.flipped && T.canconnect && 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" - if (istype(src, /obj/structure/table/woodentable/poker)) - base = "poker" - - 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 list(1,2,4,8,5,6,9,10)) - 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 && T.canconnect && canconnect) - 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)) - var/obj/structure/table/T = locate(/obj/structure/table,get_step(src.loc,dir_sum%16)) - if(T && T.canconnect && canconnect) - 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 list(1,2,4,8,5,6,9,10)) - dir = dir_sum - else - dir = 2 - -/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(HULK in user.mutations) - user.SetNextMove(CLICK_CD_MELEE) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - visible_message("[user] smashes the [src] apart!") - destroy() - - -/obj/structure/table/attack_alien(mob/user) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - visible_message("[user] slices [src] apart!") - if(istype(src, /obj/structure/table/reinforced)) - return - else if(istype(src, /obj/structure/table/woodentable/fancy/black)) - new/obj/item/weapon/table_parts/wood/fancy/black(loc) - else if(istype(src, /obj/structure/table/woodentable/fancy)) - new/obj/item/weapon/table_parts/wood/fancy(loc) - else if(istype(src, /obj/structure/table/woodentable)) - new/obj/item/weapon/table_parts/wood(loc) - else if(istype(src, /obj/structure/table/woodentable/poker)) - new/obj/item/weapon/table_parts/wood(loc) - else if(istype(src, /obj/structure/table/glass)) - var/obj/structure/table/glass/glasstable = src - glasstable.shatter() - else - new /obj/item/weapon/table_parts(loc) - density = 0 - qdel(src) - -/obj/structure/table/attack_animal(mob/living/simple_animal/user) - if(user.environment_smash) - ..() - playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) - visible_message("[user] smashes [src] apart!") - destroy() - - - -/obj/structure/table/attack_hand(mob/user) - if(HULK in user.mutations) - user.SetNextMove(CLICK_CD_MELEE) - 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=0, air_group=0) - if(air_group || (height==0)) return 1 - if(istype(mover,/obj/item/projectile)) - return (check_cover(mover,target)) - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - if(iscarbon(mover) && mover.checkpass(PASSCRAWL)) - mover.layer = 2.7 - return 1 - if(locate(/obj/structure/table) in get_turf(mover)) - return 1 - if (flipped) - if (get_dir(loc, target) == dir) - return !density - else - return 1 - return 0 - -//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, target) - if(istype(O) && O.checkpass(PASSTABLE)) - return 1 - if(istype(O) && O.checkpass(PASSCRAWL)) - O.layer = 4.0 - 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(isessence(usr) || isrobot(usr)) - return - var/obj/item/weapon/W = O - if(!W.canremove || W.flags & NODROP) - return - user.drop_item() - if (O.loc != src.loc) - step(O, get_dir(O, src)) - return - - -/obj/structure/table/attackby(obj/item/W, mob/user, params) - . = TRUE - if (istype(W, /obj/item/weapon/grab) && get_dist(src,user) < 2) - var/obj/item/weapon/grab/G = W - if(isliving(G.affecting)) - var/mob/living/M = G.affecting - var/mob/living/A = G.assailant - user.SetNextMove(CLICK_CD_MELEE) - if (G.state < GRAB_AGGRESSIVE) - if(user.a_intent == "hurt") - slam(A, M, G) - else - to_chat(user, "You need a better grip to do that!") - return - else - if(world.time < (G.last_action + UPGRADE_COOLDOWN)) - return - G.affecting.loc = src.loc - G.affecting.Weaken(5) - visible_message("[G.assailant] puts [G.affecting] on \the [src].") - M.attack_log += "\[[time_stamp()]\] Was laied by [A.name] on \the [src]([A.ckey])" - A.attack_log += "\[[time_stamp()]\] Put [M.name] on \the [src]([M.ckey])" - qdel(W) - return - - if (istype(W, /obj/item/weapon/wrench)) - if(user.is_busy()) return - to_chat(user, "\blue Now disassembling table") - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user,50, target = src)) - destroy() - return - - if(isrobot(user)) - return - if(!W.canremove || W.flags & NODROP) - return - - if(istype(W, /obj/item/weapon/melee/energy) || istype(W, /obj/item/weapon/pen/edagger) || istype(W,/obj/item/weapon/twohanded/dualsaber)) - if(istype(W, /obj/item/weapon/melee/energy/blade) || (W.force > 3 && user.a_intent == "hurt")) - if(istype(src, /obj/structure/table/reinforced) && W:active) - ..() - to_chat(user, "You tried to slice through [src] but [W] is too weak.") - return FALSE - user.do_attack_animation(src) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(src.loc, "sparks", 50, 1) - visible_message("[src] was sliced apart by [user]!", "You hear [src] coming apart.") - user.SetNextMove(CLICK_CD_MELEE) - destroy() - return FALSE - - if(!(W.flags & ABSTRACT)) - if(user.drop_item()) - W.Move(loc) - var/list/click_params = params2list(params) - //Center the icon where the user clicked. - if(!click_params || !click_params["icon-x"] || !click_params["icon-y"]) - return - W.pixel_x = Clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2) - W.pixel_y = Clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2) - return - -/obj/structure/table/proc/slam(var/mob/living/A, var/mob/living/M, var/obj/item/weapon/grab/G) - if (prob(15)) - M.Weaken(5) - M.apply_damage(8,def_zone = BP_HEAD) - visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!") - playsound(src.loc, 'sound/weapons/tablehit1.ogg', 50, 1) - M.attack_log += "\[[time_stamp()]\] Slammed with face by [A.name] against \the [src]([A.ckey])" - A.attack_log += "\[[time_stamp()]\] Slams face of [M.name] against \the [src]([M.ckey])" - msg_admin_attack("[key_name(A)] slams [key_name(M)] face against \the [src]") - -/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/do_flip() - set name = "Flip table" - set desc = "Flips a non-reinforced table." - set category = "Object" - set src in oview(1) - - if (!can_touch(usr) || ismouse(usr)) - return - - if(!flip(get_cardinal_dir(usr,src))) - to_chat(usr, "It won't budge.") - return - - usr.visible_message("[usr] flips \the [src]!") - - if(climbable) - structure_shaken() - - return - -/obj/structure/table/proc/unflipping_check(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(ismouse(usr)) - return - if (!can_touch(usr)) - return - - if (!unflipping_check()) - to_chat(usr, "It won't budge.") - return - unflip() - -/obj/structure/table/proc/flip(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) - 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) - plane = initial(plane) - 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 - -/* - * Glass tables - */ -/obj/structure/table/glass - name = "glass table" - desc = "Looks fragile. You should totally flip it. It is begging for it." - icon_state = "glasstable" - parts = /obj/item/weapon/table_parts/glass - health = 10 - -/obj/structure/table/glass/flip(direction) - if( !straight_table_check(turn(direction,90)) || !straight_table_check(turn(direction,-90)) ) - return 0 - - 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) - - shatter() - - return 1 - -/obj/structure/table/glass/proc/shatter() - 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) - A.throw_at(pick(targets),1,1) - - canconnect = FALSE - update_adjacent() - playsound(src.loc, "shatter", 50, 1) - visible_message("[src] breaks!") - var/obj/item/weapon/shard/debri = new /obj/item/weapon/shard( src.loc ) - debri.throw_at(pick(targets),1,1) - qdel(src) - -/obj/structure/table/glass/on_climb(mob/living/user) - usr.forceMove(get_turf(src)) - if(check_break(user)) - usr.visible_message("[user] tries to climb onto \the [src], but breaks it!") - else - ..() - -/obj/structure/table/glass/Crossed(atom/movable/AM) - . = ..() - check_break(AM) - -/obj/structure/table/glass/proc/check_break(mob/living/M) - if(istype(M) && (M.checkpass(PASSTABLE) || M.checkpass(PASSCRAWL))) - return FALSE - - if(has_gravity(M) && ishuman(M)) - M.Weaken(5) - shatter() - return TRUE - else - return FALSE - -/obj/structure/table/glass/slam(var/mob/living/A, var/mob/living/M, var/obj/item/weapon/grab/G) - M.Weaken(5) - visible_message("[G.assailant] slams [G.affecting]'s face against \the [src], breaking it!") - playsound(src.loc, 'sound/weapons/tablehit1.ogg', 50, 1) - M.attack_log += "\[[time_stamp()]\] Slammed with face by [A.name] against \the [src]([A.ckey]), breaking it" - A.attack_log += "\[[time_stamp()]\] Slams face of [M.name] against \the [src]([M.ckey]), breaking it" - msg_admin_attack("[key_name(A)] slams [key_name(M)] face against \the [src], breaking it") - if(prob(30) && ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] - BP.createwound(CUT, 15) - BP.embed(new /obj/item/weapon/shard) - H.emote("scream",,, 1) - else - M.apply_damage(15,def_zone = BP_HEAD) - shatter() - -/* - * 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 - -/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 - health = 50 - -/obj/structure/table/woodentable/fancy - name = "fancy table" - desc = "A standard metal table frame covered with an amazingly fancy, patterned cloth." - icon_state = "fancytable" - parts = /obj/item/weapon/table_parts/wood/fancy - -/obj/structure/table/woodentable/fancy/black - icon_state = "fancytable_black" - parts = /obj/item/weapon/table_parts/wood/fancy/black - -/* - * Reinforced tables - */ -/obj/structure/table/reinforced - name = "reinforced table" - desc = "A version of the four legged table. It is stronger." - icon_state = "reinftable" - health = 200 - var/status = 2 - parts = /obj/item/weapon/table_parts/reinforced - -/obj/structure/table/reinforced/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group || (height==0)) return 1 - if(istype(mover,/obj/item/projectile)) - return (check_cover(mover,target)) - if(istype(mover) && mover.checkpass(PASSTABLE)) - return 1 - if(locate(/obj/structure/table) in get_turf(mover)) - return 1 - if (flipped) - if (get_dir(loc, target) == dir) - return !density - else - return 1 - return 0 - -/obj/structure/table/reinforced/flip(direction) - if (status == 2) - return 0 - else - return ..() - -/obj/structure/table/reinforced/attackby(obj/item/weapon/W, mob/user, params) - if (istype(W, /obj/item/weapon/weldingtool)) - if(user.is_busy()) return FALSE - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - if(src.status == 2) - to_chat(user, "\blue Now weakening the reinforced table") - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) - if (do_after(user, 50, target = src)) - if(!src || !WT.isOn()) return - to_chat(user, "\blue Table weakened") - src.status = 1 - else - to_chat(user, "\blue Now strengthening the reinforced table") - playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) - if (do_after(user, 50, target = src)) - if(!src || !WT.isOn()) return - to_chat(user, "\blue Table strengthened") - src.status = 2 - return FALSE - return TRUE - - if (istype(W, /obj/item/weapon/wrench)) - if(src.status == 2) - return TRUE - - return ..() - -/* - * Racks - */ -/obj/structure/rack - name = "rack" - desc = "Different from the Middle Ages version." - icon = 'icons/obj/objects.dmi' - icon_state = "rack" - density = 1 - anchored = 1.0 - layer = CONTAINER_STRUCTURE_LAYER - throwpass = 1 //You can throw objects over this, despite it's density. - var/parts = /obj/item/weapon/rack_parts - -/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)) - qdel(src) - return - else if(prob(50)) - new /obj/item/weapon/rack_parts(src.loc) - qdel(src) - return - -/obj/structure/rack/CanPass(atom/movable/mover, turf/target, height=0, 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/MouseDrop_T(obj/O, mob/user) - if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) - return - if(isrobot(user) || isessence(user)) - return - var/obj/item/weapon/W = O - if(!W.canremove || W.flags & NODROP) - return - user.drop_item() - if (O.loc != src.loc) - step(O, get_dir(O, src)) - return - -/obj/structure/rack/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/wrench)) - new /obj/item/weapon/rack_parts( src.loc ) - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - qdel(src) - return - if(istype(W, /obj/item/weapon/melee/energy)||istype(W, /obj/item/weapon/twohanded/dualsaber)) - if(istype(W, /obj/item/weapon/melee/energy/blade) || (W:active && user.a_intent == "hurt")) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(src.loc, "sparks", 50, 1) - visible_message("[src] was sliced apart by [user]!", " You hear [src] coming apart.") - destroy() - return - if(isrobot(user)) - return - if(!W.canremove || W.flags & NODROP) - return - user.drop_item() - if(W && W.loc) W.loc = src.loc - return - -/obj/structure/rack/meteorhit(obj/O) - qdel(src) - - -/obj/structure/table/attack_hand(mob/user) - if(HULK in user.mutations) - user.SetNextMove(CLICK_CD_MELEE) - user.do_attack_animation(src) - visible_message("[user] smashes [src] apart!") - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - destroy() - -/obj/structure/rack/attack_paw(mob/user) - if(HULK in user.mutations) - user.SetNextMove(CLICK_CD_MELEE) - user.do_attack_animation(src) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - visible_message("[user] smashes [src] apart!") - destroy() - -/obj/structure/rack/attack_alien(mob/user) - user.do_attack_animation(src) - user.SetNextMove(CLICK_CD_MELEE) - visible_message("[user] slices [src] apart!") - destroy() - -/obj/structure/rack/attack_animal(mob/living/simple_animal/user) - if(user.environment_smash) - ..() - playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) - user.do_attack_animation(src) - visible_message("[user] smashes [src] apart!") - destroy() - -/obj/structure/rack/attack_tk() // no telehulk sorry - return +/* 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/tables.dmi' + icon_state = "table" + density = 1 + anchored = 1.0 + layer = CONTAINER_STRUCTURE_LAYER + throwpass = 1 //You can throw objects over this, despite it's density.") + climbable = 1 + + var/parts = /obj/item/weapon/table_parts + var/flipped = 0 + var/health = 100 + var/canconnect = TRUE + +/obj/structure/table/proc/update_adjacent() + for(var/direction in list(1,2,4,8,5,6,9,10)) + 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/atom_init() + . = ..() + for(var/obj/structure/table/T in src.loc) + if(T != src) + qdel(T) + update_icon() + update_adjacent() + +/obj/structure/table/Destroy() + update_adjacent() + return ..() + +/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/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 (canconnect && T && T.flipped && T.canconnect && 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" + if (istype(src, /obj/structure/table/woodentable/poker)) + base = "poker" + + 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 list(1,2,4,8,5,6,9,10)) + 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 && T.canconnect && canconnect) + 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)) + var/obj/structure/table/T = locate(/obj/structure/table,get_step(src.loc,dir_sum%16)) + if(T && T.canconnect && canconnect) + 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 list(1,2,4,8,5,6,9,10)) + dir = dir_sum + else + dir = 2 + +/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(HULK in user.mutations) + user.SetNextMove(CLICK_CD_MELEE) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + visible_message("[user] smashes the [src] apart!") + destroy() + + +/obj/structure/table/attack_alien(mob/user) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + visible_message("[user] slices [src] apart!") + if(istype(src, /obj/structure/table/reinforced)) + return + else if(istype(src, /obj/structure/table/woodentable/fancy/black)) + new/obj/item/weapon/table_parts/wood/fancy/black(loc) + else if(istype(src, /obj/structure/table/woodentable/fancy)) + new/obj/item/weapon/table_parts/wood/fancy(loc) + else if(istype(src, /obj/structure/table/woodentable)) + new/obj/item/weapon/table_parts/wood(loc) + else if(istype(src, /obj/structure/table/woodentable/poker)) + new/obj/item/weapon/table_parts/wood(loc) + else if(istype(src, /obj/structure/table/glass)) + var/obj/structure/table/glass/glasstable = src + glasstable.shatter() + else + new /obj/item/weapon/table_parts(loc) + density = 0 + qdel(src) + +/obj/structure/table/attack_animal(mob/living/simple_animal/user) + if(user.environment_smash) + ..() + playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) + visible_message("[user] smashes [src] apart!") + destroy() + + + +/obj/structure/table/attack_hand(mob/user) + if(HULK in user.mutations) + user.SetNextMove(CLICK_CD_MELEE) + 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=0, air_group=0) + if(air_group || (height==0)) return 1 + if(istype(mover,/obj/item/projectile)) + return (check_cover(mover,target)) + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + if(iscarbon(mover) && mover.checkpass(PASSCRAWL)) + mover.layer = 2.7 + return 1 + if(locate(/obj/structure/table) in get_turf(mover)) + return 1 + if (flipped) + if (get_dir(loc, target) == dir) + return !density + else + return 1 + return 0 + +//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, target) + if(istype(O) && O.checkpass(PASSTABLE)) + return 1 + if(istype(O) && O.checkpass(PASSCRAWL)) + O.layer = 4.0 + 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(isessence(usr) || isrobot(usr)) + return + var/obj/item/weapon/W = O + if(!W.canremove || W.flags & NODROP) + return + user.drop_item() + if (O.loc != src.loc) + step(O, get_dir(O, src)) + return + + +/obj/structure/table/attackby(obj/item/W, mob/user, params) + . = TRUE + if (istype(W, /obj/item/weapon/grab) && get_dist(src,user) < 2) + var/obj/item/weapon/grab/G = W + if(isliving(G.affecting)) + var/mob/living/M = G.affecting + var/mob/living/A = G.assailant + user.SetNextMove(CLICK_CD_MELEE) + if (G.state < GRAB_AGGRESSIVE) + if(user.a_intent == "hurt") + slam(A, M, G) + else + to_chat(user, "You need a better grip to do that!") + return + else + if(world.time < (G.last_action + UPGRADE_COOLDOWN)) + return + G.affecting.loc = src.loc + G.affecting.Weaken(5) + visible_message("[G.assailant] puts [G.affecting] on \the [src].") + M.attack_log += "\[[time_stamp()]\] Was laied by [A.name] on \the [src]([A.ckey])" + A.attack_log += "\[[time_stamp()]\] Put [M.name] on \the [src]([M.ckey])" + qdel(W) + return + + if (istype(W, /obj/item/weapon/wrench)) + if(user.is_busy()) return + to_chat(user, "\blue Now disassembling table") + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user,50, target = src)) + destroy() + return + + if(isrobot(user)) + return + if(!W.canremove || W.flags & NODROP) + return + + if(istype(W, /obj/item/weapon/melee/energy) || istype(W, /obj/item/weapon/pen/edagger) || istype(W,/obj/item/weapon/twohanded/dualsaber)) + if(istype(W, /obj/item/weapon/melee/energy/blade) || (W.force > 3 && user.a_intent == "hurt")) + if(istype(src, /obj/structure/table/reinforced) && W:active) + ..() + to_chat(user, "You tried to slice through [src] but [W] is too weak.") + return FALSE + user.do_attack_animation(src) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src.loc) + spark_system.start() + playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(src.loc, "sparks", 50, 1) + visible_message("[src] was sliced apart by [user]!", "You hear [src] coming apart.") + user.SetNextMove(CLICK_CD_MELEE) + destroy() + return FALSE + + if(!(W.flags & ABSTRACT)) + if(user.drop_item()) + W.Move(loc) + var/list/click_params = params2list(params) + //Center the icon where the user clicked. + if(!click_params || !click_params["icon-x"] || !click_params["icon-y"]) + return + W.pixel_x = Clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2) + W.pixel_y = Clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2) + return + +/obj/structure/table/proc/slam(var/mob/living/A, var/mob/living/M, var/obj/item/weapon/grab/G) + if (prob(15)) + M.Weaken(5) + M.apply_damage(8,def_zone = BP_HEAD) + visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!") + playsound(src.loc, 'sound/weapons/tablehit1.ogg', 50, 1) + M.attack_log += "\[[time_stamp()]\] Slammed with face by [A.name] against \the [src]([A.ckey])" + A.attack_log += "\[[time_stamp()]\] Slams face of [M.name] against \the [src]([M.ckey])" + msg_admin_attack("[key_name(A)] slams [key_name(M)] face against \the [src]") + +/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/do_flip() + set name = "Flip table" + set desc = "Flips a non-reinforced table." + set category = "Object" + set src in oview(1) + + if (!can_touch(usr) || ismouse(usr)) + return + + if(!flip(get_cardinal_dir(usr,src))) + to_chat(usr, "It won't budge.") + return + + usr.visible_message("[usr] flips \the [src]!") + + if(climbable) + structure_shaken() + + return + +/obj/structure/table/proc/unflipping_check(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(ismouse(usr)) + return + if (!can_touch(usr)) + return + + if (!unflipping_check()) + to_chat(usr, "It won't budge.") + return + unflip() + +/obj/structure/table/proc/flip(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) + 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) + plane = initial(plane) + 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 + +/* + * Glass tables + */ +/obj/structure/table/glass + name = "glass table" + desc = "Looks fragile. You should totally flip it. It is begging for it." + icon_state = "glasstable" + parts = /obj/item/weapon/table_parts/glass + health = 10 + +/obj/structure/table/glass/flip(direction) + if( !straight_table_check(turn(direction,90)) || !straight_table_check(turn(direction,-90)) ) + return 0 + + 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) + + shatter() + + return 1 + +/obj/structure/table/glass/proc/shatter() + 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) + A.throw_at(pick(targets),1,1) + + canconnect = FALSE + update_adjacent() + playsound(src.loc, "shatter", 50, 1) + visible_message("[src] breaks!") + var/obj/item/weapon/shard/debri = new /obj/item/weapon/shard( src.loc ) + debri.throw_at(pick(targets),1,1) + qdel(src) + +/obj/structure/table/glass/on_climb(mob/living/user) + usr.forceMove(get_turf(src)) + if(check_break(user)) + usr.visible_message("[user] tries to climb onto \the [src], but breaks it!") + else + ..() + +/obj/structure/table/glass/Crossed(atom/movable/AM) + . = ..() + check_break(AM) + +/obj/structure/table/glass/proc/check_break(mob/living/M) + if(istype(M) && (M.checkpass(PASSTABLE) || M.checkpass(PASSCRAWL))) + return FALSE + + if(has_gravity(M) && ishuman(M)) + M.Weaken(5) + shatter() + return TRUE + else + return FALSE + +/obj/structure/table/glass/slam(var/mob/living/A, var/mob/living/M, var/obj/item/weapon/grab/G) + M.Weaken(5) + visible_message("[G.assailant] slams [G.affecting]'s face against \the [src], breaking it!") + playsound(src.loc, 'sound/weapons/tablehit1.ogg', 50, 1) + M.attack_log += "\[[time_stamp()]\] Slammed with face by [A.name] against \the [src]([A.ckey]), breaking it" + A.attack_log += "\[[time_stamp()]\] Slams face of [M.name] against \the [src]([M.ckey]), breaking it" + msg_admin_attack("[key_name(A)] slams [key_name(M)] face against \the [src], breaking it") + if(prob(30) && ishuman(M)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] + BP.createwound(CUT, 15) + BP.embed(new /obj/item/weapon/shard) + H.emote("scream",,, 1) + else + M.apply_damage(15,def_zone = BP_HEAD) + shatter() + +/* + * 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 + +/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 + health = 50 + +/obj/structure/table/woodentable/fancy + name = "fancy table" + desc = "A standard metal table frame covered with an amazingly fancy, patterned cloth." + icon_state = "fancytable" + parts = /obj/item/weapon/table_parts/wood/fancy + +/obj/structure/table/woodentable/fancy/black + icon_state = "fancytable_black" + parts = /obj/item/weapon/table_parts/wood/fancy/black + +/* + * Reinforced tables + */ +/obj/structure/table/reinforced + name = "reinforced table" + desc = "A version of the four legged table. It is stronger." + icon_state = "reinftable" + health = 200 + var/status = 2 + parts = /obj/item/weapon/table_parts/reinforced + +/obj/structure/table/reinforced/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group || (height==0)) return 1 + if(istype(mover,/obj/item/projectile)) + return (check_cover(mover,target)) + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + if(locate(/obj/structure/table) in get_turf(mover)) + return 1 + if (flipped) + if (get_dir(loc, target) == dir) + return !density + else + return 1 + return 0 + +/obj/structure/table/reinforced/flip(direction) + if (status == 2) + return 0 + else + return ..() + +/obj/structure/table/reinforced/attackby(obj/item/weapon/W, mob/user, params) + if (istype(W, /obj/item/weapon/weldingtool)) + if(user.is_busy()) return FALSE + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + if(src.status == 2) + to_chat(user, "\blue Now weakening the reinforced table") + playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + if (do_after(user, 50, target = src)) + if(!src || !WT.isOn()) return + to_chat(user, "\blue Table weakened") + src.status = 1 + else + to_chat(user, "\blue Now strengthening the reinforced table") + playsound(src.loc, 'sound/items/Welder.ogg', 50, 1) + if (do_after(user, 50, target = src)) + if(!src || !WT.isOn()) return + to_chat(user, "\blue Table strengthened") + src.status = 2 + return FALSE + return TRUE + + if (istype(W, /obj/item/weapon/wrench)) + if(src.status == 2) + return TRUE + + return ..() + +/* + * Racks + */ +/obj/structure/rack + name = "rack" + desc = "Different from the Middle Ages version." + icon = 'icons/obj/objects.dmi' + icon_state = "rack" + density = 1 + anchored = 1.0 + layer = CONTAINER_STRUCTURE_LAYER + throwpass = 1 //You can throw objects over this, despite it's density. + var/parts = /obj/item/weapon/rack_parts + +/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)) + qdel(src) + return + else if(prob(50)) + new /obj/item/weapon/rack_parts(src.loc) + qdel(src) + return + +/obj/structure/rack/CanPass(atom/movable/mover, turf/target, height=0, 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/MouseDrop_T(obj/O, mob/user) + if ((!( istype(O, /obj/item/weapon) ) || user.get_active_hand() != O)) + return + if(isrobot(user) || isessence(user)) + return + var/obj/item/weapon/W = O + if(!W.canremove || W.flags & NODROP) + return + user.drop_item() + if (O.loc != src.loc) + step(O, get_dir(O, src)) + return + +/obj/structure/rack/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/wrench)) + new /obj/item/weapon/rack_parts( src.loc ) + playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) + qdel(src) + return + if(istype(W, /obj/item/weapon/melee/energy)||istype(W, /obj/item/weapon/twohanded/dualsaber)) + if(istype(W, /obj/item/weapon/melee/energy/blade) || (W:active && user.a_intent == "hurt")) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src.loc) + spark_system.start() + playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) + playsound(src.loc, "sparks", 50, 1) + visible_message("[src] was sliced apart by [user]!", " You hear [src] coming apart.") + destroy() + return + if(isrobot(user)) + return + if(!W.canremove || W.flags & NODROP) + return + user.drop_item() + if(W && W.loc) W.loc = src.loc + return + +/obj/structure/rack/meteorhit(obj/O) + qdel(src) + + +/obj/structure/table/attack_hand(mob/user) + if(HULK in user.mutations) + user.SetNextMove(CLICK_CD_MELEE) + user.do_attack_animation(src) + visible_message("[user] smashes [src] apart!") + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + destroy() + +/obj/structure/rack/attack_paw(mob/user) + if(HULK in user.mutations) + user.SetNextMove(CLICK_CD_MELEE) + user.do_attack_animation(src) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + visible_message("[user] smashes [src] apart!") + destroy() + +/obj/structure/rack/attack_alien(mob/user) + user.do_attack_animation(src) + user.SetNextMove(CLICK_CD_MELEE) + visible_message("[user] slices [src] apart!") + destroy() + +/obj/structure/rack/attack_animal(mob/living/simple_animal/user) + if(user.environment_smash) + ..() + playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) + user.do_attack_animation(src) + 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 4e34ee8da0e5..242bf0a0df6f 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -1,113 +1,113 @@ -/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 phoron tanks." - icon = 'icons/obj/objects.dmi' - icon_state = "dispenser" - density = 1 - anchored = 1.0 - var/oxygentanks = 10 - var/phorontanks = 10 - var/list/oxytanks = list() //sorry for the similar var names - var/list/platanks = list() - - -/obj/structure/dispenser/oxygen - phorontanks = 0 - -/obj/structure/dispenser/phoron - oxygentanks = 0 - - -/obj/structure/dispenser/atom_init() - . = ..() - update_icon() - - -/obj/structure/dispenser/update_icon() - overlays.Cut() - switch(oxygentanks) - if(1 to 3) overlays += "oxygen-[oxygentanks]" - if(4 to INFINITY) overlays += "oxygen-4" - switch(phorontanks) - if(1 to 4) overlays += "phoron-[phorontanks]" - if(5 to INFINITY) overlays += "phoron-5" - - -/obj/structure/dispenser/attack_hand(mob/user) - user.set_machine(src) - var/dat - dat += "Oxygen tanks: [oxygentanks] - [oxygentanks ? "Dispense" : "empty"]
                    " - dat += "Phoron tanks: [phorontanks] - [phorontanks ? "Dispense" : "empty"]" - var/datum/browser/popup = new(user, "window=dispenser", "[src]") - popup.set_content(dat) - popup.open() - return - - -/obj/structure/dispenser/attackby(obj/item/I, mob/user) - 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) - user.drop_item() - I.loc = 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/phoron)) - if(phorontanks < 10) - user.drop_item() - I.loc = src - platanks.Add(I) - phorontanks++ - 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["phoron"]) - if(phorontanks > 0) - var/obj/item/weapon/tank/phoron/P - if(platanks.len == phorontanks) - P = platanks[1] - platanks.Remove(P) - else - P = new /obj/item/weapon/tank/phoron(loc) - P.loc = loc - to_chat(usr, "You take [P] out of [src].") - phorontanks-- - update_icon() - add_fingerprint(usr) - updateUsrDialog() - else - usr << browse(null, "window=dispenser") - return - 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 phoron tanks." + icon = 'icons/obj/objects.dmi' + icon_state = "dispenser" + density = 1 + anchored = 1.0 + var/oxygentanks = 10 + var/phorontanks = 10 + var/list/oxytanks = list() //sorry for the similar var names + var/list/platanks = list() + + +/obj/structure/dispenser/oxygen + phorontanks = 0 + +/obj/structure/dispenser/phoron + oxygentanks = 0 + + +/obj/structure/dispenser/atom_init() + . = ..() + update_icon() + + +/obj/structure/dispenser/update_icon() + overlays.Cut() + switch(oxygentanks) + if(1 to 3) overlays += "oxygen-[oxygentanks]" + if(4 to INFINITY) overlays += "oxygen-4" + switch(phorontanks) + if(1 to 4) overlays += "phoron-[phorontanks]" + if(5 to INFINITY) overlays += "phoron-5" + + +/obj/structure/dispenser/attack_hand(mob/user) + user.set_machine(src) + var/dat + dat += "Oxygen tanks: [oxygentanks] - [oxygentanks ? "Dispense" : "empty"]
                    " + dat += "Phoron tanks: [phorontanks] - [phorontanks ? "Dispense" : "empty"]" + var/datum/browser/popup = new(user, "window=dispenser", "[src]") + popup.set_content(dat) + popup.open() + return + + +/obj/structure/dispenser/attackby(obj/item/I, mob/user) + 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) + user.drop_item() + I.loc = 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/phoron)) + if(phorontanks < 10) + user.drop_item() + I.loc = src + platanks.Add(I) + phorontanks++ + 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["phoron"]) + if(phorontanks > 0) + var/obj/item/weapon/tank/phoron/P + if(platanks.len == phorontanks) + P = platanks[1] + platanks.Remove(P) + else + P = new /obj/item/weapon/tank/phoron(loc) + P.loc = loc + to_chat(usr, "You take [P] out of [src].") + phorontanks-- + update_icon() + add_fingerprint(usr) + updateUsrDialog() + else + usr << browse(null, "window=dispenser") + return + return diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm index fdb8bb840803..efef228e9328 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 = CONDUCT - var/obj/item/target/pinned_target // the current pinned target - -/obj/structure/target_stake/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 - -/obj/structure/target_stake/attackby(obj/item/W, mob/user) - // 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)) - density = 0 - W.density = 1 - user.drop_from_inventory(W) - W.loc = loc - W.layer = 3.1 - pinned_target = W - user.SetNextMove(CLICK_CD_INTERACT) - to_chat(user, "You slide the target into the stake.") - -/obj/structure/target_stake/attack_hand(mob/user) - // 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_loc(user) - to_chat(user, "You take the target out of the stake.") - - pinned_target = null +// 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 = CONDUCT + var/obj/item/target/pinned_target // the current pinned target + +/obj/structure/target_stake/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 + +/obj/structure/target_stake/attackby(obj/item/W, mob/user) + // 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)) + density = 0 + W.density = 1 + user.drop_from_inventory(W) + W.loc = loc + W.layer = 3.1 + pinned_target = W + user.SetNextMove(CLICK_CD_INTERACT) + to_chat(user, "You slide the target into the stake.") + +/obj/structure/target_stake/attack_hand(mob/user) + // 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_loc(user) + to_chat(user, "You take the target out of the stake.") + + pinned_target = null diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 5c8c7eb6d1c1..3db5fa0cfa2e 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -1,523 +1,523 @@ -/obj/structure/window - name = "window" - desc = "A window." - icon = 'icons/obj/window.dmi' - density = 1 - layer = 3.2//Just above doors - anchored = 1.0 - flags = ON_BORDER - var/maxhealth = 14.0 - var/health - var/ini_dir = null - var/state = 2 - var/reinf = 0 - var/basestate - var/can_merge = 1 //Sometimes it's needed - var/shardtype = /obj/item/weapon/shard - var/image/crack_overlay - var/damage_threshold = 5 //This will be deducted from any physical damage source. -// var/silicate = 0 // number of units of silicate -// var/icon/silicateIcon = null // the silicated icon - -/obj/structure/window/proc/take_damage(damage = 0, damage_type = BRUTE, sound_effect = 1) - var/initialhealth = health - var/message = 1 - var/fulltile = 0 - - //if(silicate) - // damage = damage * (1 - silicate / 200) - - if(is_fulltile()) - message = 0 - fulltile = 1 - - if(fulltile && damage_threshold) - switch(damage_type) - if(BRUTE) - damage = max(0, damage - damage_threshold) - if(BURN) - damage *= 0.3 - if("generic") - damage *= 0.5 - - if(!damage) - return - - health = max(0, health - damage) - - if(health <= 0) - shatter() - else - if(sound_effect) - playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1) - if(message) - if(health < maxhealth / 4 && initialhealth >= maxhealth / 4) - visible_message("[src] looks like it's about to shatter!" ) - else if(health < maxhealth / 2 && initialhealth >= maxhealth / 2) - visible_message("[src] looks seriously damaged!" ) - else if(health < maxhealth * 3/4 && initialhealth >= maxhealth * 3/4) - visible_message("Cracks begin to appear in [src]!" ) - update_icon() - -/obj/structure/window/proc/shatter(display_message = 1) - playsound(src, "shatter", 70, 1) - if(display_message) - visible_message("[src] shatters!") - if(dir == SOUTHWEST) - var/index = null - index = 0 - while(index < 2) - new shardtype(loc) //todo pooling? - if(reinf) - new /obj/item/stack/rods(loc) - index++ - else - new shardtype(loc) //todo pooling? - if(reinf) - new /obj/item/stack/rods(loc) - qdel(src) - return - -/obj/structure/window/bullet_act(obj/item/projectile/Proj) - if(Proj.pass_flags & PASSGLASS) //Lasers mostly use this flag.. Why should they able to focus damage with direct click... - return -1 - - //Tasers and the like should not damage windows. - if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - return - - ..() - take_damage(Proj.damage, Proj.damage_type) - return - - -/obj/structure/window/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - shatter(0) - return - if(3.0) - if(prob(50)) - shatter(0) - return - - -/obj/structure/window/blob_act() - shatter() - - -/obj/structure/window/meteorhit() - shatter() - - -/obj/structure/window/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return 1 - if(dir == SOUTHWEST || dir == SOUTHEAST || dir == NORTHWEST || dir == NORTHEAST) - return 0 //full tile window, you can't move into it! - if(get_dir(loc, target) & dir) - return !density - else - return 1 - -/obj/structure/window/CanAStarPass(obj/item/weapon/card/id/ID, to_dir, caller) - if(!density) - return TRUE - if((dir == SOUTHWEST) || (dir == to_dir)) - return FALSE - - return TRUE - -/obj/structure/window/CheckExit(atom/movable/O, target) - if(istype(O) && O.checkpass(PASSGLASS)) - return 1 - if(get_dir(O.loc, target) == dir) - return 0 - return 1 - - -/obj/structure/window/hitby(AM) - ..() - visible_message("[src] was hit by [AM].") - var/tforce = 0 - if(ismob(AM)) - tforce = 40 - else if(isobj(AM)) - var/obj/item/I = AM - tforce = I.throwforce - if(reinf) - tforce *= 0.25 - if(health - tforce <= 7 && !reinf) - anchored = 0 - update_nearby_icons() - step(src, get_dir(AM, src)) - take_damage(tforce) - -/obj/structure/window/attack_tk(mob/user) - user.visible_message("Something knocks on [src].") - playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1) - -/obj/structure/window/attack_hand(mob/user) //specflags please!! - user.SetNextMove(CLICK_CD_MELEE) - if(HULK in user.mutations) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) - user.do_attack_animation(src) - take_damage(rand(15,25), "generic") - else if(user.dna && user.dna.mutantrace == "adamantine") - user.do_attack_animation(src) - take_damage(rand(15,25), "generic") - else if (user.a_intent == "hurt") - playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1) - user.visible_message("[usr.name] bangs against the [src.name]!", \ - "You bang against the [src.name]!", \ - "You hear a banging sound.") - else - playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1) - user.visible_message("[usr.name] knocks on the [src.name].", \ - "You knock on the [src.name].", \ - "You hear a knocking sound.") - - -/obj/structure/window/attack_paw(mob/user) - return attack_hand(user) - - -/obj/structure/window/proc/attack_generic(mob/user, damage) - if(!damage) - return - if(damage >= 10) - visible_message("[user] smashes into [src]!") - take_damage(damage, "generic") - else - visible_message("\The [user] bonks \the [src] harmlessly.") - user.do_attack_animation(src) - return 1 - - -/obj/structure/window/attack_alien(mob/user) - user.SetNextMove(CLICK_CD_MELEE) - if(islarva(user) || isfacehugger(user)) - return - attack_generic(user, 15) - -/obj/structure/window/attack_animal(mob/user) - if(!isanimal(user)) - return - ..() - var/mob/living/simple_animal/M = user - if(M.melee_damage_upper <= 0) - return - attack_generic(M, M.melee_damage_upper) - - -/obj/structure/window/attack_slime(mob/user) - if(!isslimeadult(user)) - return - user.SetNextMove(CLICK_CD_MELEE) - user.do_attack_animation(src) - attack_generic(user, rand(10, 15)) - - -/obj/structure/window/attackby(obj/item/W, mob/user) - if(!istype(W)) - return//I really wish I did not need this - - user.SetNextMove(CLICK_CD_INTERACT) - if(istype(W, /obj/item/weapon/airlock_painter)) - change_paintjob(W, user) - - else if(istype(W, /obj/item/weapon/screwdriver)) - if(reinf && state >= 1) - state = 3 - state - playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) - to_chat(user, (state == 1 ? "You have unfastened the window from the frame." : "You have fastened the window to the frame.")) - - else if(reinf && state == 0) - anchored = !anchored - update_nearby_icons() - playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) - to_chat(user, (anchored ? "You have fastened the frame to the floor." : "You have unfastened the frame from the floor.")) - - else if(!reinf) - anchored = !anchored - update_nearby_icons() - playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) - to_chat(user, (anchored ? "You have fastened the window to the floor." : "You have unfastened the window.")) - - else if(istype(W, /obj/item/weapon/crowbar) && reinf && state <= 1) - state = 1 - state - playsound(loc, 'sound/items/Crowbar.ogg', 75, 1) - to_chat(user, (state ? "You have pried the window into the frame." : "You have pried the window out of the frame.")) - - else 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)) - user.SetNextMove(CLICK_CD_MELEE) - var/mob/living/M = G.affecting - var/mob/living/A = G.assailant - var/state = G.state - qdel(W) //gotta delete it here because if window breaks, it won't get deleted - switch (state) - if(1) - M.apply_damage(7) - take_damage(7) - visible_message("[user] slams [M] against \the [src]!") - M.attack_log += "\[[time_stamp()]\] Slammed by [A.name] against \the [src]([A.ckey])" - A.attack_log += "\[[time_stamp()]\] Slams [M.name] against \the [src]([M.ckey])" - msg_admin_attack("[key_name(A)] slams [key_name(M)] into \the [src]") - if(2) - if (prob(50)) - M.Weaken(1) - M.apply_damage(8) - take_damage(9) - visible_message("[user] bashes [M] against \the [src]!") - M.attack_log += "\[[time_stamp()]\] Bashed by [A.name] against \the [src]([A.ckey])" - A.attack_log += "\[[time_stamp()]\] Bashes [M.name] against \the [src]([M.ckey])" - msg_admin_attack("[key_name(A)] bushes [key_name(M)] against \the [src]") - if(3) - M.Weaken(5) - M.apply_damage(20) - take_damage(12) - visible_message("[user] crushes [M] against \the [src]!") - M.attack_log += "\[[time_stamp()]\] Crushed by [A.name] against \the [src]([A.ckey])" - A.attack_log += "\[[time_stamp()]\] Crushes [M.name] against \the [src]([M.ckey])" - msg_admin_attack("[key_name(A)] crushes [key_name(M)] against \the [src]") - - else if(istype(W,/obj/item/weapon/changeling_hammer)) - var/obj/item/weapon/changeling_hammer/C = W - user.SetNextMove(CLICK_CD_MELEE) - if(C.use_charge(user)) - playsound(loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) - shatter() - else - if(W.damtype == BRUTE || W.damtype == BURN) - take_damage(W.force) - if(health <= 7) - anchored = 0 - update_nearby_icons() - step(src, get_dir(user, src)) - else - playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) - ..() - -//painter -/obj/structure/window/proc/change_paintjob(obj/item/C, mob/user) - var/obj/item/weapon/airlock_painter/W - if(istype(C, /obj/item/weapon/airlock_painter)) - W = C - else - return - - if(!W.can_use(user, 1)) - return - - var/new_color = input(user, "Choose color!") as color|null - if(!new_color) return - - if((!in_range(src, usr) && src.loc != usr) || !W.use(user, 1)) - return - else - color = new_color - -/obj/structure/window/verb/rotate() - set name = "Rotate Window Counter-Clockwise" - set category = "Object" - set src in oview(1) - - if(isobserver(usr)) //to stop ghosts from rotating - return - - if(anchored) - to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") - return 0 - - update_nearby_tiles(need_rebuild=1) //Compel updates before - dir = turn(dir, 90) -// updateSilicate() - update_nearby_tiles(need_rebuild=1) - ini_dir = dir - return - - -/obj/structure/window/verb/revrotate() - set name = "Rotate Window Clockwise" - set category = "Object" - set src in oview(1) - - if(isobserver(usr)) //to stop ghosts from rotating - return - - if(anchored) - to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") - return 0 - - update_nearby_tiles(need_rebuild=1) //Compel updates before - dir = turn(dir, 270) -// updateSilicate() - update_nearby_tiles(need_rebuild=1) - ini_dir = dir - return - - -/* -/obj/structure/window/proc/updateSilicate() - if(silicateIcon && silicate) - icon = initial(icon) - - var/icon/I = icon(icon,icon_state,dir) - - var/r = (silicate / 100) + 1 - var/g = (silicate / 70) + 1 - var/b = (silicate / 50) + 1 - I.SetIntensity(r,g,b) - icon = I - silicateIcon = I -*/ - - -/obj/structure/window/atom_init() - . = ..() - - ini_dir = dir - - health = maxhealth - - color = color_windows() - - update_nearby_tiles(need_rebuild = 1) - update_nearby_icons() - - -/obj/structure/window/Destroy() - density = 0 - playsound(src, "shatter", 70, 1) - update_nearby_tiles() - update_nearby_icons() - return ..() - - -/obj/structure/window/Move() - update_nearby_tiles(need_rebuild=1) - ..() - dir = ini_dir - update_nearby_tiles(need_rebuild=1) - -//checks if this window is full-tile one -/obj/structure/window/proc/is_fulltile() - if(dir & (dir - 1)) - return 1 - return 0 - -//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() - update_icon() - for(var/direction in cardinal) - for(var/obj/structure/window/W in get_step(src,direction) ) - W.update_icon() - -//merges adjacent full-tile windows into one (blatant ripoff from game/smoothwall.dm) -/obj/structure/window/update_icon() - //A little cludge here, since I don't know how it will work with slim windows. Most likely VERY wrong. - //this way it will only update full-tile ones - //This spawn is here so windows get properly updated when one gets deleted. - spawn(2) - if(!src) - return - if(!is_fulltile()) - icon_state = "[basestate]" - return - - var/junction = 0 //will be used to determine from which side the window is connected to other windows - if(anchored) - for(var/obj/structure/window/W in orange(src,1)) - if(W.anchored && W.density && W.is_fulltile() && W.can_merge) //Only counts anchored, not-destroyed fill-tile windows. - if(abs(x-W.x)-abs(y-W.y) ) //doesn't count windows, placed diagonally to src - junction |= get_dir(src,W) - icon_state = "[basestate][junction]" - - var/ratio = health / maxhealth - ratio = ceil(ratio * 4) * 25 - - overlays -= crack_overlay - if(ratio > 75) - return - crack_overlay = image('icons/obj/window.dmi',"damage[ratio]",-(layer+0.1)) - overlays += crack_overlay - -/obj/structure/window/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C + 800) - take_damage(round(exposed_volume / 100), BURN, 0) - ..() - - - -/obj/structure/window/basic - desc = "It looks thin and flimsy. A few knocks with... anything, really should shatter it." - icon_state = "window" - basestate = "window" - -/obj/structure/window/phoronbasic - name = "phoron window" - desc = "A phoron-glass alloy window. It looks insanely tough to break. It appears it's also insanely tough to burn through." - basestate = "phoronwindow" - icon_state = "phoronwindow" - shardtype = /obj/item/weapon/shard/phoron - maxhealth = 120.0 - -/obj/structure/window/phoronbasic/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C + 32000) - take_damage(round(exposed_volume / 1000), BURN, 0) - ..() - -/obj/structure/window/phoronreinforced - name = "reinforced phoron window" - desc = "A phoron-glass alloy window, with rods supporting it. It looks hopelessly tough to break. It also looks completely fireproof, considering how basic phoron windows are insanely fireproof." - basestate = "phoronrwindow" - icon_state = "phoronrwindow" - shardtype = /obj/item/weapon/shard/phoron - reinf = 1 - maxhealth = 160.0 - -/obj/structure/window/phoronreinforced/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/structure/window/reinforced - name = "reinforced window" - desc = "It looks rather strong. Might take a few good hits to shatter it." - icon_state = "rwindow" - basestate = "rwindow" - maxhealth = 100.0 - reinf = 1 - damage_threshold = 15 - -/obj/structure/window/reinforced/tinted - name = "tinted window" - desc = "It looks rather strong and opaque. Might take a few good hits to shatter it." - icon_state = "twindow" - basestate = "twindow" - opacity = 1 - -/obj/structure/window/reinforced/tinted/frosted //Actually, there is no icon for this!! - name = "frosted window" - desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window." - icon_state = "fwindow" - basestate = "fwindow" - maxhealth = 30.0 - damage_threshold = 0 - -/obj/structure/window/shuttle - name = "shuttle window" - desc = "It looks rather strong. Might take a few good hits to shatter it." - icon = 'icons/obj/podwindows.dmi' - icon_state = "window" - basestate = "window" - maxhealth = 150.0 - reinf = 1 - dir = 5 - damage_threshold = 30 - -/obj/structure/window/shuttle/update_icon() //icon_state has to be set manually - return +/obj/structure/window + name = "window" + desc = "A window." + icon = 'icons/obj/window.dmi' + density = 1 + layer = 3.2//Just above doors + anchored = 1.0 + flags = ON_BORDER + var/maxhealth = 14.0 + var/health + var/ini_dir = null + var/state = 2 + var/reinf = 0 + var/basestate + var/can_merge = 1 //Sometimes it's needed + var/shardtype = /obj/item/weapon/shard + var/image/crack_overlay + var/damage_threshold = 5 //This will be deducted from any physical damage source. +// var/silicate = 0 // number of units of silicate +// var/icon/silicateIcon = null // the silicated icon + +/obj/structure/window/proc/take_damage(damage = 0, damage_type = BRUTE, sound_effect = 1) + var/initialhealth = health + var/message = 1 + var/fulltile = 0 + + //if(silicate) + // damage = damage * (1 - silicate / 200) + + if(is_fulltile()) + message = 0 + fulltile = 1 + + if(fulltile && damage_threshold) + switch(damage_type) + if(BRUTE) + damage = max(0, damage - damage_threshold) + if(BURN) + damage *= 0.3 + if("generic") + damage *= 0.5 + + if(!damage) + return + + health = max(0, health - damage) + + if(health <= 0) + shatter() + else + if(sound_effect) + playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1) + if(message) + if(health < maxhealth / 4 && initialhealth >= maxhealth / 4) + visible_message("[src] looks like it's about to shatter!" ) + else if(health < maxhealth / 2 && initialhealth >= maxhealth / 2) + visible_message("[src] looks seriously damaged!" ) + else if(health < maxhealth * 3/4 && initialhealth >= maxhealth * 3/4) + visible_message("Cracks begin to appear in [src]!" ) + update_icon() + +/obj/structure/window/proc/shatter(display_message = 1) + playsound(src, "shatter", 70, 1) + if(display_message) + visible_message("[src] shatters!") + if(dir == SOUTHWEST) + var/index = null + index = 0 + while(index < 2) + new shardtype(loc) //todo pooling? + if(reinf) + new /obj/item/stack/rods(loc) + index++ + else + new shardtype(loc) //todo pooling? + if(reinf) + new /obj/item/stack/rods(loc) + qdel(src) + return + +/obj/structure/window/bullet_act(obj/item/projectile/Proj) + if(Proj.pass_flags & PASSGLASS) //Lasers mostly use this flag.. Why should they able to focus damage with direct click... + return -1 + + //Tasers and the like should not damage windows. + if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN)) + return + + ..() + take_damage(Proj.damage, Proj.damage_type) + return + + +/obj/structure/window/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + shatter(0) + return + if(3.0) + if(prob(50)) + shatter(0) + return + + +/obj/structure/window/blob_act() + shatter() + + +/obj/structure/window/meteorhit() + shatter() + + +/obj/structure/window/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return 1 + if(dir == SOUTHWEST || dir == SOUTHEAST || dir == NORTHWEST || dir == NORTHEAST) + return 0 //full tile window, you can't move into it! + if(get_dir(loc, target) & dir) + return !density + else + return 1 + +/obj/structure/window/CanAStarPass(obj/item/weapon/card/id/ID, to_dir, caller) + if(!density) + return TRUE + if((dir == SOUTHWEST) || (dir == to_dir)) + return FALSE + + return TRUE + +/obj/structure/window/CheckExit(atom/movable/O, target) + if(istype(O) && O.checkpass(PASSGLASS)) + return 1 + if(get_dir(O.loc, target) == dir) + return 0 + return 1 + + +/obj/structure/window/hitby(AM) + ..() + visible_message("[src] was hit by [AM].") + var/tforce = 0 + if(ismob(AM)) + tforce = 40 + else if(isobj(AM)) + var/obj/item/I = AM + tforce = I.throwforce + if(reinf) + tforce *= 0.25 + if(health - tforce <= 7 && !reinf) + anchored = 0 + update_nearby_icons() + step(src, get_dir(AM, src)) + take_damage(tforce) + +/obj/structure/window/attack_tk(mob/user) + user.visible_message("Something knocks on [src].") + playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1) + +/obj/structure/window/attack_hand(mob/user) //specflags please!! + user.SetNextMove(CLICK_CD_MELEE) + if(HULK in user.mutations) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) + user.do_attack_animation(src) + take_damage(rand(15,25), "generic") + else if(user.dna && user.dna.mutantrace == "adamantine") + user.do_attack_animation(src) + take_damage(rand(15,25), "generic") + else if (user.a_intent == "hurt") + playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1) + user.visible_message("[usr.name] bangs against the [src.name]!", \ + "You bang against the [src.name]!", \ + "You hear a banging sound.") + else + playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1) + user.visible_message("[usr.name] knocks on the [src.name].", \ + "You knock on the [src.name].", \ + "You hear a knocking sound.") + + +/obj/structure/window/attack_paw(mob/user) + return attack_hand(user) + + +/obj/structure/window/proc/attack_generic(mob/user, damage) + if(!damage) + return + if(damage >= 10) + visible_message("[user] smashes into [src]!") + take_damage(damage, "generic") + else + visible_message("\The [user] bonks \the [src] harmlessly.") + user.do_attack_animation(src) + return 1 + + +/obj/structure/window/attack_alien(mob/user) + user.SetNextMove(CLICK_CD_MELEE) + if(islarva(user) || isfacehugger(user)) + return + attack_generic(user, 15) + +/obj/structure/window/attack_animal(mob/user) + if(!isanimal(user)) + return + ..() + var/mob/living/simple_animal/M = user + if(M.melee_damage_upper <= 0) + return + attack_generic(M, M.melee_damage_upper) + + +/obj/structure/window/attack_slime(mob/user) + if(!isslimeadult(user)) + return + user.SetNextMove(CLICK_CD_MELEE) + user.do_attack_animation(src) + attack_generic(user, rand(10, 15)) + + +/obj/structure/window/attackby(obj/item/W, mob/user) + if(!istype(W)) + return//I really wish I did not need this + + user.SetNextMove(CLICK_CD_INTERACT) + if(istype(W, /obj/item/weapon/airlock_painter)) + change_paintjob(W, user) + + else if(istype(W, /obj/item/weapon/screwdriver)) + if(reinf && state >= 1) + state = 3 - state + playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + to_chat(user, (state == 1 ? "You have unfastened the window from the frame." : "You have fastened the window to the frame.")) + + else if(reinf && state == 0) + anchored = !anchored + update_nearby_icons() + playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + to_chat(user, (anchored ? "You have fastened the frame to the floor." : "You have unfastened the frame from the floor.")) + + else if(!reinf) + anchored = !anchored + update_nearby_icons() + playsound(loc, 'sound/items/Screwdriver.ogg', 75, 1) + to_chat(user, (anchored ? "You have fastened the window to the floor." : "You have unfastened the window.")) + + else if(istype(W, /obj/item/weapon/crowbar) && reinf && state <= 1) + state = 1 - state + playsound(loc, 'sound/items/Crowbar.ogg', 75, 1) + to_chat(user, (state ? "You have pried the window into the frame." : "You have pried the window out of the frame.")) + + else 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)) + user.SetNextMove(CLICK_CD_MELEE) + var/mob/living/M = G.affecting + var/mob/living/A = G.assailant + var/state = G.state + qdel(W) //gotta delete it here because if window breaks, it won't get deleted + switch (state) + if(1) + M.apply_damage(7) + take_damage(7) + visible_message("[user] slams [M] against \the [src]!") + M.attack_log += "\[[time_stamp()]\] Slammed by [A.name] against \the [src]([A.ckey])" + A.attack_log += "\[[time_stamp()]\] Slams [M.name] against \the [src]([M.ckey])" + msg_admin_attack("[key_name(A)] slams [key_name(M)] into \the [src]") + if(2) + if (prob(50)) + M.Weaken(1) + M.apply_damage(8) + take_damage(9) + visible_message("[user] bashes [M] against \the [src]!") + M.attack_log += "\[[time_stamp()]\] Bashed by [A.name] against \the [src]([A.ckey])" + A.attack_log += "\[[time_stamp()]\] Bashes [M.name] against \the [src]([M.ckey])" + msg_admin_attack("[key_name(A)] bushes [key_name(M)] against \the [src]") + if(3) + M.Weaken(5) + M.apply_damage(20) + take_damage(12) + visible_message("[user] crushes [M] against \the [src]!") + M.attack_log += "\[[time_stamp()]\] Crushed by [A.name] against \the [src]([A.ckey])" + A.attack_log += "\[[time_stamp()]\] Crushes [M.name] against \the [src]([M.ckey])" + msg_admin_attack("[key_name(A)] crushes [key_name(M)] against \the [src]") + + else if(istype(W,/obj/item/weapon/changeling_hammer)) + var/obj/item/weapon/changeling_hammer/C = W + user.SetNextMove(CLICK_CD_MELEE) + if(C.use_charge(user)) + playsound(loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) + shatter() + else + if(W.damtype == BRUTE || W.damtype == BURN) + take_damage(W.force) + if(health <= 7) + anchored = 0 + update_nearby_icons() + step(src, get_dir(user, src)) + else + playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) + ..() + +//painter +/obj/structure/window/proc/change_paintjob(obj/item/C, mob/user) + var/obj/item/weapon/airlock_painter/W + if(istype(C, /obj/item/weapon/airlock_painter)) + W = C + else + return + + if(!W.can_use(user, 1)) + return + + var/new_color = input(user, "Choose color!") as color|null + if(!new_color) return + + if((!in_range(src, usr) && src.loc != usr) || !W.use(user, 1)) + return + else + color = new_color + +/obj/structure/window/verb/rotate() + set name = "Rotate Window Counter-Clockwise" + set category = "Object" + set src in oview(1) + + if(isobserver(usr)) //to stop ghosts from rotating + return + + if(anchored) + to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") + return 0 + + update_nearby_tiles(need_rebuild=1) //Compel updates before + dir = turn(dir, 90) +// updateSilicate() + update_nearby_tiles(need_rebuild=1) + ini_dir = dir + return + + +/obj/structure/window/verb/revrotate() + set name = "Rotate Window Clockwise" + set category = "Object" + set src in oview(1) + + if(isobserver(usr)) //to stop ghosts from rotating + return + + if(anchored) + to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") + return 0 + + update_nearby_tiles(need_rebuild=1) //Compel updates before + dir = turn(dir, 270) +// updateSilicate() + update_nearby_tiles(need_rebuild=1) + ini_dir = dir + return + + +/* +/obj/structure/window/proc/updateSilicate() + if(silicateIcon && silicate) + icon = initial(icon) + + var/icon/I = icon(icon,icon_state,dir) + + var/r = (silicate / 100) + 1 + var/g = (silicate / 70) + 1 + var/b = (silicate / 50) + 1 + I.SetIntensity(r,g,b) + icon = I + silicateIcon = I +*/ + + +/obj/structure/window/atom_init() + . = ..() + + ini_dir = dir + + health = maxhealth + + color = color_windows() + + update_nearby_tiles(need_rebuild = 1) + update_nearby_icons() + + +/obj/structure/window/Destroy() + density = 0 + playsound(src, "shatter", 70, 1) + update_nearby_tiles() + update_nearby_icons() + return ..() + + +/obj/structure/window/Move() + update_nearby_tiles(need_rebuild=1) + ..() + dir = ini_dir + update_nearby_tiles(need_rebuild=1) + +//checks if this window is full-tile one +/obj/structure/window/proc/is_fulltile() + if(dir & (dir - 1)) + return 1 + return 0 + +//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() + update_icon() + for(var/direction in cardinal) + for(var/obj/structure/window/W in get_step(src,direction) ) + W.update_icon() + +//merges adjacent full-tile windows into one (blatant ripoff from game/smoothwall.dm) +/obj/structure/window/update_icon() + //A little cludge here, since I don't know how it will work with slim windows. Most likely VERY wrong. + //this way it will only update full-tile ones + //This spawn is here so windows get properly updated when one gets deleted. + spawn(2) + if(!src) + return + if(!is_fulltile()) + icon_state = "[basestate]" + return + + var/junction = 0 //will be used to determine from which side the window is connected to other windows + if(anchored) + for(var/obj/structure/window/W in orange(src,1)) + if(W.anchored && W.density && W.is_fulltile() && W.can_merge) //Only counts anchored, not-destroyed fill-tile windows. + if(abs(x-W.x)-abs(y-W.y) ) //doesn't count windows, placed diagonally to src + junction |= get_dir(src,W) + icon_state = "[basestate][junction]" + + var/ratio = health / maxhealth + ratio = ceil(ratio * 4) * 25 + + overlays -= crack_overlay + if(ratio > 75) + return + crack_overlay = image('icons/obj/window.dmi',"damage[ratio]",-(layer+0.1)) + overlays += crack_overlay + +/obj/structure/window/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > T0C + 800) + take_damage(round(exposed_volume / 100), BURN, 0) + ..() + + + +/obj/structure/window/basic + desc = "It looks thin and flimsy. A few knocks with... anything, really should shatter it." + icon_state = "window" + basestate = "window" + +/obj/structure/window/phoronbasic + name = "phoron window" + desc = "A phoron-glass alloy window. It looks insanely tough to break. It appears it's also insanely tough to burn through." + basestate = "phoronwindow" + icon_state = "phoronwindow" + shardtype = /obj/item/weapon/shard/phoron + maxhealth = 120.0 + +/obj/structure/window/phoronbasic/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > T0C + 32000) + take_damage(round(exposed_volume / 1000), BURN, 0) + ..() + +/obj/structure/window/phoronreinforced + name = "reinforced phoron window" + desc = "A phoron-glass alloy window, with rods supporting it. It looks hopelessly tough to break. It also looks completely fireproof, considering how basic phoron windows are insanely fireproof." + basestate = "phoronrwindow" + icon_state = "phoronrwindow" + shardtype = /obj/item/weapon/shard/phoron + reinf = 1 + maxhealth = 160.0 + +/obj/structure/window/phoronreinforced/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/structure/window/reinforced + name = "reinforced window" + desc = "It looks rather strong. Might take a few good hits to shatter it." + icon_state = "rwindow" + basestate = "rwindow" + maxhealth = 100.0 + reinf = 1 + damage_threshold = 15 + +/obj/structure/window/reinforced/tinted + name = "tinted window" + desc = "It looks rather strong and opaque. Might take a few good hits to shatter it." + icon_state = "twindow" + basestate = "twindow" + opacity = 1 + +/obj/structure/window/reinforced/tinted/frosted //Actually, there is no icon for this!! + name = "frosted window" + desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window." + icon_state = "fwindow" + basestate = "fwindow" + maxhealth = 30.0 + damage_threshold = 0 + +/obj/structure/window/shuttle + name = "shuttle window" + desc = "It looks rather strong. Might take a few good hits to shatter it." + icon = 'icons/obj/podwindows.dmi' + icon_state = "window" + basestate = "window" + maxhealth = 150.0 + reinf = 1 + dir = 5 + damage_threshold = 30 + +/obj/structure/window/shuttle/update_icon() //icon_state has to be set manually + return diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm index 6bd631e88f35..00f33adf8279 100644 --- a/code/game/shuttle_engines.dm +++ b/code/game/shuttle_engines.dm @@ -1,48 +1,48 @@ -/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 - - CanPass(atom/movable/mover, turf/target, height, air_group) - 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/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/window + name = "shuttle window" + icon = 'icons/obj/podwindows.dmi' + icon_state = "1" + density = 1 + opacity = 0 + anchored = 1 + + CanPass(atom/movable/mover, turf/target, height, air_group) + 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/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/game/skincmd.dm b/code/game/skincmd.dm index 9e2d272c44af..64d0076e7bce 100644 --- a/code/game/skincmd.dm +++ b/code/game/skincmd.dm @@ -1,13 +1,13 @@ -/mob/var/skincmds = list() -/obj/proc/SkinCmd(mob/user, data) - -/proc/SkinCmdRegister(mob/user, name, O) - 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)) +/mob/var/skincmds = list() +/obj/proc/SkinCmd(mob/user, data) + +/proc/SkinCmdRegister(mob/user, name, O) + 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)) diff --git a/code/game/smoothwall.dm b/code/game/smoothwall.dm index bbd5d5ab3d10..7fdde3e2289d 100644 --- a/code/game/smoothwall.dm +++ b/code/game/smoothwall.dm @@ -1,154 +1,154 @@ -//Separate dm because it relates to two types of atoms + ease of removal in case it's needed. -//Also assemblies.dm for falsewall checking for this when used. -//I should really make the shuttle wall check run every time it's moved, but centcom uses unsimulated floors so !effort - -/atom/proc/relativewall() //atom because it should be useable both for walls and false walls - if(istype(src,/turf/simulated/floor/vault)||istype(src,/turf/simulated/wall/vault)) //HACK!!! - return - - var/junction = 0 //will be used to determine from which side the wall is connected to other walls - - if(!istype(src,/turf/simulated/shuttle/wall)) //or else we'd have wacky shuttle merging with walls action - for(var/turf/simulated/wall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - junction |= get_dir(src,W) - for(var/obj/structure/falsewall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - junction |= get_dir(src,W) - for(var/obj/structure/falserwall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - junction |= get_dir(src,W) - -/* Commenting this out for now until we figure out what to do with shuttle smooth walls, if anything. - As they are now, they sort of work screwy and may need further coding. Or just be scrapped.*/ - /*else - for(var/turf/simulated/shuttle/wall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - junction |= get_dir(src,W) - for(var/obj/machinery/shuttle/W in orange(src,1)) //stuff like engine and propulsion should merge with walls - if(abs(src.x-W.x)-abs(src.y-W.y)) - junction |= get_dir(src,W) - for(var/obj/machinery/door/W in orange(src,1)) //doors should not result in diagonal walls, it just looks ugly. checking if area is shuttle so it won't merge with the station - if((abs(src.x-W.x)-abs(src.y-W.y)) && (istype(W.loc.loc,/area/shuttle) || istype(W.loc.loc,/area/supply))) - junction |= get_dir(src,W) - for(var/obj/structure/grille/W in orange(src,1)) //same for grilles. checking if area is shuttle so it won't merge with the station - if((abs(src.x-W.x)-abs(src.y-W.y)) && (istype(W.loc.loc,/area/shuttle) || istype(W.loc.loc,/area/supply))) - junction |= get_dir(src,W)*/ - - if(istype(src,/turf/simulated/wall)) - var/turf/simulated/wall/wall = src - wall.icon_state = "[wall.walltype][junction]" - else if (istype(src,/obj/structure/falserwall)) - src.icon_state = "rwall[junction]" - else if (istype(src,/obj/structure/falsewall)) - var/obj/structure/falsewall/fwall = src - fwall.icon_state = "[fwall.mineral][junction]" -/* else if(istype(src,/turf/simulated/shuttle/wall)) - var/newicon = icon; - var/newiconstate = icon_state; - if(junction!=5 && junction!=6 && junction!=9 && junction!=10) //if it's not diagonal, all is well, no additional calculations needed - src.icon_state = "swall[junction]" - else //if it's diagonal, we need to figure out if we're using the floor diagonal or the space diagonal sprite - var/is_floor = 0 - for(var/turf/unsimulated/floor/F in orange(src,1)) - if(abs(src.x-F.x)-abs(src.y-F.y)) - if((15-junction) & get_dir(src,F)) //if there's a floor in at least one of the empty space directions, return 1 - is_floor = 1 - newicon = F.icon - newiconstate = F.icon_state //we'll save these for later - for(var/turf/simulated/floor/F in orange(src,1)) - if(abs(src.x-F.x)-abs(src.y-F.y)) - if((15-junction) & get_dir(src,F)) //if there's a floor in at least one of the empty space directions, return 1 - is_floor = 1 - newicon = F.icon - newiconstate = F.icon_state //we'll save these for later - for(var/turf/simulated/shuttle/floor/F in orange(src,1)) - if(abs(src.x-F.x)-abs(src.y-F.y)) - if((15-junction) & get_dir(src,F)) //if there's a floor in at least one of the empty space directions, return 1 - is_floor = 1 - newicon = F.icon - newiconstate = F.icon_state //we'll save these for later - if(is_floor) //if is_floor = 1, we use the floor diagonal sprite - src.icon = newicon; //we'll set the floor's icon to the floor next to it and overlay the wall segment. shuttle floor sprites have priority - src.icon_state = newiconstate; // - src.overlays += icon('icons/turf/shuttle.dmi',"swall_f[junction]") - else //otherwise, the space one - src.icon_state = "swall_s[junction]"*/ - - return - -/atom/proc/relativewall_neighbours() - for(var/turf/simulated/wall/W in range(src,1)) - W.relativewall() - for(var/obj/structure/falsewall/W in range(src,1)) - W.relativewall() - W.update_icon()//Refreshes the wall to make sure the icons don't desync - for(var/obj/structure/falserwall/W in range(src,1)) - W.relativewall() - for(var/obj/effect/alien/resin/W in range(src,1)) - W.relativewall() - W.update_icon() - return - -/turf/simulated/wall/atom_init() - relativewall_neighbours() - . = ..() - -/turf/simulated/shuttle/wall/atom_init() - var/image/I = image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER) - I.plane = PLANE_SPACE - underlays += I - . = ..() - -/turf/simulated/wall/Destroy() - - spawn(10) - for(var/turf/simulated/wall/W in range(src,1)) - W.relativewall() - - for(var/obj/structure/falsewall/W in range(src,1)) - W.relativewall() - - 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 - - return ..() - -/turf/simulated/wall/relativewall() - if(istype(src,/turf/simulated/wall/vault)) //HACK!!! - return - - var/junction = 0 //will be used to determine from which side the wall is connected to other walls - - for(var/turf/simulated/wall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - if(src.mineral == W.mineral)//Only 'like' walls connect -Sieve - junction |= get_dir(src,W) - for(var/obj/structure/falsewall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - if(src.mineral == W.mineral) - junction |= get_dir(src,W) - for(var/obj/structure/falserwall/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - if(src.mineral == W.mineral) - junction |= get_dir(src,W) - var/turf/simulated/wall/wall = src - wall.icon_state = "[wall.walltype][junction]" - return - -/obj/effect/alien/resin/relativewall() - - var/junction = 0 //will be used to determine from which side the wall is connected to other walls - - for(var/obj/effect/alien/resin/W in orange(src,1)) - if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls - junction |= get_dir(src,W) - var/obj/effect/alien/resin/resin = src - resin.icon_state = "[resin.resintype][junction]" - - return +//Separate dm because it relates to two types of atoms + ease of removal in case it's needed. +//Also assemblies.dm for falsewall checking for this when used. +//I should really make the shuttle wall check run every time it's moved, but centcom uses unsimulated floors so !effort + +/atom/proc/relativewall() //atom because it should be useable both for walls and false walls + if(istype(src,/turf/simulated/floor/vault)||istype(src,/turf/simulated/wall/vault)) //HACK!!! + return + + var/junction = 0 //will be used to determine from which side the wall is connected to other walls + + if(!istype(src,/turf/simulated/shuttle/wall)) //or else we'd have wacky shuttle merging with walls action + for(var/turf/simulated/wall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + junction |= get_dir(src,W) + for(var/obj/structure/falsewall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + junction |= get_dir(src,W) + for(var/obj/structure/falserwall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + junction |= get_dir(src,W) + +/* Commenting this out for now until we figure out what to do with shuttle smooth walls, if anything. + As they are now, they sort of work screwy and may need further coding. Or just be scrapped.*/ + /*else + for(var/turf/simulated/shuttle/wall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + junction |= get_dir(src,W) + for(var/obj/machinery/shuttle/W in orange(src,1)) //stuff like engine and propulsion should merge with walls + if(abs(src.x-W.x)-abs(src.y-W.y)) + junction |= get_dir(src,W) + for(var/obj/machinery/door/W in orange(src,1)) //doors should not result in diagonal walls, it just looks ugly. checking if area is shuttle so it won't merge with the station + if((abs(src.x-W.x)-abs(src.y-W.y)) && (istype(W.loc.loc,/area/shuttle) || istype(W.loc.loc,/area/supply))) + junction |= get_dir(src,W) + for(var/obj/structure/grille/W in orange(src,1)) //same for grilles. checking if area is shuttle so it won't merge with the station + if((abs(src.x-W.x)-abs(src.y-W.y)) && (istype(W.loc.loc,/area/shuttle) || istype(W.loc.loc,/area/supply))) + junction |= get_dir(src,W)*/ + + if(istype(src,/turf/simulated/wall)) + var/turf/simulated/wall/wall = src + wall.icon_state = "[wall.walltype][junction]" + else if (istype(src,/obj/structure/falserwall)) + src.icon_state = "rwall[junction]" + else if (istype(src,/obj/structure/falsewall)) + var/obj/structure/falsewall/fwall = src + fwall.icon_state = "[fwall.mineral][junction]" +/* else if(istype(src,/turf/simulated/shuttle/wall)) + var/newicon = icon; + var/newiconstate = icon_state; + if(junction!=5 && junction!=6 && junction!=9 && junction!=10) //if it's not diagonal, all is well, no additional calculations needed + src.icon_state = "swall[junction]" + else //if it's diagonal, we need to figure out if we're using the floor diagonal or the space diagonal sprite + var/is_floor = 0 + for(var/turf/unsimulated/floor/F in orange(src,1)) + if(abs(src.x-F.x)-abs(src.y-F.y)) + if((15-junction) & get_dir(src,F)) //if there's a floor in at least one of the empty space directions, return 1 + is_floor = 1 + newicon = F.icon + newiconstate = F.icon_state //we'll save these for later + for(var/turf/simulated/floor/F in orange(src,1)) + if(abs(src.x-F.x)-abs(src.y-F.y)) + if((15-junction) & get_dir(src,F)) //if there's a floor in at least one of the empty space directions, return 1 + is_floor = 1 + newicon = F.icon + newiconstate = F.icon_state //we'll save these for later + for(var/turf/simulated/shuttle/floor/F in orange(src,1)) + if(abs(src.x-F.x)-abs(src.y-F.y)) + if((15-junction) & get_dir(src,F)) //if there's a floor in at least one of the empty space directions, return 1 + is_floor = 1 + newicon = F.icon + newiconstate = F.icon_state //we'll save these for later + if(is_floor) //if is_floor = 1, we use the floor diagonal sprite + src.icon = newicon; //we'll set the floor's icon to the floor next to it and overlay the wall segment. shuttle floor sprites have priority + src.icon_state = newiconstate; // + src.overlays += icon('icons/turf/shuttle.dmi',"swall_f[junction]") + else //otherwise, the space one + src.icon_state = "swall_s[junction]"*/ + + return + +/atom/proc/relativewall_neighbours() + for(var/turf/simulated/wall/W in range(src,1)) + W.relativewall() + for(var/obj/structure/falsewall/W in range(src,1)) + W.relativewall() + W.update_icon()//Refreshes the wall to make sure the icons don't desync + for(var/obj/structure/falserwall/W in range(src,1)) + W.relativewall() + for(var/obj/effect/alien/resin/W in range(src,1)) + W.relativewall() + W.update_icon() + return + +/turf/simulated/wall/atom_init() + relativewall_neighbours() + . = ..() + +/turf/simulated/shuttle/wall/atom_init() + var/image/I = image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER) + I.plane = PLANE_SPACE + underlays += I + . = ..() + +/turf/simulated/wall/Destroy() + + spawn(10) + for(var/turf/simulated/wall/W in range(src,1)) + W.relativewall() + + for(var/obj/structure/falsewall/W in range(src,1)) + W.relativewall() + + 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 + + return ..() + +/turf/simulated/wall/relativewall() + if(istype(src,/turf/simulated/wall/vault)) //HACK!!! + return + + var/junction = 0 //will be used to determine from which side the wall is connected to other walls + + for(var/turf/simulated/wall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + if(src.mineral == W.mineral)//Only 'like' walls connect -Sieve + junction |= get_dir(src,W) + for(var/obj/structure/falsewall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + if(src.mineral == W.mineral) + junction |= get_dir(src,W) + for(var/obj/structure/falserwall/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + if(src.mineral == W.mineral) + junction |= get_dir(src,W) + var/turf/simulated/wall/wall = src + wall.icon_state = "[wall.walltype][junction]" + return + +/obj/effect/alien/resin/relativewall() + + var/junction = 0 //will be used to determine from which side the wall is connected to other walls + + for(var/obj/effect/alien/resin/W in orange(src,1)) + if(abs(src.x-W.x)-abs(src.y-W.y)) //doesn't count diagonal walls + junction |= get_dir(src,W) + var/obj/effect/alien/resin/resin = src + resin.icon_state = "[resin.resintype][junction]" + + return diff --git a/code/game/sound.dm b/code/game/sound.dm index ccc2aa6471cb..44e088c9b1b4 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -1,130 +1,130 @@ -var/list/shatter_sound = list('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg') -var/list/explosion_sound = list('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg') -var/list/spark_sound = list('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks4.ogg') -var/list/rustle_sound = list('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg') -var/list/punch_sound = list('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg') -var/list/clown_sound = list('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg') -var/list/swing_hit_sound = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg') -var/list/hiss_sound = list('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') -var/list/page_sound = list('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg') -var/list/fracture_sound = list('sound/effects/bonebreak1.ogg','sound/effects/bonebreak2.ogg','sound/effects/bonebreak3.ogg','sound/effects/bonebreak4.ogg') -//var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') -//var/list/footsteps_sound = list('sound/effects/footsteps.ogg','sound/effects/footsteps2.ogg') -var/list/footsteps_sound = list('sound/effects/tile1.wav','sound/effects/tile2.wav','sound/effects/tile3.wav','sound/effects/tile4.wav') - -/proc/playsound(atom/source, soundin, vol, vary, extrarange, falloff, channel = 0, is_global) - - soundin = get_sfx(soundin) // same sound for everyone - - if(isarea(source)) - error("[source] is an area and is trying to make the sound: [soundin]") - return - - var/frequency = get_rand_frequency() // Same frequency for everybody - var/turf/turf_source = get_turf(source) - - // Looping through the player list has the added bonus of working for mobs inside containers - for (var/P in player_list) - var/mob/M = P - if(!M || !M.client) - continue - - var/distance = get_dist(M, turf_source) - if(distance <= (world.view + extrarange) * 3) - var/turf/T = get_turf(M) - - if(T && T.z == turf_source.z) - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global) - -var/const/FALLOFF_SOUNDS = 0.5 - -/mob/proc/playsound_local(turf/turf_source, soundin, vol, vary, frequency, falloff, channel = 0, is_global) - if(!src.client || ear_deaf > 0) - return FALSE - soundin = get_sfx(soundin) - - var/sound/S = sound(soundin) - S.wait = 0 //No queue - //S.channel = 0 //Any channel - S.channel = channel - S.volume = vol - S.environment = -1 - 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) - - //sound volume falloff with distance - var/distance = get_dist(T, turf_source) - - S.volume -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff. - - //sound volume falloff with pressure - var/pressure_factor = 1.0 - - var/datum/gas_mixture/hearer_env = T.return_air() - var/datum/gas_mixture/source_env = turf_source.return_air() - - if (hearer_env && source_env) - var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) - - if (pressure < ONE_ATMOSPHERE) - pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0) - else //in space - pressure_factor = 0 - - if (distance <= 1) - pressure_factor = max(pressure_factor, 0.15) //hearing through contact - - S.volume *= pressure_factor - - if (S.volume <= 0) - return FALSE //no volume means no sound - - var/dx = turf_source.x - T.x // Hearing from the right/left - S.x = dx - var/dz = turf_source.y - T.y // Hearing from infront/behind - S.z = dz - // 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) - if(!is_global) - S.environment = 2 - src << S - -/mob/living/parasite/playsound_local(turf/turf_source, soundin, vol, vary, frequency, falloff, channel = 0, is_global) - if(!host || host.ear_deaf > 0) - return FALSE - return ..() - - -/client/proc/playtitlemusic() - if(!ticker || !ticker.login_music) return - if(prefs.toggles & SOUND_LOBBY) - src << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS - -/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 ("footsteps") soundin = pick(footsteps_sound) - if ("shatter") soundin = pick(shatter_sound) - if ("explosion") soundin = pick(explosion_sound) - if ("sparks") soundin = pick(spark_sound) - if ("rustle") soundin = pick(rustle_sound) - if ("bodyfall") soundin = pick('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg') - 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 ("fracture") soundin = pick(fracture_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') +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/fracture_sound = list('sound/effects/bonebreak1.ogg','sound/effects/bonebreak2.ogg','sound/effects/bonebreak3.ogg','sound/effects/bonebreak4.ogg') +//var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') +//var/list/footsteps_sound = list('sound/effects/footsteps.ogg','sound/effects/footsteps2.ogg') +var/list/footsteps_sound = list('sound/effects/tile1.wav','sound/effects/tile2.wav','sound/effects/tile3.wav','sound/effects/tile4.wav') + +/proc/playsound(atom/source, soundin, vol, vary, extrarange, falloff, channel = 0, is_global) + + soundin = get_sfx(soundin) // same sound for everyone + + if(isarea(source)) + error("[source] is an area and is trying to make the sound: [soundin]") + return + + var/frequency = get_rand_frequency() // Same frequency for everybody + var/turf/turf_source = get_turf(source) + + // Looping through the player list has the added bonus of working for mobs inside containers + for (var/P in player_list) + var/mob/M = P + if(!M || !M.client) + continue + + var/distance = get_dist(M, turf_source) + if(distance <= (world.view + extrarange) * 3) + var/turf/T = get_turf(M) + + if(T && T.z == turf_source.z) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global) + +var/const/FALLOFF_SOUNDS = 0.5 + +/mob/proc/playsound_local(turf/turf_source, soundin, vol, vary, frequency, falloff, channel = 0, is_global) + if(!src.client || ear_deaf > 0) + return FALSE + soundin = get_sfx(soundin) + + var/sound/S = sound(soundin) + S.wait = 0 //No queue + //S.channel = 0 //Any channel + S.channel = channel + S.volume = vol + S.environment = -1 + 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) + + //sound volume falloff with distance + var/distance = get_dist(T, turf_source) + + S.volume -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff. + + //sound volume falloff with pressure + var/pressure_factor = 1.0 + + var/datum/gas_mixture/hearer_env = T.return_air() + var/datum/gas_mixture/source_env = turf_source.return_air() + + if (hearer_env && source_env) + var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) + + if (pressure < ONE_ATMOSPHERE) + pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0) + else //in space + pressure_factor = 0 + + if (distance <= 1) + pressure_factor = max(pressure_factor, 0.15) //hearing through contact + + S.volume *= pressure_factor + + if (S.volume <= 0) + return FALSE //no volume means no sound + + var/dx = turf_source.x - T.x // Hearing from the right/left + S.x = dx + var/dz = turf_source.y - T.y // Hearing from infront/behind + S.z = dz + // 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) + if(!is_global) + S.environment = 2 + src << S + +/mob/living/parasite/playsound_local(turf/turf_source, soundin, vol, vary, frequency, falloff, channel = 0, is_global) + if(!host || host.ear_deaf > 0) + return FALSE + return ..() + + +/client/proc/playtitlemusic() + if(!ticker || !ticker.login_music) return + if(prefs.toggles & SOUND_LOBBY) + src << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS + +/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 ("footsteps") soundin = pick(footsteps_sound) + if ("shatter") soundin = pick(shatter_sound) + if ("explosion") soundin = pick(explosion_sound) + if ("sparks") soundin = pick(spark_sound) + if ("rustle") soundin = pick(rustle_sound) + if ("bodyfall") soundin = pick('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg') + 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 ("fracture") soundin = pick(fracture_sound) + //if ("gunshot") soundin = pick(gun_sound) + return soundin diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index dc184cb42dc6..7f074eee0d6a 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -1,222 +1,222 @@ -/turf/simulated - name = "station" - plane = FLOOR_PLANE - - var/wet = 0 - var/image/wet_overlay = null - var/thermite = 0 - 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/dirt = 0 - -/turf/simulated/atom_init() - . = ..() - levelupdate() - -/turf/simulated/proc/AddTracks(mob/M,bloodDNA,comingdir,goingdir, blooddatum = null) - var/typepath - if(ishuman(M)) - typepath = /obj/effect/decal/cleanable/blood/tracks/footprints - else if(isalien(M)) - typepath = /obj/effect/decal/cleanable/blood/tracks/footprints/claws - else // can shomeone make shlime footprint shprites later pwetty pwease? - typepath = /obj/effect/decal/cleanable/blood/tracks/footprints/paws - - var/obj/effect/decal/cleanable/blood/tracks/tracks = locate(typepath) in src - if(!tracks) - tracks = new typepath(src) - if(!blooddatum) - blooddatum = new /datum/dirt_cover/red_blood - tracks.AddTracks(bloodDNA,comingdir,goingdir,blooddatum) - -/turf/simulated/Entered(atom/A, atom/OL) - if(movement_disabled && usr.ckey != movement_disabled_exception) - to_chat(usr, "\red Movement is admin-disabled.")//This is to identify lag problems - return - - if (istype(A, /mob/living/simple_animal/hulk)) - var/mob/living/simple_animal/hulk/Hulk = A - if(!Hulk.lying) - playsound(src, 'sound/effects/hulk_step.ogg', 50, 1) - if (istype(A,/mob/living/carbon)) - var/mob/living/carbon/M = A - if(M.lying && !M.crawling) return - - dirt++ - if (dirt >= 200) - var/obj/effect/decal/cleanable/dirt/dirtoverlay = locate(/obj/effect/decal/cleanable/dirt, src) - - if (!dirtoverlay) - dirtoverlay = new/obj/effect/decal/cleanable/dirt(src) - dirtoverlay.alpha = 20 - else - dirtoverlay.alpha = min(dirtoverlay.alpha+5, 255) - - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - - //Footstep sound - if(istype(H:shoes, /obj/item/clothing/shoes) && !H.buckled) - var/obj/item/clothing/shoes/O = H.shoes - - var/footstepsound = "footsteps" - - if(istype(H.shoes, /obj/item/clothing/shoes/clown_shoes)) - if(prob(25)) - footstepsound = "clownstep" - if(H.shoes.wet) - footstepsound = 'sound/effects/waterstep.ogg' - - if(H.m_intent == "run") - if(O.footstep >= 2) - O.footstep = 0 - playsound(src, footstepsound, 50, 1) - else - O.footstep++ - else - playsound(src, footstepsound, 20, 1) - - // Tracking blood - var/list/bloodDNA = null - var/datum/dirt_cover/blooddatum - if(M.shoes) - var/obj/item/clothing/shoes/S = M.shoes - if(S.track_blood && S.blood_DNA) - bloodDNA = S.blood_DNA - blooddatum = new/datum/dirt_cover(S.dirt_overlay) - S.track_blood-- - else - if(M.track_blood && M.feet_blood_DNA) - bloodDNA = M.feet_blood_DNA - blooddatum = new/datum/dirt_cover(M.feet_dirt_color) - M.track_blood-- - - if (bloodDNA) - src.AddTracks(M,bloodDNA,M.dir,0,blooddatum) // Coming - var/turf/simulated/from = get_step(M,reverse_direction(M.dir)) - if(istype(from) && from) - from.AddTracks(M,bloodDNA,0,M.dir,blooddatum) // Going - - bloodDNA = null - - switch (src.wet) - if(1) - if(istype(M, /mob/living/carbon/human)) // Added check since monkeys don't have shoes - if ((M.m_intent == "run") && !((istype(M:shoes, /obj/item/clothing/shoes) && M:shoes.flags&NOSLIP) || (istype(M:wear_suit, /obj/item/clothing/suit/space/rig) && M:wear_suit.flags&NOSLIP))) - M.slip("the wet floor", 5, 3) - else - M.inertia_dir = 0 - return - else - if (M.m_intent == "run") - M.slip("the wet floor", 5, 3) - else - M.inertia_dir = 0 - return - - if(2) //lube //can cause infinite loops - needs work - 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_bodypart_damage(2) // Was 5 -- TLE - M.slip("the floor", 0, 10) - if(3) // Ice - if(istype(M, /mob/living/carbon/human)) // Added check since monkeys don't have shoes - if ((M.m_intent == "run") && (!(istype(M:shoes, /obj/item/clothing/shoes) && M:shoes.flags&NOSLIP) || !(istype(M:wear_suit, /obj/item/clothing/suit/space/rig) && M:wear_suit.flags&NOSLIP)) && prob(30)) - M.slip("the icy floor", 4, 3) - step(M, M.dir) - else - M.inertia_dir = 0 - return - else - if (M.m_intent == "run" && prob(30)) - M.slip("the icy floor", 4, 3) - step(M, M.dir) - else - M.inertia_dir = 0 - return - - ..() - -//returns 1 if made bloody, returns 0 otherwise -/turf/simulated/add_blood(mob/living/carbon/human/M) - 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 - - - - //if there isn't a blood decal already, make one. - var/obj/effect/decal/cleanable/blood/newblood = new /obj/effect/decal/cleanable/blood(src) - - //Species-specific blood. - if(M.species) - newblood.basedatum = new M.species.blood_color - else - newblood.basedatum = new/datum/dirt_cover/red_blood() - - newblood.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - newblood.virus2 = virus_copylist(M.virus2) - newblood.update_icon() - - return 1 //we bloodied the floor - - -// Only adds blood on the floor -- Skie -/turf/simulated/proc/add_blood_floor(mob/living/carbon/M) - if(istype(M, /mob/living/carbon/monkey)) - var/mob/living/carbon/monkey/Monkey = M - var/obj/effect/decal/cleanable/blood/this = new /obj/effect/decal/cleanable/blood(src) - this.blood_DNA[Monkey.dna.unique_enzymes] = Monkey.dna.b_type - this.basedatum = new Monkey.blood_datum - this.update_icon() - - else if(istype(M,/mob/living/carbon/human)) - - var/obj/effect/decal/cleanable/blood/this = new /obj/effect/decal/cleanable/blood(src) - var/mob/living/carbon/human/H = M - - //Species-specific blood. - if(H.species) - this.basedatum = new/datum/dirt_cover(H.species.blood_color) - else - this.basedatum = new/datum/dirt_cover/red_blood() - this.update_icon() - - this.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - - else if( istype(M, /mob/living/carbon/alien )) - var/obj/effect/decal/cleanable/blood/xeno/this = new /obj/effect/decal/cleanable/blood/xeno(src) - this.blood_DNA["UNKNOWN BLOOD"] = "X*" - - else if( istype(M, /mob/living/silicon/robot )) - new /obj/effect/decal/cleanable/blood/oil(src) - -//Wet floor procs. -/turf/simulated/proc/make_wet_floor(severity = WATER_FLOOR) - if(wet < severity) - wet = severity - - if(severity < LUBE_FLOOR) // Thats right, lube does not add nor clean wet overlay. So if the floor was wet before and we add lube, wet overlay simply stays longer. - if(!wet_overlay) // For stealth - floor must be dry, so added lube effect will be invisible. - wet_overlay = image('icons/effects/water.dmi', "wet_floor", src) - overlays += wet_overlay - - addtimer(CALLBACK(src, .proc/make_dry_floor), rand(710,800), TIMER_UNIQUE|TIMER_OVERRIDE) - -/turf/simulated/proc/make_dry_floor() - if(wet) - if(wet_overlay) - overlays -= wet_overlay - wet_overlay = null - wet = 0 +/turf/simulated + name = "station" + plane = FLOOR_PLANE + + var/wet = 0 + var/image/wet_overlay = null + var/thermite = 0 + 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/dirt = 0 + +/turf/simulated/atom_init() + . = ..() + levelupdate() + +/turf/simulated/proc/AddTracks(mob/M,bloodDNA,comingdir,goingdir, blooddatum = null) + var/typepath + if(ishuman(M)) + typepath = /obj/effect/decal/cleanable/blood/tracks/footprints + else if(isalien(M)) + typepath = /obj/effect/decal/cleanable/blood/tracks/footprints/claws + else // can shomeone make shlime footprint shprites later pwetty pwease? + typepath = /obj/effect/decal/cleanable/blood/tracks/footprints/paws + + var/obj/effect/decal/cleanable/blood/tracks/tracks = locate(typepath) in src + if(!tracks) + tracks = new typepath(src) + if(!blooddatum) + blooddatum = new /datum/dirt_cover/red_blood + tracks.AddTracks(bloodDNA,comingdir,goingdir,blooddatum) + +/turf/simulated/Entered(atom/A, atom/OL) + if(movement_disabled && usr.ckey != movement_disabled_exception) + to_chat(usr, "\red Movement is admin-disabled.")//This is to identify lag problems + return + + if (istype(A, /mob/living/simple_animal/hulk)) + var/mob/living/simple_animal/hulk/Hulk = A + if(!Hulk.lying) + playsound(src, 'sound/effects/hulk_step.ogg', 50, 1) + if (istype(A,/mob/living/carbon)) + var/mob/living/carbon/M = A + if(M.lying && !M.crawling) return + + dirt++ + if (dirt >= 200) + var/obj/effect/decal/cleanable/dirt/dirtoverlay = locate(/obj/effect/decal/cleanable/dirt, src) + + if (!dirtoverlay) + dirtoverlay = new/obj/effect/decal/cleanable/dirt(src) + dirtoverlay.alpha = 20 + else + dirtoverlay.alpha = min(dirtoverlay.alpha+5, 255) + + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + + //Footstep sound + if(istype(H:shoes, /obj/item/clothing/shoes) && !H.buckled) + var/obj/item/clothing/shoes/O = H.shoes + + var/footstepsound = "footsteps" + + if(istype(H.shoes, /obj/item/clothing/shoes/clown_shoes)) + if(prob(25)) + footstepsound = "clownstep" + if(H.shoes.wet) + footstepsound = 'sound/effects/waterstep.ogg' + + if(H.m_intent == "run") + if(O.footstep >= 2) + O.footstep = 0 + playsound(src, footstepsound, 50, 1) + else + O.footstep++ + else + playsound(src, footstepsound, 20, 1) + + // Tracking blood + var/list/bloodDNA = null + var/datum/dirt_cover/blooddatum + if(M.shoes) + var/obj/item/clothing/shoes/S = M.shoes + if(S.track_blood && S.blood_DNA) + bloodDNA = S.blood_DNA + blooddatum = new/datum/dirt_cover(S.dirt_overlay) + S.track_blood-- + else + if(M.track_blood && M.feet_blood_DNA) + bloodDNA = M.feet_blood_DNA + blooddatum = new/datum/dirt_cover(M.feet_dirt_color) + M.track_blood-- + + if (bloodDNA) + src.AddTracks(M,bloodDNA,M.dir,0,blooddatum) // Coming + var/turf/simulated/from = get_step(M,reverse_direction(M.dir)) + if(istype(from) && from) + from.AddTracks(M,bloodDNA,0,M.dir,blooddatum) // Going + + bloodDNA = null + + switch (src.wet) + if(1) + if(istype(M, /mob/living/carbon/human)) // Added check since monkeys don't have shoes + if ((M.m_intent == "run") && !((istype(M:shoes, /obj/item/clothing/shoes) && M:shoes.flags&NOSLIP) || (istype(M:wear_suit, /obj/item/clothing/suit/space/rig) && M:wear_suit.flags&NOSLIP))) + M.slip("the wet floor", 5, 3) + else + M.inertia_dir = 0 + return + else + if (M.m_intent == "run") + M.slip("the wet floor", 5, 3) + else + M.inertia_dir = 0 + return + + if(2) //lube //can cause infinite loops - needs work + 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_bodypart_damage(2) // Was 5 -- TLE + M.slip("the floor", 0, 10) + if(3) // Ice + if(istype(M, /mob/living/carbon/human)) // Added check since monkeys don't have shoes + if ((M.m_intent == "run") && (!(istype(M:shoes, /obj/item/clothing/shoes) && M:shoes.flags&NOSLIP) || !(istype(M:wear_suit, /obj/item/clothing/suit/space/rig) && M:wear_suit.flags&NOSLIP)) && prob(30)) + M.slip("the icy floor", 4, 3) + step(M, M.dir) + else + M.inertia_dir = 0 + return + else + if (M.m_intent == "run" && prob(30)) + M.slip("the icy floor", 4, 3) + step(M, M.dir) + else + M.inertia_dir = 0 + return + + ..() + +//returns 1 if made bloody, returns 0 otherwise +/turf/simulated/add_blood(mob/living/carbon/human/M) + 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 + + + + //if there isn't a blood decal already, make one. + var/obj/effect/decal/cleanable/blood/newblood = new /obj/effect/decal/cleanable/blood(src) + + //Species-specific blood. + if(M.species) + newblood.basedatum = new M.species.blood_color + else + newblood.basedatum = new/datum/dirt_cover/red_blood() + + newblood.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type + newblood.virus2 = virus_copylist(M.virus2) + newblood.update_icon() + + return 1 //we bloodied the floor + + +// Only adds blood on the floor -- Skie +/turf/simulated/proc/add_blood_floor(mob/living/carbon/M) + if(istype(M, /mob/living/carbon/monkey)) + var/mob/living/carbon/monkey/Monkey = M + var/obj/effect/decal/cleanable/blood/this = new /obj/effect/decal/cleanable/blood(src) + this.blood_DNA[Monkey.dna.unique_enzymes] = Monkey.dna.b_type + this.basedatum = new Monkey.blood_datum + this.update_icon() + + else if(istype(M,/mob/living/carbon/human)) + + var/obj/effect/decal/cleanable/blood/this = new /obj/effect/decal/cleanable/blood(src) + var/mob/living/carbon/human/H = M + + //Species-specific blood. + if(H.species) + this.basedatum = new/datum/dirt_cover(H.species.blood_color) + else + this.basedatum = new/datum/dirt_cover/red_blood() + this.update_icon() + + this.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type + + else if( istype(M, /mob/living/carbon/alien )) + var/obj/effect/decal/cleanable/blood/xeno/this = new /obj/effect/decal/cleanable/blood/xeno(src) + this.blood_DNA["UNKNOWN BLOOD"] = "X*" + + else if( istype(M, /mob/living/silicon/robot )) + new /obj/effect/decal/cleanable/blood/oil(src) + +//Wet floor procs. +/turf/simulated/proc/make_wet_floor(severity = WATER_FLOOR) + if(wet < severity) + wet = severity + + if(severity < LUBE_FLOOR) // Thats right, lube does not add nor clean wet overlay. So if the floor was wet before and we add lube, wet overlay simply stays longer. + if(!wet_overlay) // For stealth - floor must be dry, so added lube effect will be invisible. + wet_overlay = image('icons/effects/water.dmi', "wet_floor", src) + overlays += wet_overlay + + addtimer(CALLBACK(src, .proc/make_dry_floor), rand(710,800), TIMER_UNIQUE|TIMER_OVERRIDE) + +/turf/simulated/proc/make_dry_floor() + if(wet) + if(wet_overlay) + overlays -= wet_overlay + wet_overlay = null + wet = 0 diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 8d371bf60479..f8adc8472c7c 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -1,632 +1,632 @@ -#define LIGHTFLOOR_ON_BIT 4 - -#define LIGHTFLOOR_STATE_OK 0 -#define LIGHTFLOOR_STATE_FLICKER 1 -#define LIGHTFLOOR_STATE_BREAKING 2 -#define LIGHTFLOOR_STATE_BROKEN 3 -#define LIGHTFLOOR_STATE_BITS 3 - -//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", "carpet", - "carpetcorner", "carpetside", "carpet", "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") - -/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/broken = 0 - var/burnt = 0 - var/mineral = "metal" - var/floor_type = /obj/item/stack/tile/plasteel - var/lightfloor_state // for light floors, this is the state of the tile. 0-7, 0x4 is on-bit - use the helper procs below - - proc/get_lightfloor_state() - return lightfloor_state & LIGHTFLOOR_STATE_BITS - - proc/get_lightfloor_on() - return lightfloor_state & LIGHTFLOOR_ON_BIT - - proc/set_lightfloor_state(n) - lightfloor_state = get_lightfloor_on() | (n & LIGHTFLOOR_STATE_BITS) - - proc/set_lightfloor_on(n) - if(n) - lightfloor_state |= LIGHTFLOOR_ON_BIT - else - lightfloor_state &= ~LIGHTFLOOR_ON_BIT - - proc/toggle_lightfloor_on() - lightfloor_state ^= LIGHTFLOOR_ON_BIT - -/turf/simulated/floor/atom_init() - . = ..() - 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/Destroy() - if(floor_type) - floor_type = null - return ..() - -//turf/simulated/floor/CanPass(atom/movable/mover, turf/target, height=0, 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(basetype) - if(2.0) - switch(pick(1,2;75,3)) - if (1) - src.ReplaceWithLattice() - if(prob(33)) new /obj/item/stack/sheet/metal(src) - if(2) - src.ChangeTurf(basetype) - if(3) - if(prob(80)) - src.break_tile_to_plating() - else - src.break_tile() - src.hotspot_expose(1000,CELL_VOLUME) - if(prob(33)) new /obj/item/stack/sheet/metal(src) - if(3.0) - if (prob(50)) - src.break_tile() - src.hotspot_expose(1000,CELL_VOLUME) - return - -/turf/simulated/floor/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(!burnt && prob(5)) - burn_tile() - else if(prob(1) && !is_plating()) - make_plating() - burn_tile() - return - -/turf/simulated/floor/adjacent_fire_act(turf/simulated/floor/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume) - var/dir_to = get_dir(src, adj_turf) - - for(var/obj/structure/window/W in src) - if(W.dir == dir_to || W.is_fulltile()) //Same direction or diagonal (full tile) - W.fire_act(adj_air, adj_temp, adj_volume) - -/turf/simulated/floor/blob_act() - return - -/turf/simulated/floor/singularity_pull(S, current_size) - if(current_size == STAGE_THREE) - if(prob(30)) - if(floor_type) - new floor_type(src) - make_plating() - else if(current_size == STAGE_FOUR) - if(prob(50)) - if(floor_type) - new floor_type(src) - make_plating() - else if(current_size >= STAGE_FIVE) - if(floor_type) - if(prob(70)) - new floor_type(src) - make_plating() - else if(prob(50)) - ReplaceWithLattice() - -/turf/simulated/floor/update_icon() - 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()) - if(get_lightfloor_on()) - switch(get_lightfloor_state()) - if(LIGHTFLOOR_STATE_OK) - icon_state = "light_on" - set_light(5) - if(LIGHTFLOOR_STATE_FLICKER) - var/num = pick("1","2","3","4") - icon_state = "light_on_flicker[num]" - set_light(5) - if(LIGHTFLOOR_STATE_BREAKING) - icon_state = "light_on_broken" - set_light(5) - if(LIGHTFLOOR_STATE_BROKEN) - icon_state = "light_off" - set_light(0) - 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) - if(!(icon_state in list("carpetsymbol", "blackcarpetsymbol", "purplecarpetsymbol", "orangecarpetsymbol", "greencarpetsymbol", "bluecarpetsymbol", "blue2carpetsymbol", "redcarpetsymbol", "cyancarpetsymbol"))) - 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() && FF.floor_type == floor_type) - 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() && FF.floor_type == floor_type) - 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() && FF.floor_type == floor_type) - 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() && FF.floor_type == floor_type) - 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() && FF.floor_type == floor_type) - diagonalconnect |= 8 - - var/obj/item/stack/tile/carpet/C = floor_type - var/base_icon_state = initial(C.carpet_icon_state) - icon_state = "[base_icon_state][connectdir]-[diagonalconnect]" - - else if(is_wood_floor()) - if(!broken && !burnt) - if(!(icon_state in wood_icons)) - icon_state = "wood" - //world << "[icon_state]y's got [icon_state]" - /*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) - return src.attack_hand(user) - -/turf/simulated/floor/attack_hand(mob/user) - if (is_light_floor()) - toggle_lightfloor_on() - update_icon() - ..() - -/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(ispath(floor_type, /obj/item/stack/tile/plasteel)) - return 1 - else - return 0 - -/turf/simulated/floor/is_light_floor() - if(ispath(floor_type, /obj/item/stack/tile/light)) - return 1 - else - return 0 - -/turf/simulated/floor/is_grass_floor() - if(ispath(floor_type, /obj/item/stack/tile/grass)) - return 1 - else - return 0 - -/turf/simulated/floor/is_wood_floor() - if(ispath(floor_type, /obj/item/stack/tile/wood)) - return 1 - else - return 0 - -/turf/simulated/floor/is_carpet_floor() - if(ispath(floor_type, /obj/item/stack/tile/carpet)) - return 1 - else - return 0 - -/turf/simulated/floor/is_catwalk() - return 0 - -/turf/simulated/floor/is_plating() - if(!floor_type && !is_catwalk()) - return 1 - return 0 - -/turf/simulated/floor/proc/break_tile() - if(istype(src,/turf/simulated/floor/engine)) - return - if(istype(src,/turf/simulated/floor/mech_bay_recharge_floor)) - src.ChangeTurf(/turf/simulated/floor/plating) - 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()) - var/obj/item/stack/tile/carpet/C = floor_type - icon_state = "[initial(C.carpet_icon_state)]-broken" - broken = 1 - else if(is_grass_floor()) - src.icon_state = "sand[pick("1","2","3")]" - broken = 1 - -/turf/simulated/floor/proc/burn_tile() - if(istype(src,/turf/simulated/floor/engine)) - return - if(istype(src,/turf/simulated/floor/plating/airless/asteroid)) - return//Asteroid tiles don't burn - if(broken || burnt) - return - 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()) - var/obj/item/stack/tile/carpet/C = floor_type - icon_state = "[initial(C.carpet_icon_state)]-broken" - burnt = 1 - else if(is_grass_floor()) - src.icon_state = "sand[pick("1","2","3")]" - burnt = 1 - -//This proc will set floor_type to null and the update_icon() 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_catwalk()) - 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()) - icon = 'icons/turf/floors.dmi' - spawn(5) - if(src) - for(var/direction in list(1,2,4,8,5,6,9,10)) - 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_type) - return - icon_plating = "plating" - set_light(0) - floor_type = null - intact = 0 - broken = 0 - burnt = 0 - - 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(obj/item/stack/tile/plasteel/T = null) - broken = 0 - burnt = 0 - intact = 1 - set_light(0) - if(T) - if(istype(T,/obj/item/stack/tile/plasteel)) - floor_type = T.type - 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_type = /obj/item/stack/tile/plasteel - 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(obj/item/stack/tile/light/T = null) - broken = 0 - burnt = 0 - intact = 1 - if(T) - if(istype(T,/obj/item/stack/tile/light)) - floor_type = T.type - update_icon() - levelupdate() - return - //if you gave a valid parameter, it won't get thisf ar. - floor_type = /obj/item/stack/tile/light - - 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(obj/item/stack/tile/grass/T = null) - broken = 0 - burnt = 0 - intact = 1 - if(T) - if(istype(T,/obj/item/stack/tile/grass)) - floor_type = T.type - update_icon() - levelupdate() - return - //if you gave a valid parameter, it won't get thisf ar. - floor_type = /obj/item/stack/tile/grass - - 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(obj/item/stack/tile/wood/T = null) - broken = 0 - burnt = 0 - intact = 1 - if(T) - if(istype(T,/obj/item/stack/tile/wood)) - floor_type = T.type - update_icon() - levelupdate() - return - //if you gave a valid parameter, it won't get thisf ar. - floor_type = /obj/item/stack/tile/wood - - 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(obj/item/stack/tile/carpet/T = null) - broken = 0 - burnt = 0 - intact = 1 - if(T) - if(istype(T,/obj/item/stack/tile/carpet)) - floor_type = T.type - update_icon() - levelupdate() - return - //if you gave a valid parameter, it won't get thisf ar. - floor_type = /obj/item/stack/tile/carpet - - update_icon() - levelupdate() - -/turf/simulated/floor/attackby(obj/item/C, mob/user) - - if(!C || !user) - return 0 - user.SetNextMove(CLICK_CD_INTERACT) - - if(istype(C,/obj/item/weapon/light/bulb)) //only for light tiles - if(is_light_floor()) - if(get_lightfloor_state()) - user.remove_from_mob(C) - qdel(C) - set_lightfloor_state(0) //fixing it by bashing it with a light bulb, fun eh? - update_icon() - to_chat(user, "\blue You replace the light bulb.") - else - to_chat(user, "\blue The lightbulb seems fine, no need to replace it.") - - if(istype(C, /obj/item/weapon/crowbar) && (!(is_plating()))) - if(broken || burnt) - to_chat(user, "\red You remove the broken plating.") - else - if(is_wood_floor()) - to_chat(user, "\red You forcefully pry off the planks, destroying them in the process.") - else - var/obj/item/I = new floor_type(src) - if(is_light_floor()) - var/obj/item/stack/tile/light/L = I - L.on = get_lightfloor_on() - L.state = get_lightfloor_state() - to_chat(user, "\red You remove the [I.name].") - - make_plating() - // Can't play sounds from areas. - N3X - playsound(src, 'sound/items/Crowbar.ogg', 80, 1) - - return - - if(istype(C, /obj/item/weapon/screwdriver)) - if(is_wood_floor()) - if(broken || burnt) - return - else - if(is_wood_floor()) - to_chat(user, "\red You unscrew the planks.") - new floor_type(src) - - make_plating() - playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) - if(is_catwalk()) - if(broken) - return - ReplaceWithLattice() - playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) - return - - if(istype(C, /obj/item/stack/rods)) - var/obj/item/stack/rods/R = C - if (is_plating()) - if (R.get_amount() >= 2) - if(user.is_busy()) return - to_chat(user, "\blue Reinforcing the floor...") - if(do_after(user, 30, target = src) && R.use(2) && is_plating()) - ChangeTurf(/turf/simulated/floor/engine) - playsound(src, 'sound/items/Deconstruct.ogg', 80, 1) - return - else - to_chat(user, "\red You need more rods.") - else if (is_catwalk()) - to_chat(user, "\red The entire thing is 100% rods already, it doesn't need any more.") - else - to_chat(user, "\red You must remove the plating first.") - return - - if(istype(C, /obj/item/stack/tile)) - if (is_catwalk()) - to_chat(user, "\red The catwalk is too primitive to support tiling.") - if(is_plating()) - if(!broken && !burnt) - var/obj/item/stack/tile/T = C - floor_type = T.type - icon = initial(T.turf_type.icon) - if(!T.use(1)) - return - intact = 1 - if(istype(T,/obj/item/stack/tile/light)) - var/obj/item/stack/tile/light/L = T - set_lightfloor_state(L.state) - set_lightfloor_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 list(1,2,4,8,5,6,9,10)) - 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, "\blue This section is too damaged to support a tile. Use a welder to fix the damage.") - - - if(istype(C, /obj/item/stack/cable_coil)) - if(is_plating() || is_catwalk()) - var/obj/item/stack/cable_coil/coil = C - for(var/obj/structure/cable/LC in src) - if((LC.d1==0)||(LC.d2==0)) - LC.attackby(C,user) - return - coil.turf_place(src, user) - else - to_chat(user, "\red You must remove the plating first.") - - if(istype(C, /obj/item/weapon/shovel)) - if(is_grass_floor()) - new /obj/item/weapon/ore/glass(src) - new /obj/item/weapon/ore/glass(src) //Make some sand if you shovel grass - to_chat(user, "\blue You shovel the grass.") - make_plating() - else - to_chat(user, "\red You cannot shovel this.") - - 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, "\red 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, "\blue You need more welding fuel to complete this task.") - -#undef LIGHTFLOOR_ON_BIT - -#undef LIGHTFLOOR_STATE_OK -#undef LIGHTFLOOR_STATE_FLICKER -#undef LIGHTFLOOR_STATE_BREAKING -#undef LIGHTFLOOR_STATE_BROKEN -#undef LIGHTFLOOR_STATE_BITS +#define LIGHTFLOOR_ON_BIT 4 + +#define LIGHTFLOOR_STATE_OK 0 +#define LIGHTFLOOR_STATE_FLICKER 1 +#define LIGHTFLOOR_STATE_BREAKING 2 +#define LIGHTFLOOR_STATE_BROKEN 3 +#define LIGHTFLOOR_STATE_BITS 3 + +//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", "carpet", + "carpetcorner", "carpetside", "carpet", "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") + +/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/broken = 0 + var/burnt = 0 + var/mineral = "metal" + var/floor_type = /obj/item/stack/tile/plasteel + var/lightfloor_state // for light floors, this is the state of the tile. 0-7, 0x4 is on-bit - use the helper procs below + + proc/get_lightfloor_state() + return lightfloor_state & LIGHTFLOOR_STATE_BITS + + proc/get_lightfloor_on() + return lightfloor_state & LIGHTFLOOR_ON_BIT + + proc/set_lightfloor_state(n) + lightfloor_state = get_lightfloor_on() | (n & LIGHTFLOOR_STATE_BITS) + + proc/set_lightfloor_on(n) + if(n) + lightfloor_state |= LIGHTFLOOR_ON_BIT + else + lightfloor_state &= ~LIGHTFLOOR_ON_BIT + + proc/toggle_lightfloor_on() + lightfloor_state ^= LIGHTFLOOR_ON_BIT + +/turf/simulated/floor/atom_init() + . = ..() + 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/Destroy() + if(floor_type) + floor_type = null + return ..() + +//turf/simulated/floor/CanPass(atom/movable/mover, turf/target, height=0, 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(basetype) + if(2.0) + switch(pick(1,2;75,3)) + if (1) + src.ReplaceWithLattice() + if(prob(33)) new /obj/item/stack/sheet/metal(src) + if(2) + src.ChangeTurf(basetype) + if(3) + if(prob(80)) + src.break_tile_to_plating() + else + src.break_tile() + src.hotspot_expose(1000,CELL_VOLUME) + if(prob(33)) new /obj/item/stack/sheet/metal(src) + if(3.0) + if (prob(50)) + src.break_tile() + src.hotspot_expose(1000,CELL_VOLUME) + return + +/turf/simulated/floor/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(!burnt && prob(5)) + burn_tile() + else if(prob(1) && !is_plating()) + make_plating() + burn_tile() + return + +/turf/simulated/floor/adjacent_fire_act(turf/simulated/floor/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume) + var/dir_to = get_dir(src, adj_turf) + + for(var/obj/structure/window/W in src) + if(W.dir == dir_to || W.is_fulltile()) //Same direction or diagonal (full tile) + W.fire_act(adj_air, adj_temp, adj_volume) + +/turf/simulated/floor/blob_act() + return + +/turf/simulated/floor/singularity_pull(S, current_size) + if(current_size == STAGE_THREE) + if(prob(30)) + if(floor_type) + new floor_type(src) + make_plating() + else if(current_size == STAGE_FOUR) + if(prob(50)) + if(floor_type) + new floor_type(src) + make_plating() + else if(current_size >= STAGE_FIVE) + if(floor_type) + if(prob(70)) + new floor_type(src) + make_plating() + else if(prob(50)) + ReplaceWithLattice() + +/turf/simulated/floor/update_icon() + 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()) + if(get_lightfloor_on()) + switch(get_lightfloor_state()) + if(LIGHTFLOOR_STATE_OK) + icon_state = "light_on" + set_light(5) + if(LIGHTFLOOR_STATE_FLICKER) + var/num = pick("1","2","3","4") + icon_state = "light_on_flicker[num]" + set_light(5) + if(LIGHTFLOOR_STATE_BREAKING) + icon_state = "light_on_broken" + set_light(5) + if(LIGHTFLOOR_STATE_BROKEN) + icon_state = "light_off" + set_light(0) + 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) + if(!(icon_state in list("carpetsymbol", "blackcarpetsymbol", "purplecarpetsymbol", "orangecarpetsymbol", "greencarpetsymbol", "bluecarpetsymbol", "blue2carpetsymbol", "redcarpetsymbol", "cyancarpetsymbol"))) + 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() && FF.floor_type == floor_type) + 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() && FF.floor_type == floor_type) + 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() && FF.floor_type == floor_type) + 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() && FF.floor_type == floor_type) + 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() && FF.floor_type == floor_type) + diagonalconnect |= 8 + + var/obj/item/stack/tile/carpet/C = floor_type + var/base_icon_state = initial(C.carpet_icon_state) + icon_state = "[base_icon_state][connectdir]-[diagonalconnect]" + + else if(is_wood_floor()) + if(!broken && !burnt) + if(!(icon_state in wood_icons)) + icon_state = "wood" + //world << "[icon_state]y's got [icon_state]" + /*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) + return src.attack_hand(user) + +/turf/simulated/floor/attack_hand(mob/user) + if (is_light_floor()) + toggle_lightfloor_on() + update_icon() + ..() + +/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(ispath(floor_type, /obj/item/stack/tile/plasteel)) + return 1 + else + return 0 + +/turf/simulated/floor/is_light_floor() + if(ispath(floor_type, /obj/item/stack/tile/light)) + return 1 + else + return 0 + +/turf/simulated/floor/is_grass_floor() + if(ispath(floor_type, /obj/item/stack/tile/grass)) + return 1 + else + return 0 + +/turf/simulated/floor/is_wood_floor() + if(ispath(floor_type, /obj/item/stack/tile/wood)) + return 1 + else + return 0 + +/turf/simulated/floor/is_carpet_floor() + if(ispath(floor_type, /obj/item/stack/tile/carpet)) + return 1 + else + return 0 + +/turf/simulated/floor/is_catwalk() + return 0 + +/turf/simulated/floor/is_plating() + if(!floor_type && !is_catwalk()) + return 1 + return 0 + +/turf/simulated/floor/proc/break_tile() + if(istype(src,/turf/simulated/floor/engine)) + return + if(istype(src,/turf/simulated/floor/mech_bay_recharge_floor)) + src.ChangeTurf(/turf/simulated/floor/plating) + 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()) + var/obj/item/stack/tile/carpet/C = floor_type + icon_state = "[initial(C.carpet_icon_state)]-broken" + broken = 1 + else if(is_grass_floor()) + src.icon_state = "sand[pick("1","2","3")]" + broken = 1 + +/turf/simulated/floor/proc/burn_tile() + if(istype(src,/turf/simulated/floor/engine)) + return + if(istype(src,/turf/simulated/floor/plating/airless/asteroid)) + return//Asteroid tiles don't burn + if(broken || burnt) + return + 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()) + var/obj/item/stack/tile/carpet/C = floor_type + icon_state = "[initial(C.carpet_icon_state)]-broken" + burnt = 1 + else if(is_grass_floor()) + src.icon_state = "sand[pick("1","2","3")]" + burnt = 1 + +//This proc will set floor_type to null and the update_icon() 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_catwalk()) + 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()) + icon = 'icons/turf/floors.dmi' + spawn(5) + if(src) + for(var/direction in list(1,2,4,8,5,6,9,10)) + 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_type) + return + icon_plating = "plating" + set_light(0) + floor_type = null + intact = 0 + broken = 0 + burnt = 0 + + 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(obj/item/stack/tile/plasteel/T = null) + broken = 0 + burnt = 0 + intact = 1 + set_light(0) + if(T) + if(istype(T,/obj/item/stack/tile/plasteel)) + floor_type = T.type + 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_type = /obj/item/stack/tile/plasteel + 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(obj/item/stack/tile/light/T = null) + broken = 0 + burnt = 0 + intact = 1 + if(T) + if(istype(T,/obj/item/stack/tile/light)) + floor_type = T.type + update_icon() + levelupdate() + return + //if you gave a valid parameter, it won't get thisf ar. + floor_type = /obj/item/stack/tile/light + + 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(obj/item/stack/tile/grass/T = null) + broken = 0 + burnt = 0 + intact = 1 + if(T) + if(istype(T,/obj/item/stack/tile/grass)) + floor_type = T.type + update_icon() + levelupdate() + return + //if you gave a valid parameter, it won't get thisf ar. + floor_type = /obj/item/stack/tile/grass + + 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(obj/item/stack/tile/wood/T = null) + broken = 0 + burnt = 0 + intact = 1 + if(T) + if(istype(T,/obj/item/stack/tile/wood)) + floor_type = T.type + update_icon() + levelupdate() + return + //if you gave a valid parameter, it won't get thisf ar. + floor_type = /obj/item/stack/tile/wood + + 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(obj/item/stack/tile/carpet/T = null) + broken = 0 + burnt = 0 + intact = 1 + if(T) + if(istype(T,/obj/item/stack/tile/carpet)) + floor_type = T.type + update_icon() + levelupdate() + return + //if you gave a valid parameter, it won't get thisf ar. + floor_type = /obj/item/stack/tile/carpet + + update_icon() + levelupdate() + +/turf/simulated/floor/attackby(obj/item/C, mob/user) + + if(!C || !user) + return 0 + user.SetNextMove(CLICK_CD_INTERACT) + + if(istype(C,/obj/item/weapon/light/bulb)) //only for light tiles + if(is_light_floor()) + if(get_lightfloor_state()) + user.remove_from_mob(C) + qdel(C) + set_lightfloor_state(0) //fixing it by bashing it with a light bulb, fun eh? + update_icon() + to_chat(user, "\blue You replace the light bulb.") + else + to_chat(user, "\blue The lightbulb seems fine, no need to replace it.") + + if(istype(C, /obj/item/weapon/crowbar) && (!(is_plating()))) + if(broken || burnt) + to_chat(user, "\red You remove the broken plating.") + else + if(is_wood_floor()) + to_chat(user, "\red You forcefully pry off the planks, destroying them in the process.") + else + var/obj/item/I = new floor_type(src) + if(is_light_floor()) + var/obj/item/stack/tile/light/L = I + L.on = get_lightfloor_on() + L.state = get_lightfloor_state() + to_chat(user, "\red You remove the [I.name].") + + make_plating() + // Can't play sounds from areas. - N3X + playsound(src, 'sound/items/Crowbar.ogg', 80, 1) + + return + + if(istype(C, /obj/item/weapon/screwdriver)) + if(is_wood_floor()) + if(broken || burnt) + return + else + if(is_wood_floor()) + to_chat(user, "\red You unscrew the planks.") + new floor_type(src) + + make_plating() + playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) + if(is_catwalk()) + if(broken) + return + ReplaceWithLattice() + playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) + return + + if(istype(C, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = C + if (is_plating()) + if (R.get_amount() >= 2) + if(user.is_busy()) return + to_chat(user, "\blue Reinforcing the floor...") + if(do_after(user, 30, target = src) && R.use(2) && is_plating()) + ChangeTurf(/turf/simulated/floor/engine) + playsound(src, 'sound/items/Deconstruct.ogg', 80, 1) + return + else + to_chat(user, "\red You need more rods.") + else if (is_catwalk()) + to_chat(user, "\red The entire thing is 100% rods already, it doesn't need any more.") + else + to_chat(user, "\red You must remove the plating first.") + return + + if(istype(C, /obj/item/stack/tile)) + if (is_catwalk()) + to_chat(user, "\red The catwalk is too primitive to support tiling.") + if(is_plating()) + if(!broken && !burnt) + var/obj/item/stack/tile/T = C + floor_type = T.type + icon = initial(T.turf_type.icon) + if(!T.use(1)) + return + intact = 1 + if(istype(T,/obj/item/stack/tile/light)) + var/obj/item/stack/tile/light/L = T + set_lightfloor_state(L.state) + set_lightfloor_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 list(1,2,4,8,5,6,9,10)) + 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, "\blue This section is too damaged to support a tile. Use a welder to fix the damage.") + + + if(istype(C, /obj/item/stack/cable_coil)) + if(is_plating() || is_catwalk()) + var/obj/item/stack/cable_coil/coil = C + for(var/obj/structure/cable/LC in src) + if((LC.d1==0)||(LC.d2==0)) + LC.attackby(C,user) + return + coil.turf_place(src, user) + else + to_chat(user, "\red You must remove the plating first.") + + if(istype(C, /obj/item/weapon/shovel)) + if(is_grass_floor()) + new /obj/item/weapon/ore/glass(src) + new /obj/item/weapon/ore/glass(src) //Make some sand if you shovel grass + to_chat(user, "\blue You shovel the grass.") + make_plating() + else + to_chat(user, "\red You cannot shovel this.") + + 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, "\red 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, "\blue You need more welding fuel to complete this task.") + +#undef LIGHTFLOOR_ON_BIT + +#undef LIGHTFLOOR_STATE_OK +#undef LIGHTFLOOR_STATE_FLICKER +#undef LIGHTFLOOR_STATE_BREAKING +#undef LIGHTFLOOR_STATE_BROKEN +#undef LIGHTFLOOR_STATE_BITS diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index 7fa730ede409..dc9bc9375f81 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -1,364 +1,364 @@ -/turf/simulated/floor/airless - icon_state = "floor" - name = "airless floor" - oxygen = 0.01 - nitrogen = 0.01 - temperature = TCMB - -/turf/simulated/floor/airless/atom_init() - . = ..() - name = "floor" - -/turf/simulated/floor/airless/ceiling - icon_state = "rockvault" - -/turf/simulated/floor/light - name = "Light floor" - light_range = 5 - icon_state = "light_on" - floor_type = /obj/item/stack/tile/light - -/turf/simulated/floor/light/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/turf/simulated/floor/light/atom_init_late() - update_icon() - name = initial(name) - -/turf/simulated/floor/wood - name = "floor" - icon_state = "wood" - floor_type = /obj/item/stack/tile/wood - -/turf/unsimulated/desert - name = "sand" - icon_state = "asteroid" - -/turf/simulated/floor/vault - icon_state = "rockvault" - -/turf/simulated/floor/vault/atom_init(mapload, type) - . = ..() - icon_state = "[type]vault" - -/turf/simulated/wall/vault - icon_state = "rockvault" - -/turf/simulated/wall/vault/atom_init(mapload, type) - . = ..() - icon_state = "[type]vault" - -/turf/simulated/floor/engine - name = "reinforced floor" - icon_state = "engine" - thermal_conductivity = 0.025 - heat_capacity = 325000 - -/turf/simulated/floor/engine/attackby(obj/item/weapon/C, mob/user) - if(istype(C, /obj/item/weapon/wrench)) - if(user.is_busy()) return - to_chat(user, "\blue Removing rods...") - playsound(src, 'sound/items/Ratchet.ogg', 80, 1) - if(do_after(user, 30, target = src)) - 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/singularity_pull(S, current_size) - if(current_size >= STAGE_FIVE) - if(floor_type) - if(prob(30)) - new floor_type(src) - ChangeTurf(/turf/simulated/floor) - make_plating() // why there is return for this floor type in that proc? - else if(prob(30)) - ReplaceWithLattice() - -/turf/simulated/floor/engine/cult - name = "engraved floor" - icon_state = "cult" - -/turf/simulated/floor/engine/airmix - oxygen = MOLES_O2ATMOS - nitrogen = MOLES_N2ATMOS - -/turf/simulated/floor/engine/nitrogen - oxygen = 0 - nitrogen = ATMOSTANK_NITROGEN - -/turf/simulated/floor/engine/oxygen - oxygen = ATMOSTANK_OXYGEN - nitrogen = 0 - -/turf/simulated/floor/engine/phoron - oxygen = 0 - nitrogen = 0 - phoron = ATMOSTANK_PHORON - -/turf/simulated/floor/engine/carbon_dioxide - oxygen = 0 - nitrogen = 0 - carbon_dioxide = ATMOSTANK_CO2 - -/turf/simulated/floor/engine/n20 - oxygen = 0 - nitrogen = 0 - -/turf/simulated/floor/engine/n20/atom_init() - . = ..() - - if(!air) - make_air() - - air.adjust_gas("sleeping_agent", ATMOSTANK_NITROUSOXIDE) - -/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" - floor_type = null - intact = 0 - -/turf/simulated/floor/plating/airless - icon_state = "plating" - name = "airless plating" - oxygen = 0.01 - nitrogen = 0.01 - temperature = TCMB - -/turf/simulated/floor/plating/airless/atom_init() - . = ..() - name = "plating" - -/turf/simulated/floor/bluegrid - icon = 'icons/turf/floors.dmi' - icon_state = "bcircuit" - -/turf/simulated/floor/whitegreed - icon = 'icons/turf/floors.dmi' - icon_state = "bcircuit" - -/turf/simulated/floor/greengrid - icon = 'icons/turf/floors.dmi' - icon_state = "gcircuit" - - -/turf/simulated/shuttle - name = "shuttle" - icon = 'icons/turf/shuttle.dmi' - thermal_conductivity = 0.05 - heat_capacity = 0 - layer = 2 - -/turf/simulated/shuttle/wall - name = "wall" - icon_state = "wall1" - opacity = 1 - density = 1 - blocks_air = 1 - -/turf/simulated/shuttle/floor - name = "floor" - icon_state = "floor" - -/turf/simulated/shuttle/plating - name = "plating" - icon = 'icons/turf/floors.dmi' - icon_state = "plating" - -/turf/simulated/shuttle/floor4 // Added this floor tile so that I have a seperate turf to check in the shuttle -- Polymorph - name = "Brig floor" // Also added it into the 2x3 brig area of the shuttle. - icon_state = "floor4" - -/turf/simulated/floor/beach - name = "Beach" - icon = 'icons/misc/beach.dmi' - -/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" - light_color = "#00BFFF" - light_power = 2 - light_range = 2 - -/turf/simulated/floor/beach/water/atom_init() - . = ..() - overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1) - -/turf/simulated/floor/beach/water/break_tile() - return - -/turf/simulated/floor/beach/water/burn_tile() - return - -/turf/simulated/floor/grass - name = "Grass patch" - icon_state = "grass1" - floor_type = /obj/item/stack/tile/grass - -/turf/simulated/floor/grass/atom_init() - icon_state = "grass[pick("1","2","3","4")]" - ..() - return INITIALIZE_HINT_LATELOAD - -/turf/simulated/floor/grass/atom_init_late() - 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_type = /obj/item/stack/tile/carpet - icon = 'icons/turf/carpets.dmi' - -/turf/simulated/floor/carpet/black - name = "black carpet" - icon_state = "blackcarpet" - floor_type = /obj/item/stack/tile/carpet/black - -/turf/simulated/floor/carpet/purple - name = "purple carpet" - icon_state = "purplecarpet" - floor_type = /obj/item/stack/tile/carpet/purple - -/turf/simulated/floor/carpet/orange - name = "orange carpet" - icon_state = "orangecarpet" - floor_type = /obj/item/stack/tile/carpet/orange - -/turf/simulated/floor/carpet/green - name = "green carpet" - icon_state = "greencarpet" - floor_type = /obj/item/stack/tile/carpet/green - -/turf/simulated/floor/carpet/blue - name = "blue carpet" - icon_state = "bluecarpet" - floor_type = /obj/item/stack/tile/carpet/blue - -/turf/simulated/floor/carpet/blue2 - name = "blue carpet" - icon_state = "blue2carpet" - floor_type = /obj/item/stack/tile/carpet/blue2 - -/turf/simulated/floor/carpet/red - name = "red carpet" - icon_state = "redcarpet" - floor_type = /obj/item/stack/tile/carpet/red - -/turf/simulated/floor/carpet/cyan - name = "cyan carpet" - icon_state = "cyancarpet" - floor_type = /obj/item/stack/tile/carpet/cyan - -/turf/simulated/floor/carpet/atom_init() - if(!icon_state) - icon_state = "carpet" - ..() - return INITIALIZE_HINT_LATELOAD - -/turf/simulated/floor/carpet/atom_init_late() - update_icon() - for(var/direction in list(1,2,4,8,5,6,9,10)) - 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/plating/ironsand - name = "Iron Sand" - icon_state = "ironsand1" - basetype = /turf/simulated/floor/plating/ironsand - -/turf/simulated/floor/plating/ironsand/ex_act() - return 0 - -/turf/simulated/floor/plating/ironsand/burn_tile() - return 0 - -/turf/simulated/floor/plating/ironsand/atom_init() - . = ..() - icon_state = "ironsand[rand(1,15)]" - -/turf/simulated/floor/plating/snow - basetype = /turf/simulated/floor/plating/ironsand - name = "snow" - icon = 'icons/turf/snow.dmi' - icon_state = "snow" - -/turf/simulated/floor/plating/snow/ex_act(severity) - return - -// CATWALKS -// Space and plating, all in one buggy fucking turf! -/turf/simulated/floor/plating/airless/catwalk - icon = 'icons/turf/catwalks.dmi' - icon_state = "catwalk0" - name = "catwalk" - desc = "Cats really don't like these things." - - temperature = TCMB - thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT - heat_capacity = 700000 - -// accepts_lighting=0 // Don't apply overlays - - intact = 0 - -/turf/simulated/floor/plating/airless/catwalk/atom_init() - . = ..() - update_icon(1) - set_light(1.5) - -/turf/simulated/floor/plating/airless/catwalk/update_icon(propogate=1) - underlays.Cut() - var/image/I = image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER) - I.plane = PLANE_SPACE - underlays += I - - var/dirs = 0 - for(var/direction in cardinal) - var/turf/T = get_step(src,direction) - if(T.is_catwalk()) - var/turf/simulated/floor/plating/airless/catwalk/C=T - dirs |= direction - if(propogate) - C.update_icon(0) - icon_state="catwalk[dirs]" - - -/turf/simulated/floor/plating/airless/catwalk/attackby(obj/item/C, mob/user) - if(istype(C, /obj/item/weapon/screwdriver)) - user.SetNextMove(CLICK_CD_INTERACT) - ReplaceWithLattice() - playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) - return - - if(istype(C, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/coil = C - coil.turf_place(src, user) - -/turf/simulated/floor/plating/airless/catwalk/is_catwalk() - return TRUE - +/turf/simulated/floor/airless + icon_state = "floor" + name = "airless floor" + oxygen = 0.01 + nitrogen = 0.01 + temperature = TCMB + +/turf/simulated/floor/airless/atom_init() + . = ..() + name = "floor" + +/turf/simulated/floor/airless/ceiling + icon_state = "rockvault" + +/turf/simulated/floor/light + name = "Light floor" + light_range = 5 + icon_state = "light_on" + floor_type = /obj/item/stack/tile/light + +/turf/simulated/floor/light/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/turf/simulated/floor/light/atom_init_late() + update_icon() + name = initial(name) + +/turf/simulated/floor/wood + name = "floor" + icon_state = "wood" + floor_type = /obj/item/stack/tile/wood + +/turf/unsimulated/desert + name = "sand" + icon_state = "asteroid" + +/turf/simulated/floor/vault + icon_state = "rockvault" + +/turf/simulated/floor/vault/atom_init(mapload, type) + . = ..() + icon_state = "[type]vault" + +/turf/simulated/wall/vault + icon_state = "rockvault" + +/turf/simulated/wall/vault/atom_init(mapload, type) + . = ..() + icon_state = "[type]vault" + +/turf/simulated/floor/engine + name = "reinforced floor" + icon_state = "engine" + thermal_conductivity = 0.025 + heat_capacity = 325000 + +/turf/simulated/floor/engine/attackby(obj/item/weapon/C, mob/user) + if(istype(C, /obj/item/weapon/wrench)) + if(user.is_busy()) return + to_chat(user, "\blue Removing rods...") + playsound(src, 'sound/items/Ratchet.ogg', 80, 1) + if(do_after(user, 30, target = src)) + 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/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(floor_type) + if(prob(30)) + new floor_type(src) + ChangeTurf(/turf/simulated/floor) + make_plating() // why there is return for this floor type in that proc? + else if(prob(30)) + ReplaceWithLattice() + +/turf/simulated/floor/engine/cult + name = "engraved floor" + icon_state = "cult" + +/turf/simulated/floor/engine/airmix + oxygen = MOLES_O2ATMOS + nitrogen = MOLES_N2ATMOS + +/turf/simulated/floor/engine/nitrogen + oxygen = 0 + nitrogen = ATMOSTANK_NITROGEN + +/turf/simulated/floor/engine/oxygen + oxygen = ATMOSTANK_OXYGEN + nitrogen = 0 + +/turf/simulated/floor/engine/phoron + oxygen = 0 + nitrogen = 0 + phoron = ATMOSTANK_PHORON + +/turf/simulated/floor/engine/carbon_dioxide + oxygen = 0 + nitrogen = 0 + carbon_dioxide = ATMOSTANK_CO2 + +/turf/simulated/floor/engine/n20 + oxygen = 0 + nitrogen = 0 + +/turf/simulated/floor/engine/n20/atom_init() + . = ..() + + if(!air) + make_air() + + air.adjust_gas("sleeping_agent", ATMOSTANK_NITROUSOXIDE) + +/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" + floor_type = null + intact = 0 + +/turf/simulated/floor/plating/airless + icon_state = "plating" + name = "airless plating" + oxygen = 0.01 + nitrogen = 0.01 + temperature = TCMB + +/turf/simulated/floor/plating/airless/atom_init() + . = ..() + name = "plating" + +/turf/simulated/floor/bluegrid + icon = 'icons/turf/floors.dmi' + icon_state = "bcircuit" + +/turf/simulated/floor/whitegreed + icon = 'icons/turf/floors.dmi' + icon_state = "bcircuit" + +/turf/simulated/floor/greengrid + icon = 'icons/turf/floors.dmi' + icon_state = "gcircuit" + + +/turf/simulated/shuttle + name = "shuttle" + icon = 'icons/turf/shuttle.dmi' + thermal_conductivity = 0.05 + heat_capacity = 0 + layer = 2 + +/turf/simulated/shuttle/wall + name = "wall" + icon_state = "wall1" + opacity = 1 + density = 1 + blocks_air = 1 + +/turf/simulated/shuttle/floor + name = "floor" + icon_state = "floor" + +/turf/simulated/shuttle/plating + name = "plating" + icon = 'icons/turf/floors.dmi' + icon_state = "plating" + +/turf/simulated/shuttle/floor4 // Added this floor tile so that I have a seperate turf to check in the shuttle -- Polymorph + name = "Brig floor" // Also added it into the 2x3 brig area of the shuttle. + icon_state = "floor4" + +/turf/simulated/floor/beach + name = "Beach" + icon = 'icons/misc/beach.dmi' + +/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" + light_color = "#00BFFF" + light_power = 2 + light_range = 2 + +/turf/simulated/floor/beach/water/atom_init() + . = ..() + overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water5","layer"=MOB_LAYER+0.1) + +/turf/simulated/floor/beach/water/break_tile() + return + +/turf/simulated/floor/beach/water/burn_tile() + return + +/turf/simulated/floor/grass + name = "Grass patch" + icon_state = "grass1" + floor_type = /obj/item/stack/tile/grass + +/turf/simulated/floor/grass/atom_init() + icon_state = "grass[pick("1","2","3","4")]" + ..() + return INITIALIZE_HINT_LATELOAD + +/turf/simulated/floor/grass/atom_init_late() + 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_type = /obj/item/stack/tile/carpet + icon = 'icons/turf/carpets.dmi' + +/turf/simulated/floor/carpet/black + name = "black carpet" + icon_state = "blackcarpet" + floor_type = /obj/item/stack/tile/carpet/black + +/turf/simulated/floor/carpet/purple + name = "purple carpet" + icon_state = "purplecarpet" + floor_type = /obj/item/stack/tile/carpet/purple + +/turf/simulated/floor/carpet/orange + name = "orange carpet" + icon_state = "orangecarpet" + floor_type = /obj/item/stack/tile/carpet/orange + +/turf/simulated/floor/carpet/green + name = "green carpet" + icon_state = "greencarpet" + floor_type = /obj/item/stack/tile/carpet/green + +/turf/simulated/floor/carpet/blue + name = "blue carpet" + icon_state = "bluecarpet" + floor_type = /obj/item/stack/tile/carpet/blue + +/turf/simulated/floor/carpet/blue2 + name = "blue carpet" + icon_state = "blue2carpet" + floor_type = /obj/item/stack/tile/carpet/blue2 + +/turf/simulated/floor/carpet/red + name = "red carpet" + icon_state = "redcarpet" + floor_type = /obj/item/stack/tile/carpet/red + +/turf/simulated/floor/carpet/cyan + name = "cyan carpet" + icon_state = "cyancarpet" + floor_type = /obj/item/stack/tile/carpet/cyan + +/turf/simulated/floor/carpet/atom_init() + if(!icon_state) + icon_state = "carpet" + ..() + return INITIALIZE_HINT_LATELOAD + +/turf/simulated/floor/carpet/atom_init_late() + update_icon() + for(var/direction in list(1,2,4,8,5,6,9,10)) + 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/plating/ironsand + name = "Iron Sand" + icon_state = "ironsand1" + basetype = /turf/simulated/floor/plating/ironsand + +/turf/simulated/floor/plating/ironsand/ex_act() + return 0 + +/turf/simulated/floor/plating/ironsand/burn_tile() + return 0 + +/turf/simulated/floor/plating/ironsand/atom_init() + . = ..() + icon_state = "ironsand[rand(1,15)]" + +/turf/simulated/floor/plating/snow + basetype = /turf/simulated/floor/plating/ironsand + name = "snow" + icon = 'icons/turf/snow.dmi' + icon_state = "snow" + +/turf/simulated/floor/plating/snow/ex_act(severity) + return + +// CATWALKS +// Space and plating, all in one buggy fucking turf! +/turf/simulated/floor/plating/airless/catwalk + icon = 'icons/turf/catwalks.dmi' + icon_state = "catwalk0" + name = "catwalk" + desc = "Cats really don't like these things." + + temperature = TCMB + thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT + heat_capacity = 700000 + +// accepts_lighting=0 // Don't apply overlays + + intact = 0 + +/turf/simulated/floor/plating/airless/catwalk/atom_init() + . = ..() + update_icon(1) + set_light(1.5) + +/turf/simulated/floor/plating/airless/catwalk/update_icon(propogate=1) + underlays.Cut() + var/image/I = image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=TURF_LAYER) + I.plane = PLANE_SPACE + underlays += I + + var/dirs = 0 + for(var/direction in cardinal) + var/turf/T = get_step(src,direction) + if(T.is_catwalk()) + var/turf/simulated/floor/plating/airless/catwalk/C=T + dirs |= direction + if(propogate) + C.update_icon(0) + icon_state="catwalk[dirs]" + + +/turf/simulated/floor/plating/airless/catwalk/attackby(obj/item/C, mob/user) + if(istype(C, /obj/item/weapon/screwdriver)) + user.SetNextMove(CLICK_CD_INTERACT) + ReplaceWithLattice() + playsound(src, 'sound/items/Screwdriver.ogg', 80, 1) + return + + if(istype(C, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/coil = C + coil.turf_place(src, user) + +/turf/simulated/floor/plating/airless/catwalk/is_catwalk() + return TRUE + /turf/simulated/floor/exodus \ No newline at end of file diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 3b5517763afc..45c309e9230b 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -1,486 +1,486 @@ -/turf/simulated/wall - name = "wall" - desc = "A huge chunk of metal used to seperate rooms." - icon = 'icons/turf/walls.dmi' - plane = GAME_PLANE - - var/mineral = "metal" - var/rotting = 0 - - var/damage = 0 - var/damage_cap = 100 //Wall will break down to girders if damage reaches this point - - var/damage_overlay - var/global/damage_overlays[8] - - var/max_temperature = 2200 //K, walls will take damage if they're next to a fire hotter than this - - 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/sheet_type = /obj/item/stack/sheet/metal - -/turf/simulated/wall/Destroy() - for(var/obj/effect/E in src) - if(E.name == "Wallrot") - qdel(E) - dismantle_wall() - return ..() - -/turf/simulated/wall/ChangeTurf() - for(var/obj/effect/E in src) - if(E.name == "Wallrot") - qdel(E) - . = ..() - relativewall_neighbours() - -//Appearance - -/turf/simulated/wall/examine(mob/user) - ..() - - if(!damage) - to_chat(user, "It looks fully intact.") - else - var/dam = damage / damage_cap - if(dam <= 0.3) - to_chat(user, "It looks slightly damaged.") - else if(dam <= 0.6) - to_chat(user, "It looks moderately damaged.") - else - to_chat(user, "It looks heavily damaged.") - - if(rotting) - to_chat(user, "There is fungus growing on [src].") - -/turf/simulated/wall/update_icon() - if(!damage_overlays[1]) //list hasn't been populated - generate_overlays() - - if(!damage) - overlays.Cut() - return - - var/overlay = round(damage / damage_cap * damage_overlays.len) + 1 - if(overlay > damage_overlays.len) - overlay = damage_overlays.len - - if(damage_overlay && overlay == damage_overlay) //No need to update. - return - - overlays.Cut() - overlays += damage_overlays[overlay] - damage_overlay = overlay - - return - -/turf/simulated/wall/proc/generate_overlays() - var/alpha_inc = 256 / damage_overlays.len - - for(var/i = 1; i <= damage_overlays.len; i++) - var/image/img = image(icon = 'icons/turf/walls.dmi', icon_state = "overlay_damage") - img.blend_mode = BLEND_MULTIPLY - img.alpha = (i * alpha_inc) - 1 - damage_overlays[i] = img - -//Damage - -/turf/simulated/wall/proc/take_damage(dam) - if(dam) - damage = max(0, damage + dam) - update_damage() - return - -/turf/simulated/wall/proc/update_damage() - var/cap = damage_cap - if(rotting) - cap = cap / 10 - - if(damage >= cap) - dismantle_wall() - else - update_icon() - - return - -/turf/simulated/wall/adjacent_fire_act(turf/simulated/floor/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume) - if(adj_temp > max_temperature) - take_damage(rand(10, 20) * (adj_temp / max_temperature)) - - return ..() - -/turf/simulated/wall/proc/dismantle_wall(devastated=0, explode=0) - if(devastated) - devastate_wall() - else - playsound(src, 'sound/items/Welder.ogg', 100, 1) - var/newgirder = break_wall() - transfer_fingerprints_to(newgirder) - - 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) - else - O.loc = src - ChangeTurf(/turf/simulated/floor/plating) - -/turf/simulated/wall/proc/break_wall() - if(istype(src, /turf/simulated/wall/cult)) - new /obj/effect/decal/cleanable/blood(src) - return (new /obj/structure/cultgirder(src)) - - new sheet_type(src, 2) - return (new /obj/structure/girder(src)) - -/turf/simulated/wall/proc/devastate_wall() - if(istype(src, /turf/simulated/wall/cult)) - new /obj/effect/decal/cleanable/blood(src) - new /obj/effect/decal/remains/human(src) - - new sheet_type(src, 2) - new /obj/item/stack/sheet/metal(src) - -/turf/simulated/wall/ex_act(severity) - switch(severity) - if(1.0) - src.ChangeTurf(basetype) - return - if(2.0) - if(prob(75)) - take_damage(rand(150, 250)) - else - dismantle_wall(1,1) - if(3.0) - take_damage(rand(0, 250)) - else - return - -/turf/simulated/wall/blob_act() - take_damage(rand(75, 125)) - return - -// Wall-rot effect, a nasty fungus that destroys walls. -/turf/simulated/wall/proc/rot() - if(!rotting) - rotting = 1 - - var/number_rots = rand(2,3) - for(var/i=0, iThe thermite starts melting through the wall.
                    ") - - spawn(100) - if(O) qdel(O) -// F.sd_LumReset() //TODO: ~Carn - return - -/turf/simulated/wall/meteorhit(obj/M) - if (prob(15) && !rotting) - dismantle_wall() - else if(prob(70) && !rotting) - ChangeTurf(/turf/simulated/floor/plating) - else - ReplaceWithLattice() - return 0 - -//Interactions - -/turf/simulated/wall/attack_paw(mob/user) - return src.attack_hand(user) //#Z2 - -/* -/turf/simulated/wall/attack_animal(mob/living/simple_animal/M) - if(M.wall_smash) - if (istype(src, /turf/simulated/wall/r_wall) && !rotting) - to_chat(M, text("\blue This wall is far too strong for you to destroy.")) - return - else - if (prob(40) || rotting) - to_chat(M, text("\blue You smash through the wall.")) - dismantle_wall(1) - return - else - to_chat(M, text("\blue You smash against the wall.")) - return - - to_chat(M, "\blue You push the wall but nothing happens!") - return */ - -/turf/simulated/wall/attack_animal(mob/living/simple_animal/M) - ..() - if(M.environment_smash >= 2) - if(istype(M, /mob/living/simple_animal/hulk)) - var/mob/living/simple_animal/hulk/Hulk = M - playsound(Hulk, 'sound/weapons/tablehit1.ogg', 50, 1) - Hulk.health -= rand(4,10) - playsound(M.loc, 'sound/effects/grillehit.ogg', 50, 1) - if(istype(src, /turf/simulated/wall/r_wall)) - if(M.environment_smash == 3) - take_damage(rand(25, 75)) - to_chat(M, "You smash against the wall.") - else - to_chat(M, "This wall is far too strong for you to destroy.") - else - if (prob(40) || rotting) - to_chat(M, text("\blue You smash through the wall.")) - dismantle_wall(1) - else - take_damage(rand(25, 75)) - to_chat(M, "You smash against the wall.") - return - return - -/turf/simulated/wall/attack_hand(mob/user) - user.SetNextMove(CLICK_CD_MELEE) - if(HULK in user.mutations) //#Z2 No more chances, just randomized damage and hurt intent - if(user.a_intent == "hurt") - playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) - to_chat(user, text("\blue You punch the wall.")) - take_damage(rand(15, 50)) - if(prob(25)) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - return //##Z2 - - if(rotting) - to_chat(user, "\blue The wall crumbles under your touch.") - dismantle_wall() - return - - to_chat(user, "\blue You push the wall but nothing happens!") - playsound(src, 'sound/weapons/Genhit.ogg', 25, 1) - src.add_fingerprint(user) - return - -/turf/simulated/wall/attackby(obj/item/weapon/W, mob/user) - - if (!(ishuman(user)|| ticker) && ticker.mode.name != "monkey") - to_chat(user, "You don't have the dexterity to do this!") - return - - //get the user's location - if(!isturf(user.loc)) - return //can't do this stuff whilst inside objects and such - user.SetNextMove(CLICK_CD_MELEE) - - if(rotting) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "You burn away the fungi with \the [WT].") - playsound(src, 'sound/items/Welder.ogg', 10, 1) - for(var/obj/effect/E in src) if(E.name == "Wallrot") - qdel(E) - rotting = 0 - return - else if(!is_sharp(W) && W.force >= 10 || W.force >= 20) - to_chat(user, "\The [src] crumbles away under the force of your [W.name].") - src.dismantle_wall(1) - return - - //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects - if(thermite) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - thermitemelt(user) - return - - else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - thermitemelt(user) - return - - else if(istype(W, /obj/item/weapon/melee/energy/blade)) - var/obj/item/weapon/melee/energy/blade/EB = W - - EB.spark_system.start() - to_chat(user, "You slash \the [src] with \the [EB]; the thermite ignites!") - playsound(src, "sparks", 50, 1) - playsound(src, 'sound/weapons/blade1.ogg', 50, 1) - - thermitemelt(user) - return - - var/turf/T = user.loc //get user's location for delay checks - - //DECONSTRUCTION - if(istype(W, /obj/item/weapon/weldingtool)) - if(user.is_busy()) return - - var/response = "Dismantle" - if(damage) - response = alert(user, "Would you like to repair or dismantle [src]?", "[src]", "Repair", "Dismantle") - - var/obj/item/weapon/weldingtool/WT = W - - if(WT.remove_fuel(0,user)) - if(response == "Repair") - to_chat(user, "You start repairing the damage to [src].") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - if(do_after(user, max(5, damage / 5), target = src) && WT && WT.isOn()) - to_chat(user, "You finish repairing the damage to [src].") - take_damage(-damage) - - else if(response == "Dismantle") - to_chat(user, "You begin slicing through the outer plating.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user,100, target = src)) - if(!istype(src, /turf/simulated/wall) || !user || !WT || !WT.isOn() || !T) - return - - if(user.loc == T && user.get_active_hand() == WT) - to_chat(user, "You remove the outer plating.") - dismantle_wall() - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - if(user.is_busy()) return - - to_chat(user, "You begin slicing through the outer plating.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user,60,target = src)) - if(mineral == "diamond")//Oh look, it's tougher - sleep(60) - if(!istype(src, /turf/simulated/wall) || !user || !W || !T) - return - - if(user.loc == T && user.get_active_hand() == W) - to_chat(user, "You remove the outer plating.") - dismantle_wall() - for(var/mob/O in viewers(user, 5)) - O.show_message("The wall was sliced apart by [user]!", 1, "You hear metal being sliced apart.", 2) - return - - //DRILLING - else if (istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) - if(user.is_busy()) return - - to_chat(user, "You begin to drill though the wall.") - - if(do_after(user,60,target = src)) - if(mineral == "diamond") - sleep(60) - if(!istype(src, /turf/simulated/wall) || !user || !W || !T) - return - - if(user.loc == T && user.get_active_hand() == W) - to_chat(user, "Your drill tears though the last of the reinforced plating.") - dismantle_wall() - for(var/mob/O in viewers(user, 5)) - O.show_message("The wall was drilled through by [user]!", 1, "You hear the grinding of metal.", 2) - return - - else if(istype(W, /obj/item/weapon/melee/energy/blade)) - if(user.is_busy()) return - var/obj/item/weapon/melee/energy/blade/EB = W - - EB.spark_system.start() - to_chat(user, "You stab \the [EB] into the wall and begin to slice it apart.") - playsound(src, "sparks", 50, 1) - - if(do_after(user,70,target = src)) - if(mineral == "diamond") - sleep(70) - if(!istype(src, /turf/simulated/wall) || !user || !EB || !T) - return - - if(user.loc == T && user.get_active_hand() == W) - EB.spark_system.start() - playsound(src, "sparks", 50, 1) - playsound(src, 'sound/weapons/blade1.ogg', 50, 1) - dismantle_wall(1) - for(var/mob/O in viewers(user, 5)) - O.show_message("The wall was sliced apart by [user]!", 1, "You hear metal being sliced apart and sparks flying.", 2) - return - else if(istype(W,/obj/item/weapon/changeling_hammer) && !rotting) - var/obj/item/weapon/changeling_hammer/C = W - visible_message("[user] has punched the[src]!") - user.do_attack_animation(src) - if(C.use_charge(user)) - playsound(user.loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) - take_damage(pick(10, 20, 30)) - return - - else if(istype(W,/obj/item/apc_frame)) - var/obj/item/apc_frame/AH = W - AH.try_build(src) - return - - else if(istype(W,/obj/item/newscaster_frame)) - var/obj/item/newscaster_frame/AH = W - AH.try_build(src) - return - - else if(istype(W,/obj/item/alarm_frame)) - var/obj/item/alarm_frame/AH = W - AH.try_build(src) - return - - else if(istype(W,/obj/item/firealarm_frame)) - var/obj/item/firealarm_frame/AH = W - AH.try_build(src) - return - - else if(istype(W,/obj/item/light_fixture_frame)) - var/obj/item/light_fixture_frame/AH = W - AH.try_build(src) - return - - else if(istype(W,/obj/item/light_fixture_frame/small)) - var/obj/item/light_fixture_frame/small/AH = W - AH.try_build(src) - return - - //Poster stuff - else if(istype(W,/obj/item/weapon/poster)) - place_poster(W,user) - return - - else - return attack_hand(user) - -/turf/simulated/wall/singularity_pull(S, current_size) - if(current_size >= STAGE_FIVE) - if(prob(50)) - 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 seperate rooms." + icon = 'icons/turf/walls.dmi' + plane = GAME_PLANE + + var/mineral = "metal" + var/rotting = 0 + + var/damage = 0 + var/damage_cap = 100 //Wall will break down to girders if damage reaches this point + + var/damage_overlay + var/global/damage_overlays[8] + + var/max_temperature = 2200 //K, walls will take damage if they're next to a fire hotter than this + + 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/sheet_type = /obj/item/stack/sheet/metal + +/turf/simulated/wall/Destroy() + for(var/obj/effect/E in src) + if(E.name == "Wallrot") + qdel(E) + dismantle_wall() + return ..() + +/turf/simulated/wall/ChangeTurf() + for(var/obj/effect/E in src) + if(E.name == "Wallrot") + qdel(E) + . = ..() + relativewall_neighbours() + +//Appearance + +/turf/simulated/wall/examine(mob/user) + ..() + + if(!damage) + to_chat(user, "It looks fully intact.") + else + var/dam = damage / damage_cap + if(dam <= 0.3) + to_chat(user, "It looks slightly damaged.") + else if(dam <= 0.6) + to_chat(user, "It looks moderately damaged.") + else + to_chat(user, "It looks heavily damaged.") + + if(rotting) + to_chat(user, "There is fungus growing on [src].") + +/turf/simulated/wall/update_icon() + if(!damage_overlays[1]) //list hasn't been populated + generate_overlays() + + if(!damage) + overlays.Cut() + return + + var/overlay = round(damage / damage_cap * damage_overlays.len) + 1 + if(overlay > damage_overlays.len) + overlay = damage_overlays.len + + if(damage_overlay && overlay == damage_overlay) //No need to update. + return + + overlays.Cut() + overlays += damage_overlays[overlay] + damage_overlay = overlay + + return + +/turf/simulated/wall/proc/generate_overlays() + var/alpha_inc = 256 / damage_overlays.len + + for(var/i = 1; i <= damage_overlays.len; i++) + var/image/img = image(icon = 'icons/turf/walls.dmi', icon_state = "overlay_damage") + img.blend_mode = BLEND_MULTIPLY + img.alpha = (i * alpha_inc) - 1 + damage_overlays[i] = img + +//Damage + +/turf/simulated/wall/proc/take_damage(dam) + if(dam) + damage = max(0, damage + dam) + update_damage() + return + +/turf/simulated/wall/proc/update_damage() + var/cap = damage_cap + if(rotting) + cap = cap / 10 + + if(damage >= cap) + dismantle_wall() + else + update_icon() + + return + +/turf/simulated/wall/adjacent_fire_act(turf/simulated/floor/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume) + if(adj_temp > max_temperature) + take_damage(rand(10, 20) * (adj_temp / max_temperature)) + + return ..() + +/turf/simulated/wall/proc/dismantle_wall(devastated=0, explode=0) + if(devastated) + devastate_wall() + else + playsound(src, 'sound/items/Welder.ogg', 100, 1) + var/newgirder = break_wall() + transfer_fingerprints_to(newgirder) + + 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) + else + O.loc = src + ChangeTurf(/turf/simulated/floor/plating) + +/turf/simulated/wall/proc/break_wall() + if(istype(src, /turf/simulated/wall/cult)) + new /obj/effect/decal/cleanable/blood(src) + return (new /obj/structure/cultgirder(src)) + + new sheet_type(src, 2) + return (new /obj/structure/girder(src)) + +/turf/simulated/wall/proc/devastate_wall() + if(istype(src, /turf/simulated/wall/cult)) + new /obj/effect/decal/cleanable/blood(src) + new /obj/effect/decal/remains/human(src) + + new sheet_type(src, 2) + new /obj/item/stack/sheet/metal(src) + +/turf/simulated/wall/ex_act(severity) + switch(severity) + if(1.0) + src.ChangeTurf(basetype) + return + if(2.0) + if(prob(75)) + take_damage(rand(150, 250)) + else + dismantle_wall(1,1) + if(3.0) + take_damage(rand(0, 250)) + else + return + +/turf/simulated/wall/blob_act() + take_damage(rand(75, 125)) + return + +// Wall-rot effect, a nasty fungus that destroys walls. +/turf/simulated/wall/proc/rot() + if(!rotting) + rotting = 1 + + var/number_rots = rand(2,3) + for(var/i=0, iThe thermite starts melting through the wall.
                    ") + + spawn(100) + if(O) qdel(O) +// F.sd_LumReset() //TODO: ~Carn + return + +/turf/simulated/wall/meteorhit(obj/M) + if (prob(15) && !rotting) + dismantle_wall() + else if(prob(70) && !rotting) + ChangeTurf(/turf/simulated/floor/plating) + else + ReplaceWithLattice() + return 0 + +//Interactions + +/turf/simulated/wall/attack_paw(mob/user) + return src.attack_hand(user) //#Z2 + +/* +/turf/simulated/wall/attack_animal(mob/living/simple_animal/M) + if(M.wall_smash) + if (istype(src, /turf/simulated/wall/r_wall) && !rotting) + to_chat(M, text("\blue This wall is far too strong for you to destroy.")) + return + else + if (prob(40) || rotting) + to_chat(M, text("\blue You smash through the wall.")) + dismantle_wall(1) + return + else + to_chat(M, text("\blue You smash against the wall.")) + return + + to_chat(M, "\blue You push the wall but nothing happens!") + return */ + +/turf/simulated/wall/attack_animal(mob/living/simple_animal/M) + ..() + if(M.environment_smash >= 2) + if(istype(M, /mob/living/simple_animal/hulk)) + var/mob/living/simple_animal/hulk/Hulk = M + playsound(Hulk, 'sound/weapons/tablehit1.ogg', 50, 1) + Hulk.health -= rand(4,10) + playsound(M.loc, 'sound/effects/grillehit.ogg', 50, 1) + if(istype(src, /turf/simulated/wall/r_wall)) + if(M.environment_smash == 3) + take_damage(rand(25, 75)) + to_chat(M, "You smash against the wall.") + else + to_chat(M, "This wall is far too strong for you to destroy.") + else + if (prob(40) || rotting) + to_chat(M, text("\blue You smash through the wall.")) + dismantle_wall(1) + else + take_damage(rand(25, 75)) + to_chat(M, "You smash against the wall.") + return + return + +/turf/simulated/wall/attack_hand(mob/user) + user.SetNextMove(CLICK_CD_MELEE) + if(HULK in user.mutations) //#Z2 No more chances, just randomized damage and hurt intent + if(user.a_intent == "hurt") + playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) + to_chat(user, text("\blue You punch the wall.")) + take_damage(rand(15, 50)) + if(prob(25)) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + return //##Z2 + + if(rotting) + to_chat(user, "\blue The wall crumbles under your touch.") + dismantle_wall() + return + + to_chat(user, "\blue You push the wall but nothing happens!") + playsound(src, 'sound/weapons/Genhit.ogg', 25, 1) + src.add_fingerprint(user) + return + +/turf/simulated/wall/attackby(obj/item/weapon/W, mob/user) + + if (!(ishuman(user)|| ticker) && ticker.mode.name != "monkey") + to_chat(user, "You don't have the dexterity to do this!") + return + + //get the user's location + if(!isturf(user.loc)) + return //can't do this stuff whilst inside objects and such + user.SetNextMove(CLICK_CD_MELEE) + + if(rotting) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + to_chat(user, "You burn away the fungi with \the [WT].") + playsound(src, 'sound/items/Welder.ogg', 10, 1) + for(var/obj/effect/E in src) if(E.name == "Wallrot") + qdel(E) + rotting = 0 + return + else if(!is_sharp(W) && W.force >= 10 || W.force >= 20) + to_chat(user, "\The [src] crumbles away under the force of your [W.name].") + src.dismantle_wall(1) + return + + //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects + if(thermite) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + thermitemelt(user) + return + + else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + thermitemelt(user) + return + + else if(istype(W, /obj/item/weapon/melee/energy/blade)) + var/obj/item/weapon/melee/energy/blade/EB = W + + EB.spark_system.start() + to_chat(user, "You slash \the [src] with \the [EB]; the thermite ignites!") + playsound(src, "sparks", 50, 1) + playsound(src, 'sound/weapons/blade1.ogg', 50, 1) + + thermitemelt(user) + return + + var/turf/T = user.loc //get user's location for delay checks + + //DECONSTRUCTION + if(istype(W, /obj/item/weapon/weldingtool)) + if(user.is_busy()) return + + var/response = "Dismantle" + if(damage) + response = alert(user, "Would you like to repair or dismantle [src]?", "[src]", "Repair", "Dismantle") + + var/obj/item/weapon/weldingtool/WT = W + + if(WT.remove_fuel(0,user)) + if(response == "Repair") + to_chat(user, "You start repairing the damage to [src].") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + if(do_after(user, max(5, damage / 5), target = src) && WT && WT.isOn()) + to_chat(user, "You finish repairing the damage to [src].") + take_damage(-damage) + + else if(response == "Dismantle") + to_chat(user, "You begin slicing through the outer plating.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user,100, target = src)) + if(!istype(src, /turf/simulated/wall) || !user || !WT || !WT.isOn() || !T) + return + + if(user.loc == T && user.get_active_hand() == WT) + to_chat(user, "You remove the outer plating.") + dismantle_wall() + return + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + if(user.is_busy()) return + + to_chat(user, "You begin slicing through the outer plating.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user,60,target = src)) + if(mineral == "diamond")//Oh look, it's tougher + sleep(60) + if(!istype(src, /turf/simulated/wall) || !user || !W || !T) + return + + if(user.loc == T && user.get_active_hand() == W) + to_chat(user, "You remove the outer plating.") + dismantle_wall() + for(var/mob/O in viewers(user, 5)) + O.show_message("The wall was sliced apart by [user]!", 1, "You hear metal being sliced apart.", 2) + return + + //DRILLING + else if (istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) + if(user.is_busy()) return + + to_chat(user, "You begin to drill though the wall.") + + if(do_after(user,60,target = src)) + if(mineral == "diamond") + sleep(60) + if(!istype(src, /turf/simulated/wall) || !user || !W || !T) + return + + if(user.loc == T && user.get_active_hand() == W) + to_chat(user, "Your drill tears though the last of the reinforced plating.") + dismantle_wall() + for(var/mob/O in viewers(user, 5)) + O.show_message("The wall was drilled through by [user]!", 1, "You hear the grinding of metal.", 2) + return + + else if(istype(W, /obj/item/weapon/melee/energy/blade)) + if(user.is_busy()) return + var/obj/item/weapon/melee/energy/blade/EB = W + + EB.spark_system.start() + to_chat(user, "You stab \the [EB] into the wall and begin to slice it apart.") + playsound(src, "sparks", 50, 1) + + if(do_after(user,70,target = src)) + if(mineral == "diamond") + sleep(70) + if(!istype(src, /turf/simulated/wall) || !user || !EB || !T) + return + + if(user.loc == T && user.get_active_hand() == W) + EB.spark_system.start() + playsound(src, "sparks", 50, 1) + playsound(src, 'sound/weapons/blade1.ogg', 50, 1) + dismantle_wall(1) + for(var/mob/O in viewers(user, 5)) + O.show_message("The wall was sliced apart by [user]!", 1, "You hear metal being sliced apart and sparks flying.", 2) + return + else if(istype(W,/obj/item/weapon/changeling_hammer) && !rotting) + var/obj/item/weapon/changeling_hammer/C = W + visible_message("[user] has punched the[src]!") + user.do_attack_animation(src) + if(C.use_charge(user)) + playsound(user.loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) + take_damage(pick(10, 20, 30)) + return + + else if(istype(W,/obj/item/apc_frame)) + var/obj/item/apc_frame/AH = W + AH.try_build(src) + return + + else if(istype(W,/obj/item/newscaster_frame)) + var/obj/item/newscaster_frame/AH = W + AH.try_build(src) + return + + else if(istype(W,/obj/item/alarm_frame)) + var/obj/item/alarm_frame/AH = W + AH.try_build(src) + return + + else if(istype(W,/obj/item/firealarm_frame)) + var/obj/item/firealarm_frame/AH = W + AH.try_build(src) + return + + else if(istype(W,/obj/item/light_fixture_frame)) + var/obj/item/light_fixture_frame/AH = W + AH.try_build(src) + return + + else if(istype(W,/obj/item/light_fixture_frame/small)) + var/obj/item/light_fixture_frame/small/AH = W + AH.try_build(src) + return + + //Poster stuff + else if(istype(W,/obj/item/weapon/poster)) + place_poster(W,user) + return + + else + return attack_hand(user) + +/turf/simulated/wall/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(50)) + 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 ed6800ff8a40..ca66160041f9 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -1,146 +1,146 @@ -/turf/simulated/wall/mineral - name = "mineral wall" - desc = "This shouldn't exist." - icon_state = "" - var/last_event = 0 - var/active = null - -/turf/simulated/wall/mineral/gold - name = "gold wall" - desc = "A wall with gold plating. Swag!" - icon_state = "gold0" - walltype = "gold" - mineral = "gold" - sheet_type = /obj/item/stack/sheet/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" - sheet_type = /obj/item/stack/sheet/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" - sheet_type = /obj/item/stack/sheet/mineral/diamond - -/turf/simulated/wall/mineral/clown - name = "bananium wall" - desc = "A wall with bananium plating. Honk!" - icon_state = "clown0" - walltype = "clown" - mineral = "clown" -// sheet_type = /obj/item/stack/sheet/mineral/bananium - -/turf/simulated/wall/mineral/sandstone - name = "sandstone wall" - desc = "A wall with sandstone plating." - icon_state = "sandstone0" - walltype = "sandstone" - mineral = "sandstone" - sheet_type = /obj/item/stack/sheet/mineral/sandstone - -/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" - sheet_type = /obj/item/stack/sheet/mineral/uranium - -/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) - radiate() - ..() - -/turf/simulated/wall/mineral/uranium/attackby(obj/item/weapon/W, mob/user) - radiate() - ..() - -/turf/simulated/wall/mineral/uranium/Bumped(AM) - radiate() - ..() - -/turf/simulated/wall/mineral/phoron - name = "phoron wall" - desc = "A wall with phoron plating. This is definately a bad idea." - icon_state = "phoron0" - walltype = "phoron" - mineral = "phoron" - sheet_type = /obj/item/stack/sheet/mineral/phoron - -/turf/simulated/wall/mineral/phoron/attackby(obj/item/weapon/W, mob/user) - if(is_hot(W) > 300)//If the temperature of the object is over 300, then ignite - ignite(is_hot(W)) - return - ..() - -/turf/simulated/wall/mineral/phoron/proc/PhoronBurn(temperature) - 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()*/ - target_tile.assume_gas("phoron", 20) - target_tile.hotspot_expose(400 + T0C, 400) - for(var/obj/structure/falsewall/phoron/F in range(3,src))//Hackish as fuck, but until temperature_expose works, there is nothing I can do -Sieve - var/turf/T = get_turf(F) - T.ChangeTurf(/turf/simulated/wall/mineral/phoron/) - qdel(F) - for(var/turf/simulated/wall/mineral/phoron/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/phoron/D in range(3,src)) - D.ignite(temperature/4) - -/turf/simulated/wall/mineral/phoron/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) - PhoronBurn(exposed_temperature) - -/turf/simulated/wall/mineral/phoron/proc/ignite(exposed_temperature) - if(exposed_temperature > 300) - PhoronBurn(exposed_temperature) - -/turf/simulated/wall/mineral/phoron/bullet_act(obj/item/projectile/Proj) - if(istype(Proj,/obj/item/projectile/beam)) - PhoronBurn(2500) - else if(istype(Proj,/obj/item/projectile/ion)) - PhoronBurn(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, mob/user) - if((mineral == "gold") || (mineral == "silver")) - if(shocked) - shock() -*/ +/turf/simulated/wall/mineral + name = "mineral wall" + desc = "This shouldn't exist." + icon_state = "" + var/last_event = 0 + var/active = null + +/turf/simulated/wall/mineral/gold + name = "gold wall" + desc = "A wall with gold plating. Swag!" + icon_state = "gold0" + walltype = "gold" + mineral = "gold" + sheet_type = /obj/item/stack/sheet/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" + sheet_type = /obj/item/stack/sheet/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" + sheet_type = /obj/item/stack/sheet/mineral/diamond + +/turf/simulated/wall/mineral/clown + name = "bananium wall" + desc = "A wall with bananium plating. Honk!" + icon_state = "clown0" + walltype = "clown" + mineral = "clown" +// sheet_type = /obj/item/stack/sheet/mineral/bananium + +/turf/simulated/wall/mineral/sandstone + name = "sandstone wall" + desc = "A wall with sandstone plating." + icon_state = "sandstone0" + walltype = "sandstone" + mineral = "sandstone" + sheet_type = /obj/item/stack/sheet/mineral/sandstone + +/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" + sheet_type = /obj/item/stack/sheet/mineral/uranium + +/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) + radiate() + ..() + +/turf/simulated/wall/mineral/uranium/attackby(obj/item/weapon/W, mob/user) + radiate() + ..() + +/turf/simulated/wall/mineral/uranium/Bumped(AM) + radiate() + ..() + +/turf/simulated/wall/mineral/phoron + name = "phoron wall" + desc = "A wall with phoron plating. This is definately a bad idea." + icon_state = "phoron0" + walltype = "phoron" + mineral = "phoron" + sheet_type = /obj/item/stack/sheet/mineral/phoron + +/turf/simulated/wall/mineral/phoron/attackby(obj/item/weapon/W, mob/user) + if(is_hot(W) > 300)//If the temperature of the object is over 300, then ignite + ignite(is_hot(W)) + return + ..() + +/turf/simulated/wall/mineral/phoron/proc/PhoronBurn(temperature) + 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()*/ + target_tile.assume_gas("phoron", 20) + target_tile.hotspot_expose(400 + T0C, 400) + for(var/obj/structure/falsewall/phoron/F in range(3,src))//Hackish as fuck, but until temperature_expose works, there is nothing I can do -Sieve + var/turf/T = get_turf(F) + T.ChangeTurf(/turf/simulated/wall/mineral/phoron/) + qdel(F) + for(var/turf/simulated/wall/mineral/phoron/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/phoron/D in range(3,src)) + D.ignite(temperature/4) + +/turf/simulated/wall/mineral/phoron/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) + PhoronBurn(exposed_temperature) + +/turf/simulated/wall/mineral/phoron/proc/ignite(exposed_temperature) + if(exposed_temperature > 300) + PhoronBurn(exposed_temperature) + +/turf/simulated/wall/mineral/phoron/bullet_act(obj/item/projectile/Proj) + if(istype(Proj,/obj/item/projectile/beam)) + PhoronBurn(2500) + else if(istype(Proj,/obj/item/projectile/ion)) + PhoronBurn(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, mob/user) + 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 185d1643f07a..0b68d6317262 100644 --- a/code/game/turfs/simulated/walls_misc.dm +++ b/code/game/turfs/simulated/walls_misc.dm @@ -1,5 +1,5 @@ -/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" +/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" diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index afba01165f20..5b543da66827 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -1,353 +1,353 @@ -/turf/simulated/wall/r_wall - name = "reinforced wall" - desc = "A huge chunk of reinforced metal used to seperate rooms." - icon_state = "r_wall" - opacity = 1 - density = 1 - - damage_cap = 200 - max_temperature = 20000 - - walltype = "rwall" - sheet_type = /obj/item/stack/sheet/plasteel - - var/d_state = 0 - -/turf/simulated/wall/r_wall/attack_hand(mob/user) - user.SetNextMove(CLICK_CD_MELEE) - if(HULK in user.mutations) //#Z2 - if(user.a_intent == "hurt") - to_chat(user, text("\blue You punch the wall.")) - take_damage(rand(5, 25)) - if(prob(25)) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - if(prob(5)) - playsound(user.loc, 'sound/weapons/tablehit1.ogg', 50, 1) - var/mob/living/carbon/human/H = user - var/obj/item/organ/external/BP = H.bodyparts_by_name[user.hand ? BP_L_ARM : BP_R_ARM] - BP.take_damage(rand(5, 15), used_weapon = "Reinforced wall") - to_chat(user, text("\red Ouch!!")) - else - playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) - return //##Z2 - - if(rotting) - to_chat(user, "\blue This wall feels rather unstable.") - return - - /*user << "\blue You push the wall but nothing happens!" - playsound(src, 'sound/weapons/Genhit.ogg', 25, 1) - src.add_fingerprint(user)*/ //this code is in standard wall attack_hand proc - ..() - return - - -/turf/simulated/wall/r_wall/attackby(obj/item/W, mob/user) - - if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") - to_chat(user, "You don't have the dexterity to do this!") - return - - //get the user's location - if(!isturf(user.loc)) - return //can't do this stuff whilst inside objects and such - user.SetNextMove(CLICK_CD_MELEE) - if(user.is_busy()) return - - if(rotting) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "You burn away the fungi with \the [WT].") - playsound(src, 'sound/items/Welder.ogg', 10, 1) - for(var/obj/effect/E in src) if(E.name == "Wallrot") - qdel(E) - rotting = 0 - return - else if(!is_sharp(W) && W.force >= 10 || W.force >= 20) - to_chat(user, "\The [src] crumbles away under the force of your [W.name].") - src.dismantle_wall() - return - - //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects - if(thermite) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - thermitemelt(user) - return - - else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - thermitemelt(user) - return - - else if(istype(W, /obj/item/weapon/melee/energy/blade)) - var/obj/item/weapon/melee/energy/blade/EB = W - - EB.spark_system.start() - to_chat(user, "You slash \the [src] with \the [EB]; the thermite ignites!") - playsound(src, "sparks", 50, 1) - playsound(src, 'sound/weapons/blade1.ogg', 50, 1) - - thermitemelt(user) - return - - else if(istype(W, /obj/item/weapon/melee/energy/blade)) - to_chat(user, "This wall is too thick to slice through. You will need to find a different path.") - return - - if(damage && istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - to_chat(user, "You start repairing the damage to [src].") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - if(do_after(user, max(5, damage / 5), target = src) && WT && WT.isOn()) - to_chat(user, "You finish repairing the damage to [src].") - take_damage(-damage) - return - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - var/turf/T = user.loc //get user's location for delay checks - - //DECONSTRUCTION - switch(d_state) - if(0) - if (istype(W, /obj/item/weapon/wirecutters)) - playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) - src.d_state = 1 - src.icon_state = "r_wall-1" - new /obj/item/stack/rods(src) - to_chat(user, "You cut the outer grille.") - return - - if(1) - if (istype(W, /obj/item/weapon/screwdriver)) - to_chat(user, "You begin removing the support lines.") - playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) - - if(do_after(user,40,target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) - return - - if(d_state == 1 && user.loc == T && user.get_active_hand() == W) - src.d_state = 2 - src.icon_state = "r_wall-2" - to_chat(user, "You remove the support lines.") - return - - //REPAIRING (replacing the outer grille for cosmetic damage) - else if(istype(W, /obj/item/stack/rods)) - var/obj/item/stack/O = W - if(!O.use(1)) - return - src.d_state = 0 - src.icon_state = "r_wall" - relativewall_neighbours() //call smoothwall stuff - to_chat(user, "You replace the outer grille.") - return - - if(2) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - - to_chat(user, "You begin slicing through the metal cover.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user,60,target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !WT || !WT.isOn() || !T) - return - - if(d_state == 2 && user.loc == T && user.get_active_hand() == WT) - src.d_state = 3 - src.icon_state = "r_wall-3" - to_chat(user, "You press firmly on the cover, dislodging it.") - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - - to_chat(user, "You begin slicing through the metal cover.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user,60,target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) - return - - if(d_state == 2 && user.loc == T && user.get_active_hand() == W) - src.d_state = 3 - src.icon_state = "r_wall-3" - to_chat(user, "You press firmly on the cover, dislodging it.") - return - - if(3) - if (istype(W, /obj/item/weapon/crowbar)) - - to_chat(user, "You struggle to pry off the cover.") - playsound(src, 'sound/items/Crowbar.ogg', 100, 1) - - if(do_after(user,100,target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) - return - - if(d_state == 3 && user.loc == T && user.get_active_hand() == W) - src.d_state = 4 - src.icon_state = "r_wall-4" - to_chat(user, "You pry off the cover.") - return - - if(4) - if (istype(W, /obj/item/weapon/wrench)) - - to_chat(user, "You start loosening the anchoring bolts which secure the support rods to their frame.") - playsound(src, 'sound/items/Ratchet.ogg', 100, 1) - - if(do_after(user,40,target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) - return - - if(d_state == 4 && user.loc == T && user.get_active_hand() == W) - src.d_state = 5 - src.icon_state = "r_wall-5" - to_chat(user, "You remove the bolts anchoring the support rods.") - return - - if(5) - if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - - to_chat(user, "You begin slicing through the support rods.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user,100,target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !WT || !WT.isOn() || !T) - return - - if(d_state == 5 && user.loc == T && user.get_active_hand() == WT) - src.d_state = 6 - src.icon_state = "r_wall-6" - new /obj/item/stack/rods(src) - to_chat(user, "The support rods drop out as you cut them loose from the frame.") - else - to_chat(user, "You need more welding fuel to complete this task.") - return - - if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - - to_chat(user, "You begin slicing through the support rods.") - playsound(src, 'sound/items/Welder.ogg', 100, 1) - - if(do_after(user,70,target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) - return - - if(d_state == 5 && user.loc == T && user.get_active_hand() == W) - src.d_state = 6 - src.icon_state = "r_wall-6" - new /obj/item/stack/rods(src) - to_chat(user, "The support rods drop out as you cut them loose from the frame.") - return - - if(6) - if(istype(W, /obj/item/weapon/crowbar)) - - to_chat(user, "You struggle to pry off the outer sheath.") - playsound(src, 'sound/items/Crowbar.ogg', 100, 1) - - if(do_after(user,100,target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) - return - - if(user.loc == T && user.get_active_hand() == W) - to_chat(user, "You pry off the outer sheath.") - dismantle_wall() - return - -//vv OK, we weren't performing a valid deconstruction step or igniting thermite,let's check the other possibilities vv - - //DRILLING - if(istype(W,/obj/item/weapon/changeling_hammer) && !rotting) - var/obj/item/weapon/changeling_hammer/C = W - user.do_attack_animation(src) - visible_message("\red [user] has punched \the [src]!") - if(C.use_charge(user, 4)) - playsound(user.loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) - take_damage(pick(10, 20, 30)) - return - else if (istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) - - to_chat(user, "You begin to drill though the wall.") - - if(do_after(user,200,target = src)) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) - return - - if(user.loc == T && user.get_active_hand() == W) - to_chat(user, "Your drill tears though the last of the reinforced plating.") - dismantle_wall() - - //REPAIRING - else if(istype(W, /obj/item/stack/sheet/metal) && d_state) - var/obj/item/stack/sheet/metal/MS = W - - to_chat(user, "You begin patching-up the wall with \a [MS].") - - if(do_after(user,(max(20*d_state,100)),target = src)) //time taken to repair is proportional to the damage! (max 10 seconds) - if(!istype(src, /turf/simulated/wall/r_wall) || !user || !MS || !T) - return - - if(user.loc == T && user.get_active_hand() == MS && d_state) - if(!MS.use(1)) - return - src.d_state = 0 - src.icon_state = "r_wall" - relativewall_neighbours() //call smoothwall stuff - to_chat(user, "You repair the last of the damage.") - - //APC - else if(istype(W,/obj/item/apc_frame)) - var/obj/item/apc_frame/AH = W - AH.try_build(src) - - else if(istype(W,/obj/item/newscaster_frame)) //Be damned the man who thought only mobs need attack() and walls dont need inheritance, hitler incarnate - var/obj/item/newscaster_frame/AH = W - AH.try_build(src) - return - - else if(istype(W,/obj/item/alarm_frame)) - var/obj/item/alarm_frame/AH = W - AH.try_build(src) - - else if(istype(W,/obj/item/firealarm_frame)) - var/obj/item/firealarm_frame/AH = W - AH.try_build(src) - return - - else if(istype(W,/obj/item/light_fixture_frame)) - var/obj/item/light_fixture_frame/AH = W - AH.try_build(src) - return - - else if(istype(W,/obj/item/light_fixture_frame/small)) - var/obj/item/light_fixture_frame/small/AH = W - AH.try_build(src) - return - - //Poster stuff - else if(istype(W,/obj/item/weapon/poster)) - place_poster(W,user) - return - - //Finally, CHECKING FOR FALSE WALLS if it isn't damaged - else if(!d_state) - return attack_hand(user) - return - -/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 + name = "reinforced wall" + desc = "A huge chunk of reinforced metal used to seperate rooms." + icon_state = "r_wall" + opacity = 1 + density = 1 + + damage_cap = 200 + max_temperature = 20000 + + walltype = "rwall" + sheet_type = /obj/item/stack/sheet/plasteel + + var/d_state = 0 + +/turf/simulated/wall/r_wall/attack_hand(mob/user) + user.SetNextMove(CLICK_CD_MELEE) + if(HULK in user.mutations) //#Z2 + if(user.a_intent == "hurt") + to_chat(user, text("\blue You punch the wall.")) + take_damage(rand(5, 25)) + if(prob(25)) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + if(prob(5)) + playsound(user.loc, 'sound/weapons/tablehit1.ogg', 50, 1) + var/mob/living/carbon/human/H = user + var/obj/item/organ/external/BP = H.bodyparts_by_name[user.hand ? BP_L_ARM : BP_R_ARM] + BP.take_damage(rand(5, 15), used_weapon = "Reinforced wall") + to_chat(user, text("\red Ouch!!")) + else + playsound(user.loc, 'sound/effects/grillehit.ogg', 50, 1) + return //##Z2 + + if(rotting) + to_chat(user, "\blue This wall feels rather unstable.") + return + + /*user << "\blue You push the wall but nothing happens!" + playsound(src, 'sound/weapons/Genhit.ogg', 25, 1) + src.add_fingerprint(user)*/ //this code is in standard wall attack_hand proc + ..() + return + + +/turf/simulated/wall/r_wall/attackby(obj/item/W, mob/user) + + if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") + to_chat(user, "You don't have the dexterity to do this!") + return + + //get the user's location + if(!isturf(user.loc)) + return //can't do this stuff whilst inside objects and such + user.SetNextMove(CLICK_CD_MELEE) + if(user.is_busy()) return + + if(rotting) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + to_chat(user, "You burn away the fungi with \the [WT].") + playsound(src, 'sound/items/Welder.ogg', 10, 1) + for(var/obj/effect/E in src) if(E.name == "Wallrot") + qdel(E) + rotting = 0 + return + else if(!is_sharp(W) && W.force >= 10 || W.force >= 20) + to_chat(user, "\The [src] crumbles away under the force of your [W.name].") + src.dismantle_wall() + return + + //THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects + if(thermite) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + thermitemelt(user) + return + + else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + thermitemelt(user) + return + + else if(istype(W, /obj/item/weapon/melee/energy/blade)) + var/obj/item/weapon/melee/energy/blade/EB = W + + EB.spark_system.start() + to_chat(user, "You slash \the [src] with \the [EB]; the thermite ignites!") + playsound(src, "sparks", 50, 1) + playsound(src, 'sound/weapons/blade1.ogg', 50, 1) + + thermitemelt(user) + return + + else if(istype(W, /obj/item/weapon/melee/energy/blade)) + to_chat(user, "This wall is too thick to slice through. You will need to find a different path.") + return + + if(damage && istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + to_chat(user, "You start repairing the damage to [src].") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + if(do_after(user, max(5, damage / 5), target = src) && WT && WT.isOn()) + to_chat(user, "You finish repairing the damage to [src].") + take_damage(-damage) + return + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + var/turf/T = user.loc //get user's location for delay checks + + //DECONSTRUCTION + switch(d_state) + if(0) + if (istype(W, /obj/item/weapon/wirecutters)) + playsound(src, 'sound/items/Wirecutter.ogg', 100, 1) + src.d_state = 1 + src.icon_state = "r_wall-1" + new /obj/item/stack/rods(src) + to_chat(user, "You cut the outer grille.") + return + + if(1) + if (istype(W, /obj/item/weapon/screwdriver)) + to_chat(user, "You begin removing the support lines.") + playsound(src, 'sound/items/Screwdriver.ogg', 100, 1) + + if(do_after(user,40,target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) + return + + if(d_state == 1 && user.loc == T && user.get_active_hand() == W) + src.d_state = 2 + src.icon_state = "r_wall-2" + to_chat(user, "You remove the support lines.") + return + + //REPAIRING (replacing the outer grille for cosmetic damage) + else if(istype(W, /obj/item/stack/rods)) + var/obj/item/stack/O = W + if(!O.use(1)) + return + src.d_state = 0 + src.icon_state = "r_wall" + relativewall_neighbours() //call smoothwall stuff + to_chat(user, "You replace the outer grille.") + return + + if(2) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + + to_chat(user, "You begin slicing through the metal cover.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user,60,target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !WT || !WT.isOn() || !T) + return + + if(d_state == 2 && user.loc == T && user.get_active_hand() == WT) + src.d_state = 3 + src.icon_state = "r_wall-3" + to_chat(user, "You press firmly on the cover, dislodging it.") + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + + to_chat(user, "You begin slicing through the metal cover.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user,60,target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) + return + + if(d_state == 2 && user.loc == T && user.get_active_hand() == W) + src.d_state = 3 + src.icon_state = "r_wall-3" + to_chat(user, "You press firmly on the cover, dislodging it.") + return + + if(3) + if (istype(W, /obj/item/weapon/crowbar)) + + to_chat(user, "You struggle to pry off the cover.") + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) + + if(do_after(user,100,target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) + return + + if(d_state == 3 && user.loc == T && user.get_active_hand() == W) + src.d_state = 4 + src.icon_state = "r_wall-4" + to_chat(user, "You pry off the cover.") + return + + if(4) + if (istype(W, /obj/item/weapon/wrench)) + + to_chat(user, "You start loosening the anchoring bolts which secure the support rods to their frame.") + playsound(src, 'sound/items/Ratchet.ogg', 100, 1) + + if(do_after(user,40,target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) + return + + if(d_state == 4 && user.loc == T && user.get_active_hand() == W) + src.d_state = 5 + src.icon_state = "r_wall-5" + to_chat(user, "You remove the bolts anchoring the support rods.") + return + + if(5) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0,user)) + + to_chat(user, "You begin slicing through the support rods.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user,100,target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !WT || !WT.isOn() || !T) + return + + if(d_state == 5 && user.loc == T && user.get_active_hand() == WT) + src.d_state = 6 + src.icon_state = "r_wall-6" + new /obj/item/stack/rods(src) + to_chat(user, "The support rods drop out as you cut them loose from the frame.") + else + to_chat(user, "You need more welding fuel to complete this task.") + return + + if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + + to_chat(user, "You begin slicing through the support rods.") + playsound(src, 'sound/items/Welder.ogg', 100, 1) + + if(do_after(user,70,target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) + return + + if(d_state == 5 && user.loc == T && user.get_active_hand() == W) + src.d_state = 6 + src.icon_state = "r_wall-6" + new /obj/item/stack/rods(src) + to_chat(user, "The support rods drop out as you cut them loose from the frame.") + return + + if(6) + if(istype(W, /obj/item/weapon/crowbar)) + + to_chat(user, "You struggle to pry off the outer sheath.") + playsound(src, 'sound/items/Crowbar.ogg', 100, 1) + + if(do_after(user,100,target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) + return + + if(user.loc == T && user.get_active_hand() == W) + to_chat(user, "You pry off the outer sheath.") + dismantle_wall() + return + +//vv OK, we weren't performing a valid deconstruction step or igniting thermite,let's check the other possibilities vv + + //DRILLING + if(istype(W,/obj/item/weapon/changeling_hammer) && !rotting) + var/obj/item/weapon/changeling_hammer/C = W + user.do_attack_animation(src) + visible_message("\red [user] has punched \the [src]!") + if(C.use_charge(user, 4)) + playsound(user.loc, pick('sound/effects/explosion1.ogg', 'sound/effects/explosion2.ogg'), 50, 1) + take_damage(pick(10, 20, 30)) + return + else if (istype(W, /obj/item/weapon/pickaxe/drill/diamond_drill)) + + to_chat(user, "You begin to drill though the wall.") + + if(do_after(user,200,target = src)) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !W || !T) + return + + if(user.loc == T && user.get_active_hand() == W) + to_chat(user, "Your drill tears though the last of the reinforced plating.") + dismantle_wall() + + //REPAIRING + else if(istype(W, /obj/item/stack/sheet/metal) && d_state) + var/obj/item/stack/sheet/metal/MS = W + + to_chat(user, "You begin patching-up the wall with \a [MS].") + + if(do_after(user,(max(20*d_state,100)),target = src)) //time taken to repair is proportional to the damage! (max 10 seconds) + if(!istype(src, /turf/simulated/wall/r_wall) || !user || !MS || !T) + return + + if(user.loc == T && user.get_active_hand() == MS && d_state) + if(!MS.use(1)) + return + src.d_state = 0 + src.icon_state = "r_wall" + relativewall_neighbours() //call smoothwall stuff + to_chat(user, "You repair the last of the damage.") + + //APC + else if(istype(W,/obj/item/apc_frame)) + var/obj/item/apc_frame/AH = W + AH.try_build(src) + + else if(istype(W,/obj/item/newscaster_frame)) //Be damned the man who thought only mobs need attack() and walls dont need inheritance, hitler incarnate + var/obj/item/newscaster_frame/AH = W + AH.try_build(src) + return + + else if(istype(W,/obj/item/alarm_frame)) + var/obj/item/alarm_frame/AH = W + AH.try_build(src) + + else if(istype(W,/obj/item/firealarm_frame)) + var/obj/item/firealarm_frame/AH = W + AH.try_build(src) + return + + else if(istype(W,/obj/item/light_fixture_frame)) + var/obj/item/light_fixture_frame/AH = W + AH.try_build(src) + return + + else if(istype(W,/obj/item/light_fixture_frame/small)) + var/obj/item/light_fixture_frame/small/AH = W + AH.try_build(src) + return + + //Poster stuff + else if(istype(W,/obj/item/weapon/poster)) + place_poster(W,user) + return + + //Finally, CHECKING FOR FALSE WALLS if it isn't damaged + else if(!d_state) + return attack_hand(user) + return + +/turf/simulated/wall/r_wall/singularity_pull(S, current_size) + if(current_size >= STAGE_FIVE) + if(prob(30)) + dismantle_wall() diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index e9e765e9efe0..f3e974267fb2 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -1,276 +1,276 @@ -/turf/space - icon = 'icons/turf/space.dmi' - name = "\proper space" - icon_state = "0" - dynamic_lighting = 0 - - temperature = TCMB - thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT - plane = PLANE_SPACE -// heat_capacity = 700000 No. - -/turf/space/atom_init() - if(initialized) - stack_trace("Warning: [src]([type]) initialized multiple times!") - initialized = TRUE - - if(!istype(src, /turf/space/transit)) - icon_state = SPACE_ICON_STATE - - if(light_power && light_range) - update_light() - - if(opacity) - has_opaque_atom = TRUE - - return INITIALIZE_HINT_NORMAL - -/turf/space/Destroy() - return QDEL_HINT_LETMELIVE - -/turf/space/proc/update_starlight() - for(var/turf/simulated/T in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm - set_light(2,2) - return - set_light(0) - -/turf/space/attack_paw(mob/user) - return src.attack_hand(user) - -/turf/space/attackby(obj/item/C, mob/user) - - if (istype(C, /obj/item/stack/rods)) - var/obj/item/stack/rods/R = C - var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) - user.SetNextMove(CLICK_CD_RAPID) - if(L) - if(R.get_amount() < 2) - to_chat(user, "\red You don't have enough rods to do that.") - return - if(user.is_busy()) return - to_chat(user, "\blue You begin to build a catwalk.") - if(do_after(user,30,target = src)) - if(!R.use(2)) - return - playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) - to_chat(user, "\blue You build a catwalk!") - ChangeTurf(/turf/simulated/floor/plating/airless/catwalk) - qdel(L) - return - - if(!R.use(1)) - return - to_chat(user, "\blue Constructing support lattice ...") - playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) - ReplaceWithLattice() - return - - if (istype(C, /obj/item/stack/tile/plasteel)) - var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) - if(L) - var/obj/item/stack/tile/plasteel/S = C - if(!S.use(1)) - return - qdel(L) - user.SetNextMove(CLICK_CD_RAPID) - playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) - S.build(src) - return - else - to_chat(user, "\red The plating is going to need some support.") - - -// Ported from unstable r355 - -/turf/space/Entered(atom/movable/A as mob|obj) - if(movement_disabled) - to_chat(usr, "\red Movement is admin-disabled.")//This is to identify lag problems - return - ..() - if ((!(A) || src != A.loc)) return - - if(ticker && ticker.mode) - - // Okay, so let's make it so that people can travel z levels but not nuke disks! - // if(ticker.mode.name == "nuclear emergency") return - if(A.z > ZLEVEL_EMPTY) return - if (A.x <= TRANSITIONEDGE || A.x >= (world.maxx - TRANSITIONEDGE - 1) || A.y <= TRANSITIONEDGE || A.y >= (world.maxy - TRANSITIONEDGE - 1)) - if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust)) - qdel(A) - return - - if(istype(A, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks travel Z levels ... And moving this shit down here so it only fires when they're actually trying to change z-level. - qdel(A) //The disk's Destroy() proc ensures a new one is created - return - - var/list/disk_search = A.search_contents_for(/obj/item/weapon/disk/nuclear) - if(!isemptylist(disk_search)) - if(istype(A, /mob/living)) - var/mob/living/MM = A - if(MM.client && !MM.stat) - to_chat(MM, "\red Something you are carrying is preventing you from leaving. Don't play stupid; you know exactly what it is.") - if(MM.x <= TRANSITIONEDGE) - MM.inertia_dir = 4 - else if(MM.x >= world.maxx -TRANSITIONEDGE) - MM.inertia_dir = 8 - else if(MM.y <= TRANSITIONEDGE) - MM.inertia_dir = 1 - else if(MM.y >= world.maxy -TRANSITIONEDGE) - MM.inertia_dir = 2 - else - for(var/obj/item/weapon/disk/nuclear/N in disk_search) - qdel(N)//Make the disk respawn it is on a clientless mob or corpse - else - for(var/obj/item/weapon/disk/nuclear/N in disk_search) - qdel(N)//Make the disk respawn if it is floating on its own - return - - var/move_to_z = src.z - var/safety = 1 - - while(move_to_z == src.z) - var/move_to_z_str = pickweight(accessable_z_levels) - move_to_z = text2num(move_to_z_str) - safety++ - if(safety > 10) - break - - if(!move_to_z) - return - - A.z = move_to_z - - if(src.x <= TRANSITIONEDGE) - A.x = world.maxx - TRANSITIONEDGE - 2 - A.y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2) - - else if (A.x >= (world.maxx - TRANSITIONEDGE - 1)) - A.x = TRANSITIONEDGE + 1 - A.y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2) - - else if (src.y <= TRANSITIONEDGE) - A.y = world.maxy - TRANSITIONEDGE -2 - A.x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) - - else if (A.y >= (world.maxy - TRANSITIONEDGE - 1)) - A.y = TRANSITIONEDGE + 1 - A.x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) - - - stoplag()//Let a diagonal move finish, if necessary - A.newtonian_move(A.inertia_dir) - -/turf/space/proc/Sandbox_Spacemove(atom/movable/A) - 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) - 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) - 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) - 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) - 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/ChangeTurf(path, force_lighting_update = 0) - return ..(path, TRUE) - -/turf/space/singularity_act() - return +/turf/space + icon = 'icons/turf/space.dmi' + name = "\proper space" + icon_state = "0" + dynamic_lighting = 0 + + temperature = TCMB + thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT + plane = PLANE_SPACE +// heat_capacity = 700000 No. + +/turf/space/atom_init() + if(initialized) + stack_trace("Warning: [src]([type]) initialized multiple times!") + initialized = TRUE + + if(!istype(src, /turf/space/transit)) + icon_state = SPACE_ICON_STATE + + if(light_power && light_range) + update_light() + + if(opacity) + has_opaque_atom = TRUE + + return INITIALIZE_HINT_NORMAL + +/turf/space/Destroy() + return QDEL_HINT_LETMELIVE + +/turf/space/proc/update_starlight() + for(var/turf/simulated/T in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm + set_light(2,2) + return + set_light(0) + +/turf/space/attack_paw(mob/user) + return src.attack_hand(user) + +/turf/space/attackby(obj/item/C, mob/user) + + if (istype(C, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = C + var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) + user.SetNextMove(CLICK_CD_RAPID) + if(L) + if(R.get_amount() < 2) + to_chat(user, "\red You don't have enough rods to do that.") + return + if(user.is_busy()) return + to_chat(user, "\blue You begin to build a catwalk.") + if(do_after(user,30,target = src)) + if(!R.use(2)) + return + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + to_chat(user, "\blue You build a catwalk!") + ChangeTurf(/turf/simulated/floor/plating/airless/catwalk) + qdel(L) + return + + if(!R.use(1)) + return + to_chat(user, "\blue Constructing support lattice ...") + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + ReplaceWithLattice() + return + + if (istype(C, /obj/item/stack/tile/plasteel)) + var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) + if(L) + var/obj/item/stack/tile/plasteel/S = C + if(!S.use(1)) + return + qdel(L) + user.SetNextMove(CLICK_CD_RAPID) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + S.build(src) + return + else + to_chat(user, "\red The plating is going to need some support.") + + +// Ported from unstable r355 + +/turf/space/Entered(atom/movable/A as mob|obj) + if(movement_disabled) + to_chat(usr, "\red Movement is admin-disabled.")//This is to identify lag problems + return + ..() + if ((!(A) || src != A.loc)) return + + if(ticker && ticker.mode) + + // Okay, so let's make it so that people can travel z levels but not nuke disks! + // if(ticker.mode.name == "nuclear emergency") return + if(A.z > ZLEVEL_EMPTY) return + if (A.x <= TRANSITIONEDGE || A.x >= (world.maxx - TRANSITIONEDGE - 1) || A.y <= TRANSITIONEDGE || A.y >= (world.maxy - TRANSITIONEDGE - 1)) + if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust)) + qdel(A) + return + + if(istype(A, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks travel Z levels ... And moving this shit down here so it only fires when they're actually trying to change z-level. + qdel(A) //The disk's Destroy() proc ensures a new one is created + return + + var/list/disk_search = A.search_contents_for(/obj/item/weapon/disk/nuclear) + if(!isemptylist(disk_search)) + if(istype(A, /mob/living)) + var/mob/living/MM = A + if(MM.client && !MM.stat) + to_chat(MM, "\red Something you are carrying is preventing you from leaving. Don't play stupid; you know exactly what it is.") + if(MM.x <= TRANSITIONEDGE) + MM.inertia_dir = 4 + else if(MM.x >= world.maxx -TRANSITIONEDGE) + MM.inertia_dir = 8 + else if(MM.y <= TRANSITIONEDGE) + MM.inertia_dir = 1 + else if(MM.y >= world.maxy -TRANSITIONEDGE) + MM.inertia_dir = 2 + else + for(var/obj/item/weapon/disk/nuclear/N in disk_search) + qdel(N)//Make the disk respawn it is on a clientless mob or corpse + else + for(var/obj/item/weapon/disk/nuclear/N in disk_search) + qdel(N)//Make the disk respawn if it is floating on its own + return + + var/move_to_z = src.z + var/safety = 1 + + while(move_to_z == src.z) + var/move_to_z_str = pickweight(accessable_z_levels) + move_to_z = text2num(move_to_z_str) + safety++ + if(safety > 10) + break + + if(!move_to_z) + return + + A.z = move_to_z + + if(src.x <= TRANSITIONEDGE) + A.x = world.maxx - TRANSITIONEDGE - 2 + A.y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2) + + else if (A.x >= (world.maxx - TRANSITIONEDGE - 1)) + A.x = TRANSITIONEDGE + 1 + A.y = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2) + + else if (src.y <= TRANSITIONEDGE) + A.y = world.maxy - TRANSITIONEDGE -2 + A.x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) + + else if (A.y >= (world.maxy - TRANSITIONEDGE - 1)) + A.y = TRANSITIONEDGE + 1 + A.x = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) + + + stoplag()//Let a diagonal move finish, if necessary + A.newtonian_move(A.inertia_dir) + +/turf/space/proc/Sandbox_Spacemove(atom/movable/A) + 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) + 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) + 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) + 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) + 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/ChangeTurf(path, force_lighting_update = 0) + return ..(path, TRUE) + +/turf/space/singularity_act() + return diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index b9102c9c8dfc..948b635d6aa3 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -1,113 +1,113 @@ -/turf/space/transit - var/pushdirection // push things that get caught in the transit tile this direction - -//Overwrite because we dont want people building rods in space. -/turf/space/transit/attackby(obj/O, mob/user) - return - -/turf/space/transit/north // moving to the north - - pushdirection = SOUTH // south because the space tile is scrolling south - - //IF ANYONE KNOWS A MORE EFFICIENT WAY OF MANAGING THESE SPRITES, BE MY GUEST. - shuttlespace_ns1 - icon_state = "speedspace_ns_1" - shuttlespace_ns2 - icon_state = "speedspace_ns_2" - shuttlespace_ns3 - icon_state = "speedspace_ns_3" - shuttlespace_ns4 - icon_state = "speedspace_ns_4" - shuttlespace_ns5 - icon_state = "speedspace_ns_5" - shuttlespace_ns6 - icon_state = "speedspace_ns_6" - shuttlespace_ns7 - icon_state = "speedspace_ns_7" - shuttlespace_ns8 - icon_state = "speedspace_ns_8" - shuttlespace_ns9 - icon_state = "speedspace_ns_9" - shuttlespace_ns10 - icon_state = "speedspace_ns_10" - shuttlespace_ns11 - icon_state = "speedspace_ns_11" - shuttlespace_ns12 - icon_state = "speedspace_ns_12" - shuttlespace_ns13 - icon_state = "speedspace_ns_13" - shuttlespace_ns14 - icon_state = "speedspace_ns_14" - shuttlespace_ns15 - icon_state = "speedspace_ns_15" - -/turf/space/transit/east // moving to the east - - pushdirection = WEST - - shuttlespace_ew1 - icon_state = "speedspace_ew_1" - shuttlespace_ew2 - icon_state = "speedspace_ew_2" - shuttlespace_ew3 - icon_state = "speedspace_ew_3" - shuttlespace_ew4 - icon_state = "speedspace_ew_4" - shuttlespace_ew5 - icon_state = "speedspace_ew_5" - shuttlespace_ew6 - icon_state = "speedspace_ew_6" - shuttlespace_ew7 - icon_state = "speedspace_ew_7" - shuttlespace_ew8 - icon_state = "speedspace_ew_8" - shuttlespace_ew9 - icon_state = "speedspace_ew_9" - shuttlespace_ew10 - icon_state = "speedspace_ew_10" - shuttlespace_ew11 - icon_state = "speedspace_ew_11" - shuttlespace_ew12 - icon_state = "speedspace_ew_12" - shuttlespace_ew13 - icon_state = "speedspace_ew_13" - shuttlespace_ew14 - icon_state = "speedspace_ew_14" - shuttlespace_ew15 - icon_state = "speedspace_ew_15" - - -/turf/space/transit/west // moving to the west - - pushdirection = EAST - - shuttlespace_we1 - icon_state = "speedspace_we_1" - shuttlespace_we2 - icon_state = "speedspace_we_2" - shuttlespace_we3 - icon_state = "speedspace_we_3" - shuttlespace_we4 - icon_state = "speedspace_we_4" - shuttlespace_we5 - icon_state = "speedspace_we_5" - shuttlespace_we6 - icon_state = "speedspace_we_6" - shuttlespace_we7 - icon_state = "speedspace_we_7" - shuttlespace_we8 - icon_state = "speedspace_we_8" - shuttlespace_we9 - icon_state = "speedspace_we_9" - shuttlespace_we10 - icon_state = "speedspace_we_10" - shuttlespace_we11 - icon_state = "speedspace_we_11" - shuttlespace_we12 - icon_state = "speedspace_we_12" - shuttlespace_we13 - icon_state = "speedspace_we_13" - shuttlespace_we14 - icon_state = "speedspace_we_14" - shuttlespace_we15 - icon_state = "speedspace_we_15" +/turf/space/transit + var/pushdirection // push things that get caught in the transit tile this direction + +//Overwrite because we dont want people building rods in space. +/turf/space/transit/attackby(obj/O, mob/user) + return + +/turf/space/transit/north // moving to the north + + pushdirection = SOUTH // south because the space tile is scrolling south + + //IF ANYONE KNOWS A MORE EFFICIENT WAY OF MANAGING THESE SPRITES, BE MY GUEST. + shuttlespace_ns1 + icon_state = "speedspace_ns_1" + shuttlespace_ns2 + icon_state = "speedspace_ns_2" + shuttlespace_ns3 + icon_state = "speedspace_ns_3" + shuttlespace_ns4 + icon_state = "speedspace_ns_4" + shuttlespace_ns5 + icon_state = "speedspace_ns_5" + shuttlespace_ns6 + icon_state = "speedspace_ns_6" + shuttlespace_ns7 + icon_state = "speedspace_ns_7" + shuttlespace_ns8 + icon_state = "speedspace_ns_8" + shuttlespace_ns9 + icon_state = "speedspace_ns_9" + shuttlespace_ns10 + icon_state = "speedspace_ns_10" + shuttlespace_ns11 + icon_state = "speedspace_ns_11" + shuttlespace_ns12 + icon_state = "speedspace_ns_12" + shuttlespace_ns13 + icon_state = "speedspace_ns_13" + shuttlespace_ns14 + icon_state = "speedspace_ns_14" + shuttlespace_ns15 + icon_state = "speedspace_ns_15" + +/turf/space/transit/east // moving to the east + + pushdirection = WEST + + shuttlespace_ew1 + icon_state = "speedspace_ew_1" + shuttlespace_ew2 + icon_state = "speedspace_ew_2" + shuttlespace_ew3 + icon_state = "speedspace_ew_3" + shuttlespace_ew4 + icon_state = "speedspace_ew_4" + shuttlespace_ew5 + icon_state = "speedspace_ew_5" + shuttlespace_ew6 + icon_state = "speedspace_ew_6" + shuttlespace_ew7 + icon_state = "speedspace_ew_7" + shuttlespace_ew8 + icon_state = "speedspace_ew_8" + shuttlespace_ew9 + icon_state = "speedspace_ew_9" + shuttlespace_ew10 + icon_state = "speedspace_ew_10" + shuttlespace_ew11 + icon_state = "speedspace_ew_11" + shuttlespace_ew12 + icon_state = "speedspace_ew_12" + shuttlespace_ew13 + icon_state = "speedspace_ew_13" + shuttlespace_ew14 + icon_state = "speedspace_ew_14" + shuttlespace_ew15 + icon_state = "speedspace_ew_15" + + +/turf/space/transit/west // moving to the west + + pushdirection = EAST + + shuttlespace_we1 + icon_state = "speedspace_we_1" + shuttlespace_we2 + icon_state = "speedspace_we_2" + shuttlespace_we3 + icon_state = "speedspace_we_3" + shuttlespace_we4 + icon_state = "speedspace_we_4" + shuttlespace_we5 + icon_state = "speedspace_we_5" + shuttlespace_we6 + icon_state = "speedspace_we_6" + shuttlespace_we7 + icon_state = "speedspace_we_7" + shuttlespace_we8 + icon_state = "speedspace_we_8" + shuttlespace_we9 + icon_state = "speedspace_we_9" + shuttlespace_we10 + icon_state = "speedspace_we_10" + shuttlespace_we11 + icon_state = "speedspace_we_11" + shuttlespace_we12 + icon_state = "speedspace_we_12" + shuttlespace_we13 + icon_state = "speedspace_we_13" + shuttlespace_we14 + icon_state = "speedspace_we_14" + shuttlespace_we15 + icon_state = "speedspace_we_15" diff --git a/code/game/turfs/unsimulated.dm b/code/game/turfs/unsimulated.dm index f517b240f94e..dc3f5508f13d 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 - nitrogen = MOLES_N2STANDARD +/turf/unsimulated + intact = 1 + name = "command" + oxygen = MOLES_O2STANDARD + nitrogen = MOLES_N2STANDARD diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm index fce67ea78560..702807d24bee 100644 --- a/code/game/turfs/unsimulated/beach.dm +++ b/code/game/turfs/unsimulated/beach.dm @@ -1,20 +1,20 @@ -/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/atom_init() - . = ..() - overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water2","layer"=MOB_LAYER+0.1) +/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/atom_init() + . = ..() + overlays += image("icon"='icons/misc/beach.dmi',"icon_state"="water2","layer"=MOB_LAYER+0.1) diff --git a/code/game/turfs/unsimulated/floor.dm b/code/game/turfs/unsimulated/floor.dm index 40f96f35f6bd..686c08ec9ebd 100644 --- a/code/game/turfs/unsimulated/floor.dm +++ b/code/game/turfs/unsimulated/floor.dm @@ -1,15 +1,15 @@ -/turf/unsimulated/floor - name = "floor" - icon = 'icons/turf/floors.dmi' - icon_state = "Floor3" - -/turf/unsimulated/floor/abductor - name = "alien floor" - icon_state = "alienpod1" - -/turf/unsimulated/floor/abductor/atom_init() - . = ..() - icon_state = "alienpod[rand(1,9)]" - -/turf/unsimulated/floor/attack_paw(user) - return src.attack_hand(user) +/turf/unsimulated/floor + name = "floor" + icon = 'icons/turf/floors.dmi' + icon_state = "Floor3" + +/turf/unsimulated/floor/abductor + name = "alien floor" + icon_state = "alienpod1" + +/turf/unsimulated/floor/abductor/atom_init() + . = ..() + icon_state = "alienpod[rand(1,9)]" + +/turf/unsimulated/floor/attack_paw(user) + return src.attack_hand(user) diff --git a/code/game/turfs/unsimulated/walls.dm b/code/game/turfs/unsimulated/walls.dm index 217935a63480..60fb52daa710 100644 --- a/code/game/turfs/unsimulated/walls.dm +++ b/code/game/turfs/unsimulated/walls.dm @@ -1,33 +1,33 @@ -/turf/unsimulated/wall - name = "wall" - icon = 'icons/turf/walls.dmi' - icon_state = "riveted" - opacity = 1 - density = 1 - -/turf/unsimulated/wall/fakeglass - name = "window" - icon_state = "fakewindows" - opacity = 0 - -/turf/unsimulated/wall/splashscreen - name = "Space Station 13" - icon = 'icons/misc/fullscreen_loading.dmi' - icon_state = "title" - layer = FLY_LAYER - -/turf/unsimulated/wall/splashscreen/atom_init() - . = ..() - var/newyear = FALSE - #ifdef NEWYEARCONTENT - icon = pick('icons/misc/fullscreen_newyear.dmi', 'icons/misc/fullscreen_leshiy.dmi') - newyear = TRUE - #endif - if(!newyear) - icon = pick('icons/misc/fullscreen_standart.dmi', 'icons/misc/fullscreen_leshiy.dmi') - -/turf/unsimulated/wall/other - icon_state = "r_wall" - -/turf/unsimulated/wall/abductor - icon_state = "alien1" +/turf/unsimulated/wall + name = "wall" + icon = 'icons/turf/walls.dmi' + icon_state = "riveted" + opacity = 1 + density = 1 + +/turf/unsimulated/wall/fakeglass + name = "window" + icon_state = "fakewindows" + opacity = 0 + +/turf/unsimulated/wall/splashscreen + name = "Space Station 13" + icon = 'icons/misc/fullscreen_loading.dmi' + icon_state = "title" + layer = FLY_LAYER + +/turf/unsimulated/wall/splashscreen/atom_init() + . = ..() + var/newyear = FALSE + #ifdef NEWYEARCONTENT + icon = pick('icons/misc/fullscreen_newyear.dmi', 'icons/misc/fullscreen_leshiy.dmi') + newyear = TRUE + #endif + if(!newyear) + icon = pick('icons/misc/fullscreen_standart.dmi', 'icons/misc/fullscreen_leshiy.dmi') + +/turf/unsimulated/wall/other + icon_state = "r_wall" + +/turf/unsimulated/wall/abductor + icon_state = "alien1" diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index 81f2c67468b8..095958a4fec1 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -1,178 +1,178 @@ - -var/global/normal_ooc_colour = "#002eb8" - -/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, "\red Speech is currently admin-disabled.") - return - - if(!mob) return - if(IsGuestKey(key)) - to_chat(src, "Guests may not use OOC.") - return - - msg = sanitize(msg) - if(!msg) return - - if(!(prefs.chat_toggles & CHAT_OOC)) - to_chat(src, "\red You have OOC muted.") - return - - if(prefs.muted & MUTE_OOC) - to_chat(src, "\red You cannot use OOC (muted).") - return - - if(!holder) - if(!ooc_allowed) - to_chat(src, "\red OOC is globally muted") - return - if(!dooc_allowed && (mob.stat == DEAD)) - to_chat(usr, "\red OOC for dead mobs has been turned off.") - 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] : [msg]") - - var/display_colour = normal_ooc_colour - if(holder && !holder.fakekey) - display_colour = "#704F80" - 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.aooccolor - else - display_colour = "#b82e00" //orange - - for(var/client/C in clients) - if(C.prefs.chat_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 - - if(supporter && prefs.ooccolor) - display_name = "[display_name]" - - to_chat(C, "OOC: [display_name]: [msg]") - - /* - 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) - to_chat(C, "OOC: [src.key][holder.fakekey ? "/([holder.fakekey])" : ""]: [msg]") - else - to_chat(C, "OOC: [src.key]: [msg]") - - else - to_chat(C, "OOC: [holder.fakekey ? holder.fakekey : src.key]: [msg]") - else - to_chat(C, "OOC: [src.key]: [msg]") - */ - -/client/proc/set_global_ooc(newColor as color) - set name = "Set Global OOC Colour" - set desc = "Set to yellow for eye burning goodness." - set category = "OOC" - if(!holder) - return - normal_ooc_colour = newColor - -/client/verb/set_name_ooc() - set name = "Set Name OOC Colour" - set category = "OOC" - - if(!supporter) - to_chat(usr, "This is only for [config.donate_info_url ? "supporters" : "supporters"][config.allow_byond_membership ? " and Byond Members" : ""].") - 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() - -/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)) - to_chat(src, "Guests may not use OOC.") - return - - msg = sanitize(msg) - if(!msg) return - - if(!(prefs.chat_toggles & CHAT_LOOC)) - to_chat(src, "You have LOOC muted.") - return - - if(!holder) - if(!looc_allowed) - to_chat(src, "LOOC is globally muted") - return - if(!dooc_allowed && (mob.stat == DEAD)) - to_chat(usr, "OOC for dead mobs has been turned off.") - return - if(prefs.muted & MUTE_OOC) - to_chat(src, "You cannot use OOC (muted).") - 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 - - var/display_name = "[mob.name]" - var/is_fake_key = FALSE - if(holder && holder.fakekey) - display_name = holder.fakekey - is_fake_key = TRUE - if(isobserver(mob)) - display_name = "(Ghost) [key]" - else if(prefs.chat_toggles & CHAT_CKEY) - display_name += " ([key])" - - log_ooc("(LOCAL) [mob.name]/[key] : [msg]") - - var/list/heard = get_mobs_in_view(7, src.mob) - for(var/mob/M in heard) - - if(!M.client) - continue - var/client/C = M.client - if (C in admins) - continue //they are handled after that - - if(C.prefs.chat_toggles & CHAT_LOOC) - if(is_fake_key && C.holder) - display_name = "[holder.fakekey]/([key])" - to_chat(C, "LOOC: [display_name]: [msg]") - - for(var/client/C in admins) - if(C.prefs.chat_toggles & CHAT_LOOC) - var/prefix = "(R)LOOC" - if (C.mob in heard) - prefix = "LOOC" - to_chat(C, "[prefix]: [mob.name]/([key]): [msg]") + +var/global/normal_ooc_colour = "#002eb8" + +/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, "\red Speech is currently admin-disabled.") + return + + if(!mob) return + if(IsGuestKey(key)) + to_chat(src, "Guests may not use OOC.") + return + + msg = sanitize(msg) + if(!msg) return + + if(!(prefs.chat_toggles & CHAT_OOC)) + to_chat(src, "\red You have OOC muted.") + return + + if(prefs.muted & MUTE_OOC) + to_chat(src, "\red You cannot use OOC (muted).") + return + + if(!holder) + if(!ooc_allowed) + to_chat(src, "\red OOC is globally muted") + return + if(!dooc_allowed && (mob.stat == DEAD)) + to_chat(usr, "\red OOC for dead mobs has been turned off.") + 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] : [msg]") + + var/display_colour = normal_ooc_colour + if(holder && !holder.fakekey) + display_colour = "#704F80" + 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.aooccolor + else + display_colour = "#b82e00" //orange + + for(var/client/C in clients) + if(C.prefs.chat_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 + + if(supporter && prefs.ooccolor) + display_name = "[display_name]" + + to_chat(C, "OOC: [display_name]: [msg]") + + /* + 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) + to_chat(C, "OOC: [src.key][holder.fakekey ? "/([holder.fakekey])" : ""]: [msg]") + else + to_chat(C, "OOC: [src.key]: [msg]") + + else + to_chat(C, "OOC: [holder.fakekey ? holder.fakekey : src.key]: [msg]") + else + to_chat(C, "OOC: [src.key]: [msg]") + */ + +/client/proc/set_global_ooc(newColor as color) + set name = "Set Global OOC Colour" + set desc = "Set to yellow for eye burning goodness." + set category = "OOC" + if(!holder) + return + normal_ooc_colour = newColor + +/client/verb/set_name_ooc() + set name = "Set Name OOC Colour" + set category = "OOC" + + if(!supporter) + to_chat(usr, "This is only for [config.donate_info_url ? "supporters" : "supporters"][config.allow_byond_membership ? " and Byond Members" : ""].") + 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() + +/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)) + to_chat(src, "Guests may not use OOC.") + return + + msg = sanitize(msg) + if(!msg) return + + if(!(prefs.chat_toggles & CHAT_LOOC)) + to_chat(src, "You have LOOC muted.") + return + + if(!holder) + if(!looc_allowed) + to_chat(src, "LOOC is globally muted") + return + if(!dooc_allowed && (mob.stat == DEAD)) + to_chat(usr, "OOC for dead mobs has been turned off.") + return + if(prefs.muted & MUTE_OOC) + to_chat(src, "You cannot use OOC (muted).") + 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 + + var/display_name = "[mob.name]" + var/is_fake_key = FALSE + if(holder && holder.fakekey) + display_name = holder.fakekey + is_fake_key = TRUE + if(isobserver(mob)) + display_name = "(Ghost) [key]" + else if(prefs.chat_toggles & CHAT_CKEY) + display_name += " ([key])" + + log_ooc("(LOCAL) [mob.name]/[key] : [msg]") + + var/list/heard = get_mobs_in_view(7, src.mob) + for(var/mob/M in heard) + + if(!M.client) + continue + var/client/C = M.client + if (C in admins) + continue //they are handled after that + + if(C.prefs.chat_toggles & CHAT_LOOC) + if(is_fake_key && C.holder) + display_name = "[holder.fakekey]/([key])" + to_chat(C, "LOOC: [display_name]: [msg]") + + for(var/client/C in admins) + if(C.prefs.chat_toggles & CHAT_LOOC) + var/prefix = "(R)LOOC" + if (C.mob in heard) + prefix = "LOOC" + to_chat(C, "[prefix]: [mob.name]/([key]): [msg]") diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm index a88b1ad61c6d..3d27acbae357 100644 --- a/code/game/verbs/suicide.dm +++ b/code/game/verbs/suicide.dm @@ -1,234 +1,234 @@ -/mob/var/suiciding = 0 - -/mob/living/carbon/human/verb/suicide() - set hidden = 1 - - if (stat == DEAD) - to_chat(src, "You're already dead!") - return - - if (!ticker) - to_chat(src, "You can't commit suicide before the game starts!") - return - - - var/permitted = 0 - 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 due to not being antagonist as human. (JMP)") - to_chat(src, "No. Adminhelp if there is a legitimate 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! ((You can type Ghost instead however.))") - 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 - - - to_chat(viewers(src), pick("\red [src] is attempting to bite \his tongue off! It looks like \he's trying to commit suicide.", \ - "\red [src] is jamming \his thumbs into \his eye sockets! It looks like \he's trying to commit suicide.", \ - "\red [src] is twisting \his own neck! It looks like \he's trying to commit suicide.", \ - "\red [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 (stat == DEAD) - to_chat(src, "You're already dead!") - return - - if (!ticker) - to_chat(src, "You can't commit suicide before the game starts!") - 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 - to_chat(viewers(loc), "\red [src]'s brain is growing dull and lifeless. It looks like it's lost the will to live.") - spawn(50) - death(0) - suiciding = 0 - -/mob/living/carbon/monkey/verb/suicide() - set hidden = 1 - - if (stat == DEAD) - to_chat(src, "You're already dead!") - return - - if (!ticker) - to_chat(src, "You can't commit suicide before the game starts!") - 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()) - 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 - to_chat(viewers(src), "\red [src] is attempting to bite \his tongue. 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 - to_chat(viewers(src), "\red [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 - to_chat(viewers(src), "\red [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/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_or_move(card.loc) - for (var/mob/M in viewers(T)) - M.show_message("\blue [src] flashes a message across its screen, \"Wiping core files. Please acquire a new personality to continue using pAI device functions.\"", 3, "\blue [src] bleeps electronically.", 2) - death(0) - else - to_chat(src, "Aborting suicide attempt.") - -/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 - to_chat(viewers(src), "\red [src] is thrashing 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 - setOxyLoss(100) - adjustBruteLoss(100 - getBruteLoss()) - setToxLoss(100) - setCloneLoss(100) - - updatehealth() +/mob/var/suiciding = 0 + +/mob/living/carbon/human/verb/suicide() + set hidden = 1 + + if (stat == DEAD) + to_chat(src, "You're already dead!") + return + + if (!ticker) + to_chat(src, "You can't commit suicide before the game starts!") + return + + + var/permitted = 0 + 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 due to not being antagonist as human. (JMP)") + to_chat(src, "No. Adminhelp if there is a legitimate 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! ((You can type Ghost instead however.))") + 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 + + + to_chat(viewers(src), pick("\red [src] is attempting to bite \his tongue off! It looks like \he's trying to commit suicide.", \ + "\red [src] is jamming \his thumbs into \his eye sockets! It looks like \he's trying to commit suicide.", \ + "\red [src] is twisting \his own neck! It looks like \he's trying to commit suicide.", \ + "\red [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 (stat == DEAD) + to_chat(src, "You're already dead!") + return + + if (!ticker) + to_chat(src, "You can't commit suicide before the game starts!") + 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 + to_chat(viewers(loc), "\red [src]'s brain is growing dull and lifeless. It looks like it's lost the will to live.") + spawn(50) + death(0) + suiciding = 0 + +/mob/living/carbon/monkey/verb/suicide() + set hidden = 1 + + if (stat == DEAD) + to_chat(src, "You're already dead!") + return + + if (!ticker) + to_chat(src, "You can't commit suicide before the game starts!") + 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()) + 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 + to_chat(viewers(src), "\red [src] is attempting to bite \his tongue. 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 + to_chat(viewers(src), "\red [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 + to_chat(viewers(src), "\red [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/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_or_move(card.loc) + for (var/mob/M in viewers(T)) + M.show_message("\blue [src] flashes a message across its screen, \"Wiping core files. Please acquire a new personality to continue using pAI device functions.\"", 3, "\blue [src] bleeps electronically.", 2) + death(0) + else + to_chat(src, "Aborting suicide attempt.") + +/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 + to_chat(viewers(src), "\red [src] is thrashing 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 + setOxyLoss(100) + adjustBruteLoss(100 - getBruteLoss()) + setToxLoss(100) + setCloneLoss(100) + + updatehealth() diff --git a/code/game/verbs/who.dm b/code/game/verbs/who.dm index 83086328d124..24fa2064bc78 100644 --- a/code/game/verbs/who.dm +++ b/code/game/verbs/who.dm @@ -1,124 +1,124 @@ - -/client/verb/who() - set name = "Who" - set category = "OOC" - - var/msg = "Current Players:\n" - - var/list/Lines = list() - - if(holder && (R_ADMIN & holder.rights)) - for(var/client/C in clients) - if(C.ckey in stealth_keys) continue - var/entry = " [C.key]" - if(C.holder && C.holder.fakekey) - entry += " (as [C.holder.fakekey])" - 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 - entry += " - DEAD" - - var/age - if(isnum(C.player_age)) - age = C.player_age - else - age = 0 - - if(age <= 1) - age = "[age]" - else if(age < 10) - age = "[age]" - - entry += " - [age]" - - var/ingame_age - if(isnum(C.player_ingame_age)) - ingame_age = C.player_ingame_age - else - ingame_age = 0 - - if(ingame_age <= 60) - ingame_age = "[ingame_age]" - else if(ingame_age < 1440) - ingame_age = "[ingame_age]" - - entry += " - [ingame_age]" - - if(is_special_character(C.mob)) - entry += " - Antagonist" - entry += " (?)" - Lines += entry - else - for(var/client/C in clients) - if(C.ckey in stealth_keys) continue - 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)]" - to_chat(src, msg) - -/client/verb/staffwho() - set category = "Admin" - set name = "Staffwho" - - var/list/messages = list("", "") - var/list/num_online = list(0, 0) - if(holder) - for(var/client/C in admins) - if(C.ckey in stealth_keys) - continue - if(C.holder.fakekey && !(R_ADMIN & holder.rights)) - continue - messages[1] += " [C] is a [C.holder.rank]" - if(C.holder.fakekey) - messages[1] += " (as [C.holder.fakekey])" - if(isobserver(C.mob)) - messages[1] += " - Observing" - else if(isnewplayer(C.mob)) - messages[1] += " - Lobby" - else - messages[1] += " - Playing" - if(C.is_afk()) - messages[1] += " (AFK)" - messages[1] += "\n" - num_online[1]++ - for(var/client/C in mentors) - messages[2] += " [C] is a Mentor" - if(isobserver(C.mob)) - messages[2] += " - Observing" - else if(isnewplayer(C.mob)) - messages[2] += " - Lobby" - else - messages[2] += " - Playing" - if(C.is_afk()) - messages[2] += " (AFK)" - messages[2] += "\n" - num_online[2]++ - else - for(var/client/C in admins) - if(C.ckey in stealth_keys) - continue - if(!C.holder.fakekey) - messages[1] += " [C] is a [C.holder.rank]\n" - num_online[1]++ - for(var/client/C in mentors) - messages[2] += " [C] is a Mentor\n" - num_online[2]++ - - messages[1] = num_online[1] ? "Current Admins ([num_online[1]]):\n" + messages[1] : "No Admins online\n" - messages[1] += num_online[2] ? "\nCurrent Mentors ([num_online[2]]):\n" + messages[2] : "\nNo Mentors online\n" - to_chat(src, messages[1]) + +/client/verb/who() + set name = "Who" + set category = "OOC" + + var/msg = "Current Players:\n" + + var/list/Lines = list() + + if(holder && (R_ADMIN & holder.rights)) + for(var/client/C in clients) + if(C.ckey in stealth_keys) continue + var/entry = " [C.key]" + if(C.holder && C.holder.fakekey) + entry += " (as [C.holder.fakekey])" + 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 + entry += " - DEAD" + + var/age + if(isnum(C.player_age)) + age = C.player_age + else + age = 0 + + if(age <= 1) + age = "[age]" + else if(age < 10) + age = "[age]" + + entry += " - [age]" + + var/ingame_age + if(isnum(C.player_ingame_age)) + ingame_age = C.player_ingame_age + else + ingame_age = 0 + + if(ingame_age <= 60) + ingame_age = "[ingame_age]" + else if(ingame_age < 1440) + ingame_age = "[ingame_age]" + + entry += " - [ingame_age]" + + if(is_special_character(C.mob)) + entry += " - Antagonist" + entry += " (?)" + Lines += entry + else + for(var/client/C in clients) + if(C.ckey in stealth_keys) continue + 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)]" + to_chat(src, msg) + +/client/verb/staffwho() + set category = "Admin" + set name = "Staffwho" + + var/list/messages = list("", "") + var/list/num_online = list(0, 0) + if(holder) + for(var/client/C in admins) + if(C.ckey in stealth_keys) + continue + if(C.holder.fakekey && !(R_ADMIN & holder.rights)) + continue + messages[1] += " [C] is a [C.holder.rank]" + if(C.holder.fakekey) + messages[1] += " (as [C.holder.fakekey])" + if(isobserver(C.mob)) + messages[1] += " - Observing" + else if(isnewplayer(C.mob)) + messages[1] += " - Lobby" + else + messages[1] += " - Playing" + if(C.is_afk()) + messages[1] += " (AFK)" + messages[1] += "\n" + num_online[1]++ + for(var/client/C in mentors) + messages[2] += " [C] is a Mentor" + if(isobserver(C.mob)) + messages[2] += " - Observing" + else if(isnewplayer(C.mob)) + messages[2] += " - Lobby" + else + messages[2] += " - Playing" + if(C.is_afk()) + messages[2] += " (AFK)" + messages[2] += "\n" + num_online[2]++ + else + for(var/client/C in admins) + if(C.ckey in stealth_keys) + continue + if(!C.holder.fakekey) + messages[1] += " [C] is a [C.holder.rank]\n" + num_online[1]++ + for(var/client/C in mentors) + messages[2] += " [C] is a Mentor\n" + num_online[2]++ + + messages[1] = num_online[1] ? "Current Admins ([num_online[1]]):\n" + messages[1] : "No Admins online\n" + messages[1] += num_online[2] ? "\nCurrent Mentors ([num_online[2]]):\n" + messages[2] : "\nNo Mentors online\n" + to_chat(src, messages[1]) diff --git a/code/hub.dm b/code/hub.dm index b0839097a430..a06489e78e26 100644 --- a/code/hub.dm +++ b/code/hub.dm @@ -1,13 +1,13 @@ -/world - - hub = "Exadv1.spacestation13" - hub_password = "kMZy3U5jJHSiBQjr" - name = "Tau Ceti Station" -/* 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 = "kMZy3U5jJHSiBQjr" + name = "Tau Ceti Station" +/* 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" +*/ diff --git a/code/js/byjax.dm b/code/js/byjax.dm index bf9d7789891f..18b8180214dc 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 78f55e719b6e..d1cd99ef3f26 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\]); + } + } +} +"} diff --git a/code/modules/admin/NewBan.dm b/code/modules/admin/NewBan.dm index 23ce8eab1536..4c413f30ddc0 100644 --- a/code/modules/admin/NewBan.dm +++ b/code/modules/admin/NewBan.dm @@ -1,226 +1,226 @@ -var/CMinutes = null -var/savefile/Banlist - - -/proc/CheckBan(ckey, id, 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("\red Ban already exists.")) - 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) - 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) - 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: \blue(U) = Unban , (E) = Edit Ban\green (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("") - - dat += "
                    (U)(E) Key: [key]ComputerID: [id]IP: [ip] [expiry](By: [by])(Reason: [reason])
                    " - dat = "
                    Bans: (U) = Unban , (E) = Edit Ban - ([count] Bans)
                    [dat]" - usr << browse(entity_ja(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]" - 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) - +var/CMinutes = null +var/savefile/Banlist + + +/proc/CheckBan(ckey, id, 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("\red Ban already exists.")) + 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) + 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) + 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: \blue(U) = Unban , (E) = Edit Ban\green (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("") + + dat += "
                    (U)(E) Key: [key]ComputerID: [id]IP: [ip] [expiry](By: [by])(Reason: [reason])
                    " + dat = "
                    Bans: (U) = Unban , (E) = Edit Ban - ([count] Bans)
                    [dat]" + usr << browse(entity_ja(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]" + 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) + diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 823a79749e82..6f01bc599607 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1,1303 +1,1303 @@ - -var/global/BSACooldown = 0 - - -//////////////////////////////// -/proc/message_admins(msg) - msg = "ADMIN LOG: [msg]" - log_adminwarn(msg) - for(var/client/C in admins) - if(C.holder.rights & R_ADMIN) - to_chat(C, msg) - -/proc/msg_admin_attack(text) //Toggleable Attack Messages - log_attack(text) - var/rendered = "ATTACK: [text]" - for(var/client/C in admins) - if(R_ADMIN & C.holder.rights) - if(C.prefs.chat_toggles & CHAT_ATTACKLOGS) - var/msg = rendered - to_chat(C, msg) - - -///////////////////////////////////////////////////////////////////////////////////////////////Panels - -/datum/admins/proc/show_player_panel(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 - - var/body = "Options for [M.key]" - body += "Options panel for [M]" - if(M.client) - body += " played by [M.client] " - body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]" - - if(isnewplayer(M)) - body += " Hasn't Entered Game " - else - body += " \[Heal\] " - - body += {" -

                    \[ - VV - - TP - - PM - - SM - - FLW\]
                    - Mob type = [M.type]

                    - GeoIP:Get | - List of CIDs:Get (Ignore Warning)
                    - Related accounts by IP and cid: Get

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

                    - Jump to | - Get | - Send To -

                    - [check_rights(R_ADMIN,0) ? "Traitor panel | " : "" ] - Narrate to | - Subtle message - "} - - if (M.client) - if(!isnewplayer(M)) - body += "

                    " - body += "Transformations:" - body += "
                    " - - //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 Alien | - Make slime | - Make Blob | - "} - - //Simple Animals - if(isanimal(M)) - body += "Re-Animalize " - else - body += "Animalize " - - // DNA2 - Admin Hax - if(M.dna && iscarbon(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+="
                    " - - body += {"

                    - Rudimentary transformations:
                    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 | - Crab | - Coffee | - \[ Construct: Armoured , - Builder , - Wraith \] - Shade - Meme -
                    - "} - - if (M.client) - body += {"

                    - Other actions: -
                    - Forcesay | - Thunderdome 1 | - Thunderdome 2 | - Thunderdome Admin | - Thunderdome Observer | - "} - - body += {"
                    - - "} - - usr << browse(entity_ja(body), "window=adminplayeropts;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/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(entity_ja(dat), "window=player_notes;size=400x400") - - -/datum/admins/proc/player_has_info(key) - 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 - - -/datum/admins/proc/show_player_info(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]" - dat += "" - - //Display player age and player warn bans - var/p_age - var/p_ingame_age - for(var/client/C in clients) - if(C.ckey == key) - p_age = C.player_age - p_ingame_age = C.player_ingame_age - - dat +="Player age: [p_age] / In-game age: [p_ingame_age]
                    " - - 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 || I.author == "Adminbot" || check_rights(R_PERMISSIONS, FALSE)) - dat += "Remove" - dat += "

                    " - if(update_file) - info << infos - - dat += "
                    " - dat += "Add Comment
                    " - - dat += "" - usr << browse(entity_ja(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]
                    - 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" - - //world << "Channelname: [src.admincaster_feed_channel.channel_name] [src.admincaster_feed_channel.author]" - //world << "Msg: [src.admincaster_feed_message.author] [src.admincaster_feed_message.body]" - usr << browse(entity_ja(dat), "window=admincaster_main;size=400x600") - onclose(usr, "admincaster_main") - -/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 Airflow Settings
                    - Edit Phoron Settings
                    - Choose a default ZAS setting
                    - "} - - usr << browse(entity_ja(dat), "window=admin2;size=210x280") - 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_ADMIN,0)) - dat += {" - Admin Secrets
                    -
                    - Cure all diseases currently in existence
                    - Restore air in your zone
                    - 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
                    - !Freeze the station!
                    - Spawn a wave of meteors (aka lagocolyptic shower)
                    - Spawn a bluespace anomaly
                    - Spawn a energetic flux anomaly
                    - Spawn a pyroclastic anomaly
                    - Spawn a gravitational anomaly (new)
                    - Spawn a vortex anomaly
                    - Spawn a gravitational anomaly (aka lagitational anomolag)
                    - Spawn wormholes
                    - Spawn blob
                    - Trigger a Xenomorph infestation
                    - Trigger a Cortical Borer infestation
                    - Spawn an Alien silently
                    - Trigger a Spider infestation
                    - Send in a space ninja
                    - Send in a strike team
                    - Trigger an Carp migration
                    - Irradiate the station
                    - Trigger a Prison Break
                    - Trigger a Virus Outbreak
                    - Spawn an Immovable Rod
                    - Give guns to crew
                    - Give spells to crew
                    - Toggle a "lights out" event
                    - Spawn an Ion Storm
                    - Spawn Space-Vines
                    - Trigger a communication blackout
                    - Drop asteroid
                    -
                    - Fun Secrets
                    -
                    - 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
                    - 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
                    - Japanese Animes Mode
                    - Egalitarian Station Mode
                    - Move Administration Shuttle
                    - Move Ferry
                    - Move Alien Dinghy
                    - Move Mining Shuttle
                    - Break all lights
                    - Fix all lights
                    - Best Friend AI
                    - Advanced darkness! (DANGEROUS: extremely dark)
                    - The floor is lava! (DANGEROUS: extremely lame)
                    - "} - - if(check_rights(R_SERVER,0)) - dat += "Toggle bomb cap
                    " - - 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
                    -
                    - Coder Secrets
                    -
                    - Show Job Debug
                    - Admin Log
                    -
                    - "} - - usr << browse(entity_ja(dat), "window=secrets") - return - - - -/////////////////////////////////////////////////////////////////////////////////////////////////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, "\red Restarting world! \blue 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() - - 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 = sanitize(input("Global message to send:", "Admin Announce", null, null) as message, 500, extra = 0) - - if(message) - to_chat(world, "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n [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.") - 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/togglelooc() - set category = "Server" - set desc="Globally Toggles LOOC" - set name="Toggle LOOC" - looc_allowed = !( looc_allowed ) - if (looc_allowed) - to_chat(world, "The LOOC channel has been globally enabled!") - else - to_chat(world, "The LOOC channel has been globally disabled!") - log_admin("[key_name(usr)] toggled LOOC.") - message_admins("[key_name_admin(usr)] toggled LOOC.") - feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggledsay() - set category = "Server" - set desc="Globally Toggles DSAY" - set name="Toggle DSAY" - dsay_allowed = !( dsay_allowed ) - if (dsay_allowed) - to_chat(world, "Deadchat has been globally enabled!") - else - to_chat(world, "Deadchat has been globally disabled!") - log_admin("[key_name(usr)] toggled deadchat.") - message_admins("[key_name_admin(usr)] toggled deadchat.") - feedback_add_details("admin_verb","TDSAY") //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.") - 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"].") - 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.current_state == GAME_STATE_PREGAME) - ticker.can_fire = 1 - ticker.timeLeft = 0 - 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 if (ticker.current_state == GAME_STATE_STARTUP) - to_chat(usr, "Error: Start Now: Game is in startup, please wait until it has finished.") - 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("\blue [key_name_admin(usr)] toggled new player game entering.") - 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("\blue [key_name_admin(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].") - 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"].") - feedback_add_details("admin_verb","TA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/toggle_space_ninja() - set category = "Server" - set desc="Toggle space ninjas spawning." - set name="Toggle Space Ninjas" - toggle_space_ninja = !toggle_space_ninja - log_admin("[key_name(usr)] toggled Space Ninjas to [toggle_space_ninja].") - message_admins("[key_name_admin(usr)] toggled Space Ninjas [toggle_space_ninja ? "on" : "off"].") - feedback_add_details("admin_verb","TSN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/delay() - set category = "Server" - set desc="Delay the game start" - set name="Delay pre-game" - - if(!check_rights(R_SERVER)) return - var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(ticker.timeLeft/10)) as num|null - if(ticker.current_state > GAME_STATE_PREGAME) - return alert("Too late... The game has already started!") - if(newtime) - ticker.timeLeft = newtime * 10 - if(newtime < 0) - to_chat(world, "The game start has been delayed.") - log_admin("[key_name(usr)] delayed the round start.") - send2slack_service("[key_name(usr)] delayed the round start.") - else - to_chat(world, "The game will start in [newtime] seconds.") - log_admin("[key_name(usr)] set the pre-game delay to [newtime] seconds.") - send2slack_service("[key_name(usr)] set the pre-game delay to [newtime] seconds.") - feedback_add_details("admin_verb","DELAY") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/delay_end() - set category = "Server" - set desc="Delay the game end" - set name="Delay end-game" - - if(!check_rights(R_SERVER)) return - if(ticker.current_state > GAME_STATE_PREGAME) - 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"].") - send2slack_service("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") - else - return alert("The game has not started yet!") - -/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("\blue 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("\blue 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("\blue 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, "\red Rebooting world! \blue 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() - - world.Reboot() - -/datum/admins/proc/toggle_job_restriction() - set category = "Server" - set desc="Toggles job restrictions for aliens" - set name="Toggle Job Restriction" - - if(!check_rights(R_WHITELIST)) - return - config.use_alien_job_restriction = !config.use_alien_job_restriction - to_chat(world, "Job restrictions for xenos was [config.use_alien_job_restriction ? "en" : "dis"]abled.") - message_admins("[key_name(usr)] toggled Job restrictions for xenos.") - feedback_add_details("admin_verb","TJR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/unprison(mob/M in mob_list) - set category = "Admin" - set name = "Unprison" - if (M.z == ZLEVEL_CENTCOMM) - if (config.allow_admin_jump) - M.loc = pick(latejoin) - message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]") - 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) // returns 1 for specail characters and 2 for heroes of gamemode - if(!ticker || !ticker.mode) - return 0 - if (!istype(M)) - return 0 - if((M.mind in ticker.mode.head_revolutionaries) || (M.mind in ticker.mode.revolutionaries)) - if (ticker.mode.config_tag == "revolution") - return 2 - return 1 - if(M.mind in ticker.mode.cult) - if (ticker.mode.config_tag == "cult") - return 2 - return 1 - if(M.mind in ticker.mode.malf_ai) - if (ticker.mode.config_tag == "malfunction") - return 2 - return 1 - if(M.mind in ticker.mode.syndicates) - if (ticker.mode.config_tag == "nuclear") - return 2 - return 1 - if(M.mind in ticker.mode.wizards) - if (ticker.mode.config_tag == "wizard") - return 2 - return 1 - if(M.mind in ticker.mode.changelings) - if (ticker.mode.config_tag == "changeling") - return 2 - return 1 - - for(var/datum/disease/D in M.viruses) - if(istype(D, /datum/disease/jungle_fever)) - 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(target) - switch(target) - if(1) - return "Destroy at least 70% of the phoron canisters on the station" - if(2) - return "Destroy the AI" - if(3) - var/count = 0 - for(var/mob/living/carbon/monkey/Monkey in not_world) - if(Monkey.z == ZLEVEL_STATION) - 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(object as text) - set category = "Debug" - set desc = "(atom path) Spawn an atom." - set name = "Spawn" - - if(!check_rights(R_SPAWN)) return - - var/list/types = typesof(/atom) - var/list/matches = new() - - for(var/path in types) - 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(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.") - 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("\blue [key_name_admin(usr)] toggled guests game entering [guests_allowed?"":"dis"]allowed.") - feedback_add_details("admin_verb","TGU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/datum/admins/proc/output_ai_laws() - var/ai_number = 0 - for(var/mob/living/silicon/S in silicon_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)) - to_chat(usr, "pAI [key_name(S, usr)]'s laws:") - else - to_chat(usr, "SOMETHING SILICON [key_name(S, usr)]'s laws:") - - 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) - 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() - - -/proc/get_options_bar(whom, detail = 2, name = 0, link = 1, reply = null) - if(!whom) - return "(*null*)" - var/mob/M - var/client/C - if(istype(whom, /client)) - C = whom - M = C.mob - else if(istype(whom, /mob)) - M = whom - C = M.client - else - return "(*not an mob*)" - switch(detail) - if(0) - return "[key_name(C, link, name, 0, reply)]" - if(1) - return "[key_name(C, link, name, 1, reply)](?)" - if(2) - var/ref_mob = "\ref[M]" - return "[key_name(C, link, name, 1, reply)](?) (PP) (VV) (SM) (JMP) (CA)" - - - -// -// -//ALL DONE -//********************************************************************************************************* -//TO-DO: -// -// -/datum/admins/proc/cmd_ghost_drag(mob/dead/observer/frommob, mob/living/tomob) - - //this is the exact two check rights checks required to edit a ckey with vv. - if (!check_rights(R_ADMIN,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]?" - - var/ask = alert(question, "Place ghost in control of mob?", "Yes", "No") - if (ask != "Yes") - return 1 - - if (!frommob || !tomob) //make sure the mobs don't go away while we waited for a response - return 1 - - tomob.ghostize(can_reenter_corpse = FALSE) - - 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 - -/**********************Administration Shuttle**************************/ - -var/admin_shuttle_location = 0 // 0 = centcom 13, 1 = station - -/proc/move_admin_shuttle() - var/area/fromArea - var/area/toArea - var/static/moving = FALSE - - if(moving) - return - moving = TRUE - - if (admin_shuttle_location == 1) - fromArea = locate(/area/shuttle/administration/station) - toArea = locate(/area/shuttle/administration/centcom) - - SSshuttle.undock_act(fromArea) - SSshuttle.undock_act(/area/hallway/secondary/entry, "arrival_admin") - else - fromArea = locate(/area/shuttle/administration/centcom) - toArea = locate(/area/shuttle/administration/station) - - SSshuttle.undock_act(fromArea) - SSshuttle.undock_act(/area/centcom/specops, "centcomm_admin") - - fromArea.move_contents_to(toArea) - - if (admin_shuttle_location) - admin_shuttle_location = 0 - - SSshuttle.dock_act(toArea) - SSshuttle.dock_act(/area/centcom/specops, "centcomm_admin") - else - admin_shuttle_location = 1 - - SSshuttle.dock_act(toArea) - SSshuttle.dock_act(/area/hallway/secondary/entry, "arrival_admin") - - moving = FALSE - -/**********************Centcom Ferry**************************/ - -var/ferry_location = 0 // 0 = centcom , 1 = station - -/proc/move_ferry() - var/area/fromArea - var/area/toArea - var/static/moving = FALSE - - if(moving) - return - moving = TRUE - - if (ferry_location == 1) - fromArea = locate(/area/shuttle/transport1/station) - toArea = locate(/area/shuttle/transport1/centcom) - - SSshuttle.undock_act(fromArea) - SSshuttle.undock_act(/area/hallway/secondary/entry, "arrival_ferry") - else - fromArea = locate(/area/shuttle/transport1/centcom) - toArea = locate(/area/shuttle/transport1/station) - - SSshuttle.undock_act(fromArea) - SSshuttle.undock_act(/area/centcom/evac, "centcomm_ferry") - - fromArea.move_contents_to(toArea) - - if (ferry_location) - ferry_location = 0 - - SSshuttle.dock_act(toArea) - SSshuttle.dock_act(/area/centcom/evac, "centcomm_ferry") - else - ferry_location = 1 - - SSshuttle.dock_act(toArea) - SSshuttle.dock_act(/area/hallway/secondary/entry, "arrival_ferry") - - moving = FALSE - -/**********************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 + +var/global/BSACooldown = 0 + + +//////////////////////////////// +/proc/message_admins(msg) + msg = "ADMIN LOG: [msg]" + log_adminwarn(msg) + for(var/client/C in admins) + if(C.holder.rights & R_ADMIN) + to_chat(C, msg) + +/proc/msg_admin_attack(text) //Toggleable Attack Messages + log_attack(text) + var/rendered = "ATTACK: [text]" + for(var/client/C in admins) + if(R_ADMIN & C.holder.rights) + if(C.prefs.chat_toggles & CHAT_ATTACKLOGS) + var/msg = rendered + to_chat(C, msg) + + +///////////////////////////////////////////////////////////////////////////////////////////////Panels + +/datum/admins/proc/show_player_panel(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 + + var/body = "Options for [M.key]" + body += "Options panel for [M]" + if(M.client) + body += " played by [M.client] " + body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]" + + if(isnewplayer(M)) + body += " Hasn't Entered Game " + else + body += " \[Heal\] " + + body += {" +

                    \[ + VV - + TP - + PM - + SM - + FLW\]

                    + Mob type = [M.type]

                    + GeoIP: Get | + List of CIDs: Get (Ignore Warning)
                    + Related accounts by IP and cid: Get

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

                    + Jump to | + Get | + Send To +

                    + [check_rights(R_ADMIN,0) ? "Traitor panel | " : "" ] + Narrate to | + Subtle message + "} + + if (M.client) + if(!isnewplayer(M)) + body += "

                    " + body += "Transformations:" + body += "
                    " + + //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 Alien | + Make slime | + Make Blob | + "} + + //Simple Animals + if(isanimal(M)) + body += "Re-Animalize " + else + body += "Animalize " + + // DNA2 - Admin Hax + if(M.dna && iscarbon(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+="
                    " + + body += {"

                    + Rudimentary transformations:
                    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 | + Crab | + Coffee | + \[ Construct: Armoured , + Builder , + Wraith \] + Shade + Meme +
                    + "} + + if (M.client) + body += {"

                    + Other actions: +
                    + Forcesay | + Thunderdome 1 | + Thunderdome 2 | + Thunderdome Admin | + Thunderdome Observer | + "} + + body += {"
                    + + "} + + usr << browse(entity_ja(body), "window=adminplayeropts;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/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(entity_ja(dat), "window=player_notes;size=400x400") + + +/datum/admins/proc/player_has_info(key) + 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 + + +/datum/admins/proc/show_player_info(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]" + dat += "" + + //Display player age and player warn bans + var/p_age + var/p_ingame_age + for(var/client/C in clients) + if(C.ckey == key) + p_age = C.player_age + p_ingame_age = C.player_ingame_age + + dat +="Player age: [p_age] / In-game age: [p_ingame_age]
                    " + + 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 || I.author == "Adminbot" || check_rights(R_PERMISSIONS, FALSE)) + dat += "Remove" + dat += "

                    " + if(update_file) + info << infos + + dat += "
                    " + dat += "Add Comment
                    " + + dat += "" + usr << browse(entity_ja(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]
                    + 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" + + //world << "Channelname: [src.admincaster_feed_channel.channel_name] [src.admincaster_feed_channel.author]" + //world << "Msg: [src.admincaster_feed_message.author] [src.admincaster_feed_message.body]" + usr << browse(entity_ja(dat), "window=admincaster_main;size=400x600") + onclose(usr, "admincaster_main") + +/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 Airflow Settings
                    + Edit Phoron Settings
                    + Choose a default ZAS setting
                    + "} + + usr << browse(entity_ja(dat), "window=admin2;size=210x280") + 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_ADMIN,0)) + dat += {" + Admin Secrets
                    +
                    + Cure all diseases currently in existence
                    + Restore air in your zone
                    + 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
                    + !Freeze the station!
                    + Spawn a wave of meteors (aka lagocolyptic shower)
                    + Spawn a bluespace anomaly
                    + Spawn a energetic flux anomaly
                    + Spawn a pyroclastic anomaly
                    + Spawn a gravitational anomaly (new)
                    + Spawn a vortex anomaly
                    + Spawn a gravitational anomaly (aka lagitational anomolag)
                    + Spawn wormholes
                    + Spawn blob
                    + Trigger a Xenomorph infestation
                    + Trigger a Cortical Borer infestation
                    + Spawn an Alien silently
                    + Trigger a Spider infestation
                    + Send in a space ninja
                    + Send in a strike team
                    + Trigger an Carp migration
                    + Irradiate the station
                    + Trigger a Prison Break
                    + Trigger a Virus Outbreak
                    + Spawn an Immovable Rod
                    + Give guns to crew
                    + Give spells to crew
                    + Toggle a "lights out" event
                    + Spawn an Ion Storm
                    + Spawn Space-Vines
                    + Trigger a communication blackout
                    + Drop asteroid
                    +
                    + Fun Secrets
                    +
                    + 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
                    + 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
                    + Japanese Animes Mode
                    + Egalitarian Station Mode
                    + Move Administration Shuttle
                    + Move Ferry
                    + Move Alien Dinghy
                    + Move Mining Shuttle
                    + Break all lights
                    + Fix all lights
                    + Best Friend AI
                    + Advanced darkness! (DANGEROUS: extremely dark)
                    + The floor is lava! (DANGEROUS: extremely lame)
                    + "} + + if(check_rights(R_SERVER,0)) + dat += "Toggle bomb cap
                    " + + 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
                    +
                    + Coder Secrets
                    +
                    + Show Job Debug
                    + Admin Log
                    +
                    + "} + + usr << browse(entity_ja(dat), "window=secrets") + return + + + +/////////////////////////////////////////////////////////////////////////////////////////////////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, "\red Restarting world! \blue 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() + + 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 = sanitize(input("Global message to send:", "Admin Announce", null, null) as message, 500, extra = 0) + + if(message) + to_chat(world, "[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:\n [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.") + 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/togglelooc() + set category = "Server" + set desc="Globally Toggles LOOC" + set name="Toggle LOOC" + looc_allowed = !( looc_allowed ) + if (looc_allowed) + to_chat(world, "The LOOC channel has been globally enabled!") + else + to_chat(world, "The LOOC channel has been globally disabled!") + log_admin("[key_name(usr)] toggled LOOC.") + message_admins("[key_name_admin(usr)] toggled LOOC.") + feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggledsay() + set category = "Server" + set desc="Globally Toggles DSAY" + set name="Toggle DSAY" + dsay_allowed = !( dsay_allowed ) + if (dsay_allowed) + to_chat(world, "Deadchat has been globally enabled!") + else + to_chat(world, "Deadchat has been globally disabled!") + log_admin("[key_name(usr)] toggled deadchat.") + message_admins("[key_name_admin(usr)] toggled deadchat.") + feedback_add_details("admin_verb","TDSAY") //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.") + 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"].") + 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.current_state == GAME_STATE_PREGAME) + ticker.can_fire = 1 + ticker.timeLeft = 0 + 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 if (ticker.current_state == GAME_STATE_STARTUP) + to_chat(usr, "Error: Start Now: Game is in startup, please wait until it has finished.") + 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("\blue [key_name_admin(usr)] toggled new player game entering.") + 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("\blue [key_name_admin(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].") + 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"].") + feedback_add_details("admin_verb","TA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/toggle_space_ninja() + set category = "Server" + set desc="Toggle space ninjas spawning." + set name="Toggle Space Ninjas" + toggle_space_ninja = !toggle_space_ninja + log_admin("[key_name(usr)] toggled Space Ninjas to [toggle_space_ninja].") + message_admins("[key_name_admin(usr)] toggled Space Ninjas [toggle_space_ninja ? "on" : "off"].") + feedback_add_details("admin_verb","TSN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/delay() + set category = "Server" + set desc="Delay the game start" + set name="Delay pre-game" + + if(!check_rights(R_SERVER)) return + var/newtime = input("Set a new time in seconds. Set -1 for indefinite delay.","Set Delay",round(ticker.timeLeft/10)) as num|null + if(ticker.current_state > GAME_STATE_PREGAME) + return alert("Too late... The game has already started!") + if(newtime) + ticker.timeLeft = newtime * 10 + if(newtime < 0) + to_chat(world, "The game start has been delayed.") + log_admin("[key_name(usr)] delayed the round start.") + send2slack_service("[key_name(usr)] delayed the round start.") + else + to_chat(world, "The game will start in [newtime] seconds.") + log_admin("[key_name(usr)] set the pre-game delay to [newtime] seconds.") + send2slack_service("[key_name(usr)] set the pre-game delay to [newtime] seconds.") + feedback_add_details("admin_verb","DELAY") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/delay_end() + set category = "Server" + set desc="Delay the game end" + set name="Delay end-game" + + if(!check_rights(R_SERVER)) return + if(ticker.current_state > GAME_STATE_PREGAME) + 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"].") + send2slack_service("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") + else + return alert("The game has not started yet!") + +/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("\blue 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("\blue 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("\blue 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, "\red Rebooting world! \blue 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() + + world.Reboot() + +/datum/admins/proc/toggle_job_restriction() + set category = "Server" + set desc="Toggles job restrictions for aliens" + set name="Toggle Job Restriction" + + if(!check_rights(R_WHITELIST)) + return + config.use_alien_job_restriction = !config.use_alien_job_restriction + to_chat(world, "Job restrictions for xenos was [config.use_alien_job_restriction ? "en" : "dis"]abled.") + message_admins("[key_name(usr)] toggled Job restrictions for xenos.") + feedback_add_details("admin_verb","TJR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/unprison(mob/M in mob_list) + set category = "Admin" + set name = "Unprison" + if (M.z == ZLEVEL_CENTCOMM) + if (config.allow_admin_jump) + M.loc = pick(latejoin) + message_admins("[key_name_admin(usr)] has unprisoned [key_name_admin(M)]") + 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) // returns 1 for specail characters and 2 for heroes of gamemode + if(!ticker || !ticker.mode) + return 0 + if (!istype(M)) + return 0 + if((M.mind in ticker.mode.head_revolutionaries) || (M.mind in ticker.mode.revolutionaries)) + if (ticker.mode.config_tag == "revolution") + return 2 + return 1 + if(M.mind in ticker.mode.cult) + if (ticker.mode.config_tag == "cult") + return 2 + return 1 + if(M.mind in ticker.mode.malf_ai) + if (ticker.mode.config_tag == "malfunction") + return 2 + return 1 + if(M.mind in ticker.mode.syndicates) + if (ticker.mode.config_tag == "nuclear") + return 2 + return 1 + if(M.mind in ticker.mode.wizards) + if (ticker.mode.config_tag == "wizard") + return 2 + return 1 + if(M.mind in ticker.mode.changelings) + if (ticker.mode.config_tag == "changeling") + return 2 + return 1 + + for(var/datum/disease/D in M.viruses) + if(istype(D, /datum/disease/jungle_fever)) + 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(target) + switch(target) + if(1) + return "Destroy at least 70% of the phoron canisters on the station" + if(2) + return "Destroy the AI" + if(3) + var/count = 0 + for(var/mob/living/carbon/monkey/Monkey in not_world) + if(Monkey.z == ZLEVEL_STATION) + 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(object as text) + set category = "Debug" + set desc = "(atom path) Spawn an atom." + set name = "Spawn" + + if(!check_rights(R_SPAWN)) return + + var/list/types = typesof(/atom) + var/list/matches = new() + + for(var/path in types) + 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(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.") + 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("\blue [key_name_admin(usr)] toggled guests game entering [guests_allowed?"":"dis"]allowed.") + feedback_add_details("admin_verb","TGU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/output_ai_laws() + var/ai_number = 0 + for(var/mob/living/silicon/S in silicon_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)) + to_chat(usr, "pAI [key_name(S, usr)]'s laws:") + else + to_chat(usr, "SOMETHING SILICON [key_name(S, usr)]'s laws:") + + 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) + 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() + + +/proc/get_options_bar(whom, detail = 2, name = 0, link = 1, reply = null) + if(!whom) + return "(*null*)" + var/mob/M + var/client/C + if(istype(whom, /client)) + C = whom + M = C.mob + else if(istype(whom, /mob)) + M = whom + C = M.client + else + return "(*not an mob*)" + switch(detail) + if(0) + return "[key_name(C, link, name, 0, reply)]" + if(1) + return "[key_name(C, link, name, 1, reply)](?)" + if(2) + var/ref_mob = "\ref[M]" + return "[key_name(C, link, name, 1, reply)](?) (PP) (VV) (SM) (JMP) (CA)" + + + +// +// +//ALL DONE +//********************************************************************************************************* +//TO-DO: +// +// +/datum/admins/proc/cmd_ghost_drag(mob/dead/observer/frommob, mob/living/tomob) + + //this is the exact two check rights checks required to edit a ckey with vv. + if (!check_rights(R_ADMIN,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]?" + + var/ask = alert(question, "Place ghost in control of mob?", "Yes", "No") + if (ask != "Yes") + return 1 + + if (!frommob || !tomob) //make sure the mobs don't go away while we waited for a response + return 1 + + tomob.ghostize(can_reenter_corpse = FALSE) + + 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 + +/**********************Administration Shuttle**************************/ + +var/admin_shuttle_location = 0 // 0 = centcom 13, 1 = station + +/proc/move_admin_shuttle() + var/area/fromArea + var/area/toArea + var/static/moving = FALSE + + if(moving) + return + moving = TRUE + + if (admin_shuttle_location == 1) + fromArea = locate(/area/shuttle/administration/station) + toArea = locate(/area/shuttle/administration/centcom) + + SSshuttle.undock_act(fromArea) + SSshuttle.undock_act(/area/hallway/secondary/entry, "arrival_admin") + else + fromArea = locate(/area/shuttle/administration/centcom) + toArea = locate(/area/shuttle/administration/station) + + SSshuttle.undock_act(fromArea) + SSshuttle.undock_act(/area/centcom/specops, "centcomm_admin") + + fromArea.move_contents_to(toArea) + + if (admin_shuttle_location) + admin_shuttle_location = 0 + + SSshuttle.dock_act(toArea) + SSshuttle.dock_act(/area/centcom/specops, "centcomm_admin") + else + admin_shuttle_location = 1 + + SSshuttle.dock_act(toArea) + SSshuttle.dock_act(/area/hallway/secondary/entry, "arrival_admin") + + moving = FALSE + +/**********************Centcom Ferry**************************/ + +var/ferry_location = 0 // 0 = centcom , 1 = station + +/proc/move_ferry() + var/area/fromArea + var/area/toArea + var/static/moving = FALSE + + if(moving) + return + moving = TRUE + + if (ferry_location == 1) + fromArea = locate(/area/shuttle/transport1/station) + toArea = locate(/area/shuttle/transport1/centcom) + + SSshuttle.undock_act(fromArea) + SSshuttle.undock_act(/area/hallway/secondary/entry, "arrival_ferry") + else + fromArea = locate(/area/shuttle/transport1/centcom) + toArea = locate(/area/shuttle/transport1/station) + + SSshuttle.undock_act(fromArea) + SSshuttle.undock_act(/area/centcom/evac, "centcomm_ferry") + + fromArea.move_contents_to(toArea) + + if (ferry_location) + ferry_location = 0 + + SSshuttle.dock_act(toArea) + SSshuttle.dock_act(/area/centcom/evac, "centcomm_ferry") + else + ferry_location = 1 + + SSshuttle.dock_act(toArea) + SSshuttle.dock_act(/area/hallway/secondary/entry, "arrival_ferry") + + moving = FALSE + +/**********************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 diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 5da446b4dfc6..e724130eb96c 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -1,163 +1,163 @@ -var/list/admin_ranks = list() //list of all ranks with associated rights - -//load our rank - > rights associations -/proc/load_admin_ranks() - admin_ranks.Cut() - - 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 = splittext(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("event") rights |= R_EVENT - - 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.Cut() - for(var/client/C in admins) - C.remove_admin_verbs() - C.holder = null - admins.Cut() - - 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 = splittext(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()) - error("Failed to connect to database in load_admins(). Reverting to legacy system.") - log_misc("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) - error("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.") - log_misc("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.Cut() + + 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 = splittext(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("event") rights |= R_EVENT + + 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.Cut() + for(var/client/C in admins) + C.remove_admin_verbs() + C.holder = null + admins.Cut() + + 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 = splittext(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()) + error("Failed to connect to database in load_admins(). Reverting to legacy system.") + log_misc("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) + error("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.") + log_misc("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 34cf66c2269e..3a69c831a6ef 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -1,1124 +1,1124 @@ -//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( - /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/cmd_mentor_check_new_players, - /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ - /client/proc/player_panel, - /client/proc/debug_variables /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/ - ) -var/list/admin_verbs_admin = list( - /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/getserverlog, /*allows us to fetch server logs (diary) for other days*/ - /client/proc/get_whitelist, //Whitelist - /client/proc/add_to_whitelist, - /datum/admins/proc/whitelist_panel, - /datum/admins/proc/customitems_panel, - /datum/admins/proc/customitemspremoderation_panel, - /datum/admins/proc/library_recycle_bin, - /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_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/check_antagonists, - /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, - /datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/ - /datum/admins/proc/togglelooc, /*toggles looc on/off for everyone*/ - /datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/ - /datum/admins/proc/toggledsay, /*toggles dsay on/off for everyone*/ - /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, - /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/toggleghostwriters, - /client/proc/toggledrones, - /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 */ - /client/proc/aooc, - /client/proc/change_security_level, - /client/proc/empty_ai_core_toggle_latejoin, - /client/proc/send_fax_message - ) -var/list/admin_verbs_ban = list( - /client/proc/unban_panel -// /client/proc/stickybanpanel, - ) -var/list/admin_verbs_sounds = list( - /client/proc/play_local_sound, - /client/proc/play_server_sound, - /client/proc/play_sound, - /client/proc/stop_server_sound - ) -var/list/admin_verbs_fun = list( - /client/proc/object_talk, - /client/proc/cmd_admin_dress, - /client/proc/cmd_admin_gib_self, - /client/proc/drop_bomb, - /client/proc/everyone_random, - /client/proc/one_click_antag, - /datum/admins/proc/toggle_aliens, - /datum/admins/proc/toggle_space_ninja, - /client/proc/send_space_ninja, - /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_global_ooc, - /client/proc/editappear, - /client/proc/roll_dices, - /client/proc/epileptic_anomaly, -// /client/proc/Noir_anomaly, - /client/proc/epileptic_anomaly_cancel, - /client/proc/achievement, - /client/proc/toggle_AI_interact, /*toggle admin ability to interact with machines as an AI*/ - /client/proc/centcom_barriers_toggle, - /client/proc/gateway_toggle - ) -var/list/admin_verbs_spawn = list( - /datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ - /client/proc/respawn_character, - /datum/admins/proc/spawn_fluid_verb - ) -var/list/admin_verbs_server = list( - /client/proc/Set_Holiday, - /datum/admins/proc/startnow, - /datum/admins/proc/restart, - /datum/admins/proc/delay, - /datum/admins/proc/delay_end, - /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, - /datum/admins/proc/toggle_space_ninja, - /client/proc/toggle_random_events, - /client/proc/nanomapgen_DumpImage - ) -var/list/admin_verbs_debug = list( - /client/proc/restart_controller, - /client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/ - /client/proc/cmd_admin_list_open_jobs, - /client/proc/Debug2, - /client/proc/ZASSettings, - /client/proc/cmd_debug_make_powernets, - /client/proc/cmd_debug_load_junkyard, - /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/cmd_debug_tog_vcounter, - /client/proc/cmd_message_spam_control, - /client/proc/investigate_show, - /client/proc/reload_admins, - /client/proc/reload_mentors, - /client/proc/reload_nanoui_resources, -// /client/proc/remake_distribution_map, -// /client/proc/show_distribution_map, - /client/proc/enable_debug_verbs, - /*/client/proc/callproc,*/ -// /proc/machine_upgrade, - /client/proc/toggledebuglogs, - /client/proc/view_runtimes, - /client/proc/cmd_display_del_log, - /client/proc/cmd_display_init_log - ) -var/list/admin_verbs_possess = list( - /proc/possess, - /proc/release - ) -var/list/admin_verbs_permissions = list( - /client/proc/edit_admin_permissions, - /client/proc/gsw_add, - /client/proc/library_debug_remove, - /client/proc/library_debug_read - ) -var/list/admin_verbs_rejuv = list( - /client/proc/respawn_character - ) -var/list/admin_verbs_whitelist = list( - /client/proc/get_whitelist, //Whitelist - /client/proc/add_to_whitelist, - /datum/admins/proc/whitelist_panel, - /datum/admins/proc/toggle_job_restriction - ) -var/list/admin_verbs_event = list( - /client/proc/event_map_loader - ) - -//verbs which can be hidden - needs work -var/list/admin_verbs_hideable = list( - /client/proc/set_global_ooc, - /datum/admins/proc/library_recycle_bin, - /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/get_whitelist, //Whitelist - /client/proc/add_to_whitelist, - /datum/admins/proc/whitelist_panel, - /client/proc/gsw_add, - /datum/admins/proc/toggle_aliens, - /datum/admins/proc/toggle_space_ninja, - /client/proc/send_space_ninja, - /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, - /datum/admins/proc/startnow, - /datum/admins/proc/restart, - /datum/admins/proc/delay, - /datum/admins/proc/delay_end, - /datum/admins/proc/toggleaban, - /client/proc/toggle_log_hrefs, - /datum/admins/proc/immreboot, - /client/proc/everyone_random, - /datum/admins/proc/toggleAI, - /client/proc/restart_controller, - /datum/admins/proc/adrev, - /datum/admins/proc/adspawn, - /datum/admins/proc/adjump, - /client/proc/cmd_admin_list_open_jobs, - /*/client/proc/callproc,*/ - /client/proc/Debug2, - /client/proc/reload_admins, - /client/proc/cmd_debug_make_powernets, - /client/proc/startSinglo, - /client/proc/cmd_debug_mob_lists, - /client/proc/cmd_debug_del_all, - /client/proc/cmd_debug_tog_aliens, - /client/proc/cmd_debug_tog_vcounter, - /client/proc/enable_debug_verbs, - /proc/possess, - /proc/release - ) - -/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_WHITELIST) - verbs += admin_verbs_whitelist - if(holder.rights & R_EVENT) - verbs += admin_verbs_event - - if(holder.rights & R_ADMIN) - control_freak = CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS - -/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_event, - /*Debug verbs added by "show debug verbs"*/ - /client/proc/Cell, - /client/proc/do_not_use_these, - /client/proc/camera_view, - /client/proc/sec_camera_report, - /client/proc/intercom_view, - /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/startSinglo, - /client/proc/set_fps, - /client/proc/cmd_admin_grantfullaccess, - /client/proc/splash, - /client/proc/cmd_admin_areatest - ) - -/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 = TRUE - 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(isnewplayer(mob)) - to_chat(src, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.") - else - //ghostize - var/mob/body = mob - body.ghostize(can_reenter_corpse = TRUE) - 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, "\red Invisimin off. Invisibility reset.") - mob.alpha = max(mob.alpha + 100, 255) - else - mob.invisibility = INVISIBILITY_OBSERVER - to_chat(mob, "\blue Invisimin on. You are now as invisible as a ghost.") - mob.alpha = max(mob.alpha - 100, 0) - - -/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/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 = "OOC" - set name = "Set Admin OOC Color" - if(!holder) - return - if(!config.allow_admin_ooccolor) - to_chat(usr, "Currently disabled by config.") - var/new_aooccolor = input(src, "Please select your OOC colour.", "OOC colour") as color|null - if(new_aooccolor) - prefs.aooccolor = new_aooccolor - prefs.save_preferences() - 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 - mob.invisibility = initial(mob.invisibility) - mob.alpha = 127//initial(mob.alpha) - mob.name = initial(mob.name) - 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 - mob.invisibility = INVISIBILITY_MAXIMUM + 1 //JUST IN CASE - mob.alpha = 0 //JUUUUST IN CASE - mob.name = " " - 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"]") - feedback_add_details("admin_verb","SM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/warn(warned_ckey) - if(!check_rights(R_ADMIN)) - return - - warned_ckey = ckey(warned_ckey) - - var/reason = input(usr, "Reason?", "Warn Reason","") as text|null - - if(!warned_ckey || !reason) - return - - notes_add(warned_ckey, "ADMINWARN: " + reason, src) - - var/client/C = directory[warned_ckey] - reason = sanitize(reason) - - if(C) - to_chat(C, "You have been formally warned by an administrator.
                    Reason: [reason].
                    ") - - log_admin("[src.key] has warned [warned_ckey] with reason: [reason]") - message_admins("[key_name_admin(src)] has warned [C ? key_name_admin(C) : warned_ckey] with reason: [reason].") - - feedback_add_details("admin_verb","WARN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/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", "Medium Bomb", "Big Bomb", "Custom Bomb", "Cancel") - var/choice = input("What size explosion would you like to produce?") in choices - switch(choice) - if(null) - return 0 - if("Small Bomb") - explosion(epicenter, 1, 2, 3, 3) - if("Medium Bomb") - explosion(epicenter, 2, 3, 4, 4) - if("Big Bomb") - 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) - if("Cancel") - return 0 - log_admin("[ckey] creating an admin explosion at [epicenter.loc].") - message_admins("\blue [ckey] creating an admin explosion at [epicenter.loc].") - feedback_add_details("admin_verb","DB") //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/list/spell_names = list() - for(var/v in spells) - // "/obj/effect/proc_holder/spell/" 30 symbols ~Intercross21 - spell_names.Add(copytext("[v]", 31, 0)) - var/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spell_names - if(!S) return - var/path = text2path("/obj/effect/proc_holder/spell/[S]") - T.AddSpell(new path) - feedback_add_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].") - message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the spell [S].") - -/client/proc/give_disease(mob/T as mob in mob_list) // -- Giacom - set category = "Fun" - set name = "Give Disease (old)" - set desc = "Gives a (tg-style) Disease to a mob." - var/list/disease_names = list() - for(var/v in diseases) - // "/datum/disease/" 15 symbols ~Intercross - disease_names.Add(copytext("[v]", 16, 0)) - var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in disease_names - if(!D) return - var/path = text2path("/datum/disease/[D]") - T.contract_disease(new path, 1) - feedback_add_details("admin_verb","GD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] gave [key_name(T)] the disease [D].") - message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the disease [D].") - -/client/proc/give_disease2(mob/T as mob in mob_list) // -- Giacom - set category = "Fun" - set name = "Give Disease" - set desc = "Gives a Disease to a mob." - - var/datum/disease2/disease/D = new /datum/disease2/disease() - - var/disease_type = input("Is this a lesser or greater disease?", "Give Disease") in list("Lesser", "Greater", "Custom") - var/greater = (disease_type == "Greater") - - if(disease_type == "Custom") - D.uniqueID = rand(0,10000) - D.antigen |= text2num(pick(ANTIGENS)) - D.antigen |= text2num(pick(ANTIGENS)) - - var/list/datum/disease2/effect/possible_effects = list() - for(var/e in subtypesof(/datum/disease2/effect)) - var/datum/disease2/effect/f = new e - if (f.level > 4) //we don't want such strong effects - continue - if (f.level < 1) - continue - possible_effects += f - - while(TRUE) - var/command = input("Disease menu, ([D.effects.len] symptoms)", "Make custom disease") in list("Add symptom", "Remove symptom", "Done") - if(command == "Add symptom" && D.effects.len < D.max_symptoms) - if(!possible_effects.len) - continue - var/effect = input("Add symptom", "Select symptom") as null|anything in possible_effects - if(!effect) - continue - possible_effects -= effect - var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder - holder.effect = effect - holder.name = holder.effect.name - holder.chance = rand(holder.effect.chance_minm, holder.effect.chance_maxm) - D.addeffect(holder) - if(command == "Remove symptom" && D.effects.len > 0) - var/datum/disease2/effectholder/holder = input("Remove symptom", "Select symptom to remove") as null|anything in D.effects - if(!holder) - continue - possible_effects += holder.effect - D.effects -= holder - qdel(holder) - - if(command == "Done") - break - disease_type = "[disease_type] ([jointext(D.effects, ", ")])" - else - D.makerandom(greater) - if (!greater) - D.infectionchance = 1 - - D.infectionchance = input("How virulent is this disease? (1-100)", "Give Disease", D.infectionchance) as num - - infect_virus2(T,D,1) - - feedback_add_details("admin_verb","GD2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] gave [key_name(T)] a [disease_type] disease2 with infection chance [D.infectionchance].") - message_admins("[key_name_admin(usr)] gave [key_name(T)] a [disease_type] disease2 with infection chance [D.infectionchance].") - -/* disabled because this is not a sound but a hearable message, and also very hard to use since you need to choose an item from a huge list and not a view at least. - so, this proc needs rewrite to be a verb per object or something like that and also better name because it can be named more obvious than using desc. - also "in world" -/client/proc/make_sound(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(O) - var/message = sanitize(input("What do you want the message to be?", "Make Sound") as text|null) - if(!message) - return - for (var/mob/V in hearers(O)) - V.show_message(message, 2) - log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound") - message_admins("\blue [key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z] (JMP) make a sound") - 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(msg as text) // -- TLE - set category = "Special Verbs" - set name = "oSay" - set desc = "Display a message to everyone who can hear the target." - if(mob.control_object) - if(!msg) - return - for (var/mob/V in hearers(mob.control_object)) - V.show_message("[mob.control_object.name] says: \"" + msg + "\"", 2) - feedback_add_details("admin_verb","OT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/readmin_self() - set name = "Re-admin self" - set category = "Admin" - - if(deadmin_holder) - deadmin_holder.reassociate() - log_admin("[src] re-admined themself.") - message_admins("[src] re-admined themself.") - to_chat(src, "You now have the keys to control the planet, or at least a small space station.") - verbs -= /client/proc/readmin_self - feedback_add_details("admin_verb","RAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/deadmin_self() - set name = "De-admin self" - set category = "Admin" - - if(holder) - if(alert("Confirm self-deadmin for the round?",,"Yes","No") == "Yes") - log_admin("[src] deadmined themself.") - message_admins("[src] deadmined themself.") - deadmin() - to_chat(src, "You are now a normal player.") - verbs += /client/proc/readmin_self - 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() - -/client/proc/change_security_level() - set name = "Set security level" - set desc = "Sets the station security level." - set category = "Admin" - - if(!check_rights(R_ADMIN)) - return - var/sec_level = input(usr, "It's currently code [get_security_level()].", "Select Security Level") as null|anything in (list("green","blue","red","delta")-get_security_level()) - if(alert("Switch from code [get_security_level()] to code [sec_level]?","Change security level?","Yes","No") == "Yes") - set_security_level(sec_level) - log_admin("[key_name(usr)] changed the security level to code [sec_level].") - - -//---- 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 human_list) - set name = "Edit Appearance" - set category = "Fun" - - if(!check_rights(R_FUN)) - return - - if(!istype(M, /mob/living/carbon/human)) - to_chat(usr, "\red 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_skin = input("Please select body color. This is for Tajaran, Unathi, and Skrell only!", "Character Generation") as color - if(new_skin) - M.r_skin = hex2num(copytext(new_skin, 2, 4)) - M.g_skin = hex2num(copytext(new_skin, 4, 6)) - M.b_skin = hex2num(copytext(new_skin, 6, 8)) - - var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text - - if (new_tone) - 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.gender = MALE - else - M.gender = 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 SSjob.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) - SSjob.FreeRole(job) - return - -/client/proc/toggleattacklogs() - set name = "Toggle Attack Log Messages" - set category = "Preferences" - - prefs.chat_toggles ^= CHAT_ATTACKLOGS - if (prefs.chat_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/toggleghostwriters() - set name = "Toggle ghost writers" - set category = "Server" - if(!holder) return - if(config) - if(config.cult_ghostwriter) - config.cult_ghostwriter = 0 - to_chat(src, "Disallowed ghost writers.") - message_admins("Admin [key_name_admin(usr)] has disabled ghost writers.") - else - config.cult_ghostwriter = 1 - to_chat(src, "Enabled ghost writers.") - message_admins("Admin [key_name_admin(usr)] has enabled ghost writers.") - -/client/proc/toggledrones() - set name = "Toggle maintenance drones" - set category = "Server" - if(!holder) return - if(config) - if(config.allow_drone_spawn) - config.allow_drone_spawn = 0 - to_chat(src, "Disallowed maint drones.") - message_admins("Admin [key_name_admin(usr)] has disabled maint drones.") - else - config.allow_drone_spawn = 1 - to_chat(src, "Enabled maint drones.") - message_admins("Admin [key_name_admin(usr)] has enabled maint drones.") - -/client/proc/toggledebuglogs() - set name = "Toggle Debug Log Messages" - set category = "Preferences" - - prefs.chat_toggles ^= CHAT_DEBUGLOGS - if (prefs.chat_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 player_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.") - T << 'sound/voice/ManUp1.ogg' - - log_admin("[key_name(usr)] told [key_name(T)] to man up and deal with it.") - message_admins("\blue [key_name_admin(usr)] told [key_name(T)] to man up and deal with it.") - -/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 player_list) - to_chat(T, "
                    Man up.
                    Deal with it.

                    Move on.

                    ") - T << 'sound/voice/ManUp1.ogg' - - log_admin("[key_name(usr)] told everyone to man up and deal with it.") - message_admins("\blue [key_name_admin(usr)] told everyone to man up and deal with it.") - -/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") in player_list - var/name = sanitize(input("What will you call your achievement?", "Achievement Winner", "New Achievement")) - var/desc = sanitize(input("What description will you give it?", "Achievement Description", "You Win")) - - if(istype(winner, /mob/living)) - achoice = alert("Give our winner his own trophy?","Achievement Trophy", "Confirm","Cancel") - - 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 - winner.put_in_hands(C) - winner.update_icons() - else - to_chat(winner, "You win [name]! [desc]") - - var/icon/cup = icon('icons/obj/drinks.dmi', "golden_cup") - - if(glob == "No!") - winner.client << sound('sound/misc/achievement.ogg') - else - world << sound('sound/misc/achievement.ogg') - to_chat(world, "[bicon(cup)] [winner.name] wins \"[name]\"!") - - to_chat(winner, "Congratulations!") - - achievements += "[winner.key] as [winner.name] won \"[name]\"! \"[desc]\"" - -/client/proc/aooc() - set category = "Admin" - set name = "Antag OOC" - - if(!check_rights(R_ADMIN)) - return - - var/msg = sanitize(input(usr, "", "Antag OOC") as text) - if(!msg) return - - var/display_name = src.key - if(holder && holder.fakekey) - display_name = holder.fakekey - - for(var/mob/M in player_list) - if((M.mind && M.mind.special_role) || (M.client && M.client.holder)) - to_chat(M, "Antag-OOC: [display_name]: [msg]") - - log_ooc("Antag-OOC: [key] : [msg]") - -/client/proc/toggle_AI_interact() - set name = "Toggle Admin AI Interact" - set category = "Fun" - set desc = "Allows you to interact with most machines as an AI would as a ghost" - - AI_Interact = !AI_Interact - machine_interactive_ghost = AI_Interact - log_admin("[key_name(usr)] has [AI_Interact ? "activated" : "deactivated"] Admin AI Interact") - message_admins("[key_name_admin(usr)] has [AI_Interact ? "activated" : "deactivated"] their AI interaction") - -////////////////////////////// -// Map loader -////////////////////////////// - -/client/proc/event_map_loader() - set category = "Event" - set name = "Event map loader" - if(!check_rights(R_EVENT)) - return - - var/list/AllowedMaps = list() - - var/list/Lines = file2list("maps/event_map_list.txt") - if(!Lines.len) return - 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 - if (pos) - // No, don't do lowertext here, that breaks paths on linux - name = copytext(t, 1, pos) - // value = copytext(t, pos + 1) - else - // No, don't do lowertext here, that breaks paths on linux - name = t - if (!name) - continue - - AllowedMaps.Add(name) - - - AllowedMaps += "--CANCEL--" - - var/choice = input("Select a map", , "CANCEL") in AllowedMaps - if(choice == "--CANCEL--") return - - message_admins("[key_name_admin(src)] started loading event-map [choice]") - log_admin("[key_name_admin(src)] started loading event-map [choice]") - - if(maploader.load_new_z_level(choice))//, load_speed = 100) - message_admins("[key_name_admin(src)] loaded event-map [choice], zlevel [world.maxz]") - log_admin("[key_name_admin(src)] loaded event-map [choice], zlevel [world.maxz]") - else - message_admins("[key_name_admin(src)] failed to load event-map [choice].") - -////////////////////////////// -// Noir event -////////////////////////////// -/* -/client/proc/Noir_anomaly() - set category = "Event" - set name = "Noir event(in dev!)" - if(!check_rights(R_PERMISSIONS)) return - - if(alert("Are you really sure?",,"Yes","No") != "Yes") - return - - for(var/atom/O in not_world) - if(O.icon) - if(O.color) - O.color = null - - var/icon/newIcon = icon(O.icon) - newIcon.GrayScale() - O.icon = newIcon - - log_admin("[key_name(src)] started noir event!", 1) - message_admins("\blue [key_name_admin(src)] started noir event!", 1) -*/ -////////////////////////////// -// Gateway -////////////////////////////// - -/client/proc/gateway_toggle() - set category = "Event" - set name = "Toggle Station Gateway" - - if(!check_rights(R_FUN)) - return - - config.gateway_enabled = !config.gateway_enabled - - log_admin("[key_name(src)] toggle [config.gateway_enabled ? "on" : "off"] station gateway") - message_admins("[key_name(src)] toggle [config.gateway_enabled ? "on" : "off"] station gateway") - -////////////////////////////// -// Velocity\Centcomm barriers -////////////////////////////// -var/centcom_barriers_stat = 1 - -/client/proc/centcom_barriers_toggle() - set category = "Event" - set name = "Centcom Barriers Toggle" - - centcom_barriers_stat = !centcom_barriers_stat - - if(!check_rights(R_FUN)) - return - - for(var/obj/effect/landmark/trololo/L in landmarks_list) - L.active = centcom_barriers_stat - for(var/obj/structure/centcom_barrier/B in centcom_barrier_list) - B.density = centcom_barriers_stat - - log_admin("[key_name(src)] switched [centcom_barriers_stat? "on" : "off"] centcomm barriers") - message_admins("\blue [key_name_admin(src)] switched [centcom_barriers_stat? "on" : "off"] centcomm barriers") - -/obj/effect/landmark/trololo - name = "Rickroll" - //var/melody = 'sound/Never_Gonna_Give_You_Up.ogg' //NOPE - var/message = "\blue It's not the door you're looking for..." - var/active = 1 - var/lchannel = 999 - -/obj/effect/landmark/trololo/Crossed(mob/M) - if(!active) return - /*if(istype(M, /mob/living/carbon)) - M << sound(melody,0,1,lchannel,20)*/ - -/obj/structure/centcom_barrier - name = "Invisible wall" - anchored = 1 - density = 1 - invisibility = 101 - icon = 'icons/mob/screen1.dmi' - icon_state = "x3" - -/obj/structure/centcom_barrier/atom_init() - . = ..() - centcom_barrier_list += src - -/obj/structure/centcom_barrier/Destroy() - centcom_barrier_list -= src - return ..() +//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( + /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/cmd_mentor_check_new_players, + /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/ + /client/proc/player_panel, + /client/proc/debug_variables /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/ + ) +var/list/admin_verbs_admin = list( + /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/getserverlog, /*allows us to fetch server logs (diary) for other days*/ + /client/proc/get_whitelist, //Whitelist + /client/proc/add_to_whitelist, + /datum/admins/proc/whitelist_panel, + /datum/admins/proc/customitems_panel, + /datum/admins/proc/customitemspremoderation_panel, + /datum/admins/proc/library_recycle_bin, + /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_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/check_antagonists, + /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, + /datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/ + /datum/admins/proc/togglelooc, /*toggles looc on/off for everyone*/ + /datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/ + /datum/admins/proc/toggledsay, /*toggles dsay on/off for everyone*/ + /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, + /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/toggleghostwriters, + /client/proc/toggledrones, + /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 */ + /client/proc/aooc, + /client/proc/change_security_level, + /client/proc/empty_ai_core_toggle_latejoin, + /client/proc/send_fax_message + ) +var/list/admin_verbs_ban = list( + /client/proc/unban_panel +// /client/proc/stickybanpanel, + ) +var/list/admin_verbs_sounds = list( + /client/proc/play_local_sound, + /client/proc/play_server_sound, + /client/proc/play_sound, + /client/proc/stop_server_sound + ) +var/list/admin_verbs_fun = list( + /client/proc/object_talk, + /client/proc/cmd_admin_dress, + /client/proc/cmd_admin_gib_self, + /client/proc/drop_bomb, + /client/proc/everyone_random, + /client/proc/one_click_antag, + /datum/admins/proc/toggle_aliens, + /datum/admins/proc/toggle_space_ninja, + /client/proc/send_space_ninja, + /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_global_ooc, + /client/proc/editappear, + /client/proc/roll_dices, + /client/proc/epileptic_anomaly, +// /client/proc/Noir_anomaly, + /client/proc/epileptic_anomaly_cancel, + /client/proc/achievement, + /client/proc/toggle_AI_interact, /*toggle admin ability to interact with machines as an AI*/ + /client/proc/centcom_barriers_toggle, + /client/proc/gateway_toggle + ) +var/list/admin_verbs_spawn = list( + /datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ + /client/proc/respawn_character, + /datum/admins/proc/spawn_fluid_verb + ) +var/list/admin_verbs_server = list( + /client/proc/Set_Holiday, + /datum/admins/proc/startnow, + /datum/admins/proc/restart, + /datum/admins/proc/delay, + /datum/admins/proc/delay_end, + /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, + /datum/admins/proc/toggle_space_ninja, + /client/proc/toggle_random_events, + /client/proc/nanomapgen_DumpImage + ) +var/list/admin_verbs_debug = list( + /client/proc/restart_controller, + /client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/ + /client/proc/cmd_admin_list_open_jobs, + /client/proc/Debug2, + /client/proc/ZASSettings, + /client/proc/cmd_debug_make_powernets, + /client/proc/cmd_debug_load_junkyard, + /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/cmd_debug_tog_vcounter, + /client/proc/cmd_message_spam_control, + /client/proc/investigate_show, + /client/proc/reload_admins, + /client/proc/reload_mentors, + /client/proc/reload_nanoui_resources, +// /client/proc/remake_distribution_map, +// /client/proc/show_distribution_map, + /client/proc/enable_debug_verbs, + /*/client/proc/callproc,*/ +// /proc/machine_upgrade, + /client/proc/toggledebuglogs, + /client/proc/view_runtimes, + /client/proc/cmd_display_del_log, + /client/proc/cmd_display_init_log + ) +var/list/admin_verbs_possess = list( + /proc/possess, + /proc/release + ) +var/list/admin_verbs_permissions = list( + /client/proc/edit_admin_permissions, + /client/proc/gsw_add, + /client/proc/library_debug_remove, + /client/proc/library_debug_read + ) +var/list/admin_verbs_rejuv = list( + /client/proc/respawn_character + ) +var/list/admin_verbs_whitelist = list( + /client/proc/get_whitelist, //Whitelist + /client/proc/add_to_whitelist, + /datum/admins/proc/whitelist_panel, + /datum/admins/proc/toggle_job_restriction + ) +var/list/admin_verbs_event = list( + /client/proc/event_map_loader + ) + +//verbs which can be hidden - needs work +var/list/admin_verbs_hideable = list( + /client/proc/set_global_ooc, + /datum/admins/proc/library_recycle_bin, + /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/get_whitelist, //Whitelist + /client/proc/add_to_whitelist, + /datum/admins/proc/whitelist_panel, + /client/proc/gsw_add, + /datum/admins/proc/toggle_aliens, + /datum/admins/proc/toggle_space_ninja, + /client/proc/send_space_ninja, + /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, + /datum/admins/proc/startnow, + /datum/admins/proc/restart, + /datum/admins/proc/delay, + /datum/admins/proc/delay_end, + /datum/admins/proc/toggleaban, + /client/proc/toggle_log_hrefs, + /datum/admins/proc/immreboot, + /client/proc/everyone_random, + /datum/admins/proc/toggleAI, + /client/proc/restart_controller, + /datum/admins/proc/adrev, + /datum/admins/proc/adspawn, + /datum/admins/proc/adjump, + /client/proc/cmd_admin_list_open_jobs, + /*/client/proc/callproc,*/ + /client/proc/Debug2, + /client/proc/reload_admins, + /client/proc/cmd_debug_make_powernets, + /client/proc/startSinglo, + /client/proc/cmd_debug_mob_lists, + /client/proc/cmd_debug_del_all, + /client/proc/cmd_debug_tog_aliens, + /client/proc/cmd_debug_tog_vcounter, + /client/proc/enable_debug_verbs, + /proc/possess, + /proc/release + ) + +/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_WHITELIST) + verbs += admin_verbs_whitelist + if(holder.rights & R_EVENT) + verbs += admin_verbs_event + + if(holder.rights & R_ADMIN) + control_freak = CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS + +/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_event, + /*Debug verbs added by "show debug verbs"*/ + /client/proc/Cell, + /client/proc/do_not_use_these, + /client/proc/camera_view, + /client/proc/sec_camera_report, + /client/proc/intercom_view, + /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/startSinglo, + /client/proc/set_fps, + /client/proc/cmd_admin_grantfullaccess, + /client/proc/splash, + /client/proc/cmd_admin_areatest + ) + +/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 = TRUE + 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(isnewplayer(mob)) + to_chat(src, "Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.") + else + //ghostize + var/mob/body = mob + body.ghostize(can_reenter_corpse = TRUE) + 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, "\red Invisimin off. Invisibility reset.") + mob.alpha = max(mob.alpha + 100, 255) + else + mob.invisibility = INVISIBILITY_OBSERVER + to_chat(mob, "\blue Invisimin on. You are now as invisible as a ghost.") + mob.alpha = max(mob.alpha - 100, 0) + + +/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/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 = "OOC" + set name = "Set Admin OOC Color" + if(!holder) + return + if(!config.allow_admin_ooccolor) + to_chat(usr, "Currently disabled by config.") + var/new_aooccolor = input(src, "Please select your OOC colour.", "OOC colour") as color|null + if(new_aooccolor) + prefs.aooccolor = new_aooccolor + prefs.save_preferences() + 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 + mob.invisibility = initial(mob.invisibility) + mob.alpha = 127//initial(mob.alpha) + mob.name = initial(mob.name) + 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 + mob.invisibility = INVISIBILITY_MAXIMUM + 1 //JUST IN CASE + mob.alpha = 0 //JUUUUST IN CASE + mob.name = " " + 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"]") + feedback_add_details("admin_verb","SM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/warn(warned_ckey) + if(!check_rights(R_ADMIN)) + return + + warned_ckey = ckey(warned_ckey) + + var/reason = input(usr, "Reason?", "Warn Reason","") as text|null + + if(!warned_ckey || !reason) + return + + notes_add(warned_ckey, "ADMINWARN: " + reason, src) + + var/client/C = directory[warned_ckey] + reason = sanitize(reason) + + if(C) + to_chat(C, "You have been formally warned by an administrator.
                    Reason: [reason].
                    ") + + log_admin("[src.key] has warned [warned_ckey] with reason: [reason]") + message_admins("[key_name_admin(src)] has warned [C ? key_name_admin(C) : warned_ckey] with reason: [reason].") + + feedback_add_details("admin_verb","WARN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/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", "Medium Bomb", "Big Bomb", "Custom Bomb", "Cancel") + var/choice = input("What size explosion would you like to produce?") in choices + switch(choice) + if(null) + return 0 + if("Small Bomb") + explosion(epicenter, 1, 2, 3, 3) + if("Medium Bomb") + explosion(epicenter, 2, 3, 4, 4) + if("Big Bomb") + 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) + if("Cancel") + return 0 + log_admin("[ckey] creating an admin explosion at [epicenter.loc].") + message_admins("\blue [ckey] creating an admin explosion at [epicenter.loc].") + feedback_add_details("admin_verb","DB") //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/list/spell_names = list() + for(var/v in spells) + // "/obj/effect/proc_holder/spell/" 30 symbols ~Intercross21 + spell_names.Add(copytext("[v]", 31, 0)) + var/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spell_names + if(!S) return + var/path = text2path("/obj/effect/proc_holder/spell/[S]") + T.AddSpell(new path) + feedback_add_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].") + message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the spell [S].") + +/client/proc/give_disease(mob/T as mob in mob_list) // -- Giacom + set category = "Fun" + set name = "Give Disease (old)" + set desc = "Gives a (tg-style) Disease to a mob." + var/list/disease_names = list() + for(var/v in diseases) + // "/datum/disease/" 15 symbols ~Intercross + disease_names.Add(copytext("[v]", 16, 0)) + var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in disease_names + if(!D) return + var/path = text2path("/datum/disease/[D]") + T.contract_disease(new path, 1) + feedback_add_details("admin_verb","GD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] gave [key_name(T)] the disease [D].") + message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the disease [D].") + +/client/proc/give_disease2(mob/T as mob in mob_list) // -- Giacom + set category = "Fun" + set name = "Give Disease" + set desc = "Gives a Disease to a mob." + + var/datum/disease2/disease/D = new /datum/disease2/disease() + + var/disease_type = input("Is this a lesser or greater disease?", "Give Disease") in list("Lesser", "Greater", "Custom") + var/greater = (disease_type == "Greater") + + if(disease_type == "Custom") + D.uniqueID = rand(0,10000) + D.antigen |= text2num(pick(ANTIGENS)) + D.antigen |= text2num(pick(ANTIGENS)) + + var/list/datum/disease2/effect/possible_effects = list() + for(var/e in subtypesof(/datum/disease2/effect)) + var/datum/disease2/effect/f = new e + if (f.level > 4) //we don't want such strong effects + continue + if (f.level < 1) + continue + possible_effects += f + + while(TRUE) + var/command = input("Disease menu, ([D.effects.len] symptoms)", "Make custom disease") in list("Add symptom", "Remove symptom", "Done") + if(command == "Add symptom" && D.effects.len < D.max_symptoms) + if(!possible_effects.len) + continue + var/effect = input("Add symptom", "Select symptom") as null|anything in possible_effects + if(!effect) + continue + possible_effects -= effect + var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder + holder.effect = effect + holder.name = holder.effect.name + holder.chance = rand(holder.effect.chance_minm, holder.effect.chance_maxm) + D.addeffect(holder) + if(command == "Remove symptom" && D.effects.len > 0) + var/datum/disease2/effectholder/holder = input("Remove symptom", "Select symptom to remove") as null|anything in D.effects + if(!holder) + continue + possible_effects += holder.effect + D.effects -= holder + qdel(holder) + + if(command == "Done") + break + disease_type = "[disease_type] ([jointext(D.effects, ", ")])" + else + D.makerandom(greater) + if (!greater) + D.infectionchance = 1 + + D.infectionchance = input("How virulent is this disease? (1-100)", "Give Disease", D.infectionchance) as num + + infect_virus2(T,D,1) + + feedback_add_details("admin_verb","GD2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] gave [key_name(T)] a [disease_type] disease2 with infection chance [D.infectionchance].") + message_admins("[key_name_admin(usr)] gave [key_name(T)] a [disease_type] disease2 with infection chance [D.infectionchance].") + +/* disabled because this is not a sound but a hearable message, and also very hard to use since you need to choose an item from a huge list and not a view at least. + so, this proc needs rewrite to be a verb per object or something like that and also better name because it can be named more obvious than using desc. + also "in world" +/client/proc/make_sound(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(O) + var/message = sanitize(input("What do you want the message to be?", "Make Sound") as text|null) + if(!message) + return + for (var/mob/V in hearers(O)) + V.show_message(message, 2) + log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z]. make a sound") + message_admins("\blue [key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z] (JMP) make a sound") + 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(msg as text) // -- TLE + set category = "Special Verbs" + set name = "oSay" + set desc = "Display a message to everyone who can hear the target." + if(mob.control_object) + if(!msg) + return + for (var/mob/V in hearers(mob.control_object)) + V.show_message("[mob.control_object.name] says: \"" + msg + "\"", 2) + feedback_add_details("admin_verb","OT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/readmin_self() + set name = "Re-admin self" + set category = "Admin" + + if(deadmin_holder) + deadmin_holder.reassociate() + log_admin("[src] re-admined themself.") + message_admins("[src] re-admined themself.") + to_chat(src, "You now have the keys to control the planet, or at least a small space station.") + verbs -= /client/proc/readmin_self + feedback_add_details("admin_verb","RAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/deadmin_self() + set name = "De-admin self" + set category = "Admin" + + if(holder) + if(alert("Confirm self-deadmin for the round?",,"Yes","No") == "Yes") + log_admin("[src] deadmined themself.") + message_admins("[src] deadmined themself.") + deadmin() + to_chat(src, "You are now a normal player.") + verbs += /client/proc/readmin_self + 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() + +/client/proc/change_security_level() + set name = "Set security level" + set desc = "Sets the station security level." + set category = "Admin" + + if(!check_rights(R_ADMIN)) + return + var/sec_level = input(usr, "It's currently code [get_security_level()].", "Select Security Level") as null|anything in (list("green","blue","red","delta")-get_security_level()) + if(alert("Switch from code [get_security_level()] to code [sec_level]?","Change security level?","Yes","No") == "Yes") + set_security_level(sec_level) + log_admin("[key_name(usr)] changed the security level to code [sec_level].") + + +//---- 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 human_list) + set name = "Edit Appearance" + set category = "Fun" + + if(!check_rights(R_FUN)) + return + + if(!istype(M, /mob/living/carbon/human)) + to_chat(usr, "\red 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_skin = input("Please select body color. This is for Tajaran, Unathi, and Skrell only!", "Character Generation") as color + if(new_skin) + M.r_skin = hex2num(copytext(new_skin, 2, 4)) + M.g_skin = hex2num(copytext(new_skin, 4, 6)) + M.b_skin = hex2num(copytext(new_skin, 6, 8)) + + var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as text + + if (new_tone) + 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.gender = MALE + else + M.gender = 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 SSjob.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) + SSjob.FreeRole(job) + return + +/client/proc/toggleattacklogs() + set name = "Toggle Attack Log Messages" + set category = "Preferences" + + prefs.chat_toggles ^= CHAT_ATTACKLOGS + if (prefs.chat_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/toggleghostwriters() + set name = "Toggle ghost writers" + set category = "Server" + if(!holder) return + if(config) + if(config.cult_ghostwriter) + config.cult_ghostwriter = 0 + to_chat(src, "Disallowed ghost writers.") + message_admins("Admin [key_name_admin(usr)] has disabled ghost writers.") + else + config.cult_ghostwriter = 1 + to_chat(src, "Enabled ghost writers.") + message_admins("Admin [key_name_admin(usr)] has enabled ghost writers.") + +/client/proc/toggledrones() + set name = "Toggle maintenance drones" + set category = "Server" + if(!holder) return + if(config) + if(config.allow_drone_spawn) + config.allow_drone_spawn = 0 + to_chat(src, "Disallowed maint drones.") + message_admins("Admin [key_name_admin(usr)] has disabled maint drones.") + else + config.allow_drone_spawn = 1 + to_chat(src, "Enabled maint drones.") + message_admins("Admin [key_name_admin(usr)] has enabled maint drones.") + +/client/proc/toggledebuglogs() + set name = "Toggle Debug Log Messages" + set category = "Preferences" + + prefs.chat_toggles ^= CHAT_DEBUGLOGS + if (prefs.chat_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 player_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.") + T << 'sound/voice/ManUp1.ogg' + + log_admin("[key_name(usr)] told [key_name(T)] to man up and deal with it.") + message_admins("\blue [key_name_admin(usr)] told [key_name(T)] to man up and deal with it.") + +/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 player_list) + to_chat(T, "
                    Man up.
                    Deal with it.

                    Move on.

                    ") + T << 'sound/voice/ManUp1.ogg' + + log_admin("[key_name(usr)] told everyone to man up and deal with it.") + message_admins("\blue [key_name_admin(usr)] told everyone to man up and deal with it.") + +/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") in player_list + var/name = sanitize(input("What will you call your achievement?", "Achievement Winner", "New Achievement")) + var/desc = sanitize(input("What description will you give it?", "Achievement Description", "You Win")) + + if(istype(winner, /mob/living)) + achoice = alert("Give our winner his own trophy?","Achievement Trophy", "Confirm","Cancel") + + 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 + winner.put_in_hands(C) + winner.update_icons() + else + to_chat(winner, "You win [name]! [desc]") + + var/icon/cup = icon('icons/obj/drinks.dmi', "golden_cup") + + if(glob == "No!") + winner.client << sound('sound/misc/achievement.ogg') + else + world << sound('sound/misc/achievement.ogg') + to_chat(world, "[bicon(cup)] [winner.name] wins \"[name]\"!") + + to_chat(winner, "Congratulations!") + + achievements += "[winner.key] as [winner.name] won \"[name]\"! \"[desc]\"" + +/client/proc/aooc() + set category = "Admin" + set name = "Antag OOC" + + if(!check_rights(R_ADMIN)) + return + + var/msg = sanitize(input(usr, "", "Antag OOC") as text) + if(!msg) return + + var/display_name = src.key + if(holder && holder.fakekey) + display_name = holder.fakekey + + for(var/mob/M in player_list) + if((M.mind && M.mind.special_role) || (M.client && M.client.holder)) + to_chat(M, "Antag-OOC: [display_name]: [msg]") + + log_ooc("Antag-OOC: [key] : [msg]") + +/client/proc/toggle_AI_interact() + set name = "Toggle Admin AI Interact" + set category = "Fun" + set desc = "Allows you to interact with most machines as an AI would as a ghost" + + AI_Interact = !AI_Interact + machine_interactive_ghost = AI_Interact + log_admin("[key_name(usr)] has [AI_Interact ? "activated" : "deactivated"] Admin AI Interact") + message_admins("[key_name_admin(usr)] has [AI_Interact ? "activated" : "deactivated"] their AI interaction") + +////////////////////////////// +// Map loader +////////////////////////////// + +/client/proc/event_map_loader() + set category = "Event" + set name = "Event map loader" + if(!check_rights(R_EVENT)) + return + + var/list/AllowedMaps = list() + + var/list/Lines = file2list("maps/event_map_list.txt") + if(!Lines.len) return + 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 + if (pos) + // No, don't do lowertext here, that breaks paths on linux + name = copytext(t, 1, pos) + // value = copytext(t, pos + 1) + else + // No, don't do lowertext here, that breaks paths on linux + name = t + if (!name) + continue + + AllowedMaps.Add(name) + + + AllowedMaps += "--CANCEL--" + + var/choice = input("Select a map", , "CANCEL") in AllowedMaps + if(choice == "--CANCEL--") return + + message_admins("[key_name_admin(src)] started loading event-map [choice]") + log_admin("[key_name_admin(src)] started loading event-map [choice]") + + if(maploader.load_new_z_level(choice))//, load_speed = 100) + message_admins("[key_name_admin(src)] loaded event-map [choice], zlevel [world.maxz]") + log_admin("[key_name_admin(src)] loaded event-map [choice], zlevel [world.maxz]") + else + message_admins("[key_name_admin(src)] failed to load event-map [choice].") + +////////////////////////////// +// Noir event +////////////////////////////// +/* +/client/proc/Noir_anomaly() + set category = "Event" + set name = "Noir event(in dev!)" + if(!check_rights(R_PERMISSIONS)) return + + if(alert("Are you really sure?",,"Yes","No") != "Yes") + return + + for(var/atom/O in not_world) + if(O.icon) + if(O.color) + O.color = null + + var/icon/newIcon = icon(O.icon) + newIcon.GrayScale() + O.icon = newIcon + + log_admin("[key_name(src)] started noir event!", 1) + message_admins("\blue [key_name_admin(src)] started noir event!", 1) +*/ +////////////////////////////// +// Gateway +////////////////////////////// + +/client/proc/gateway_toggle() + set category = "Event" + set name = "Toggle Station Gateway" + + if(!check_rights(R_FUN)) + return + + config.gateway_enabled = !config.gateway_enabled + + log_admin("[key_name(src)] toggle [config.gateway_enabled ? "on" : "off"] station gateway") + message_admins("[key_name(src)] toggle [config.gateway_enabled ? "on" : "off"] station gateway") + +////////////////////////////// +// Velocity\Centcomm barriers +////////////////////////////// +var/centcom_barriers_stat = 1 + +/client/proc/centcom_barriers_toggle() + set category = "Event" + set name = "Centcom Barriers Toggle" + + centcom_barriers_stat = !centcom_barriers_stat + + if(!check_rights(R_FUN)) + return + + for(var/obj/effect/landmark/trololo/L in landmarks_list) + L.active = centcom_barriers_stat + for(var/obj/structure/centcom_barrier/B in centcom_barrier_list) + B.density = centcom_barriers_stat + + log_admin("[key_name(src)] switched [centcom_barriers_stat? "on" : "off"] centcomm barriers") + message_admins("\blue [key_name_admin(src)] switched [centcom_barriers_stat? "on" : "off"] centcomm barriers") + +/obj/effect/landmark/trololo + name = "Rickroll" + //var/melody = 'sound/Never_Gonna_Give_You_Up.ogg' //NOPE + var/message = "\blue It's not the door you're looking for..." + var/active = 1 + var/lchannel = 999 + +/obj/effect/landmark/trololo/Crossed(mob/M) + if(!active) return + /*if(istype(M, /mob/living/carbon)) + M << sound(melody,0,1,lchannel,20)*/ + +/obj/structure/centcom_barrier + name = "Invisible wall" + anchored = 1 + density = 1 + invisibility = 101 + icon = 'icons/mob/screen1.dmi' + icon_state = "x3" + +/obj/structure/centcom_barrier/atom_init() + . = ..() + centcom_barrier_list += src + +/obj/structure/centcom_barrier/Destroy() + centcom_barrier_list -= src + return ..() diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index 8aaa014baea9..57076a6bc14b 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -1,37 +1,37 @@ -//returns a reason if M is banned from rank, returns 0 otherwise -/proc/jobban_isbanned(mob/M, rank) - if(!M || !istype(M) || !M.ckey) - return 0 - - if(!M.client) //no cache. fallback to a DBQuery - var/DBQuery/query = dbcon.NewQuery("SELECT reason FROM erro_ban WHERE ckey = '[sanitize_sql(M.ckey)]' AND job = '[sanitize_sql(rank)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") - if(!query.Execute()) - log_game("SQL ERROR obtaining jobbans. Error : \[[query.ErrorMsg()]\]\n") - return - if(query.NextRow()) - var/reason = query.item[1] - return reason ? reason : 1 //we don't want to return "" if there is no ban reason, as that would evaluate to false - else - return 0 - - if(!M.client.jobbancache) - jobban_buildcache(M.client) - - if(rank in M.client.jobbancache) - var/reason = M.client.jobbancache[rank] - return (reason) ? reason : 1 //see above for why we need to do this - - return 0 - -/proc/jobban_buildcache(client/C) - if(C && istype(C)) - C.jobbancache = list() - var/DBQuery/query = dbcon.NewQuery("SELECT job, reason FROM erro_ban WHERE ckey = '[sanitize_sql(C.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") - if(!query.Execute()) - log_game("SQL ERROR obtaining jobbans. Error : \[[query.ErrorMsg()]\]\n") - return - while(query.NextRow()) - C.jobbancache[query.item[1]] = query.item[2] - -/proc/ban_unban_log_save(formatted_log) - text2file(formatted_log,"data/ban_unban_log.txt") +//returns a reason if M is banned from rank, returns 0 otherwise +/proc/jobban_isbanned(mob/M, rank) + if(!M || !istype(M) || !M.ckey) + return 0 + + if(!M.client) //no cache. fallback to a DBQuery + var/DBQuery/query = dbcon.NewQuery("SELECT reason FROM erro_ban WHERE ckey = '[sanitize_sql(M.ckey)]' AND job = '[sanitize_sql(rank)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") + if(!query.Execute()) + log_game("SQL ERROR obtaining jobbans. Error : \[[query.ErrorMsg()]\]\n") + return + if(query.NextRow()) + var/reason = query.item[1] + return reason ? reason : 1 //we don't want to return "" if there is no ban reason, as that would evaluate to false + else + return 0 + + if(!M.client.jobbancache) + jobban_buildcache(M.client) + + if(rank in M.client.jobbancache) + var/reason = M.client.jobbancache[rank] + return (reason) ? reason : 1 //see above for why we need to do this + + return 0 + +/proc/jobban_buildcache(client/C) + if(C && istype(C)) + C.jobbancache = list() + var/DBQuery/query = dbcon.NewQuery("SELECT job, reason FROM erro_ban WHERE ckey = '[sanitize_sql(C.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") + if(!query.Execute()) + log_game("SQL ERROR obtaining jobbans. Error : \[[query.ErrorMsg()]\]\n") + return + while(query.NextRow()) + C.jobbancache[query.item[1]] = query.item[2] + +/proc/ban_unban_log_save(formatted_log) + text2file(formatted_log,"data/ban_unban_log.txt") diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index 1d6fb69259ef..ca8124f48285 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(mob/user) - if (!create_mob_html) - var/mobjs = null - mobjs = jointext(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=425x475") +/var/create_mob_html = null +/datum/admins/proc/create_mob(mob/user) + if (!create_mob_html) + var/mobjs = null + mobjs = jointext(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=425x475") diff --git a/code/modules/admin/create_object.dm b/code/modules/admin/create_object.dm index 8ce343a93292..f0188193c6a5 100644 --- a/code/modules/admin/create_object.dm +++ b/code/modules/admin/create_object.dm @@ -1,27 +1,27 @@ -var/create_object_html = null -var/list/create_object_forms = list( - /obj, /obj/structure, /obj/machinery, /obj/effect, - /obj/item, /obj/item/clothing, /obj/item/stack, /obj/item/device, - /obj/item/weapon, /obj/item/weapon/reagent_containers, /obj/item/weapon/gun) - -/datum/admins/proc/create_object(mob/user) - if (!create_object_html) - var/objectjs = null - objectjs = jointext(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(mob/user) - var/path = input("Select the path of the object you wish to create.", "Path", /obj) in create_object_forms - var/html_form = create_object_forms[path] - - if (!html_form) - var/objectjs = jointext(typesof(path), ";") - html_form = file2text('html/create_object.html') - html_form = replacetext(html_form, "null /* object types */", "\"[objectjs]\"") - create_object_forms[path] = html_form - - user << browse(replacetext(html_form, "/* ref src */", "\ref[src]"), "window=qco[path];size=425x475") +var/create_object_html = null +var/list/create_object_forms = list( + /obj, /obj/structure, /obj/machinery, /obj/effect, + /obj/item, /obj/item/clothing, /obj/item/stack, /obj/item/device, + /obj/item/weapon, /obj/item/weapon/reagent_containers, /obj/item/weapon/gun) + +/datum/admins/proc/create_object(mob/user) + if (!create_object_html) + var/objectjs = null + objectjs = jointext(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(mob/user) + var/path = input("Select the path of the object you wish to create.", "Path", /obj) in create_object_forms + var/html_form = create_object_forms[path] + + if (!html_form) + var/objectjs = jointext(typesof(path), ";") + html_form = file2text('html/create_object.html') + html_form = replacetext(html_form, "null /* object types */", "\"[objectjs]\"") + create_object_forms[path] = html_form + + user << browse(replacetext(html_form, "/* ref src */", "\ref[src]"), "window=qco[path];size=425x475") diff --git a/code/modules/admin/create_turf.dm b/code/modules/admin/create_turf.dm index 4bfa6a0a09da..15abae34b37c 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(mob/user) - if (!create_turf_html) - var/turfjs = null - turfjs = jointext(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(mob/user) + if (!create_turf_html) + var/turfjs = null + turfjs = jointext(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 65a2e8dde193..cb13286e6117 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -1,104 +1,104 @@ -var/list/admin_datums = list() - -/datum/admins - var/rank = "Temporary Admin" - var/client/owner = null - var/rights = 0 - var/fakekey = null - var/deadminned = FALSE - - 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 - -/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") - qdel(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 - -/datum/admins/proc/disassociate() - if(owner) - admins -= owner - owner.remove_admin_verbs() - owner.deadmin_holder = owner.holder - owner.holder = null - deadminned = TRUE - -/datum/admins/proc/reassociate() - if(owner) - admins += owner - owner.holder = src - owner.deadmin_holder = null - deadminned = FALSE - owner.add_admin_verbs() - -/* -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.holder.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) - to_chat(usr, "Error: You are not an admin.") - 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 - -//This proc checks whether subject has at least ONE of the rights specified in rights_required. -/proc/check_rights_for(client/subject, rights_required) - if(subject && subject.holder) - if(rights_required && !(rights_required & subject.holder.rights)) - return FALSE - return TRUE - return FALSE - -/client/proc/deadmin() - if(holder) - holder.disassociate() - //qdel(holder) - return 1 +var/list/admin_datums = list() + +/datum/admins + var/rank = "Temporary Admin" + var/client/owner = null + var/rights = 0 + var/fakekey = null + var/deadminned = FALSE + + 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 + +/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") + qdel(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 + +/datum/admins/proc/disassociate() + if(owner) + admins -= owner + owner.remove_admin_verbs() + owner.deadmin_holder = owner.holder + owner.holder = null + deadminned = TRUE + +/datum/admins/proc/reassociate() + if(owner) + admins += owner + owner.holder = src + owner.deadmin_holder = null + deadminned = FALSE + owner.add_admin_verbs() + +/* +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.holder.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) + to_chat(usr, "Error: You are not an admin.") + 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 + +//This proc checks whether subject has at least ONE of the rights specified in rights_required. +/proc/check_rights_for(client/subject, rights_required) + if(subject && subject.holder) + if(rights_required && !(rights_required & subject.holder.rights)) + return FALSE + return TRUE + return FALSE + +/client/proc/deadmin() + if(holder) + holder.disassociate() + //qdel(holder) + return 1 diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm index a89fbd0cc9e9..3e67f503ba61 100644 --- a/code/modules/admin/permissionverbs/permissionedit.dm +++ b/code/modules/admin/permissionverbs/permissionedit.dm @@ -1,325 +1,325 @@ -/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 += "" - output += "" - output += "" - output += "" - - for(var/ment_ckey in mentor_ckeys) - output += "" - output += "" - output += "" - output += "" - output += "" - - output += {" -
                    CKEY \[+\]RANKPERMISSIONS
                    [adm_ckey] \[-\][rank][rights]
                    [ment_ckey] \[-\]Mentor
                    -
                    Search:
                    - -"} - - usr << browse(entity_ja(output),"window=editrights;size=600x500") - -/datum/admins/proc/add_admin() - 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 - var/adm_ckey = ckey(input(usr,"New admin's ckey","Admin ckey", null) as text|null) - if(!adm_ckey) - return - if(adm_ckey in admin_datums) - to_chat(usr, "Error: Topic 'editrights': [adm_ckey] is already an admin") - return - if(adm_ckey in mentor_ckeys) - remove_mentor(adm_ckey) - edit_rank(adm_ckey) - -/datum/admins/proc/remove_admin(adm_ckey) - 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 - if(!adm_ckey) - to_chat(usr, "Error: Topic 'editrights': No valid ckey") - return - var/datum/admins/D = admin_datums[adm_ckey] - if(alert("Are you sure you want to remove [adm_ckey] from admins?","Message","Yes","Cancel") == "Yes") - if(!D) - return - admin_datums -= adm_ckey - D.disassociate() - db_admin_rank_modification(adm_ckey, "Removed") - 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") - -/datum/admins/proc/edit_rank(adm_ckey) - 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 - if(!adm_ckey) - return - var/datum/admins/D = admin_datums[adm_ckey] - 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 = sanitize(input("Please input a new rank", "New custom rank", null, null) as null|text) - if(!new_rank) - to_chat(usr, "Error: Topic 'editrights': Invalid rank") - return - 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 - db_admin_rank_modification(adm_ckey, new_rank) - 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]") - - -/datum/admins/proc/get_new_rights(adm_ckey) - if(!usr.client) - return - if(!adm_ckey) - return - var/datum/admins/D = admin_datums[adm_ckey] - if(!D) - return - var/output = {" - - -Permissions modification panel - - -
                    -Check all needed flags. -
                    -"} - for(var/i=1, i<=R_MAXPERMISSION, i<<=1) - output += {"[rights2text(i)]
                    "} - output += {"
                    -
                    - - -"} - usr << browse(entity_ja(output),"window=change_permissions;size=250x380;") - - -/datum/admins/proc/change_permissions(adm_ckey, new_rights) - 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 - if(!adm_ckey) - return - if(!new_rights) - return - var/datum/admins/D = admin_datums[adm_ckey] - if(!D) - return - var/added_rights = "" - var/removed_rights = "" - for(var/mask = 1, mask <= R_MAXPERMISSION, mask <<= 1) - var/masked_newrights = new_rights & mask - var/masked_oldrights = D.rights & mask - if(masked_newrights == masked_oldrights) - continue - if(masked_newrights) - added_rights += rights2text(mask," ") - else - removed_rights += rights2text(mask," ") - D.rights = new_rights - if(added_rights) - message_admins("[key_name_admin(usr)] added[added_rights] permissions of [adm_ckey]") - log_admin("[key_name(usr)] added[added_rights] permission of [adm_ckey]") - if(removed_rights) - message_admins("[key_name_admin(usr)] removed[removed_rights] permissions of [adm_ckey]") - log_admin("[key_name(usr)] removed[removed_rights] permission of [adm_ckey]") - - establish_db_connection() - if(!dbcon.IsConnected()) - to_chat(usr, "Failed to establish database connection") - return - adm_ckey = ckey(adm_ckey) - if(!istext(adm_ckey) || !isnum(new_rights)) - return - var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'") - select_query.Execute() - var/admin_id - while(select_query.NextRow()) - admin_id = text2num(select_query.item[1]) - if(!admin_id) - return - var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = [new_rights] WHERE id = [admin_id]") - insert_query.Execute() - if(removed_rights) - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission[removed_rights] to admin [adm_ckey]');") - log_query.Execute() - to_chat(usr, "Permissions removed.") - if(added_rights) - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission[added_rights] to admin [adm_ckey]')") - log_query.Execute() - to_chat(usr, "Permissions added.") - -/datum/admins/proc/add_mentor() - 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 - var/ment_ckey = ckey(input(usr,"New mentor's ckey","Mentor ckey", null) as text|null) - if(!ment_ckey) - return - if(ment_ckey in mentor_ckeys) - to_chat(usr, "Error: Topic 'editmentorlist': [ment_ckey] is already a mentor.") - return - if(ment_ckey in admin_datums) - remove_admin(ment_ckey) - mentor_ckeys += ment_ckey - mentors += directory[ment_ckey] - message_admins("[key_name_admin(usr)] added [ment_ckey] to the mentors list") - log_admin("[key_name(usr)] added [ment_ckey] to the mentors list") - - establish_db_connection() - if(!dbcon.IsConnected()) - to_chat(usr, "Failed to establish database connection") - return - ment_ckey = ckey(ment_ckey) - var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO `erro_mentor` (`id`, `ckey`) VALUES (null, '[ment_ckey]');") - insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new mentor [ment_ckey].');") - log_query.Execute() - to_chat(usr, "New mentor added.") - -/datum/admins/proc/remove_mentor(ment_ckey) - 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 - if(!ment_ckey) - to_chat(usr, "Error: Topic 'editmentorlist': [ment_ckey] is not a valid mentor.") - return - if(alert("Are you sure you want to remove [ment_ckey] from mentors?","Message","Yes","Cancel") == "Yes") - mentor_ckeys -= ment_ckey - mentors -= directory[ment_ckey] - message_admins("[key_name_admin(usr)] removed [ment_ckey] from the mentors list") - log_admin("[key_name(usr)] removed [ment_ckey] from the mentors list") - - establish_db_connection() - if(!dbcon.IsConnected()) - to_chat(usr, "Failed to establish database connection") - return - ment_ckey = ckey(ment_ckey) - var/DBQuery/remove_query = dbcon.NewQuery("DELETE FROM `erro_mentor` WHERE `ckey` = '[ment_ckey]';") - remove_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed mentor [ment_ckey].');") - log_query.Execute() - to_chat(usr, "Mentor removed.") - - -/datum/admins/proc/db_admin_rank_modification(adm_ckey, 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()) - 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 `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 `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.") +/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 += "" + output += "" + output += "" + output += "" + + for(var/ment_ckey in mentor_ckeys) + output += "" + output += "" + output += "" + output += "" + output += "" + + output += {" +
                    CKEY \[+\]RANKPERMISSIONS
                    [adm_ckey] \[-\][rank][rights]
                    [ment_ckey] \[-\]Mentor
                    +
                    Search:
                    + +"} + + usr << browse(entity_ja(output),"window=editrights;size=600x500") + +/datum/admins/proc/add_admin() + 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 + var/adm_ckey = ckey(input(usr,"New admin's ckey","Admin ckey", null) as text|null) + if(!adm_ckey) + return + if(adm_ckey in admin_datums) + to_chat(usr, "Error: Topic 'editrights': [adm_ckey] is already an admin") + return + if(adm_ckey in mentor_ckeys) + remove_mentor(adm_ckey) + edit_rank(adm_ckey) + +/datum/admins/proc/remove_admin(adm_ckey) + 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 + if(!adm_ckey) + to_chat(usr, "Error: Topic 'editrights': No valid ckey") + return + var/datum/admins/D = admin_datums[adm_ckey] + if(alert("Are you sure you want to remove [adm_ckey] from admins?","Message","Yes","Cancel") == "Yes") + if(!D) + return + admin_datums -= adm_ckey + D.disassociate() + db_admin_rank_modification(adm_ckey, "Removed") + 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") + +/datum/admins/proc/edit_rank(adm_ckey) + 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 + if(!adm_ckey) + return + var/datum/admins/D = admin_datums[adm_ckey] + 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 = sanitize(input("Please input a new rank", "New custom rank", null, null) as null|text) + if(!new_rank) + to_chat(usr, "Error: Topic 'editrights': Invalid rank") + return + 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 + db_admin_rank_modification(adm_ckey, new_rank) + 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]") + + +/datum/admins/proc/get_new_rights(adm_ckey) + if(!usr.client) + return + if(!adm_ckey) + return + var/datum/admins/D = admin_datums[adm_ckey] + if(!D) + return + var/output = {" + + +Permissions modification panel + + +
                    +Check all needed flags. +
                    +"} + for(var/i=1, i<=R_MAXPERMISSION, i<<=1) + output += {"[rights2text(i)]
                    "} + output += {"
                    +
                    + + +"} + usr << browse(entity_ja(output),"window=change_permissions;size=250x380;") + + +/datum/admins/proc/change_permissions(adm_ckey, new_rights) + 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 + if(!adm_ckey) + return + if(!new_rights) + return + var/datum/admins/D = admin_datums[adm_ckey] + if(!D) + return + var/added_rights = "" + var/removed_rights = "" + for(var/mask = 1, mask <= R_MAXPERMISSION, mask <<= 1) + var/masked_newrights = new_rights & mask + var/masked_oldrights = D.rights & mask + if(masked_newrights == masked_oldrights) + continue + if(masked_newrights) + added_rights += rights2text(mask," ") + else + removed_rights += rights2text(mask," ") + D.rights = new_rights + if(added_rights) + message_admins("[key_name_admin(usr)] added[added_rights] permissions of [adm_ckey]") + log_admin("[key_name(usr)] added[added_rights] permission of [adm_ckey]") + if(removed_rights) + message_admins("[key_name_admin(usr)] removed[removed_rights] permissions of [adm_ckey]") + log_admin("[key_name(usr)] removed[removed_rights] permission of [adm_ckey]") + + establish_db_connection() + if(!dbcon.IsConnected()) + to_chat(usr, "Failed to establish database connection") + return + adm_ckey = ckey(adm_ckey) + if(!istext(adm_ckey) || !isnum(new_rights)) + return + var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'") + select_query.Execute() + var/admin_id + while(select_query.NextRow()) + admin_id = text2num(select_query.item[1]) + if(!admin_id) + return + var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = [new_rights] WHERE id = [admin_id]") + insert_query.Execute() + if(removed_rights) + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission[removed_rights] to admin [adm_ckey]');") + log_query.Execute() + to_chat(usr, "Permissions removed.") + if(added_rights) + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission[added_rights] to admin [adm_ckey]')") + log_query.Execute() + to_chat(usr, "Permissions added.") + +/datum/admins/proc/add_mentor() + 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 + var/ment_ckey = ckey(input(usr,"New mentor's ckey","Mentor ckey", null) as text|null) + if(!ment_ckey) + return + if(ment_ckey in mentor_ckeys) + to_chat(usr, "Error: Topic 'editmentorlist': [ment_ckey] is already a mentor.") + return + if(ment_ckey in admin_datums) + remove_admin(ment_ckey) + mentor_ckeys += ment_ckey + mentors += directory[ment_ckey] + message_admins("[key_name_admin(usr)] added [ment_ckey] to the mentors list") + log_admin("[key_name(usr)] added [ment_ckey] to the mentors list") + + establish_db_connection() + if(!dbcon.IsConnected()) + to_chat(usr, "Failed to establish database connection") + return + ment_ckey = ckey(ment_ckey) + var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO `erro_mentor` (`id`, `ckey`) VALUES (null, '[ment_ckey]');") + insert_query.Execute() + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new mentor [ment_ckey].');") + log_query.Execute() + to_chat(usr, "New mentor added.") + +/datum/admins/proc/remove_mentor(ment_ckey) + 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 + if(!ment_ckey) + to_chat(usr, "Error: Topic 'editmentorlist': [ment_ckey] is not a valid mentor.") + return + if(alert("Are you sure you want to remove [ment_ckey] from mentors?","Message","Yes","Cancel") == "Yes") + mentor_ckeys -= ment_ckey + mentors -= directory[ment_ckey] + message_admins("[key_name_admin(usr)] removed [ment_ckey] from the mentors list") + log_admin("[key_name(usr)] removed [ment_ckey] from the mentors list") + + establish_db_connection() + if(!dbcon.IsConnected()) + to_chat(usr, "Failed to establish database connection") + return + ment_ckey = ckey(ment_ckey) + var/DBQuery/remove_query = dbcon.NewQuery("DELETE FROM `erro_mentor` WHERE `ckey` = '[ment_ckey]';") + remove_query.Execute() + var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed mentor [ment_ckey].');") + log_query.Execute() + to_chat(usr, "Mentor removed.") + + +/datum/admins/proc/db_admin_rank_modification(adm_ckey, 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()) + 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 `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 `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.") diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index a3dbb8aac496..07a8c68b53f8 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1,2876 +1,2876 @@ -/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 - - if(ticker.mode && ticker.mode.check_antagonists_topic(href, href_list)) - check_antagonists() - return - -// if(href_list["stickyban"]) -// stickyban(href_list["stickyban"],href_list) - - 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, "\red Unfortunately there weren't enough candidates available.") - if("2") - log_admin("[key_name(usr)] has spawned a changeling.") - if(!src.makeChanglings()) - to_chat(usr, "\red Unfortunately there weren't enough candidates available.") - if("3") - log_admin("[key_name(usr)] has spawned revolutionaries.") - if(!src.makeRevs()) - to_chat(usr, "\red Unfortunately there weren't enough candidates available.") - if("4") - log_admin("[key_name(usr)] has spawned a cultists.") - if(!src.makeCult()) - to_chat(usr, "\red 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, "\red Unfortunately there weren't enough candidates available.") - if("6") - log_admin("[key_name(usr)] has spawned a wizard.") - if(!src.makeWizard()) - to_chat(usr, "\red 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, "\red Unfortunately there weren't enough candidates available.") - if("8") - log_admin("[key_name(usr)] has spawned a ninja.") - src.makeSpaceNinja() - 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("11") - log_admin("[key_name(usr)] has spawned vox raiders.") - if(!src.makeVoxRaiders()) - to_chat(usr, "\red Unfortunately there weren't enough candidates available.") - if("12") - message_admins("[key_name(usr)] started a gang war.") - log_admin("[key_name(usr)] started a gang war.") - if(!src.makeGangsters()) - to_chat(usr, "Unfortunatly there were not enough candidates available.") - - else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"] || href_list["dbsearchip"] || href_list["dbsearchcid"] || href_list["dbsearchbantype"]) - var/adminckey = href_list["dbsearchadmin"] - var/playerckey = href_list["dbsearchckey"] - var/playerip = href_list["dbsearchip"] - var/playercid = href_list["dbsearchcid"] - var/dbbantype = text2num(href_list["dbsearchbantype"]) - var/match = 0 - - if("dbmatch" in href_list) - match = 1 - - DB_ban_panel(playerckey, adminckey, playerip, playercid, dbbantype, match) - 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/banip = href_list["dbbanaddip"] - var/bancid = href_list["dbbanaddcid"] - var/banduration = text2num(href_list["dbbaddduration"]) - var/banjob = href_list["dbbanaddjob"] - var/banreason = sanitize(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 - - var/mob/playermob - - for(var/mob/M in player_list) - if(M.ckey == banckey) - playermob = M - break - - - banreason = "(MANUAL BAN) "+banreason - - if(!playermob) - if(banip) - banreason = "[banreason] (CUSTOM IP)" - if(bancid) - banreason = "[banreason] (CUSTOM CID)" - else - message_admins("Ban process: A mob matching [playermob.ckey] was found at location [playermob.x], [playermob.y], [playermob.z]. Custom ip and computer id fields replaced with the ip and computer id from the located mob") - - DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey, banip, bancid ) - - 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/target_ckey = ckey(href_list["ckey"]) - var/task = href_list["editrights"] - if(!task) - return - switch(task) - if("add") - var/response = alert(usr, "Who do you want to add?","Message","Admin","Mentor","Cancel") - switch(response) - if("Admin") - add_admin() - if("Mentor") - add_mentor() - else - return - if("remove_admin") - remove_admin(target_ckey) - if("remove_mentor") - remove_mentor(target_ckey) - if("rank") - edit_rank(target_ckey) - if("permissions") - var/new_rights = text2num(href_list["new_rights"]) - change_permissions(target_ckey, new_rights) - usr << browse(null,"window=change_permissions;") - if("get_new_rights") - get_new_rights(target_ckey) - return - edit_admin_permissions() - - else if(href_list["whitelist"]) - if(!check_rights(R_ADMIN)) - return - - var/target_ckey = ckey(href_list["ckey"]) - var/task = href_list["whitelist"] - if(!task) - return - var/role = href_list["role"] - - switch(task) - if("add_user") - whitelist_add_user() - if("add_role") - whitelist_add_role(target_ckey) - if("showroles") - whitelist_view(target_ckey) - if("edit_ban") - whitelist_edit(target_ckey, role, ban_edit = TRUE) - if("edit_reason") - whitelist_edit(target_ckey, role) - - else if(href_list["custom_items"]) - if(!check_rights(R_PERMISSIONS)) - return - - var/target_ckey = ckey(href_list["ckey"]) - var/task = href_list["custom_items"] - var/index = href_list["index"] - if(!task) - return - - switch(task) - if("add") - customs_items_add() - if("addckey") - customs_items_add(target_ckey) - if("history") - customs_items_history(target_ckey) - if("history_remove") - index = text2num(index) - customs_items_remove(target_ckey, index) - if("moderation_view") - var/itemname = href_list["itemname"] - editing_item_list[usr.ckey] = get_custom_item(target_ckey, itemname) - if(editing_item_list[usr.ckey]) - edit_custom_item_panel(null, usr, readonly = TRUE, adminview = TRUE) - if("moderation_accept") - var/itemname = href_list["itemname"] - custom_item_premoderation_accept(target_ckey, itemname) - if(href_list["viewthis"]) - customitemsview_panel(target_ckey) - else - customitemspremoderation_panel() - if("moderation_reject") - var/itemname = href_list["itemname"] - - var/reason = sanitize(input("Write reason for item rejection or leave empty for no reason","Text") as null|text) - - custom_item_premoderation_reject(target_ckey, itemname, reason) - if(href_list["viewthis"]) - customitemsview_panel(target_ckey) - else - customitemspremoderation_panel() - if("moderation_viewbyckey") - var/viewckey = ckey(input("Enter player ckey","Text") as null|text) - if(viewckey) - customitemsview_panel(viewckey) - if("moderation_viewpremoderation") - customitemspremoderation_panel() - - 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 ) || SSshuttle.location)) - return - SSshuttle.incall() - captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - world << sound('sound/AI/shuttlecalled.ogg') - log_admin("[key_name(usr)] called the Emergency Shuttle") - message_admins("\blue [key_name_admin(usr)] called the Emergency Shuttle to the station") - make_maint_all_access(FALSE) - - if("2") - if ((!( ticker ) || SSshuttle.location || SSshuttle.direction == 0)) - return - switch(SSshuttle.direction) - if(-1) - SSshuttle.incall() - captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - log_admin("[key_name(usr)] called the Emergency Shuttle") - message_admins("\blue [key_name_admin(usr)] called the Emergency Shuttle to the station") - make_maint_all_access(FALSE) - if(1) - SSshuttle.recall() - log_admin("[key_name(usr)] sent the Emergency Shuttle back") - message_admins("\blue [key_name_admin(usr)] sent the Emergency Shuttle back") - if(timer_maint_revoke_id) - deltimer(timer_maint_revoke_id) - timer_maint_revoke_id = 0 - timer_maint_revoke_id = addtimer(CALLBACK(GLOBAL_PROC, .proc/revoke_maint_all_access, FALSE), 600, TIMER_UNIQUE|TIMER_STOPPABLE) - - href_list["secretsadmin"] = "check_antagonist" - - else if(href_list["edit_shuttle_time"]) - if(!check_rights(R_SERVER)) return - - SSshuttle.settimeleft( input("Enter new shuttle duration (seconds):","Edit Shuttle Timeleft", SSshuttle.timeleft() ) as num ) - log_admin("[key_name(usr)] edited the Emergency Shuttle's timeleft to [SSshuttle.timeleft()]") - captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - message_admins("\blue [key_name_admin(usr)] edited the Emergency Shuttle's timeleft to [SSshuttle.timeleft()]") - 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("\blue [key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") - send2slack_service("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") - 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("\blue [key_name_admin(usr)] has used rudimentary transformation on [key_name_admin(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]") - - switch(href_list["simplemake"]) - if("observer") M.change_mob_type( /mob/dead/observer , null, null, delmob ) - if("drone") M.change_mob_type( /mob/living/carbon/alien/humanoid/drone , null, null, delmob ) - if("hunter") M.change_mob_type( /mob/living/carbon/alien/humanoid/hunter , null, null, delmob ) - if("queen") M.change_mob_type( /mob/living/carbon/alien/humanoid/queen , null, null, delmob ) - if("sentinel") M.change_mob_type( /mob/living/carbon/alien/humanoid/sentinel , null, null, delmob ) - if("larva") M.change_mob_type( /mob/living/carbon/alien/larva , null, null, delmob ) - if("human") M.change_mob_type( /mob/living/carbon/human , null, null, delmob ) - if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob ) - if("adultslime") M.change_mob_type( /mob/living/carbon/slime/adult , null, null, delmob ) - if("monkey") M.change_mob_type( /mob/living/carbon/monkey , null, null, delmob ) - if("robot") M.change_mob_type( /mob/living/silicon/robot , null, null, delmob ) - if("cat") M.change_mob_type( /mob/living/simple_animal/cat , null, null, delmob ) - if("runtime") M.change_mob_type( /mob/living/simple_animal/cat/Runtime , null, null, delmob ) - if("corgi") M.change_mob_type( /mob/living/simple_animal/corgi , null, null, delmob ) - if("crab") M.change_mob_type( /mob/living/simple_animal/crab , null, null, delmob ) - if("coffee") M.change_mob_type( /mob/living/simple_animal/crab/Coffee , null, null, delmob ) - if("parrot") M.change_mob_type( /mob/living/simple_animal/parrot , null, null, delmob ) - if("polyparrot") M.change_mob_type( /mob/living/simple_animal/parrot/Poly , null, null, delmob ) - if("constructarmoured") M.change_mob_type( /mob/living/simple_animal/construct/armoured , null, null, delmob ) - if("constructbuilder") M.change_mob_type( /mob/living/simple_animal/construct/builder , null, null, delmob ) - if("constructwraith") M.change_mob_type( /mob/living/simple_animal/construct/wraith , null, null, delmob ) - if("shade") M.change_mob_type( /mob/living/simple_animal/shade , null, null, delmob ) - if("meme") - var/mob/living/parasite/meme/newmeme = new - M.mind.transfer_to(newmeme) - newmeme.clearHUD() - - var/found = 0 - for(var/mob/living/carbon/human/H in human_list) if(H.client && !H.parasites.len) - found = 1 - newmeme.enter_host(H) - - message_admins("[H] has become [newmeme.key]'s host") - - break - - // if there was no host, abort - if(!found) - newmeme.mind.transfer_to(M) - message_admins("Failed to find host for meme [M.key]. Aborting.") - - ticker.mode.memes += newmeme - - if(delmob) - qdel(M) - - - /////////////////////////////////////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["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 = sanitize(input(usr,"Reason?","reason",reason2) as text|null) - if(!reason) return - if("No") - temp = 0 - duration = "Perma" - reason = sanitize(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("\blue [key_name_admin(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]") - Banlist.cd = "/base/[banfolder]" - Banlist["reason"] << reason - Banlist["temp"] << temp - Banlist["minutes"] << minutes - Banlist["bannedby"] << usr.ckey - Banlist.cd = "/base" - feedback_inc("ban_edit",1) - unbanpanel() - - /////////////////////////////////////new ban stuff - - 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(!SSjob) - 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 = SSjob.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 = SSjob.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 = SSjob.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 = SSjob.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 = SSjob.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 = SSjob.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 = SSjob.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, ROLE_DRONE)) - jobs += "" - else - jobs += "" - - //pAI isn't technically a job, but it goes in here. - - if(jobban_isbanned(M, ROLE_PAI)) - jobs += "" - else - jobs += "" - - //Observer is no job and probably not at all human still there's no better place. - - if(jobban_isbanned(M, "Observer")) - jobs += "" - else - jobs += "" - - if(jobban_isbanned(M, "AntagHUD")) - jobs += "" - else - jobs += "" - -/* - //Clown&Mime - counter = 0 - jobs += "
                    Non-human Positions
                    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
                    [ROLE_DRONE][ROLE_DRONE][ROLE_PAI][ROLE_PAI]ObserverObserverAntagHUDAntagHUD
                    " - jobs += "" - for(var/jobPos in entertaiment_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 += "
                    Entertaiment Positions
                    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
                    " */ - - //Antagonist (Orange) - var/isbanned_dept = jobban_isbanned(M, "Syndicate") - jobs += "" - jobs += "" - - //Traitor - if(jobban_isbanned(M, ROLE_TRAITOR) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Changeling - if(jobban_isbanned(M, ROLE_CHANGELING) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Nuke Operative - if(jobban_isbanned(M, ROLE_OPERATIVE) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Revolutionary - if(jobban_isbanned(M, ROLE_REV) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Raider (New heist) - if(jobban_isbanned(M, ROLE_RAIDER) || isbanned_dept) - jobs += "" - else - jobs += "" - - jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries - - //Cultist - if(jobban_isbanned(M, ROLE_CULTIST) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Wizard - if(jobban_isbanned(M, ROLE_WIZARD) || isbanned_dept) - jobs += "" - else - jobs += "" - - //ERT - if(jobban_isbanned(M, ROLE_ERT) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Meme - if(jobban_isbanned(M, ROLE_MEME) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Mutineer - if(jobban_isbanned(M, ROLE_MUTINEER) || isbanned_dept) - jobs += "" - else - jobs += "" - - jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries - - //Shadowling - if(jobban_isbanned(M, ROLE_SHADOWLING) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Abductor - if(jobban_isbanned(M, ROLE_ABDUCTOR) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Ninja - if(jobban_isbanned(M, ROLE_NINJA) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Blob - if(jobban_isbanned(M, ROLE_BLOB) || isbanned_dept) - jobs += "" - else - jobs += "" - - //Malfunctioning AI - if(jobban_isbanned(M, ROLE_MALF) || isbanned_dept) - jobs += "" - else - jobs += "" - - jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries - - //Xenomorph - if(jobban_isbanned(M, ROLE_ALIEN) || isbanned_dept) - jobs += "" - else - jobs += "" - - jobs += "
                    Antagonist Positions
                    [ROLE_TRAITOR][ROLE_TRAITOR][ROLE_CHANGELING][ROLE_CHANGELING][ROLE_OPERATIVE][ROLE_OPERATIVE][ROLE_REV][ROLE_REV][ROLE_RAIDER][ROLE_RAIDER]
                    [ROLE_CULTIST][ROLE_CULTIST][ROLE_WIZARD][ROLE_WIZARD][ROLE_ERT][ROLE_ERT][ROLE_MEME][ROLE_MEME][ROLE_MUTINEER][ROLE_MUTINEER]
                    [ROLE_SHADOWLING][ROLE_SHADOWLING][ROLE_ABDUCTOR][ROLE_ABDUCTOR][ROLE_NINJA][ROLE_NINJA][ROLE_BLOB][ROLE_BLOB][ROLE_MALF][ROLE_MALF]
                    [ROLE_ALIEN][ROLE_ALIEN]
                    " - - //Other races (BLUE, because I have no idea what other color to make this) - jobs += "" - jobs += "" - - if(jobban_isbanned(M, ROLE_PLANT)) - jobs += "" - else - jobs += "" - - if(jobban_isbanned(M, "Mouse")) - jobs += "" - else - jobs += "" - - - jobs += "
                    Other Races
                    [ROLE_PLANT][ROLE_PLANT]MouseMouse
                    " - - - body = "[jobs]" - dat = "[header][body]" - usr << browse(entity_ja(dat), "window=jobban2;size=800x490") - return - - //JOBBAN'S INNARDS - else if(href_list["jobban3"]) - if(!check_rights(R_ADMIN)) - 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(!SSjob) - 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 = SSjob.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("securitydept") - for(var/jobPos in security_positions) - if(!jobPos) continue - var/datum/job/temp = SSjob.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("engineeringdept") - for(var/jobPos in engineering_positions) - if(!jobPos) continue - var/datum/job/temp = SSjob.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("medicaldept") - for(var/jobPos in medical_positions) - if(!jobPos) continue - var/datum/job/temp = SSjob.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("sciencedept") - for(var/jobPos in science_positions) - if(!jobPos) continue - var/datum/job/temp = SSjob.GetJob(jobPos) - if(!temp) continue - joblist += temp.title - if("civiliandept") - for(var/jobPos in civilian_positions) - if(!jobPos) continue - var/datum/job/temp = SSjob.GetJob(jobPos) - if(!temp) continue - joblist += temp.title -/* if("entertaimentdept") - for(var/jobPos in entertaiment_positions) - if(!jobPos) continue - var/datum/job/temp = job_master.GetJob(jobPos) - if(!temp) continue - joblist += temp.title */ - if("nonhumandept") - joblist += ROLE_DRONE - joblist += ROLE_PAI - for(var/jobPos in nonhuman_positions) - if(!jobPos) continue - var/datum/job/temp = SSjob.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(!check_rights(R_BAN)) return - var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null - if(!mins) - return - var/reason = sanitize(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) - if(M.client) - jobban_buildcache(M.client) - feedback_add_details("ban_job_tmp","- [job]") - if(!msg) - msg = job - else - msg += ", [job]" - notes_add(M.ckey, "Banned from [msg] - [reason]") - message_admins("\blue [key_name_admin(usr)] banned [key_name_admin(M)] from [msg] for [mins] minutes") - to_chat(M, "\redYou have been jobbanned by [usr.client.ckey] from: [msg].") - to_chat(M, "\red The reason is: [reason]") - to_chat(M, "\red This jobban will be lifted in [mins] minutes.") - href_list["jobban2"] = 1 // lets it fall through and refresh - return 1 - if("No") - if(!check_rights(R_BAN)) - return - var/reason = sanitize(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) - if(M.client) - jobban_buildcache(M.client) - feedback_add_details("ban_job","- [job]") - if(!msg) msg = job - else msg += ", [job]" - notes_add(M.ckey, "Banned from [msg] - [reason]") - message_admins("\blue [key_name_admin(usr)] banned [key_name_admin(M)] from [msg]") - to_chat(M, "\redYou have been jobbanned by [usr.client.ckey] from: [msg].") - to_chat(M, "\red The reason is: [reason]") - to_chat(M, "\red 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. - 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_ANY_JOB, job) - if(M.client) - jobban_buildcache(M.client) - feedback_inc("ban_job_unban",1) - feedback_add_details("ban_job_unban","- [job]") - if(!msg) msg = job - else msg += ", [job]" - else - continue - if(msg) - message_admins("\blue [key_name_admin(usr)] unbanned [key_name_admin(M)] from [msg]") - to_chat(M, "\redYou 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["geoip"]) - var/mob/M = locate(href_list["geoip"]) - if (ismob(M)) - if(!M.client) - return - var/dat = "GeoIP info" - var/client/C = M.client - if(C.geoip.status != "updated" || C.geoip.status != "admin") - C.geoip.try_update_geoip(C, C.address) - dat += "
                    Ckey: [M.ckey]
                    " - dat += "Country: [C.geoip.country]
                    " - dat += "CountryCode: [C.geoip.countryCode]
                    " - dat += "Region: [C.geoip.region]
                    " - dat += "Region Name: [C.geoip.regionName]
                    " - dat += "City: [C.geoip.city]
                    " - dat += "Timezone: [C.geoip.timezone]
                    " - dat += "ISP: [C.geoip.isp]
                    " - dat += "Mobile: [C.geoip.mobile]
                    " - dat += "Proxy: [C.geoip.proxy]
                    " - dat += "IP: [C.geoip.ip]
                    " - dat += "
                    Status: [C.geoip.status]" - usr << browse(entity_ja(dat), "window=geoip") - - else if(href_list["cid_list"]) - var/mob/M = locate(href_list["cid_list"]) - if (ismob(M)) - if(!M.client) - return - var/client/C = M.client - var/dat = "[C.ckey] cid list" - dat += "
                    Ckey: [C.ckey] | Ignore warning: [C.prefs.ignore_cid_warning ? "yes" : "no"]
                    " - for(var/x in C.prefs.cid_list) - dat += "computer_id: [x] - first seen: [C.prefs.cid_list[x]["first_seen"]] - last seen: [C.prefs.cid_list[x]["last_seen"]]
                    " - usr << browse(entity_ja(dat), "window=[C.ckey]_cid_list") - - else if(href_list["cid_ignore"]) - var/mob/M = locate(href_list["cid_ignore"]) - if (ismob(M)) - if(!M.client) - return - var/client/C = M.client - C.prefs.ignore_cid_warning = !(C.prefs.ignore_cid_warning) - log_admin("[key_name(usr)] has [C.prefs.ignore_cid_warning ? "disabled" : "enabled"] multiple cid notice for [C.ckey].") - message_admins("[key_name_admin(usr)] has [C.prefs.ignore_cid_warning ? "disabled" : "enabled"] multiple cid notice for [C.ckey].") - - else if(href_list["related_accounts"]) - var/mob/M = locate(href_list["related_accounts"]) - if (ismob(M)) - if(!M.client) - return - var/client/C = M.client - - var/dat = "[C.key] related accounts by IP and cid" - dat += "
                    Ckey: [C.ckey]

                    " - dat += "IP: [C.related_accounts_ip]
                    " - dat += "CID: [C.related_accounts_cid]" - - usr << browse(entity_ja(dat), "window=[C.ckey]_related_accounts") - - else if(href_list["boot2"]) - var/mob/M = locate(href_list["boot2"]) - if (ismob(M)) - if(!check_if_greater_rights_than(M.client)) - return - var/reason = sanitize(input("Please enter reason")) - if(!reason) - to_chat(M, "\red You have been kicked from the server") - else - to_chat(M, "\red You have been kicked from the server: [reason]") - log_admin("[key_name(usr)] booted [key_name(M)].") - message_admins("\blue [key_name_admin(usr)] booted [key_name_admin(M)].") - //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["newban"]) - if(!check_rights(R_BAN)) return - - var/mob/M = locate(href_list["newban"]) - if(!ismob(M)) return - - 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 = sanitize(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, "\redYou have been banned by [usr.client.ckey].\nReason: [reason].") - to_chat(M, "\red 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, "\red To try to resolve this matter head to [config.banappeals]") - else - to_chat(M, "\red 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("\blue[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") - if(!check_rights(R_BAN)) return - var/reason = sanitize(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) - to_chat(M, "\redYou have been banned by [usr.client.ckey].\nReason: [reason].") - to_chat(M, "\red This is a permanent ban.") - if(config.banappeals) - to_chat(M, "\red To try to resolve this matter head to [config.banappeals]") - else - to_chat(M, "\red 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("\blue[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["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(entity_ja(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(entity_ja(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("\blue [key_name_admin(usr)] set the mode as [master_mode].") - to_chat(world, "\blue 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("\blue [key_name_admin(usr)] set the forced secret mode as [secret_force_mode].") - 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("\blue [key_name_admin(usr)] attempting to monkeyize [key_name_admin(H)]") - H.monkeyize() - - 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("\blue [key_name_admin(usr)] attempting to corgize [key_name_admin(H)]") - H.corgize() - - 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("\blue [key_name_admin(usr)] forced [key_name_admin(M)] to say: [speech]") - - else if(href_list["sendtoprison"]) - if(!check_rights(R_ADMIN)) return - - if(alert(usr, "Send to admin prison for the round?", "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.drop_from_inventory(I, locker) - M.update_icons() - - //so they black out before warping - M.Paralyse(5) - sleep(5) - if(!M) return - - 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, "\red You have been sent to the prison station!") - log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.") - message_admins("\blue [key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.") - - else if(href_list["tdome1"]) - if(!check_rights(R_FUN)) - return - - if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") - return - - var/mob/M = locate(href_list["tdome1"]) - 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.drop_from_inventory(I) - - M.Paralyse(5) - sleep(5) - M.loc = pick(tdome1) - spawn(50) - to_chat(M, "\blue You have been sent to the Thunderdome.") - log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team 1)") - message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Team 1)") - - else if(href_list["tdome2"]) - if(!check_rights(R_FUN)) - return - - if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") - return - - var/mob/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 - - for(var/obj/item/I in M) - M.drop_from_inventory(I) - - M.Paralyse(5) - sleep(5) - M.loc = pick(tdome2) - spawn(50) - to_chat(M, "\blue You have been sent to the Thunderdome.") - log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team 2)") - message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Team 2)") - - 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, "\blue 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.)") - - 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.drop_from_inventory(I) - - 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, "\blue 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.)") - - 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() - message_admins("\red Admin [key_name_admin(usr)] healed / revived [key_name_admin(L)]!") - log_admin("[key_name(usr)] healed / Rrvived [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("\red Admin [key_name_admin(usr)] AIized [key_name_admin(H)]!") - log_admin("[key_name(usr)] AIized [key_name(H)]") - H.AIize() - - 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 - - usr.client.cmd_admin_alienize(H) - - 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 - - usr.client.cmd_admin_slimeize(H) - - else if(href_list["makeblob"]) - if(!check_rights(R_SPAWN)) return - - var/mob/living/carbon/human/H = locate(href_list["makeblob"]) - if(!istype(H)) - to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") - return - - usr.client.cmd_admin_blobize(H) - - 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 - - usr.client.cmd_admin_robotize(H) - - else if(href_list["makeanimal"]) - if(!check_rights(R_SPAWN)) return - - var/mob/M = locate(href_list["makeanimal"]) - if(isnewplayer(M)) - to_chat(usr, "This cannot be used on instances of type /mob/dead/new_player") - return - - usr.client.cmd_admin_animalize(M) - - 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() - - else if(href_list["adminplayeropts"]) - if(!check_rights(R_ADMIN)) - return - - var/mob/M = locate(href_list["adminplayeropts"]) - show_player_panel(M) - - else if(href_list["adminplayerobservejump"]) - if(!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) - C.jumptomob(M) - - else if(href_list["check_antagonist"]) - if(!check_rights(R_ADMIN)) - return - - check_antagonists() - - else if(href_list["adminplayerobservefollow"]) - if(!isobserver(usr) && !check_rights(R_ADMIN)) - return - - var/atom/movable/AM = locate(href_list["adminplayerobservefollow"]) - - var/client/C = usr.client - if(!isobserver(usr)) C.admin_ghost() - var/mob/dead/observer/A = C.mob - A.ManualFollow(AM) - - 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"]) - if(!check_rights(R_ADMIN)) - return - - 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/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]" - - to_chat(src.owner, "Info about [M.name]: ") - to_chat(src.owner, "Mob type = [M.type]; 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)) - 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, "\blue 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/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.l_ear, /obj/item/device/radio/headset) && !istype(H.r_ear, /obj/item/device/radio/headset)) - to_chat(usr, "The person you are trying to contact is not wearing a headset") - return - - var/input = sanitize(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]\"") - send2slack_custommsg("[key_name(src.owner)] replied to [key_name(H)]'s Centcom message", input, ":job-cap:") - 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.l_ear, /obj/item/device/radio/headset) && !istype(H.r_ear, /obj/item/device/radio/headset)) - to_chat(usr, "The person you are trying to contact is not wearing a headset") - return - - var/input = sanitize(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].") - message_admins("[src.owner] replied to [key_name(H)]'s Syndicate message with: \"[input]\"") - send2slack_custommsg("[key_name(src.owner)] replied to [key_name(H)]'s Syndicate message", input, ":job-nuke:") - 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["CentcommFaxViewInfo"]) - var/info = locate(href_list["CentcommFaxViewInfo"]) - var/stamps = locate(href_list["CentcommFaxViewStamps"]) - - usr << browse("Centcomm Fax Message[entity_ja(info)][stamps]", "window=Centcomm Fax Message") - - else if(href_list["CentcommFaxReply"]) - var/mob/living/carbon/human/H = locate(href_list["CentcommFaxReply"]) - - var/input = sanitize(input(src.owner, "Please, enter a message to reply to [key_name(H)] via secure connection. NOTE: BBCode does not work.", "Outgoing message from Centcomm", "") as message|null, extra = FALSE) - if(!input) - return - - var/customname = sanitize_safe(input(src.owner, "Pick a title for the report", "Title") as text|null) - - var/obj/item/weapon/paper/P = new - P.name = "[command_name()]- [customname]" - P.info = input - - var/obj/item/weapon/stamp/centcomm/S = new - S.stamp_paper(P, use_stamp_by_message = TRUE) - - send_fax(usr, P, "All") - - to_chat(src.owner, "Message reply to transmitted successfully.") - log_admin("[key_name(src.owner)] replied to a fax message from [key_name(H)]: [input]") - message_admins("[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(H)]") - send2slack_custommsg("[key_name(src.owner)] replied to a fax message from [key_name(H)]", input, ":fax:") - - - 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["traitor"]) - if(!check_rights(R_ADMIN)) - 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) - - 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/item/weapon/melee/energy/blade))//Not an item one should be able to spawn./N - 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" + jointext(removed_paths, "\n")) - - var/list/offset = splittext(href_list["offset"],",") - var/number = dd_range(1, 100, text2num(href_list["object_count"])) - 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 list(1,2,4,8,5,6,9,10))) - obj_dir = 2 - var/obj_name = sanitize(href_list["object_name"]) - var/atom/target //Where the object will be spawned - var/where = href_list["object_where"] - if (!( where in list("onfloor","inhand","inmarked","dropped") )) - where = "onfloor" - - - switch(where) - if("inhand") - if (!iscarbon(usr) && !isrobot(usr)) - to_chat(usr, "Can only spawn in hand when you're a carbon mob or cyborg.") - where = "onfloor" - if(isrobot(usr)) - var/mob/living/silicon/robot/R = usr - if(!R.module) - to_chat(R, "Cyborg doesn't has module, you can't do that.") - return - target = usr - if("onfloor", "dropped") - 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") - 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 - else - target = marked_datum - - - if(target) - for (var/path in paths) - for (var/i = 0; i < number; i++) - if(where == "dropped") - new /obj/effect/falling_effect(target, path) - else if(path in typesof(/turf)) - var/turf/O = target - var/turf/N = O.ChangeTurf(path) - if(N && 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(where == "inhand" && isliving(usr) && istype(O, /obj/item)) - var/mob/living/L = usr - var/obj/item/I = O - L.put_in_hands(I) - if(isrobot(L)) - var/mob/living/silicon/robot/R = L - if(R.module) - R.module.modules += I - I.loc = R.module - R.module.rebuild() - R.activate_module(I) - - if (number == 1) - log_admin("[key_name(usr)] created a [english_list(paths)]") - for(var/path in paths) - if(ispath(path, /mob)) - message_admins("[key_name_admin(usr)] created a [english_list(paths)]") - break - else - log_admin("[key_name(usr)] created [number]ea [english_list(paths)]") - for(var/path in paths) - if(ispath(path, /mob)) - message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)]") - break - return - - else if(href_list["secretsfun"]) - if(!check_rights(R_FUN|R_EVENT)) - 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) - qdel(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) - qdel(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) - qdel(O) - for(var/obj/structure/grille/O in world) - qdel(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 - qdel(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 human_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 human_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 all_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.") - message_admins("\blue [key_name_admin(usr)] toggled gravity on.") - command_alert("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") - else - log_admin("[key_name(usr)] toggled gravity off.") - message_admins("\blue [key_name_admin(usr)] toggled gravity off.") - 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") - message_admins("\blue [key_name_admin(usr)] spawned a meteor wave.") - 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") - message_admins("\blue [key_name_admin(usr)] spawned a blob.") - 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") - message_admins("\blue [key_name_admin(usr)] attempted an alien infestation") - new /datum/event/alien_infestation - if("borers") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Borers") - log_admin("[key_name(usr)] spawned a cortical borer infestation.") - message_admins("\blue [key_name_admin(usr)] spawned a cortical borer infestation.") - new /datum/event/borer_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") - message_admins("\blue [key_name_admin(usr)] made all areas powered") - power_restore(badminery=1) - 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") - message_admins("\blue [key_name_admin(usr)] made all areas unpowered") - power_failure() - if("quickpower") - if(power_fail_event) - to_chat(usr, "Power fail event is in progress.. Please wait or use normal power restore.") - return - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","QP") - log_admin("[key_name(usr)] made all SMESs powered") - message_admins("\blue [key_name_admin(usr)] made all SMESs powered") - power_restore_quick() - 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("\blue [key_name_admin(usr)] teleported all players to the prison station.") - for(var/mob/living/carbon/human/H in human_list) - var/turf/loc = find_loc(H) - var/security = 0 - if(loc.z > ZLEVEL_STATION || prisonwarped.Find(H)) -//don't warp them if they aren't ready or are already there - continue - H.Paralyse(5) - if(H.wear_id) - var/obj/item/weapon/card/id/id = H.get_idcard() - for(var/A in id.access) - if(A == access_security) - security++ - if(!security) - //strip their stuff before they teleport into a cell :downs: - for(var/obj/item/weapon/W in H) - if(istype(W, /obj/item/organ/external)) - continue - //don't strip organs - H.drop_from_inventory(W) - //teleport person to cell - H.loc = pick(prisonwarp) - H.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(H), slot_shoes) - else - //teleport security person - H.loc = pick(prisonsecuritywarp) - prisonwarped += H - if("traitor_all") - if(!ticker) - alert("The game hasn't started yet!") - return - var/objective = sanitize(input("Enter an objective")) - 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 == DEAD || !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("\blue [key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]") - log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]") - - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ShM") - if("moveadminshuttle") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ShA") - move_admin_shuttle() - message_admins("\blue [key_name_admin(usr)] moved the centcom administration shuttle") - 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") - move_ferry() - message_admins("\blue [key_name_admin(usr)] moved the centcom ferry") - 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("\blue [key_name_admin(usr)] moved the alien dinghy") - 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 - if(128) 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("\red [key_name_admin(usr)] changed the bomb cap to [range_dev], [range_high], [range_low]") - 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 != DEAD && 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("\blue You shudder as if cold..."), 1) - if(2) - M.show_message(text("\blue You feel something gliding across your back..."), 1) - if(3) - M.show_message(text("\blue Your eyes twitch, you feel like something you can't see is here..."), 1) - if(4) - M.show_message(text("\blue 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 != DEAD) - M.show_message(text("\blue The chilling wind suddenly stops..."), 1) - - if("wave") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","MW") - new /datum/event/meteor_wave - - if("bluespaceanomaly") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BA") - message_admins("[key_name_admin(usr)] has triggered a bluespace anomaly") - new /datum/event/anomaly/anomaly_bluespace() - - if("energeticflux") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FLUX") - message_admins("[key_name_admin(usr)] has triggered an energetic flux") - new /datum/event/anomaly/anomaly_flux() - - if("frost") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FROST") - message_admins("[key_name_admin(usr)] freezed the station") - var/datum/anomaly_frost/FROST = new /datum/anomaly_frost() - FROST.set_params(usr) - - if("pyroanomalies") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","PYRO") - message_admins("[key_name_admin(usr)] has spawned a pyroclastic anomaly") - new /datum/event/anomaly/anomaly_pyro() - - if("gravanomalies1") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","GA") - message_admins("[key_name_admin(usr)] has spawned a gravitational anomaly") - new /datum/event/anomaly/anomaly_grav() - - if("blackhole") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BH") - message_admins("[key_name_admin(usr)] has spawned a vortex anomaly") - new /datum/event/anomaly/anomaly_vortex() - - 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") - 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)) - qdel(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") - 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") - 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") - 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.") - if("spaceninja") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SN") - if(toggle_space_ninja) - if(space_ninja_arrival())//If the ninja is actually spawned. They may not be depending on a few factors. - message_admins("[key_name_admin(usr)] has sent in a space ninja") - 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.") - 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") - 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") - immovablerod() - if("spawnguns") - feedback_inc("admin_secrets_fun_used", 1) - feedback_add_details("admin_secrets_fun_used", "SG") - rightandwrong(0, usr) - if("spawnspells") - feedback_inc("admin_secrets_fun_used", 1) - feedback_add_details("admin_secrets_fun_used", "SP") - rightandwrong(1, usr) - 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") - prison_break() - if("lighstout") - 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") - 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") - 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 machines) - L.fix() - message_admins("[key_name_admin(usr)] fixed all lights") - if("friendai") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FA") - for(var/mob/camera/Eye/ai/aE in ai_eyes_list) - aE.icon_state = "ai_friend" - for(var/obj/machinery/ai_status_display/A in ai_status_display_list) - A.emotion = "Friend Computer" - for(var/obj/machinery/status_display/A in status_display_list) - A.friendc = 1 - message_admins("[key_name_admin(usr)] turned all AIs into best friends.") - if("floorlava") - SSweather.run_weather("the floor is lava", ZLEVEL_STATION) - if("advanceddarkness") - SSweather.run_weather("advanced darkness", ZLEVEL_STATION) - 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.") - else - virus2_greater_infection() - message_admins("[key_name_admin(usr)] has triggered a greater virus outbreak.") - 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, "\red 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("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.item_color = "schoolgirl" - message_admins("[key_name_admin(usr)] activated Japanese Animes mode") - 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 airlock_list) - if(W.z == ZLEVEL_STATION && !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.") - 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 human_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") - IonStorm() - 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") - 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") - 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("drop_asteroid") - if(!check_rights(R_EVENT)) - to_chat(usr, "You don't have permissions for this") - return - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ASTEROID") - usr.client.drop_asteroid() - 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") - //I do nothing - if("clear_virus") - var/choice1 = input("Are you sure you want to cure all disease?") in list("Yes", "Cancel") - if(choice1 == "Yes") - message_admins("[key_name_admin(usr)] has cured all diseases.") - for(var/mob/living/carbon/M in carbon_list) - if(M.virus2.len) - for(var/ID in M.virus2) - var/datum/disease2/disease/V = M.virus2[ID] - V.cure(M) - - for(var/obj/effect/decal/cleanable/O in decal_cleanable) - if(istype(O,/obj/effect/decal/cleanable/blood)) - var/obj/effect/decal/cleanable/blood/B = O - if(B.virus2.len) - B.virus2.Cut() - - else if(istype(O,/obj/effect/decal/cleanable/mucus)) - var/obj/effect/decal/cleanable/mucus/N = O - if(N.virus2.len) - N.virus2.Cut() - if("restore_air") // this is unproper way to restore turfs default gas values, since you can delete sleeping agent for example. - var/turf/simulated/T = get_turf(usr) - if((istype(T, /turf/simulated/floor) || istype(T, /turf/simulated/shuttle/floor)) && T.zone.air) - var/datum/gas_mixture/GM = T.zone.air - - for(var/g in gas_data.gases) - GM.gas -= g - - GM.gas["carbon_dioxide"] = T.carbon_dioxide - GM.gas["phoron"] = T.phoron - GM.gas["nitrogen"] = T.nitrogen - GM.gas["oxygen"] = T.oxygen - GM.temperature = 293 - GM.update_values() - - message_admins("[key_name_admin(usr)] has restored air in [T.x] [T.y] [T.z] JMP.") - else - to_chat(usr, "You are staying on incorrect turf.") - if("list_bombers") - var/dat = "Bombing List
                    " - for(var/l in bombers) - dat += text("[l]
                    ") - usr << browse(entity_ja(dat), "window=bombers") - if("list_signalers") - var/dat = "Showing last [length(lastsignalers)] signalers.
                    " - for(var/sig in lastsignalers) - dat += "[sig]
                    " - usr << browse(entity_ja(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(entity_ja(dat), "window=lawchanges;size=800x500") - if("list_job_debug") - var/dat = "Job Debug info.
                    " - if(SSjob) - for(var/line in SSjob.job_debug) - dat += "[line]
                    " - dat+= "*******

                    " - for(var/datum/job/job in SSjob.occupations) - if(!job) continue - dat += "job: [job.title], current_positions: [job.current_positions], total_positions: [job.total_positions]
                    " - usr << browse(entity_ja(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 human_list) - if(H.ckey) - dat += text("", H.name, H.get_assignment()) - dat += "
                    NamePosition
                    [][]
                    " - usr << browse(entity_ja(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 human_list) - if(H.dna && H.ckey) - dat += "" - dat += "
                    NameDNABlood Type
                    [H][H.dna.unique_enzymes][H.b_type]
                    " - usr << browse(entity_ja(dat), "window=DNA;size=440x410") - if("fingerprints") - var/dat = "Showing Fingerprints.
                    " - dat += "" - for(var/mob/living/carbon/human/H in human_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(entity_ja(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(entity_ja(dat), "window=admin_log") - if("maint_access_brig") - for(var/obj/machinery/door/airlock/maintenance/M in airlock_list) - 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 airlock_list) - 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 = SSjob.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.") - - 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 = sanitize(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", input_default(admincaster_feed_channel.channel_name))) - 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 = 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 = sanitize(input(usr, "Write your Feed story", "Network Channel Handler", input_default(admincaster_feed_message.body)), extra = FALSE) - 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 = sanitize(input(usr, "Provide the name of the Wanted person", "Network Security Handler", input_default(admincaster_feed_message.author))) - src.access_news_network() - - else if(href_list["ac_set_wanted_desc"]) - src.admincaster_feed_message.body = sanitize(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", "")) - 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 = sanitize(input(usr, "Provide your desired signature", "Network Identity Handler", "")) - src.access_news_network() - - else if(href_list["readbook"]) - var/bookid = text2num(href_list["readbook"]) - - if(!isnum(bookid)) - return - - var/DBQuery/query = dbcon_old.NewQuery("SELECT content FROM library WHERE id = '[bookid]'") - - if(!query.Execute()) - return - - var/content - if(query.NextRow()) - content = query.item[1] - else - return - - usr << browse(entity_ja(content), "window=book") - - else if(href_list["restorebook"]) - if(!check_rights(R_PERMISSIONS)) - return - - if(alert(usr, "Confirm restoring?", "Message", "Yes", "No") != "Yes") - return - var/bookid = text2num(href_list["restorebook"]) - - if(!isnum(bookid)) - return - - var/DBQuery/query = dbcon_old.NewQuery("SELECT title FROM library WHERE id = '[bookid]'") - if(!query.Execute()) - return - - var/title - if(query.NextRow()) - title = query.item[1] - else - return - - query = dbcon_old.NewQuery("UPDATE library SET deletereason = NULL WHERE id = '[bookid]'") - if(!query.Execute()) - return - - library_recycle_bin() - log_admin("[key_name_admin(usr)] restored [title] from the recycle bin") - message_admins("[key_name_admin(usr)] restored [title] from the recycle bin") - - else if(href_list["deletebook"]) - if(!check_rights(R_PERMISSIONS)) - return - - if(alert(usr, "Confirm removal?", "Message", "Yes", "No") != "Yes") - return - - var/bookid = text2num(href_list["deletebook"]) - - if(!isnum(bookid)) - return - - var/DBQuery/query = dbcon_old.NewQuery("SELECT title FROM library WHERE id = '[bookid]'") - - if(!query.Execute()) - return - - var/title - if(query.NextRow()) - title = query.item[1] - else - return - - query = dbcon_old.NewQuery("DELETE FROM library WHERE id='[bookid]'") - if(!query.Execute()) - return - - library_recycle_bin() - log_admin("[key_name_admin(usr)] restored [title] from the recycle bin") - message_admins("[key_name_admin(usr)] removed [title] from the library database") - - else if(href_list["vsc"]) - if(check_rights(R_ADMIN|R_SERVER)) - if(href_list["vsc"] == "airflow") - vsc.ChangeSettingsDialog(usr,vsc.settings) - if(href_list["vsc"] == "phoron") - vsc.ChangeSettingsDialog(usr,vsc.plc.settings) - if(href_list["vsc"] == "default") - vsc.SetDefault(usr) - - else if(href_list["viewruntime"]) - if(!check_rights(R_DEBUG)) - return - - var/datum/error_viewer/error_viewer = locate(href_list["viewruntime"]) - if(!istype(error_viewer)) - to_chat(usr, "That runtime viewer no longer exists.") - return - - if(href_list["viewruntime_backto"]) - error_viewer.show_to(owner, locate(href_list["viewruntime_backto"]), href_list["viewruntime_linear"]) - else - error_viewer.show_to(owner, null, href_list["viewruntime_linear"]) - - // 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//sanitise below in notes_add - if(!add) return - - notes_add(key, add, usr.client) - 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, usr.client) - 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 +/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 + + if(ticker.mode && ticker.mode.check_antagonists_topic(href, href_list)) + check_antagonists() + return + +// if(href_list["stickyban"]) +// stickyban(href_list["stickyban"],href_list) + + 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, "\red Unfortunately there weren't enough candidates available.") + if("2") + log_admin("[key_name(usr)] has spawned a changeling.") + if(!src.makeChanglings()) + to_chat(usr, "\red Unfortunately there weren't enough candidates available.") + if("3") + log_admin("[key_name(usr)] has spawned revolutionaries.") + if(!src.makeRevs()) + to_chat(usr, "\red Unfortunately there weren't enough candidates available.") + if("4") + log_admin("[key_name(usr)] has spawned a cultists.") + if(!src.makeCult()) + to_chat(usr, "\red 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, "\red Unfortunately there weren't enough candidates available.") + if("6") + log_admin("[key_name(usr)] has spawned a wizard.") + if(!src.makeWizard()) + to_chat(usr, "\red 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, "\red Unfortunately there weren't enough candidates available.") + if("8") + log_admin("[key_name(usr)] has spawned a ninja.") + src.makeSpaceNinja() + 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("11") + log_admin("[key_name(usr)] has spawned vox raiders.") + if(!src.makeVoxRaiders()) + to_chat(usr, "\red Unfortunately there weren't enough candidates available.") + if("12") + message_admins("[key_name(usr)] started a gang war.") + log_admin("[key_name(usr)] started a gang war.") + if(!src.makeGangsters()) + to_chat(usr, "Unfortunatly there were not enough candidates available.") + + else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"] || href_list["dbsearchip"] || href_list["dbsearchcid"] || href_list["dbsearchbantype"]) + var/adminckey = href_list["dbsearchadmin"] + var/playerckey = href_list["dbsearchckey"] + var/playerip = href_list["dbsearchip"] + var/playercid = href_list["dbsearchcid"] + var/dbbantype = text2num(href_list["dbsearchbantype"]) + var/match = 0 + + if("dbmatch" in href_list) + match = 1 + + DB_ban_panel(playerckey, adminckey, playerip, playercid, dbbantype, match) + 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/banip = href_list["dbbanaddip"] + var/bancid = href_list["dbbanaddcid"] + var/banduration = text2num(href_list["dbbaddduration"]) + var/banjob = href_list["dbbanaddjob"] + var/banreason = sanitize(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 + + var/mob/playermob + + for(var/mob/M in player_list) + if(M.ckey == banckey) + playermob = M + break + + + banreason = "(MANUAL BAN) "+banreason + + if(!playermob) + if(banip) + banreason = "[banreason] (CUSTOM IP)" + if(bancid) + banreason = "[banreason] (CUSTOM CID)" + else + message_admins("Ban process: A mob matching [playermob.ckey] was found at location [playermob.x], [playermob.y], [playermob.z]. Custom ip and computer id fields replaced with the ip and computer id from the located mob") + + DB_ban_record(bantype, playermob, banduration, banreason, banjob, null, banckey, banip, bancid ) + + 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/target_ckey = ckey(href_list["ckey"]) + var/task = href_list["editrights"] + if(!task) + return + switch(task) + if("add") + var/response = alert(usr, "Who do you want to add?","Message","Admin","Mentor","Cancel") + switch(response) + if("Admin") + add_admin() + if("Mentor") + add_mentor() + else + return + if("remove_admin") + remove_admin(target_ckey) + if("remove_mentor") + remove_mentor(target_ckey) + if("rank") + edit_rank(target_ckey) + if("permissions") + var/new_rights = text2num(href_list["new_rights"]) + change_permissions(target_ckey, new_rights) + usr << browse(null,"window=change_permissions;") + if("get_new_rights") + get_new_rights(target_ckey) + return + edit_admin_permissions() + + else if(href_list["whitelist"]) + if(!check_rights(R_ADMIN)) + return + + var/target_ckey = ckey(href_list["ckey"]) + var/task = href_list["whitelist"] + if(!task) + return + var/role = href_list["role"] + + switch(task) + if("add_user") + whitelist_add_user() + if("add_role") + whitelist_add_role(target_ckey) + if("showroles") + whitelist_view(target_ckey) + if("edit_ban") + whitelist_edit(target_ckey, role, ban_edit = TRUE) + if("edit_reason") + whitelist_edit(target_ckey, role) + + else if(href_list["custom_items"]) + if(!check_rights(R_PERMISSIONS)) + return + + var/target_ckey = ckey(href_list["ckey"]) + var/task = href_list["custom_items"] + var/index = href_list["index"] + if(!task) + return + + switch(task) + if("add") + customs_items_add() + if("addckey") + customs_items_add(target_ckey) + if("history") + customs_items_history(target_ckey) + if("history_remove") + index = text2num(index) + customs_items_remove(target_ckey, index) + if("moderation_view") + var/itemname = href_list["itemname"] + editing_item_list[usr.ckey] = get_custom_item(target_ckey, itemname) + if(editing_item_list[usr.ckey]) + edit_custom_item_panel(null, usr, readonly = TRUE, adminview = TRUE) + if("moderation_accept") + var/itemname = href_list["itemname"] + custom_item_premoderation_accept(target_ckey, itemname) + if(href_list["viewthis"]) + customitemsview_panel(target_ckey) + else + customitemspremoderation_panel() + if("moderation_reject") + var/itemname = href_list["itemname"] + + var/reason = sanitize(input("Write reason for item rejection or leave empty for no reason","Text") as null|text) + + custom_item_premoderation_reject(target_ckey, itemname, reason) + if(href_list["viewthis"]) + customitemsview_panel(target_ckey) + else + customitemspremoderation_panel() + if("moderation_viewbyckey") + var/viewckey = ckey(input("Enter player ckey","Text") as null|text) + if(viewckey) + customitemsview_panel(viewckey) + if("moderation_viewpremoderation") + customitemspremoderation_panel() + + 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 ) || SSshuttle.location)) + return + SSshuttle.incall() + captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + world << sound('sound/AI/shuttlecalled.ogg') + log_admin("[key_name(usr)] called the Emergency Shuttle") + message_admins("\blue [key_name_admin(usr)] called the Emergency Shuttle to the station") + make_maint_all_access(FALSE) + + if("2") + if ((!( ticker ) || SSshuttle.location || SSshuttle.direction == 0)) + return + switch(SSshuttle.direction) + if(-1) + SSshuttle.incall() + captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + log_admin("[key_name(usr)] called the Emergency Shuttle") + message_admins("\blue [key_name_admin(usr)] called the Emergency Shuttle to the station") + make_maint_all_access(FALSE) + if(1) + SSshuttle.recall() + log_admin("[key_name(usr)] sent the Emergency Shuttle back") + message_admins("\blue [key_name_admin(usr)] sent the Emergency Shuttle back") + if(timer_maint_revoke_id) + deltimer(timer_maint_revoke_id) + timer_maint_revoke_id = 0 + timer_maint_revoke_id = addtimer(CALLBACK(GLOBAL_PROC, .proc/revoke_maint_all_access, FALSE), 600, TIMER_UNIQUE|TIMER_STOPPABLE) + + href_list["secretsadmin"] = "check_antagonist" + + else if(href_list["edit_shuttle_time"]) + if(!check_rights(R_SERVER)) return + + SSshuttle.settimeleft( input("Enter new shuttle duration (seconds):","Edit Shuttle Timeleft", SSshuttle.timeleft() ) as num ) + log_admin("[key_name(usr)] edited the Emergency Shuttle's timeleft to [SSshuttle.timeleft()]") + captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + message_admins("\blue [key_name_admin(usr)] edited the Emergency Shuttle's timeleft to [SSshuttle.timeleft()]") + 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("\blue [key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") + send2slack_service("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].") + 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("\blue [key_name_admin(usr)] has used rudimentary transformation on [key_name_admin(M)]. Transforming to [href_list["simplemake"]]; deletemob=[delmob]") + + switch(href_list["simplemake"]) + if("observer") M.change_mob_type( /mob/dead/observer , null, null, delmob ) + if("drone") M.change_mob_type( /mob/living/carbon/alien/humanoid/drone , null, null, delmob ) + if("hunter") M.change_mob_type( /mob/living/carbon/alien/humanoid/hunter , null, null, delmob ) + if("queen") M.change_mob_type( /mob/living/carbon/alien/humanoid/queen , null, null, delmob ) + if("sentinel") M.change_mob_type( /mob/living/carbon/alien/humanoid/sentinel , null, null, delmob ) + if("larva") M.change_mob_type( /mob/living/carbon/alien/larva , null, null, delmob ) + if("human") M.change_mob_type( /mob/living/carbon/human , null, null, delmob ) + if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob ) + if("adultslime") M.change_mob_type( /mob/living/carbon/slime/adult , null, null, delmob ) + if("monkey") M.change_mob_type( /mob/living/carbon/monkey , null, null, delmob ) + if("robot") M.change_mob_type( /mob/living/silicon/robot , null, null, delmob ) + if("cat") M.change_mob_type( /mob/living/simple_animal/cat , null, null, delmob ) + if("runtime") M.change_mob_type( /mob/living/simple_animal/cat/Runtime , null, null, delmob ) + if("corgi") M.change_mob_type( /mob/living/simple_animal/corgi , null, null, delmob ) + if("crab") M.change_mob_type( /mob/living/simple_animal/crab , null, null, delmob ) + if("coffee") M.change_mob_type( /mob/living/simple_animal/crab/Coffee , null, null, delmob ) + if("parrot") M.change_mob_type( /mob/living/simple_animal/parrot , null, null, delmob ) + if("polyparrot") M.change_mob_type( /mob/living/simple_animal/parrot/Poly , null, null, delmob ) + if("constructarmoured") M.change_mob_type( /mob/living/simple_animal/construct/armoured , null, null, delmob ) + if("constructbuilder") M.change_mob_type( /mob/living/simple_animal/construct/builder , null, null, delmob ) + if("constructwraith") M.change_mob_type( /mob/living/simple_animal/construct/wraith , null, null, delmob ) + if("shade") M.change_mob_type( /mob/living/simple_animal/shade , null, null, delmob ) + if("meme") + var/mob/living/parasite/meme/newmeme = new + M.mind.transfer_to(newmeme) + newmeme.clearHUD() + + var/found = 0 + for(var/mob/living/carbon/human/H in human_list) if(H.client && !H.parasites.len) + found = 1 + newmeme.enter_host(H) + + message_admins("[H] has become [newmeme.key]'s host") + + break + + // if there was no host, abort + if(!found) + newmeme.mind.transfer_to(M) + message_admins("Failed to find host for meme [M.key]. Aborting.") + + ticker.mode.memes += newmeme + + if(delmob) + qdel(M) + + + /////////////////////////////////////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["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 = sanitize(input(usr,"Reason?","reason",reason2) as text|null) + if(!reason) return + if("No") + temp = 0 + duration = "Perma" + reason = sanitize(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("\blue [key_name_admin(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]") + Banlist.cd = "/base/[banfolder]" + Banlist["reason"] << reason + Banlist["temp"] << temp + Banlist["minutes"] << minutes + Banlist["bannedby"] << usr.ckey + Banlist.cd = "/base" + feedback_inc("ban_edit",1) + unbanpanel() + + /////////////////////////////////////new ban stuff + + 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(!SSjob) + 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 = SSjob.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 = SSjob.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 = SSjob.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 = SSjob.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 = SSjob.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 = SSjob.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 = SSjob.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, ROLE_DRONE)) + jobs += "" + else + jobs += "" + + //pAI isn't technically a job, but it goes in here. + + if(jobban_isbanned(M, ROLE_PAI)) + jobs += "" + else + jobs += "" + + //Observer is no job and probably not at all human still there's no better place. + + if(jobban_isbanned(M, "Observer")) + jobs += "" + else + jobs += "" + + if(jobban_isbanned(M, "AntagHUD")) + jobs += "" + else + jobs += "" + +/* + //Clown&Mime + counter = 0 + jobs += "
                    Non-human Positions
                    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
                    [ROLE_DRONE][ROLE_DRONE][ROLE_PAI][ROLE_PAI]ObserverObserverAntagHUDAntagHUD
                    " + jobs += "" + for(var/jobPos in entertaiment_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 += "
                    Entertaiment Positions
                    [replacetext(job.title, " ", " ")][replacetext(job.title, " ", " ")]
                    " */ + + //Antagonist (Orange) + var/isbanned_dept = jobban_isbanned(M, "Syndicate") + jobs += "" + jobs += "" + + //Traitor + if(jobban_isbanned(M, ROLE_TRAITOR) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Changeling + if(jobban_isbanned(M, ROLE_CHANGELING) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Nuke Operative + if(jobban_isbanned(M, ROLE_OPERATIVE) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Revolutionary + if(jobban_isbanned(M, ROLE_REV) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Raider (New heist) + if(jobban_isbanned(M, ROLE_RAIDER) || isbanned_dept) + jobs += "" + else + jobs += "" + + jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries + + //Cultist + if(jobban_isbanned(M, ROLE_CULTIST) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Wizard + if(jobban_isbanned(M, ROLE_WIZARD) || isbanned_dept) + jobs += "" + else + jobs += "" + + //ERT + if(jobban_isbanned(M, ROLE_ERT) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Meme + if(jobban_isbanned(M, ROLE_MEME) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Mutineer + if(jobban_isbanned(M, ROLE_MUTINEER) || isbanned_dept) + jobs += "" + else + jobs += "" + + jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries + + //Shadowling + if(jobban_isbanned(M, ROLE_SHADOWLING) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Abductor + if(jobban_isbanned(M, ROLE_ABDUCTOR) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Ninja + if(jobban_isbanned(M, ROLE_NINJA) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Blob + if(jobban_isbanned(M, ROLE_BLOB) || isbanned_dept) + jobs += "" + else + jobs += "" + + //Malfunctioning AI + if(jobban_isbanned(M, ROLE_MALF) || isbanned_dept) + jobs += "" + else + jobs += "" + + jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries + + //Xenomorph + if(jobban_isbanned(M, ROLE_ALIEN) || isbanned_dept) + jobs += "" + else + jobs += "" + + jobs += "
                    Antagonist Positions
                    [ROLE_TRAITOR][ROLE_TRAITOR][ROLE_CHANGELING][ROLE_CHANGELING][ROLE_OPERATIVE][ROLE_OPERATIVE][ROLE_REV][ROLE_REV][ROLE_RAIDER][ROLE_RAIDER]
                    [ROLE_CULTIST][ROLE_CULTIST][ROLE_WIZARD][ROLE_WIZARD][ROLE_ERT][ROLE_ERT][ROLE_MEME][ROLE_MEME][ROLE_MUTINEER][ROLE_MUTINEER]
                    [ROLE_SHADOWLING][ROLE_SHADOWLING][ROLE_ABDUCTOR][ROLE_ABDUCTOR][ROLE_NINJA][ROLE_NINJA][ROLE_BLOB][ROLE_BLOB][ROLE_MALF][ROLE_MALF]
                    [ROLE_ALIEN][ROLE_ALIEN]
                    " + + //Other races (BLUE, because I have no idea what other color to make this) + jobs += "" + jobs += "" + + if(jobban_isbanned(M, ROLE_PLANT)) + jobs += "" + else + jobs += "" + + if(jobban_isbanned(M, "Mouse")) + jobs += "" + else + jobs += "" + + + jobs += "
                    Other Races
                    [ROLE_PLANT][ROLE_PLANT]MouseMouse
                    " + + + body = "[jobs]" + dat = "[header][body]" + usr << browse(entity_ja(dat), "window=jobban2;size=800x490") + return + + //JOBBAN'S INNARDS + else if(href_list["jobban3"]) + if(!check_rights(R_ADMIN)) + 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(!SSjob) + 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 = SSjob.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("securitydept") + for(var/jobPos in security_positions) + if(!jobPos) continue + var/datum/job/temp = SSjob.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("engineeringdept") + for(var/jobPos in engineering_positions) + if(!jobPos) continue + var/datum/job/temp = SSjob.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("medicaldept") + for(var/jobPos in medical_positions) + if(!jobPos) continue + var/datum/job/temp = SSjob.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("sciencedept") + for(var/jobPos in science_positions) + if(!jobPos) continue + var/datum/job/temp = SSjob.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("civiliandept") + for(var/jobPos in civilian_positions) + if(!jobPos) continue + var/datum/job/temp = SSjob.GetJob(jobPos) + if(!temp) continue + joblist += temp.title +/* if("entertaimentdept") + for(var/jobPos in entertaiment_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title */ + if("nonhumandept") + joblist += ROLE_DRONE + joblist += ROLE_PAI + for(var/jobPos in nonhuman_positions) + if(!jobPos) continue + var/datum/job/temp = SSjob.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(!check_rights(R_BAN)) return + var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null + if(!mins) + return + var/reason = sanitize(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) + if(M.client) + jobban_buildcache(M.client) + feedback_add_details("ban_job_tmp","- [job]") + if(!msg) + msg = job + else + msg += ", [job]" + notes_add(M.ckey, "Banned from [msg] - [reason]") + message_admins("\blue [key_name_admin(usr)] banned [key_name_admin(M)] from [msg] for [mins] minutes") + to_chat(M, "\redYou have been jobbanned by [usr.client.ckey] from: [msg].") + to_chat(M, "\red The reason is: [reason]") + to_chat(M, "\red This jobban will be lifted in [mins] minutes.") + href_list["jobban2"] = 1 // lets it fall through and refresh + return 1 + if("No") + if(!check_rights(R_BAN)) + return + var/reason = sanitize(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) + if(M.client) + jobban_buildcache(M.client) + feedback_add_details("ban_job","- [job]") + if(!msg) msg = job + else msg += ", [job]" + notes_add(M.ckey, "Banned from [msg] - [reason]") + message_admins("\blue [key_name_admin(usr)] banned [key_name_admin(M)] from [msg]") + to_chat(M, "\redYou have been jobbanned by [usr.client.ckey] from: [msg].") + to_chat(M, "\red The reason is: [reason]") + to_chat(M, "\red 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. + 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_ANY_JOB, job) + if(M.client) + jobban_buildcache(M.client) + feedback_inc("ban_job_unban",1) + feedback_add_details("ban_job_unban","- [job]") + if(!msg) msg = job + else msg += ", [job]" + else + continue + if(msg) + message_admins("\blue [key_name_admin(usr)] unbanned [key_name_admin(M)] from [msg]") + to_chat(M, "\redYou 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["geoip"]) + var/mob/M = locate(href_list["geoip"]) + if (ismob(M)) + if(!M.client) + return + var/dat = "GeoIP info" + var/client/C = M.client + if(C.geoip.status != "updated" || C.geoip.status != "admin") + C.geoip.try_update_geoip(C, C.address) + dat += "
                    Ckey: [M.ckey]
                    " + dat += "Country: [C.geoip.country]
                    " + dat += "CountryCode: [C.geoip.countryCode]
                    " + dat += "Region: [C.geoip.region]
                    " + dat += "Region Name: [C.geoip.regionName]
                    " + dat += "City: [C.geoip.city]
                    " + dat += "Timezone: [C.geoip.timezone]
                    " + dat += "ISP: [C.geoip.isp]
                    " + dat += "Mobile: [C.geoip.mobile]
                    " + dat += "Proxy: [C.geoip.proxy]
                    " + dat += "IP: [C.geoip.ip]
                    " + dat += "
                    Status: [C.geoip.status]" + usr << browse(entity_ja(dat), "window=geoip") + + else if(href_list["cid_list"]) + var/mob/M = locate(href_list["cid_list"]) + if (ismob(M)) + if(!M.client) + return + var/client/C = M.client + var/dat = "[C.ckey] cid list" + dat += "
                    Ckey: [C.ckey] | Ignore warning: [C.prefs.ignore_cid_warning ? "yes" : "no"]
                    " + for(var/x in C.prefs.cid_list) + dat += "computer_id: [x] - first seen: [C.prefs.cid_list[x]["first_seen"]] - last seen: [C.prefs.cid_list[x]["last_seen"]]
                    " + usr << browse(entity_ja(dat), "window=[C.ckey]_cid_list") + + else if(href_list["cid_ignore"]) + var/mob/M = locate(href_list["cid_ignore"]) + if (ismob(M)) + if(!M.client) + return + var/client/C = M.client + C.prefs.ignore_cid_warning = !(C.prefs.ignore_cid_warning) + log_admin("[key_name(usr)] has [C.prefs.ignore_cid_warning ? "disabled" : "enabled"] multiple cid notice for [C.ckey].") + message_admins("[key_name_admin(usr)] has [C.prefs.ignore_cid_warning ? "disabled" : "enabled"] multiple cid notice for [C.ckey].") + + else if(href_list["related_accounts"]) + var/mob/M = locate(href_list["related_accounts"]) + if (ismob(M)) + if(!M.client) + return + var/client/C = M.client + + var/dat = "[C.key] related accounts by IP and cid" + dat += "
                    Ckey: [C.ckey]

                    " + dat += "IP: [C.related_accounts_ip]
                    " + dat += "CID: [C.related_accounts_cid]" + + usr << browse(entity_ja(dat), "window=[C.ckey]_related_accounts") + + else if(href_list["boot2"]) + var/mob/M = locate(href_list["boot2"]) + if (ismob(M)) + if(!check_if_greater_rights_than(M.client)) + return + var/reason = sanitize(input("Please enter reason")) + if(!reason) + to_chat(M, "\red You have been kicked from the server") + else + to_chat(M, "\red You have been kicked from the server: [reason]") + log_admin("[key_name(usr)] booted [key_name(M)].") + message_admins("\blue [key_name_admin(usr)] booted [key_name_admin(M)].") + //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["newban"]) + if(!check_rights(R_BAN)) return + + var/mob/M = locate(href_list["newban"]) + if(!ismob(M)) return + + 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 = sanitize(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, "\redYou have been banned by [usr.client.ckey].\nReason: [reason].") + to_chat(M, "\red 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, "\red To try to resolve this matter head to [config.banappeals]") + else + to_chat(M, "\red 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("\blue[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") + if(!check_rights(R_BAN)) return + var/reason = sanitize(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) + to_chat(M, "\redYou have been banned by [usr.client.ckey].\nReason: [reason].") + to_chat(M, "\red This is a permanent ban.") + if(config.banappeals) + to_chat(M, "\red To try to resolve this matter head to [config.banappeals]") + else + to_chat(M, "\red 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("\blue[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["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(entity_ja(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(entity_ja(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("\blue [key_name_admin(usr)] set the mode as [master_mode].") + to_chat(world, "\blue 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("\blue [key_name_admin(usr)] set the forced secret mode as [secret_force_mode].") + 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("\blue [key_name_admin(usr)] attempting to monkeyize [key_name_admin(H)]") + H.monkeyize() + + 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("\blue [key_name_admin(usr)] attempting to corgize [key_name_admin(H)]") + H.corgize() + + 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("\blue [key_name_admin(usr)] forced [key_name_admin(M)] to say: [speech]") + + else if(href_list["sendtoprison"]) + if(!check_rights(R_ADMIN)) return + + if(alert(usr, "Send to admin prison for the round?", "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.drop_from_inventory(I, locker) + M.update_icons() + + //so they black out before warping + M.Paralyse(5) + sleep(5) + if(!M) return + + 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, "\red You have been sent to the prison station!") + log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.") + message_admins("\blue [key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.") + + else if(href_list["tdome1"]) + if(!check_rights(R_FUN)) + return + + if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") + return + + var/mob/M = locate(href_list["tdome1"]) + 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.drop_from_inventory(I) + + M.Paralyse(5) + sleep(5) + M.loc = pick(tdome1) + spawn(50) + to_chat(M, "\blue You have been sent to the Thunderdome.") + log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team 1)") + message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Team 1)") + + else if(href_list["tdome2"]) + if(!check_rights(R_FUN)) + return + + if(alert(usr, "Confirm?", "Message", "Yes", "No") != "Yes") + return + + var/mob/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 + + for(var/obj/item/I in M) + M.drop_from_inventory(I) + + M.Paralyse(5) + sleep(5) + M.loc = pick(tdome2) + spawn(50) + to_chat(M, "\blue You have been sent to the Thunderdome.") + log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team 2)") + message_admins("[key_name_admin(usr)] has sent [key_name_admin(M)] to the thunderdome. (Team 2)") + + 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, "\blue 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.)") + + 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.drop_from_inventory(I) + + 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, "\blue 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.)") + + 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() + message_admins("\red Admin [key_name_admin(usr)] healed / revived [key_name_admin(L)]!") + log_admin("[key_name(usr)] healed / Rrvived [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("\red Admin [key_name_admin(usr)] AIized [key_name_admin(H)]!") + log_admin("[key_name(usr)] AIized [key_name(H)]") + H.AIize() + + 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 + + usr.client.cmd_admin_alienize(H) + + 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 + + usr.client.cmd_admin_slimeize(H) + + else if(href_list["makeblob"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["makeblob"]) + if(!istype(H)) + to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human") + return + + usr.client.cmd_admin_blobize(H) + + 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 + + usr.client.cmd_admin_robotize(H) + + else if(href_list["makeanimal"]) + if(!check_rights(R_SPAWN)) return + + var/mob/M = locate(href_list["makeanimal"]) + if(isnewplayer(M)) + to_chat(usr, "This cannot be used on instances of type /mob/dead/new_player") + return + + usr.client.cmd_admin_animalize(M) + + 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() + + else if(href_list["adminplayeropts"]) + if(!check_rights(R_ADMIN)) + return + + var/mob/M = locate(href_list["adminplayeropts"]) + show_player_panel(M) + + else if(href_list["adminplayerobservejump"]) + if(!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) + C.jumptomob(M) + + else if(href_list["check_antagonist"]) + if(!check_rights(R_ADMIN)) + return + + check_antagonists() + + else if(href_list["adminplayerobservefollow"]) + if(!isobserver(usr) && !check_rights(R_ADMIN)) + return + + var/atom/movable/AM = locate(href_list["adminplayerobservefollow"]) + + var/client/C = usr.client + if(!isobserver(usr)) C.admin_ghost() + var/mob/dead/observer/A = C.mob + A.ManualFollow(AM) + + 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"]) + if(!check_rights(R_ADMIN)) + return + + 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/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]" + + to_chat(src.owner, "Info about [M.name]: ") + to_chat(src.owner, "Mob type = [M.type]; 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)) + 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, "\blue 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/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.l_ear, /obj/item/device/radio/headset) && !istype(H.r_ear, /obj/item/device/radio/headset)) + to_chat(usr, "The person you are trying to contact is not wearing a headset") + return + + var/input = sanitize(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]\"") + send2slack_custommsg("[key_name(src.owner)] replied to [key_name(H)]'s Centcom message", input, ":job-cap:") + 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.l_ear, /obj/item/device/radio/headset) && !istype(H.r_ear, /obj/item/device/radio/headset)) + to_chat(usr, "The person you are trying to contact is not wearing a headset") + return + + var/input = sanitize(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].") + message_admins("[src.owner] replied to [key_name(H)]'s Syndicate message with: \"[input]\"") + send2slack_custommsg("[key_name(src.owner)] replied to [key_name(H)]'s Syndicate message", input, ":job-nuke:") + 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["CentcommFaxViewInfo"]) + var/info = locate(href_list["CentcommFaxViewInfo"]) + var/stamps = locate(href_list["CentcommFaxViewStamps"]) + + usr << browse("Centcomm Fax Message[entity_ja(info)][stamps]", "window=Centcomm Fax Message") + + else if(href_list["CentcommFaxReply"]) + var/mob/living/carbon/human/H = locate(href_list["CentcommFaxReply"]) + + var/input = sanitize(input(src.owner, "Please, enter a message to reply to [key_name(H)] via secure connection. NOTE: BBCode does not work.", "Outgoing message from Centcomm", "") as message|null, extra = FALSE) + if(!input) + return + + var/customname = sanitize_safe(input(src.owner, "Pick a title for the report", "Title") as text|null) + + var/obj/item/weapon/paper/P = new + P.name = "[command_name()]- [customname]" + P.info = input + + var/obj/item/weapon/stamp/centcomm/S = new + S.stamp_paper(P, use_stamp_by_message = TRUE) + + send_fax(usr, P, "All") + + to_chat(src.owner, "Message reply to transmitted successfully.") + log_admin("[key_name(src.owner)] replied to a fax message from [key_name(H)]: [input]") + message_admins("[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(H)]") + send2slack_custommsg("[key_name(src.owner)] replied to a fax message from [key_name(H)]", input, ":fax:") + + + 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["traitor"]) + if(!check_rights(R_ADMIN)) + 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) + + 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/item/weapon/melee/energy/blade))//Not an item one should be able to spawn./N + 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" + jointext(removed_paths, "\n")) + + var/list/offset = splittext(href_list["offset"],",") + var/number = dd_range(1, 100, text2num(href_list["object_count"])) + 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 list(1,2,4,8,5,6,9,10))) + obj_dir = 2 + var/obj_name = sanitize(href_list["object_name"]) + var/atom/target //Where the object will be spawned + var/where = href_list["object_where"] + if (!( where in list("onfloor","inhand","inmarked","dropped") )) + where = "onfloor" + + + switch(where) + if("inhand") + if (!iscarbon(usr) && !isrobot(usr)) + to_chat(usr, "Can only spawn in hand when you're a carbon mob or cyborg.") + where = "onfloor" + if(isrobot(usr)) + var/mob/living/silicon/robot/R = usr + if(!R.module) + to_chat(R, "Cyborg doesn't has module, you can't do that.") + return + target = usr + if("onfloor", "dropped") + 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") + 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 + else + target = marked_datum + + + if(target) + for (var/path in paths) + for (var/i = 0; i < number; i++) + if(where == "dropped") + new /obj/effect/falling_effect(target, path) + else if(path in typesof(/turf)) + var/turf/O = target + var/turf/N = O.ChangeTurf(path) + if(N && 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(where == "inhand" && isliving(usr) && istype(O, /obj/item)) + var/mob/living/L = usr + var/obj/item/I = O + L.put_in_hands(I) + if(isrobot(L)) + var/mob/living/silicon/robot/R = L + if(R.module) + R.module.modules += I + I.loc = R.module + R.module.rebuild() + R.activate_module(I) + + if (number == 1) + log_admin("[key_name(usr)] created a [english_list(paths)]") + for(var/path in paths) + if(ispath(path, /mob)) + message_admins("[key_name_admin(usr)] created a [english_list(paths)]") + break + else + log_admin("[key_name(usr)] created [number]ea [english_list(paths)]") + for(var/path in paths) + if(ispath(path, /mob)) + message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)]") + break + return + + else if(href_list["secretsfun"]) + if(!check_rights(R_FUN|R_EVENT)) + 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) + qdel(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) + qdel(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) + qdel(O) + for(var/obj/structure/grille/O in world) + qdel(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 + qdel(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 human_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 human_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 all_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.") + message_admins("\blue [key_name_admin(usr)] toggled gravity on.") + command_alert("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") + else + log_admin("[key_name(usr)] toggled gravity off.") + message_admins("\blue [key_name_admin(usr)] toggled gravity off.") + 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") + message_admins("\blue [key_name_admin(usr)] spawned a meteor wave.") + 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") + message_admins("\blue [key_name_admin(usr)] spawned a blob.") + 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") + message_admins("\blue [key_name_admin(usr)] attempted an alien infestation") + new /datum/event/alien_infestation + if("borers") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","Borers") + log_admin("[key_name(usr)] spawned a cortical borer infestation.") + message_admins("\blue [key_name_admin(usr)] spawned a cortical borer infestation.") + new /datum/event/borer_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") + message_admins("\blue [key_name_admin(usr)] made all areas powered") + power_restore(badminery=1) + 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") + message_admins("\blue [key_name_admin(usr)] made all areas unpowered") + power_failure() + if("quickpower") + if(power_fail_event) + to_chat(usr, "Power fail event is in progress.. Please wait or use normal power restore.") + return + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","QP") + log_admin("[key_name(usr)] made all SMESs powered") + message_admins("\blue [key_name_admin(usr)] made all SMESs powered") + power_restore_quick() + 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("\blue [key_name_admin(usr)] teleported all players to the prison station.") + for(var/mob/living/carbon/human/H in human_list) + var/turf/loc = find_loc(H) + var/security = 0 + if(loc.z > ZLEVEL_STATION || prisonwarped.Find(H)) +//don't warp them if they aren't ready or are already there + continue + H.Paralyse(5) + if(H.wear_id) + var/obj/item/weapon/card/id/id = H.get_idcard() + for(var/A in id.access) + if(A == access_security) + security++ + if(!security) + //strip their stuff before they teleport into a cell :downs: + for(var/obj/item/weapon/W in H) + if(istype(W, /obj/item/organ/external)) + continue + //don't strip organs + H.drop_from_inventory(W) + //teleport person to cell + H.loc = pick(prisonwarp) + H.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(H), slot_shoes) + else + //teleport security person + H.loc = pick(prisonsecuritywarp) + prisonwarped += H + if("traitor_all") + if(!ticker) + alert("The game hasn't started yet!") + return + var/objective = sanitize(input("Enter an objective")) + 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 == DEAD || !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("\blue [key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]") + log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]") + + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","ShM") + if("moveadminshuttle") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","ShA") + move_admin_shuttle() + message_admins("\blue [key_name_admin(usr)] moved the centcom administration shuttle") + 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") + move_ferry() + message_admins("\blue [key_name_admin(usr)] moved the centcom ferry") + 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("\blue [key_name_admin(usr)] moved the alien dinghy") + 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 + if(128) 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("\red [key_name_admin(usr)] changed the bomb cap to [range_dev], [range_high], [range_low]") + 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 != DEAD && 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("\blue You shudder as if cold..."), 1) + if(2) + M.show_message(text("\blue You feel something gliding across your back..."), 1) + if(3) + M.show_message(text("\blue Your eyes twitch, you feel like something you can't see is here..."), 1) + if(4) + M.show_message(text("\blue 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 != DEAD) + M.show_message(text("\blue The chilling wind suddenly stops..."), 1) + + if("wave") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","MW") + new /datum/event/meteor_wave + + if("bluespaceanomaly") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BA") + message_admins("[key_name_admin(usr)] has triggered a bluespace anomaly") + new /datum/event/anomaly/anomaly_bluespace() + + if("energeticflux") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","FLUX") + message_admins("[key_name_admin(usr)] has triggered an energetic flux") + new /datum/event/anomaly/anomaly_flux() + + if("frost") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","FROST") + message_admins("[key_name_admin(usr)] freezed the station") + var/datum/anomaly_frost/FROST = new /datum/anomaly_frost() + FROST.set_params(usr) + + if("pyroanomalies") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","PYRO") + message_admins("[key_name_admin(usr)] has spawned a pyroclastic anomaly") + new /datum/event/anomaly/anomaly_pyro() + + if("gravanomalies1") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","GA") + message_admins("[key_name_admin(usr)] has spawned a gravitational anomaly") + new /datum/event/anomaly/anomaly_grav() + + if("blackhole") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","BH") + message_admins("[key_name_admin(usr)] has spawned a vortex anomaly") + new /datum/event/anomaly/anomaly_vortex() + + 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") + 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)) + qdel(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") + 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") + 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") + 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.") + if("spaceninja") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","SN") + if(toggle_space_ninja) + if(space_ninja_arrival())//If the ninja is actually spawned. They may not be depending on a few factors. + message_admins("[key_name_admin(usr)] has sent in a space ninja") + 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.") + 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") + 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") + immovablerod() + if("spawnguns") + feedback_inc("admin_secrets_fun_used", 1) + feedback_add_details("admin_secrets_fun_used", "SG") + rightandwrong(0, usr) + if("spawnspells") + feedback_inc("admin_secrets_fun_used", 1) + feedback_add_details("admin_secrets_fun_used", "SP") + rightandwrong(1, usr) + 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") + prison_break() + if("lighstout") + 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") + 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") + 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 machines) + L.fix() + message_admins("[key_name_admin(usr)] fixed all lights") + if("friendai") + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","FA") + for(var/mob/camera/Eye/ai/aE in ai_eyes_list) + aE.icon_state = "ai_friend" + for(var/obj/machinery/ai_status_display/A in ai_status_display_list) + A.emotion = "Friend Computer" + for(var/obj/machinery/status_display/A in status_display_list) + A.friendc = 1 + message_admins("[key_name_admin(usr)] turned all AIs into best friends.") + if("floorlava") + SSweather.run_weather("the floor is lava", ZLEVEL_STATION) + if("advanceddarkness") + SSweather.run_weather("advanced darkness", ZLEVEL_STATION) + 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.") + else + virus2_greater_infection() + message_admins("[key_name_admin(usr)] has triggered a greater virus outbreak.") + 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, "\red 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("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.item_color = "schoolgirl" + message_admins("[key_name_admin(usr)] activated Japanese Animes mode") + 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 airlock_list) + if(W.z == ZLEVEL_STATION && !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.") + 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 human_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") + IonStorm() + 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") + 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") + 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("drop_asteroid") + if(!check_rights(R_EVENT)) + to_chat(usr, "You don't have permissions for this") + return + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","ASTEROID") + usr.client.drop_asteroid() + 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") + //I do nothing + if("clear_virus") + var/choice1 = input("Are you sure you want to cure all disease?") in list("Yes", "Cancel") + if(choice1 == "Yes") + message_admins("[key_name_admin(usr)] has cured all diseases.") + for(var/mob/living/carbon/M in carbon_list) + if(M.virus2.len) + for(var/ID in M.virus2) + var/datum/disease2/disease/V = M.virus2[ID] + V.cure(M) + + for(var/obj/effect/decal/cleanable/O in decal_cleanable) + if(istype(O,/obj/effect/decal/cleanable/blood)) + var/obj/effect/decal/cleanable/blood/B = O + if(B.virus2.len) + B.virus2.Cut() + + else if(istype(O,/obj/effect/decal/cleanable/mucus)) + var/obj/effect/decal/cleanable/mucus/N = O + if(N.virus2.len) + N.virus2.Cut() + if("restore_air") // this is unproper way to restore turfs default gas values, since you can delete sleeping agent for example. + var/turf/simulated/T = get_turf(usr) + if((istype(T, /turf/simulated/floor) || istype(T, /turf/simulated/shuttle/floor)) && T.zone.air) + var/datum/gas_mixture/GM = T.zone.air + + for(var/g in gas_data.gases) + GM.gas -= g + + GM.gas["carbon_dioxide"] = T.carbon_dioxide + GM.gas["phoron"] = T.phoron + GM.gas["nitrogen"] = T.nitrogen + GM.gas["oxygen"] = T.oxygen + GM.temperature = 293 + GM.update_values() + + message_admins("[key_name_admin(usr)] has restored air in [T.x] [T.y] [T.z] JMP.") + else + to_chat(usr, "You are staying on incorrect turf.") + if("list_bombers") + var/dat = "Bombing List
                    " + for(var/l in bombers) + dat += text("[l]
                    ") + usr << browse(entity_ja(dat), "window=bombers") + if("list_signalers") + var/dat = "Showing last [length(lastsignalers)] signalers.
                    " + for(var/sig in lastsignalers) + dat += "[sig]
                    " + usr << browse(entity_ja(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(entity_ja(dat), "window=lawchanges;size=800x500") + if("list_job_debug") + var/dat = "Job Debug info.
                    " + if(SSjob) + for(var/line in SSjob.job_debug) + dat += "[line]
                    " + dat+= "*******

                    " + for(var/datum/job/job in SSjob.occupations) + if(!job) continue + dat += "job: [job.title], current_positions: [job.current_positions], total_positions: [job.total_positions]
                    " + usr << browse(entity_ja(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 human_list) + if(H.ckey) + dat += text("", H.name, H.get_assignment()) + dat += "
                    NamePosition
                    [][]
                    " + usr << browse(entity_ja(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 human_list) + if(H.dna && H.ckey) + dat += "" + dat += "
                    NameDNABlood Type
                    [H][H.dna.unique_enzymes][H.b_type]
                    " + usr << browse(entity_ja(dat), "window=DNA;size=440x410") + if("fingerprints") + var/dat = "Showing Fingerprints.
                    " + dat += "" + for(var/mob/living/carbon/human/H in human_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(entity_ja(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(entity_ja(dat), "window=admin_log") + if("maint_access_brig") + for(var/obj/machinery/door/airlock/maintenance/M in airlock_list) + 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 airlock_list) + 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 = SSjob.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.") + + 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 = sanitize(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", input_default(admincaster_feed_channel.channel_name))) + 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 = 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 = sanitize(input(usr, "Write your Feed story", "Network Channel Handler", input_default(admincaster_feed_message.body)), extra = FALSE) + 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 = sanitize(input(usr, "Provide the name of the Wanted person", "Network Security Handler", input_default(admincaster_feed_message.author))) + src.access_news_network() + + else if(href_list["ac_set_wanted_desc"]) + src.admincaster_feed_message.body = sanitize(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", "")) + 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 = sanitize(input(usr, "Provide your desired signature", "Network Identity Handler", "")) + src.access_news_network() + + else if(href_list["readbook"]) + var/bookid = text2num(href_list["readbook"]) + + if(!isnum(bookid)) + return + + var/DBQuery/query = dbcon_old.NewQuery("SELECT content FROM library WHERE id = '[bookid]'") + + if(!query.Execute()) + return + + var/content + if(query.NextRow()) + content = query.item[1] + else + return + + usr << browse(entity_ja(content), "window=book") + + else if(href_list["restorebook"]) + if(!check_rights(R_PERMISSIONS)) + return + + if(alert(usr, "Confirm restoring?", "Message", "Yes", "No") != "Yes") + return + var/bookid = text2num(href_list["restorebook"]) + + if(!isnum(bookid)) + return + + var/DBQuery/query = dbcon_old.NewQuery("SELECT title FROM library WHERE id = '[bookid]'") + if(!query.Execute()) + return + + var/title + if(query.NextRow()) + title = query.item[1] + else + return + + query = dbcon_old.NewQuery("UPDATE library SET deletereason = NULL WHERE id = '[bookid]'") + if(!query.Execute()) + return + + library_recycle_bin() + log_admin("[key_name_admin(usr)] restored [title] from the recycle bin") + message_admins("[key_name_admin(usr)] restored [title] from the recycle bin") + + else if(href_list["deletebook"]) + if(!check_rights(R_PERMISSIONS)) + return + + if(alert(usr, "Confirm removal?", "Message", "Yes", "No") != "Yes") + return + + var/bookid = text2num(href_list["deletebook"]) + + if(!isnum(bookid)) + return + + var/DBQuery/query = dbcon_old.NewQuery("SELECT title FROM library WHERE id = '[bookid]'") + + if(!query.Execute()) + return + + var/title + if(query.NextRow()) + title = query.item[1] + else + return + + query = dbcon_old.NewQuery("DELETE FROM library WHERE id='[bookid]'") + if(!query.Execute()) + return + + library_recycle_bin() + log_admin("[key_name_admin(usr)] restored [title] from the recycle bin") + message_admins("[key_name_admin(usr)] removed [title] from the library database") + + else if(href_list["vsc"]) + if(check_rights(R_ADMIN|R_SERVER)) + if(href_list["vsc"] == "airflow") + vsc.ChangeSettingsDialog(usr,vsc.settings) + if(href_list["vsc"] == "phoron") + vsc.ChangeSettingsDialog(usr,vsc.plc.settings) + if(href_list["vsc"] == "default") + vsc.SetDefault(usr) + + else if(href_list["viewruntime"]) + if(!check_rights(R_DEBUG)) + return + + var/datum/error_viewer/error_viewer = locate(href_list["viewruntime"]) + if(!istype(error_viewer)) + to_chat(usr, "That runtime viewer no longer exists.") + return + + if(href_list["viewruntime_backto"]) + error_viewer.show_to(owner, locate(href_list["viewruntime_backto"]), href_list["viewruntime_linear"]) + else + error_viewer.show_to(owner, null, href_list["viewruntime_linear"]) + + // 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//sanitise below in notes_add + if(!add) return + + notes_add(key, add, usr.client) + 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, usr.client) + 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 diff --git a/code/modules/admin/verbs/BrokenInhands.dm b/code/modules/admin/verbs/BrokenInhands.dm index aa90cc8ce3d5..b481e0a4b96c 100644 --- a/code/modules/admin/verbs/BrokenInhands.dm +++ b/code/modules/admin/verbs/BrokenInhands.dm @@ -1,34 +1,34 @@ -/proc/getbrokeninhands() - var/text - for(var/A in typesof(/obj/item)) - var/obj/item/O = new A( locate(1,1,1) ) - if(!O) continue - var/icon/IL = new(O.lefthand_file) - var/list/Lstates = IL.IconStates() - var/icon/IR = new(O.righthand_file) - var/list/Rstates = IR.IconStates() - 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" - qdel(O) - if(text) - var/F = file("broken_icons.txt") - fdel(F) - to_chat(F, text) - to_chat(world, "Completeled successfully and written to [F]") - - +/proc/getbrokeninhands() + var/text + for(var/A in typesof(/obj/item)) + var/obj/item/O = new A( locate(1,1,1) ) + if(!O) continue + var/icon/IL = new(O.lefthand_file) + var/list/Lstates = IL.IconStates() + var/icon/IR = new(O.righthand_file) + var/list/Rstates = IR.IconStates() + 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" + qdel(O) + if(text) + var/F = file("broken_icons.txt") + fdel(F) + to_chat(F, text) + to_chat(world, "Completeled successfully and written to [F]") + + diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index ed1888ce1489..86ddff7926b1 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -1,19 +1,19 @@ -/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, "\red Speech is currently admin-disabled.") - return - - if(!mob) - return //this doesn't happen - - //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 - - staffhelp(msg, help_type = "AH") +/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, "\red Speech is currently admin-disabled.") + return + + if(!mob) + return //this doesn't happen + + //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 + + staffhelp(msg, help_type = "AH") diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index bb997f71a693..aff8c66c9361 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -1,161 +1,161 @@ -/client/proc/Jump(area/A in return_sorted_areas()) - 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(src.mob) - var/mob/AM = src.mob - AM.forceMove(pick(get_area_turfs(A))) - log_admin("[key_name(usr)] jumped to [A]") - message_admins("[key_name_admin(usr)] jumped to [A]") - 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(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) - if(src.mob) - var/mob/A = src.mob - A.forceMove(T) - 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]") - 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(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) - - if(src.mob) - var/mob/A = src.mob - var/turf/T = get_turf(M) - if(T && isturf(T)) - A.forceMove(T) - log_admin("[key_name(usr)] jumped to [key_name(M)]") - message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]") - feedback_add_details("admin_verb","JM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - 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) - to_chat(src, "Only administrators may use this command.") - return - - if (config.allow_admin_jump) - if(src.mob) - var/mob/A = src.mob - A.forceMove(locate(tx,ty,tz)) - log_admin("[key_name(usr)] jumped to coordinates [tx], [ty], [tz]") - message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]") - feedback_add_details("admin_verb","JC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - 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) - keys += M.client - var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys) - if(!selection) - to_chat(src, "No keys found.") - return - var/mob/M = selection:mob - if(src.mob) - var/mob/A = src.mob - A.forceMove(M.loc) - log_admin("[key_name(usr)] jumped to [key_name(M)]") - message_admins("[key_name_admin(usr)] jumped to [key_name_admin(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(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) - M.forceMove(get_turf(usr)) - log_admin("[key_name(usr)] teleported [key_name(M)]") - message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]") - 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) - keys += M.client - var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys) - if(!selection) - return - var/mob/M = selection:mob - - if(!M) - return - - if(M) - M.forceMove(get_turf(usr)) - log_admin("[key_name(usr)] teleported [key_name(M)]") - message_admins("[key_name_admin(usr)] teleported [key_name(M)]") - 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(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 return_sorted_areas() - if(A) - if(config.allow_admin_jump) - M.forceMove(pick(get_area_turfs(A))) - log_admin("[key_name(usr)] teleported [key_name(M)] to [A]") - message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]") - feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - else - alert("Admin jumping disabled") +/client/proc/Jump(area/A in return_sorted_areas()) + 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(src.mob) + var/mob/AM = src.mob + AM.forceMove(pick(get_area_turfs(A))) + log_admin("[key_name(usr)] jumped to [A]") + message_admins("[key_name_admin(usr)] jumped to [A]") + 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(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) + if(src.mob) + var/mob/A = src.mob + A.forceMove(T) + 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]") + 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(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) + + if(src.mob) + var/mob/A = src.mob + var/turf/T = get_turf(M) + if(T && isturf(T)) + A.forceMove(T) + log_admin("[key_name(usr)] jumped to [key_name(M)]") + message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]") + feedback_add_details("admin_verb","JM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + 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) + to_chat(src, "Only administrators may use this command.") + return + + if (config.allow_admin_jump) + if(src.mob) + var/mob/A = src.mob + A.forceMove(locate(tx,ty,tz)) + log_admin("[key_name(usr)] jumped to coordinates [tx], [ty], [tz]") + message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]") + feedback_add_details("admin_verb","JC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + 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) + keys += M.client + var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys) + if(!selection) + to_chat(src, "No keys found.") + return + var/mob/M = selection:mob + if(src.mob) + var/mob/A = src.mob + A.forceMove(M.loc) + log_admin("[key_name(usr)] jumped to [key_name(M)]") + message_admins("[key_name_admin(usr)] jumped to [key_name_admin(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(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) + M.forceMove(get_turf(usr)) + log_admin("[key_name(usr)] teleported [key_name(M)]") + message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]") + 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) + keys += M.client + var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in sortKey(keys) + if(!selection) + return + var/mob/M = selection:mob + + if(!M) + return + + if(M) + M.forceMove(get_turf(usr)) + log_admin("[key_name(usr)] teleported [key_name(M)]") + message_admins("[key_name_admin(usr)] teleported [key_name(M)]") + 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(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 return_sorted_areas() + if(A) + if(config.allow_admin_jump) + M.forceMove(pick(get_area_turfs(A))) + log_admin("[key_name(usr)] teleported [key_name(M)] to [A]") + message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]") + feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + else + alert("Admin jumping disabled") diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index f96737f2fe62..298adb4fe915 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -1,22 +1,22 @@ -/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 - if(prefs.muted & MUTE_ADMINHELP) - to_chat(src, "Error: ASAY: You cannot use asay (Muted).") - return - - msg = sanitize(msg) - if(!msg) - return - - log_adminsay("[key_name(src)] : [msg]", "ADMINSAY") - - msg = "ADMINSAY: [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_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 + if(prefs.muted & MUTE_ADMINHELP) + to_chat(src, "Error: ASAY: You cannot use asay (Muted).") + return + + msg = sanitize(msg) + if(!msg) + return + + log_adminsay("[key_name(src)] : [msg]", "ADMINSAY") + + msg = "ADMINSAY: [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! diff --git a/code/modules/admin/verbs/atmosdebug.dm b/code/modules/admin/verbs/atmosdebug.dm index 0255bec13c01..198f981c4d37 100644 --- a/code/modules/admin/verbs/atmosdebug.dm +++ b/code/modules/admin/verbs/atmosdebug.dm @@ -1,41 +1,41 @@ -/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 machines) - if (plumbing.nodealert) - to_chat(usr, "Unconnected [plumbing.name] located at [plumbing.x],[plumbing.y],[plumbing.z] ([get_area(plumbing.loc)])") - - //Manifolds - for (var/obj/machinery/atmospherics/pipe/manifold/pipe in machines) - if (!pipe.NODE1 || !pipe.NODE2 || !pipe.NODE3) - to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])") - - //Pipes - for (var/obj/machinery/atmospherics/pipe/simple/pipe in machines) - if (!pipe.NODE1 || !pipe.NODE2) - to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])") - -/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] - 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] - 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)]") +/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 machines) + if (plumbing.nodealert) + to_chat(usr, "Unconnected [plumbing.name] located at [plumbing.x],[plumbing.y],[plumbing.z] ([get_area(plumbing.loc)])") + + //Manifolds + for (var/obj/machinery/atmospherics/pipe/manifold/pipe in machines) + if (!pipe.NODE1 || !pipe.NODE2 || !pipe.NODE3) + to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])") + + //Pipes + for (var/obj/machinery/atmospherics/pipe/simple/pipe in machines) + if (!pipe.NODE1 || !pipe.NODE2) + to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])") + +/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] + 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] + 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 6ba5397074aa..83bb2c64e8dc 100644 --- a/code/modules/admin/verbs/deadsay.dm +++ b/code/modules/admin/verbs/deadsay.dm @@ -1,44 +1,44 @@ -/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) - to_chat(src, "\red You cannot send DSAY messages (muted).") - return - - if(!(prefs.chat_toggles & CHAT_DEAD)) - to_chat(src, "\red You have deadchat muted.") - return - - if (src.handle_spam_prevention(msg,MUTE_DEADCHAT)) - return - - var/stafftype = null - - if (src.holder.rights & R_ADMIN) - stafftype = "ADMIN" - - msg = sanitize(msg) - log_admin("[key_name(src)] : [msg]") - - if (!msg) - return - - var/rendered = "DEAD: [stafftype]([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 (isnewplayer(M)) - continue - - if(M.client && M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD)) // show the message to admins who have deadchat toggled on - M.show_message(rendered, 2) - - else if(M.stat == DEAD && (M.client.prefs.chat_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! +/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) + to_chat(src, "\red You cannot send DSAY messages (muted).") + return + + if(!(prefs.chat_toggles & CHAT_DEAD)) + to_chat(src, "\red You have deadchat muted.") + return + + if (src.handle_spam_prevention(msg,MUTE_DEADCHAT)) + return + + var/stafftype = null + + if (src.holder.rights & R_ADMIN) + stafftype = "ADMIN" + + msg = sanitize(msg) + log_admin("[key_name(src)] : [msg]") + + if (!msg) + return + + var/rendered = "DEAD: [stafftype]([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 (isnewplayer(M)) + continue + + if(M.client && M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD)) // show the message to admins who have deadchat toggled on + M.show_message(rendered, 2) + + else if(M.stat == DEAD && (M.client.prefs.chat_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! diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index e66945478a18..690a1fa0c0b4 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -1,1969 +1,1969 @@ -/client/proc/Debug2() - set category = "Debug" - set name = "Debug-Game" - if(!check_rights(R_DEBUG)) return - - if(Debug2) - Debug2 = 0 - message_admins("[key_name(src)] toggled debugging off.") - log_admin("[key_name(src)] toggled debugging off.") - else - Debug2 = 1 - message_admins("[key_name(src)] toggled debugging on.") - log_admin("[key_name(src)] toggled debugging on.") - - feedback_add_details("admin_verb","DG2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - - -/* 21st Sept 2010 -Updated by Skie -- Still not perfect but better! -Stuff you can't do: -Call proc /mob/proc/make_dizzy() for some player -Because if you select a player mob as owner it tries to do the proc for -/mob/living/carbon/human/ instead. And that gives a run-time error. -But you can call procs that are of type /mob/living/carbon/human/proc/ for that player. -*/ - -/client/proc/callproc() - set category = "Debug" - set name = "Advanced ProcCall" - - if(!check_rights(R_PERMISSIONS)) - return - - if(1) return //TODO: config option - - spawn(0) - var/target = null - var/targetselected = 0 - var/lst[] // List reference - lst = new/list() // Make the list - var/returnval = null - var/class = null - - switch(alert("Proc owned by something?",,"Yes","No")) - if("Yes") - targetselected = 1 - class = input("Proc owned by...","Owner",null) as null|anything in list("Obj","Mob","Area or Turf","Client") - switch(class) - if("Obj") - target = input("Enter target:","Target",usr) as obj in world - if("Mob") - target = input("Enter target:","Target",usr) as mob in world - if("Area or Turf") - target = input("Enter target:","Target",usr.loc) as area|turf in world - if("Client") - var/list/keys = list() - for(var/client/C) - keys += C - target = input("Please, select a player!", "Selection", null, null) as null|anything in keys - else - return - if("No") - target = null - targetselected = 0 - - var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null - if(!procname) return - - var/argnum = input("Number of arguments","Number:",0) as num|null - if(!argnum && (argnum!=0)) return - - lst.len = argnum // Expand to right length - //TODO: make a list to store whether each argument was initialised as null. - //Reason: So we can abort the proccall if say, one of our arguments was a mob which no longer exists - //this will protect us from a fair few errors ~Carn - - var/i - for(i=1, iError: callproc(): owner of proc no longer exists.") - return - if(!hascall(target,procname)) - to_chat(usr, "Error: callproc(): target has no such call [procname].") - return - log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") - returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc - else - //this currently has no hascall protection. wasn't able to get it working. - log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") - returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc - - to_chat(usr, "[procname] returned: [returnval ? returnval : "null"]") - feedback_add_details("admin_verb","APC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/Cell() - set category = "Debug" - set name = "Air Status in Location" - if(!mob) - return - var/turf/T = mob.loc - - if (!( istype(T, /turf) )) - return - - var/datum/gas_mixture/env = T.return_air() - - var/t = "Coordinates: [T.x],[T.y],[T.z]\n" - t += "Temperature: [env.temperature]\n" - t += "Pressure: [env.return_pressure()]kPa\n" - for(var/g in env.gas) - t += "[g]: [env.gas[g]] / [env.gas[g] * R_IDEAL_GAS_EQUATION * env.temperature / env.volume]kPa\n" - - - usr.show_message(t, 1) - feedback_add_details("admin_verb","ASL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_robotize(mob/M in mob_list) - set category = "Fun" - set name = "Make Robot" - - if(!ticker) - alert("Wait until the game starts") - return - if(ishuman(M)) - log_admin("[key_name(src)] has robotized [M.key].") - spawn(10) - M:Robotize() - - else - alert("Invalid mob") - -/client/proc/cmd_admin_animalize(mob/M in mob_list) - set category = "Fun" - set name = "Make Simple Animal" - - if(!ticker) - alert("Wait until the game starts") - return - - if(!M) - alert("That mob doesn't seem to exist, close the panel and try again.") - return - - if(isnewplayer(M)) - alert("The mob must not be a new_player.") - return - - log_admin("[key_name(src)] has animalized [M.key].") - spawn(10) - M.Animalize() - - -/client/proc/makepAI(turf/T in mob_list) - set category = "Fun" - set name = "Make pAI" - set desc = "Specify a location to spawn a pAI device, then specify a key to play that pAI." - - var/list/available = list() - for(var/mob/C in mob_list) - if(C.key) - available.Add(C) - var/mob/choice = input("Choose a player to play the pAI", "Spawn pAI") in available - if(!choice) - return 0 - if(!isobserver(choice)) - var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank him out of them out of their body and place them in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No") - if(confirm != "Yes") - return 0 - var/obj/item/device/paicard/card = new(T) - var/mob/living/silicon/pai/pai = new(card) - pai.name = sanitize_safe(input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text, MAX_NAME_LEN) - pai.real_name = pai.name - pai.key = choice.key - card.setPersonality(pai) - for(var/datum/paiCandidate/candidate in paiController.pai_candidates) - if(candidate.key == choice.key) - paiController.pai_candidates.Remove(candidate) - feedback_add_details("admin_verb","MPAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_alienize(mob/M in mob_list) - set category = "Fun" - set name = "Make Alien" - - if(!ticker) - alert("Wait until the game starts") - return - if(ishuman(M)) - log_admin("[key_name(src)] has alienized [M.key].") - spawn(10) - M:Alienize() - feedback_add_details("admin_verb","MKAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] made [key_name(M)] into an alien.") - message_admins("\blue [key_name_admin(usr)] made [key_name(M)] into an alien.") - else - alert("Invalid mob") - -/client/proc/cmd_admin_slimeize(mob/M in mob_list) - set category = "Fun" - set name = "Make slime" - - if(!ticker) - alert("Wait until the game starts") - return - if(ishuman(M)) - log_admin("[key_name(src)] has slimeized [M.key].") - spawn(10) - M:slimeize() - feedback_add_details("admin_verb","MKMET") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(usr)] made [key_name(M)] into a slime.") - message_admins("\blue [key_name_admin(usr)] made [key_name(M)] into a slime.") - else - alert("Invalid mob") - -/client/proc/cmd_admin_blobize(mob/M in mob_list) - set category = "Fun" - set name = "Make Blob" - - if(!ticker) - alert("Wait until the game starts") - return - if(istype(M, /mob/living/carbon/human)) - log_admin("[key_name(src)] has blobized [M.key].") - var/mob/living/carbon/human/H = M - spawn(10) - H.Blobize() - - else - alert("Invalid mob") - -/* -/client/proc/cmd_admin_monkeyize(mob/M in world) - set category = "Fun" - set name = "Make Monkey" - - if(!ticker) - alert("Wait until the game starts") - return - if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/target = M - log_admin("[key_name(src)] is attempting to monkeyize [M.key].") - spawn(10) - target.monkeyize() - else - alert("Invalid mob") - -/client/proc/cmd_admin_changelinginize(mob/M in world) - set category = "Fun" - set name = "Make Changeling" - - if(!ticker) - alert("Wait until the game starts") - return - if(istype(M, /mob/living/carbon/human)) - log_admin("[key_name(src)] has made [M.key] a changeling.") - spawn(10) - M.absorbed_dna[M.real_name] = M.dna.Clone() - M.make_changeling() - if(M.mind) - M.mind.special_role = "Changeling" - else - alert("Invalid mob") -*/ -/* -/client/proc/cmd_admin_abominize(mob/M in world) - set category = null - set name = "Make Abomination" - - to_chat(usr, "Ruby Mode disabled. Command aborted.") - return - if(!ticker) - alert("Wait until the game starts.") - return - if(istype(M, /mob/living/carbon/human)) - log_admin("[key_name(src)] has made [M.key] an abomination.") - - // spawn(10) - // M.make_abomination() - -*/ -/* -/client/proc/make_cultist(mob/M in world) // -- TLE, modified by Urist - set category = "Fun" - set name = "Make Cultist" - set desc = "Makes target a cultist" - if(!cultwords["travel"]) - runerandom() - if(M) - if(M.mind in ticker.mode.cult) - return - else - if(alert("Spawn that person a tome?",,"Yes","No")=="Yes") - to_chat(M, "\red 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. A tome, a message from your new master, appears on the ground.") - new /obj/item/weapon/book/tome(M.loc) - else - to_chat(M, "\red 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.") - var/glimpse=pick("1","2","3","4","5","6","7","8") - switch(glimpse) - if("1") - to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["travel"]] is travel...") - if("2") - to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["blood"]] is blood...") - if("3") - to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["join"]] is join...") - if("4") - to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["hell"]] is Hell...") - if("5") - to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["destroy"]] is destroy...") - if("6") - to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["technology"]] is technology...") - if("7") - to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["self"]] is self...") - if("8") - to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["see"]] is see...") - - if(M.mind) - M.mind.special_role = "Cultist" - ticker.mode.cult += M.mind - to_chat(src, "Made [M] a cultist.") -*/ - -//TODO: merge the vievars version into this or something maybe mayhaps -/client/proc/cmd_debug_del_all() - set category = "Debug" - set name = "Del-All" - - // to prevent REALLY stupid deletions - var/blocked = list(/obj, /mob, /mob/living, /mob/living/carbon, /mob/living/carbon/human, /mob/dead, /mob/dead/observer, /mob/living/silicon, /mob/living/silicon/robot, /mob/living/silicon/ai) - var/hsbitem = input(usr, "Choose an object to delete.", "Delete:") as null|anything in typesof(/obj) + typesof(/mob) - blocked - if(hsbitem) - for(var/atom/O in world) - if(istype(O, hsbitem)) - qdel(O) - CHECK_TICK - log_admin("[key_name(src)] has deleted all instances of [hsbitem].") - message_admins("[key_name_admin(src)] has deleted all instances of [hsbitem].") - feedback_add_details("admin_verb","DELA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_debug_make_powernets() - set category = "Debug" - set name = "Make Powernets" - SSmachine.makepowernets() - log_admin("[key_name(src)] has remade the powernet. makepowernets() called.") - message_admins("[key_name_admin(src)] has remade the powernets. makepowernets() called.") - feedback_add_details("admin_verb","MPWN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/proc/cmd_debug_load_junkyard() - set category = "Debug" - set name = "Load Junkyard" - SSjunkyard.populate_junkyard() - - //todo: safe gate ref in map datum - for(var/obj/machinery/gateway/center/G in gateways_list) - if (G.name == "Junkyard Gateway") - G.toggleon() - - log_admin("[key_name(src)] pupulated junkyard. SSjunkyard.populate_junkyard() called.") - message_admins("[key_name_admin(src)] pupulated junkyard. SSjunkyard.populate_junkyard() called.") - feedback_add_details("admin_verb","PPJYD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - - -/client/proc/cmd_debug_tog_aliens() - set category = "Server" - set name = "Toggle Aliens" - - aliens_allowed = !aliens_allowed - log_admin("[key_name(src)] has turned aliens [aliens_allowed ? "on" : "off"].") - message_admins("[key_name_admin(src)] has turned aliens [aliens_allowed ? "on" : "off"].") - feedback_add_details("admin_verb","TAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_debug_tog_vcounter() - set category = "Server" - set name = "Toggle Visual Counters" - - visual_counter = !visual_counter - log_admin("[key_name(src)] has turned visual counters [visual_counter ? "on" : "off"].") - message_admins("[key_name_admin(src)] has turned visual counters [visual_counter ? "on" : "off"].") - feedback_add_details("admin_verb","TVC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_message_spam_control() - set category = "Server" - set name = "Global Message Cooldown" - - global_message_cooldown = !global_message_cooldown - log_admin("[key_name(src)] has turned global message cooldown [global_message_cooldown ? "on" : "off"].") - message_admins("[key_name_admin(src)] has turned global message cooldown [global_message_cooldown ? "on" : "off"].") - feedback_add_details("admin_verb","TGMC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_grantfullaccess(mob/M in mob_list) - set category = "Admin" - set name = "Grant Full Access" - - if (!ticker) - alert("Wait until the game starts") - return - if (istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if (H.wear_id) - var/obj/item/weapon/card/id/id = H.wear_id - if(istype(H.wear_id, /obj/item/device/pda)) - var/obj/item/device/pda/pda = H.wear_id - id = pda.id - id.icon_state = "gold" - id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access() - else - var/obj/item/weapon/card/id/id = new/obj/item/weapon/card/id(M); - id.icon_state = "gold" - id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access() - id.registered_name = H.real_name - id.assignment = "Captain" - id.name = "[id.registered_name]'s ID Card ([id.assignment])" - H.equip_to_slot_or_del(id, slot_wear_id) - H.update_inv_wear_id() - else - alert("Invalid mob") - feedback_add_details("admin_verb","GFA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_admin("[key_name(src)] has granted [M.key] full access.") - message_admins("\blue [key_name_admin(usr)] has granted [M.key] full access.") - -/client/proc/cmd_assume_direct_control(mob/M in mob_list) - set category = "Admin" - set name = "Assume direct control" - set desc = "Direct intervention." - - if(!check_rights(R_DEBUG|R_ADMIN)) - return - if(M.ckey) - if(alert("This mob is being controlled by [M.ckey]. Are you sure you wish to assume control of it? [M.ckey] will be made a ghost.",,"Yes","No") != "Yes") - return - else - var/mob/dead/observer/ghost = new/mob/dead/observer(M,1) - ghost.ckey = M.ckey - message_admins("\blue [key_name_admin(usr)] assumed direct control of [M].") - log_admin("[key_name(usr)] assumed direct control of [M].") - var/mob/adminmob = src.mob - M.ckey = src.ckey - if( isobserver(adminmob) ) - qdel(adminmob) - feedback_add_details("admin_verb","ADC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - - - - -/client/proc/cmd_switch_radio() - set category = "Debug" - set name = "Switch Radio Mode" - set desc = "Toggle between normal radios and experimental radios. Have a coder present if you do this." - - GLOBAL_RADIO_TYPE = !GLOBAL_RADIO_TYPE // toggle - log_admin("[key_name(src)] has turned the experimental radio system [GLOBAL_RADIO_TYPE ? "on" : "off"].") - message_admins("[key_name_admin(src)] has turned the experimental radio system [GLOBAL_RADIO_TYPE ? "on" : "off"].") - feedback_add_details("admin_verb","SRM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_admin_areatest() - set category = "Mapping" - set name = "Test areas" - - var/list/areas_all = list() - var/list/areas_with_APC = list() - var/list/areas_with_air_alarm = list() - var/list/areas_with_RC = list() - var/list/areas_with_light = list() - var/list/areas_with_LS = list() - var/list/areas_with_intercom = list() - var/list/areas_with_camera = list() - - for(var/area/A in world) - if(!(A.type in areas_all)) - areas_all.Add(A.type) - - for(var/obj/machinery/power/apc/APC in machines) - var/area/A = get_area(APC) - if(!(A.type in areas_with_APC)) - areas_with_APC.Add(A.type) - - for(var/obj/machinery/alarm/alarm in machines) - var/area/A = get_area(alarm) - if(!(A.type in areas_with_air_alarm)) - areas_with_air_alarm.Add(A.type) - - for(var/obj/machinery/requests_console/RC in machines) - var/area/A = get_area(RC) - if(!(A.type in areas_with_RC)) - areas_with_RC.Add(A.type) - - for(var/obj/machinery/light/L in machines) - var/area/A = get_area(L) - if(!(A.type in areas_with_light)) - areas_with_light.Add(A.type) - - for(var/obj/machinery/light_switch/LS in machines) - var/area/A = get_area(LS) - if(!(A.type in areas_with_LS)) - areas_with_LS.Add(A.type) - - for(var/obj/item/device/radio/intercom/I in machines) - var/area/A = get_area(I) - if(!(A.type in areas_with_intercom)) - areas_with_intercom.Add(A.type) - - for(var/obj/machinery/camera/C in machines) - var/area/A = get_area(C) - if(!(A.type in areas_with_camera)) - areas_with_camera.Add(A.type) - - var/list/areas_without_APC = areas_all - areas_with_APC - var/list/areas_without_air_alarm = areas_all - areas_with_air_alarm - var/list/areas_without_RC = areas_all - areas_with_RC - var/list/areas_without_light = areas_all - areas_with_light - var/list/areas_without_LS = areas_all - areas_with_LS - var/list/areas_without_intercom = areas_all - areas_with_intercom - var/list/areas_without_camera = areas_all - areas_with_camera - - to_chat(world, "AREAS WITHOUT AN APC:") - for(var/areatype in areas_without_APC) - to_chat(world, "* [areatype]") - - to_chat(world, "AREAS WITHOUT AN AIR ALARM:") - for(var/areatype in areas_without_air_alarm) - to_chat(world, "* [areatype]") - - to_chat(world, "AREAS WITHOUT A REQUEST CONSOLE:") - for(var/areatype in areas_without_RC) - to_chat(world, "* [areatype]") - - to_chat(world, "AREAS WITHOUT ANY LIGHTS:") - for(var/areatype in areas_without_light) - to_chat(world, "* [areatype]") - - to_chat(world, "AREAS WITHOUT A LIGHT SWITCH:") - for(var/areatype in areas_without_LS) - to_chat(world, "* [areatype]") - - to_chat(world, "AREAS WITHOUT ANY INTERCOMS:") - for(var/areatype in areas_without_intercom) - to_chat(world, "* [areatype]") - - to_chat(world, "AREAS WITHOUT ANY CAMERAS:") - for(var/areatype in areas_without_camera) - to_chat(world, "* [areatype]") - -/client/proc/cmd_admin_dress(mob/living/carbon/human/M in mob_list) - set category = "Fun" - set name = "Select equipment" - if(!ishuman(M)) - alert("Invalid mob") - return - //log_admin("[key_name(src)] has alienized [M.key].") - var/list/dresspacks = list( - "strip", - "standard space gear", - "tournament standard red", - "tournament standard green", - "tournament gangster", - "tournament chef", - "tournament janitor", - "pirate", - "space pirate", - "soviet admiral", - "tunnel clown", - "masked killer", - "assassin", - "preparation", - "death commando", - "syndicate commando", - "special ops officer", - "blue wizard", - "red wizard", - "marisa wizard", - "emergency response team", - "nanotrasen representative", - "nanotrasen officer", - "nanotrasen captain", - "captain", - "hop", - "hos", - "cmo", - "rd", - "ce", - "warden", - "security officer", - "detective", - "doctor", - "paramedic", - "chemist", - "virologist", - "psychiatrist", - "engineer", - "atmos-tech", - "scientist", - "xenobiologist", - "xenoarchaeologist", - "roboticist", - "geneticist", - "janitor", - "chef", - "bartender", - "barber", - "botanist", - "qm", - "cargo", - "miner", - "librarian", - "agent", - "assistant", - "test subject", - "tourist", - "mime", - "clown" - ) - var/list/dresspacks_without_money = list( - "strip", - "blue wizard", - "red wizard", - "marisa wizard" - ) - var/dresscode = input("Select dress for [M]", "Robust quick dress shop") as null|anything in dresspacks - if (isnull(dresscode)) - return - feedback_add_details("admin_verb","SEQ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - for (var/obj/item/I in M) - if (istype(I, /obj/item/weapon/implant)) - continue - qdel(I) - switch(dresscode) - if ("strip") - //do nothing - if ("standard space gear") - 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/under/color/grey(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/globose(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/globose(M), slot_head) - var/obj/item/weapon/tank/jetpack/J = new /obj/item/weapon/tank/jetpack/oxygen(M) - M.equip_to_slot_or_del(J, slot_back) - J.toggle() - M.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(M), slot_wear_mask) - J.Topic(null, list("stat" = 1)) - if ("tournament standard red","tournament standard green") //we think stunning weapon is too overpowered to use it on tournaments. --rastaf0 - if (dresscode=="tournament standard red") - M.equip_to_slot_or_del(new /obj/item/clothing/under/color/red(M), slot_w_uniform) - else - M.equip_to_slot_or_del(new /obj/item/clothing/under/color/green(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/armor/vest(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/thunderdome(M), slot_head) - - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/destroyer(M), slot_r_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_l_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/grenade/smokebomb(M), slot_r_store) - - - if ("tournament gangster") //gangster are supposed to fight each other. --rastaf0 - M.equip_to_slot_or_del(new /obj/item/clothing/under/det(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/storage/det_suit(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/clothing/head/det_hat(M), slot_head) - - M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile(M), slot_r_hand) - M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_l_store) - - if ("tournament chef") //Steven Seagal FTW - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chef(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/chef(M), slot_wear_suit) - 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/head/chefhat(M), slot_head) - - M.equip_to_slot_or_del(new /obj/item/weapon/kitchen/rollingpin(M), slot_r_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_l_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_r_store) - M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_s_store) - - if ("tournament janitor") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/janitor(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) - var/obj/item/weapon/storage/backpack/backpack = new(M) - for(var/obj/item/I in backpack) - qdel(I) - M.equip_to_slot_or_del(backpack, slot_back) - - M.equip_to_slot_or_del(new /obj/item/weapon/mop(M), slot_r_hand) - var/obj/item/weapon/reagent_containers/glass/bucket/bucket = new(M) - bucket.reagents.add_reagent("water", 70) - M.equip_to_slot_or_del(bucket, slot_l_hand) - - M.equip_to_slot_or_del(new /obj/item/weapon/grenade/chem_grenade/cleaner(M), slot_r_store) - M.equip_to_slot_or_del(new /obj/item/weapon/grenade/chem_grenade/cleaner(M), slot_l_store) - M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) - - if ("pirate") - M.equip_to_slot_or_del(new /obj/item/clothing/under/pirate(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/head/bandana(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword/pirate(M), slot_r_hand) - - if ("space pirate") - M.equip_to_slot_or_del(new /obj/item/clothing/under/pirate(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/pirate(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/pirate(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses) - - M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword/pirate(M), slot_r_hand) - - if ("soviet soldier") - M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(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/head/ushanka(M), slot_head) - - if("tunnel clown")//Tunnel clowns rule! - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(M), slot_wear_mask) - M.equip_to_slot_or_del(new /obj/item/clothing/head/chaplain_hood(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/chaplain_hoodie(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(M), slot_l_store) - M.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(M), slot_r_store) - - var/obj/item/weapon/card/id/W = new(M) - W.assignment = "Tunnel Clown!" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = get_all_accesses() - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - var/obj/item/weapon/twohanded/fireaxe/fire_axe = new(M) - M.equip_to_slot_or_del(fire_axe, slot_r_hand) - - if("masked killer") - M.equip_to_slot_or_del(new /obj/item/clothing/under/overalls(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/latex(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(M), slot_wear_mask) - M.equip_to_slot_or_del(new /obj/item/clothing/head/welding(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_l_store) - M.equip_to_slot_or_del(new /obj/item/weapon/scalpel(M), slot_r_store) - - var/obj/item/weapon/twohanded/fireaxe/fire_axe = new(M) - M.equip_to_slot_or_del(fire_axe, slot_r_hand) - - for(var/obj/item/carried_item in M.contents) - if(!istype(carried_item, /obj/item/weapon/implant))//If it's not an implant. - carried_item.add_blood(M)//Oh yes, there will be blood... - - if("assassin") - M.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket(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/gloves/black(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/wcoat(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(M), slot_l_store) - - var/obj/item/weapon/storage/secure/briefcase/sec_briefcase = new(M) - for(var/obj/item/briefcase_item in sec_briefcase) - qdel(briefcase_item) - for(var/i=3, i>0, i--) - sec_briefcase.contents += new /obj/item/weapon/spacecash/c1000 - sec_briefcase.contents += new /obj/item/weapon/gun/energy/crossbow - sec_briefcase.contents += new /obj/item/weapon/gun/projectile/revolver/mateba - sec_briefcase.contents += new /obj/item/ammo_box/a357 - sec_briefcase.contents += new /obj/item/weapon/plastique - M.equip_to_slot_or_del(sec_briefcase, slot_l_hand) - - var/obj/item/device/pda/heads/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Reaper" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/syndicate/W = new(M) - W.assignment = "Reaper" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = get_all_accesses() - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("preparation") - 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/jackboots(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_l_store) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) - var/obj/item/weapon/card/id/syndicate/W = new(M) - W.assignment = "Unknown" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = get_all_accesses() - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - if("death commando")//Was looking to add this for a while. - M.equip_death_commando() - - if("syndicate commando") - M.equip_syndicate_commando() - - if("nanotrasen representative") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom/representative(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/centcom(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/hop(M), slot_l_ear) - - var/obj/item/device/pda/heads/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "NanoTrasen Navy Representative" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - - M.equip_to_slot_or_del(pda, slot_r_store) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_l_store) - M.equip_to_slot_or_del(new /obj/item/weapon/clipboard(M), slot_belt) - - var/obj/item/weapon/card/id/centcom/W = new(M) - W.assignment = "NanoTrasen Navy Representative" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.icon_state = "centcom" - W.item_state = "id_inv" - W.access = get_all_accesses() - W.access += list("VIP Guest","Custodian","Thunderdome Overseer","Intel Officer","Medical Officer","Death Commando","Research Officer") - W.rank = "NanoTrasen Representative" - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - if("nanotrasen officer") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom/officer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/centcom(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/head/beret/centcomofficer(M), slot_head) - - var/obj/item/device/pda/heads/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "NanoTrasen Navy Officer" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - - M.equip_to_slot_or_del(pda, slot_r_store) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_l_store) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy(M), slot_belt) - - var/obj/item/weapon/card/id/centcom/W = new(M) - W.assignment = "NanoTrasen Navy Officer" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = get_all_accesses() - W.access += get_all_centcom_access() - W.rank = "NanoTrasen Representative" - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - - if("nanotrasen captain") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom/captain(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/centcom(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/head/beret/centcomcaptain(M), slot_head) - - var/obj/item/device/pda/heads/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "NanoTrasen Navy Captain" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - - M.equip_to_slot_or_del(pda, slot_r_store) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_l_store) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy(M), slot_belt) - - var/obj/item/weapon/card/id/centcom/W = new(M) - W.assignment = "NanoTrasen Navy Captain" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = get_all_accesses() - W.access += get_all_centcom_access() - W.rank = "NanoTrasen Representative" - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - if("emergency response team") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/ert(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) - - var/obj/item/weapon/card/id/ert/W = new(M) - W.assignment = "Emergency Response Team" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.icon_state = "centcom" - W.access = get_all_accesses() - W.access += get_all_centcom_access() - W.rank = "Emergency Response Team" - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - if("special ops officer") - M.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate/combat(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/swat/officer(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/cigarette/cigar/havana(M), slot_wear_mask) - M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad/beret(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/M1911(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/weapon/lighter/zippo(M), slot_r_store) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) - - var/obj/item/weapon/card/id/centcom/W = new(M) - W.assignment = "Special Operations Officer" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.icon_state = "centcom" - W.access = get_all_accesses() - W.access += get_all_centcom_access() - W.rank = "NanoTrasen Representative" - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - if("blue wizard") - M.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(M), slot_r_store) - M.equip_to_slot_or_del(new /obj/item/weapon/spellbook(M), slot_r_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/staff(M), slot_l_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack) - - if("red wizard") - M.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/red(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/red(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(M), slot_r_store) - M.equip_to_slot_or_del(new /obj/item/weapon/spellbook(M), slot_r_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/staff(M), slot_l_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack) - - if("marisa wizard") - M.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/marisa(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/marisa(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/marisa(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(M), slot_r_store) - M.equip_to_slot_or_del(new /obj/item/weapon/spellbook(M), slot_r_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/staff(M), slot_l_hand) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack) - if("soviet admiral") - M.equip_to_slot_or_del(new /obj/item/clothing/head/hgpiratecap(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/hgpirate(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform) - var/obj/item/weapon/card/id/W = new(M) - W.assignment = "Admiral" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = get_all_accesses() - W.access += get_all_centcom_access() - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("captain") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/captain(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/head/caphat(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) - - var/obj/item/device/pda/captain/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Captain" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/gold/W = new(M) - W.assignment = "Captain" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = get_all_accesses() - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - var/obj/item/weapon/implant/mindshield/loyalty/L = new(M) - START_PROCESSING(SSobj, L) - L.inject(M) - if("hop") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_personnel(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/hop(M), slot_l_ear) - - var/obj/item/device/pda/heads/hop/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Head of Personnel" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/silver/W = new(M) - W.assignment = "Head of Personnel" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers, - access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads, - access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, - access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer, - access_theatre, access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, - access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway, access_barber) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("hos") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/hos(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(M), slot_l_store) - - var/obj/item/device/pda/heads/hos/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Head of Security" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/secGold/W = new(M) - W.assignment = "Head of Security" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.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, access_detective) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - var/obj/item/weapon/implant/mindshield/loyalty/L = new(M) - L.inject(M) - START_PROCESSING(SSobj, L) - if("cmo") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_medical_officer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/cmo(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/cmo(M), slot_l_ear) - - var/obj/item/device/pda/heads/cmo/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Chief Medical Officer" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/medGold/W = new(M) - W.assignment = "Chief Medical Officer" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.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_psychiatrist) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("rd") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/rd(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/research_director(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(M), slot_wear_suit) - - var/obj/item/device/pda/heads/rd/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Research Director" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/sciGold/W = new(M) - W.assignment = "Research Director" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, - access_tox_storage, access_teleporter, access_sec_doors, access_minisat, - access_research, access_robotics, access_xenobiology, access_ai_upload, - access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("ce") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_engineer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/white(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) - - var/obj/item/device/pda/heads/ce/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Chief Engineer" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_l_store) - - var/obj/item/weapon/card/id/engGold/W = new(M) - W.assignment = "Chief Engineer" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.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_minisat, - access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("warden") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(M), slot_l_ear) - - var/obj/item/device/pda/warden/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Warden" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_l_store) - - var/obj/item/weapon/card/id/sec/W = new(M) - W.assignment = "Warden" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("security officer") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/security(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(M), slot_r_store) - M.equip_to_slot_or_del(new /obj/item/device/flash(M), slot_l_store) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(M), slot_l_ear) - - var/obj/item/device/pda/security/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Security Officer" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_l_store) - - var/obj/item/weapon/card/id/sec/W = new(M) - W.assignment = "Security Officer" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("detective") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/det(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_suit(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/head/det_hat(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/device/detective_scanner(M), slot_r_hand) - - var/obj/item/device/pda/detective/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Detective" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/sec/W = new(M) - W.assignment = "Detective" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_security, access_sec_doors, access_detective, access_maint_tunnels, access_court) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("doctor") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - - var/obj/item/device/pda/medical/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Medical Doctor" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/med/W = new(M) - W.assignment = "Medical Doctor" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_medical, access_morgue, access_surgery) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("paramedic") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/fr_jacket(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - - var/obj/item/device/pda/medical/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Paramedic" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/med/W = new(M) - W.assignment = "Paramedic" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_medical, access_morgue, access_maint_tunnels, access_external_airlocks, access_security, access_engine_equip, access_research, access_mailsorting) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("chemist") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chemist(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/chemist(M), slot_wear_suit) - - var/obj/item/device/pda/chemist/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Chemist" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/med/W = new(M) - W.assignment = "Chemist" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_medical, access_chemistry) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("virologist") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/virologist(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(M), slot_wear_mask) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/virologist(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) - - var/obj/item/device/pda/viro/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Virologist" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/med/W = new(M) - W.assignment = "Virologist" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_medical, access_virology) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("psychiatrist") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) - - var/obj/item/device/pda/medical/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Psychiatrist" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/med/W = new(M) - W.assignment = "Psychiatrist" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_medical, access_psychiatrist) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("engineer") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/yellow(M), slot_head) - - var/obj/item/device/pda/engineering/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Station Egnineer" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_l_store) - - var/obj/item/weapon/card/id/eng/W = new(M) - W.assignment = "Station Engineer" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("atmos-tech") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/atmospheric_technician(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/atmostech/(M), slot_belt) - - var/obj/item/device/pda/atmos/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Atmospheric Technician" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_l_store) - - var/obj/item/weapon/card/id/eng/W = new(M) - W.assignment = "Atmospheric Technician" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("scientist") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(M), slot_wear_suit) - - var/obj/item/device/pda/science/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Scientist" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/sci/W = new(M) - W.assignment = "Scientist" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_tox, access_tox_storage, access_research, access_xenoarch) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("xenoarchaeologist") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(M), slot_wear_suit) - - var/obj/item/device/pda/science/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Xenoarchaeologist" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/sci/W = new(M) - W.assignment = "Xenoarchaeologist" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_research, access_xenoarch) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("xenobiologist") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(M), slot_wear_suit) - - var/obj/item/device/pda/science/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Xenobiologist" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/sci/W = new(M) - W.assignment = "Xenobiologist" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_research, access_xenobiology) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("roboticist") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/roboticist(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/storage/labcoat(M), slot_wear_suit) - - var/obj/item/device/pda/roboticist/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Roboticist" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/sci/W = new(M) - W.assignment = "Roboticist" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_robotics, access_tech_storage, access_morgue, access_research) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("geneticist") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_medsci(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/geneticist(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/genetics(M), slot_wear_suit) - - var/obj/item/device/pda/geneticist/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Geneticist" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/med/W = new(M) - W.assignment = "Geneticist" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_medical, access_morgue, access_genetics, access_research) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("janitor") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/janitor(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/device/radio/headset(M), slot_l_ear) - - var/obj/item/device/pda/janitor/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Janitor" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/civ/W = new(M) - W.assignment = "Janitor" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_janitor, access_maint_tunnels) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("chef") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chef(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/chef(M), slot_wear_suit) - 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/head/chefhat(M), slot_head) - - var/obj/item/device/pda/chef/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Chef" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/civ/W = new(M) - W.assignment = "Chef" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_kitchen) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("bartender") - 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/armor/vest(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - - var/obj/item/device/pda/bar/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Bartender" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/civ/W = new(M) - W.assignment = "Bartender" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_bar) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("barber") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/barber(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/wcoat(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(M), slot_shoes) - - var/obj/item/device/pda/barber/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Barber" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/civ/W = new(M) - W.assignment = "Barber" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_barber) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("botanist") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/hydroponics(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/gloves/botanic_leather(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/device/plant_analyzer(M), slot_s_store) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - - var/obj/item/device/pda/botanist/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Botanist" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/civ/W = new(M) - W.assignment = "Botanist" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_hydroponics, access_morgue) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("qm") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargo(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) - - var/obj/item/device/pda/cargo/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Quartermastert" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/cargoGold/W = new(M) - W.assignment = "Quartermaster" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("cargo") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargotech(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) - - var/obj/item/device/pda/cargo/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Cargo Technician" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/cargo/W = new(M) - W.assignment = "Cargo Technician" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("miner") - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/miner(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/device/radio/headset/headset_cargo(M), slot_l_ear) - - var/obj/item/device/pda/shaftminer/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Shaft Miner" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/cargo/W = new(M) - W.assignment = "Shaft Miner" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_mining, access_mint, access_mining_station, access_mailsorting) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("librarian") - M.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket/red(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/device/radio/headset(M), slot_l_ear) - - var/obj/item/device/pda/librarian/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Librarian" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/civ/W = new(M) - W.assignment = "Librarian" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_library) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("agent") - M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(M), slot_l_ear) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/internalaffairs(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/internalaffairs(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/big(M), slot_glasses) - - var/obj/item/device/pda/lawyer/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Internal Affairs Agent" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/civ/W = new(M) - W.assignment = "Internal Affairs Agent" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_lawyer, access_court, access_sec_doors) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - var/obj/item/weapon/implant/mindshield/loyalty/L = new(M) - L.inject(M) - START_PROCESSING(SSobj, L) - if("assistant") - M.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(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/device/radio/headset(M), slot_l_ear) - - var/obj/item/device/pda/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Assistant" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/W = new(M) - W.assignment = "Assistant" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_library) - if(config.assistant_maint) - W.access += access_maint_tunnels - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("test subject") - M.equip_to_slot_or_del(new /obj/item/clothing/under/fluff/jane_sidsuit(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/device/radio/headset(M), slot_l_ear) - - var/obj/item/device/pda/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Test Subject" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/W = new(M) - W.assignment = "Test Subject" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_library) - if(config.assistant_maint) - W.access += access_maint_tunnels - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - if("tourist") - M.equip_to_slot_or_del(new /obj/item/clothing/under/tourist(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/tourist(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) - if("mime") - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/clothing/under/mime(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/device/pda/mime(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/mime(M), slot_wear_mask) - M.equip_to_slot_or_del(new /obj/item/clothing/head/beret(M), slot_head) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(M), slot_wear_suit) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M.back), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/toy/crayon/mime(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(M), slot_in_backpack) - - var/obj/item/device/pda/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Mime" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/mime/W = new(M) - W.assignment = "Mime" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_library, access_clown, access_theatre) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - if("clown") - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/clown(M), slot_back) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M.back), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(M), slot_shoes) - M.equip_to_slot_or_del(new /obj/item/device/pda/clown(M), slot_belt) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(M), slot_wear_mask) - M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/weapon/stamp/clown(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/toy/crayon/rainbow(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/fancy/crayons(M), slot_in_backpack) - M.equip_to_slot_or_del(new /obj/item/toy/waterflower(M), slot_in_backpack) - - var/obj/item/device/pda/pda = new(M) - pda.owner = M.real_name - pda.ownjob = "Clown" - pda.name = "PDA-[M.real_name] ([pda.ownjob])" - M.equip_to_slot_or_del(pda, slot_belt) - - var/obj/item/weapon/card/id/clown/W = new(M) - W.assignment = "Clown" - W.name = "[M.real_name]'s ID Card ([W.assignment])" - W.access = list(access_library, access_clown, access_theatre) - W.registered_name = M.real_name - M.equip_to_slot_or_del(W, slot_wear_id) - - if(!(dresscode in dresspacks_without_money) && M.mind) - if(M.mind.initial_account) - if(M.mind.initial_account.owner_name != M.real_name) - qdel(M.mind.initial_account) - M.mind.initial_account = null - create_random_account_and_store_in_mind(M) - //else do nothing - else - create_random_account_and_store_in_mind(M) - - M.regenerate_icons() - - log_admin("[key_name(usr)] changed the equipment of [key_name(M)] to [dresscode].") - message_admins("\blue [key_name_admin(usr)] changed the equipment of [key_name_admin(M)] to [dresscode]..") - return - -/client/proc/startSinglo() - - set category = "Debug" - set name = "Start Singularity" - set desc = "Sets up the singularity and all machines to get power flowing through the station." - - if(alert("Are you sure? This will start up the engine. Should only be used during debug!",,"Yes","No") != "Yes") - return - - for(var/obj/machinery/power/emitter/E in machines) - if(E.anchored) - E.active = 1 - - for(var/obj/machinery/field_generator/F in machines) - if(F.anchored) - F.var_edit_start = 1 - spawn(30) - for(var/obj/machinery/the_singularitygen/G in machines) - if(G.anchored) - var/obj/singularity/S = new /obj/singularity(get_turf(G), 50) - spawn(0) - qdel(G) - S.energy = 1750 - S.current_size = STAGE_FOUR - S.icon = 'icons/effects/224x224.dmi' - S.icon_state = "singularity_s7" - S.pixel_x = -96 - S.pixel_y = -96 - S.grav_pull = 0 - //S.consume_range = 3 - S.dissipate = 0 - //S.dissipate_delay = 10 - //S.dissipate_track = 0 - //S.dissipate_strength = 10 - - for(var/obj/machinery/power/rad_collector/Rad in machines) - if(Rad.anchored) - if(!Rad.P) - var/obj/item/weapon/tank/phoron/Phoron = new/obj/item/weapon/tank/phoron(Rad) - Phoron.air_contents.gas["phoron"] = 70 - Rad.drainratio = 0 - Rad.P = Phoron - Phoron.loc = Rad - - if(!Rad.active) - Rad.toggle_power() - - for(var/obj/machinery/power/smes/SMES in machines) - if(SMES.anchored) - SMES.chargemode = 1 - -/client/proc/setup_supermatter_engine() - set category = "Debug" - set name = "Setup supermatter" - set desc = "Sets up the supermatter engine." - - if(!check_rights(R_DEBUG)) - return - - var/response = alert("Are you sure? This will start up the engine. Should only be used during debug!",,"Setup Completely","Setup except coolant","No") - - if(response == "No") - return - - var/found_the_pump = 0 - var/obj/machinery/power/supermatter/SM - - for(var/obj/machinery/M in machines) - if(!M) - continue - if(!M.loc) - continue - if(!M.loc.loc) - continue - - if(istype(M,/obj/machinery/power/rad_collector)) - var/obj/machinery/power/rad_collector/Rad = M - Rad.anchored = 1 - Rad.connect_to_network() - - var/obj/item/weapon/tank/phoron/Phoron = new/obj/item/weapon/tank/phoron(Rad) - - Phoron.air_contents.gas["phoron"] = 29.1154 //This is a full tank if you filled it from a canister - Rad.P = Phoron - - Phoron.loc = Rad - - if(!Rad.active) - Rad.toggle_power() - Rad.update_icon() - - else if(istype(M,/obj/machinery/atmospherics/components/binary/pump)) //Turning on every pump. - var/obj/machinery/atmospherics/components/binary/pump/Pump = M - if(Pump.name == "Engine Feed" && response == "Setup Completely") - var/datum/gas_mixture/air2 = Pump.AIR2 - - found_the_pump = 1 - air2.gas["nitrogen"] = 3750 //The contents of 2 canisters. - air2.temperature = 50 - air2.update_values() - //Pump.on=1 - Pump.target_pressure = 4500 - Pump.update_icon() - - else if(istype(M,/obj/machinery/power/supermatter)) - SM = M - spawn(50) - SM.power = 320 - - else if(istype(M,/obj/machinery/power/smes)) //This is the SMES inside the engine room. We don't need much power. - var/obj/machinery/power/smes/SMES = M - SMES.chargemode = 1 - SMES.chargelevel = 200000 - SMES.output = 75000 - - if(!found_the_pump && response == "Setup Completely") - to_chat(src, "\red Unable to locate air supply to fill up with coolant, adding some coolant around the supermatter") - var/turf/simulated/T = SM.loc - T.zone.air.gas["nitrogen"] += 450 - T.zone.air.temperature = 50 - T.zone.air.update_values() - - - log_admin("[key_name(usr)] setup the supermatter engine [response == "Setup except coolant" ? "without coolant" : ""]") - message_admins("\blue [key_name_admin(usr)] setup the supermatter engine [response == "Setup except coolant" ? "without coolant": ""]") - return - - - -/client/proc/cmd_debug_mob_lists() - set category = "Debug" - set name = "Debug Mob Lists" - set desc = "For when you just gotta know." - - switch(input("Which list?") in list("Players","Admins","Mobs","Alive Mobs","Dead Mobs", "Clients", "Joined Clients")) - if("Players") - to_chat(usr, jointext(player_list,",")) - if("Admins") - to_chat(usr, jointext(admins,",")) - if("Mobs") - to_chat(usr, jointext(mob_list,",")) - if("Alive Mobs") - to_chat(usr, jointext(alive_mob_list,",")) - if("Dead Mobs") - to_chat(usr, jointext(dead_mob_list,",")) - if("Clients") - to_chat(usr, jointext(clients,",")) - if("Joined Clients") - to_chat(usr, jointext(joined_player_list,",")) - -/client/proc/cmd_display_del_log() - set category = "Debug" - set name = "Display del() Log" - set desc = "Display del's log of everything that's passed through it." - - var/list/dellog = list("List of things that have gone through qdel this round

                      ") - sortTim(SSgarbage.items, cmp=/proc/cmp_qdel_item_time, associative = TRUE) - for(var/path in SSgarbage.items) - var/datum/qdel_item/I = SSgarbage.items[path] - dellog += "
                    1. [path]
                        " - if (I.failures) - dellog += "
                      • Failures: [I.failures]
                      • " - dellog += "
                      • qdel() Count: [I.qdels]
                      • " - dellog += "
                      • Destroy() Cost: [I.destroy_time]ms
                      • " - if (I.hard_deletes) - dellog += "
                      • Total Hard Deletes [I.hard_deletes]
                      • " - dellog += "
                      • Time Spent Hard Deleting: [I.hard_delete_time]ms
                      • " - if (I.slept_destroy) - dellog += "
                      • Sleeps: [I.slept_destroy]
                      • " - if (I.no_hint) - dellog += "
                      • No hint: [I.no_hint]
                      • " - dellog += "
                    2. " - - dellog += "
                    " - - usr << browse(dellog.Join(), "window=dellog") - -/client/proc/cmd_display_init_log() - set category = "Debug" - set name = "Display Initialzie() Log" - set desc = "Displays a list of things that didn't handle Initialize() properly" - - if(!LAZYLEN(SSatoms.BadInitializeCalls)) - to_chat(usr, "There is no bad initializations found in log.") - else - usr << browse(replacetext(SSatoms.InitLog(), "\n", "
                    "), "window=initlog") - -// DNA2 - Admin Hax -/client/proc/cmd_admin_toggle_block(mob/M,block) - if(!ticker) - alert("Wait until the game starts") - return - if(istype(M, /mob/living/carbon)) - var/saved_key = M.key - M.dna.SetSEState(block,!M.dna.GetSEState(block)) - //domutcheck(M,null,MUTCHK_FORCED) //#Z2 - genemutcheck(M,block,null,MUTCHK_FORCED) //#Z2 - if(istype(M, /mob/living/carbon)) - M.update_mutations() - var/state="[M.dna.GetSEState(block)?"on":"off"]" - var/blockname=assigned_blocks[block] - message_admins("[key_name_admin(src)] has toggled [M.key]'s [blockname] block [state]!") - log_admin("[key_name(src)] has toggled [M.key]'s [blockname] block [state]!") - else - message_admins("[key_name_admin(src)] has toggled [saved_key]'s HULK block on!") - log_admin("[key_name(src)] has toggled [saved_key]'s HULK block on!") - else - alert("Invalid mob") - -/client/proc/reload_nanoui_resources() - set category = "Debug" - set name = "Reload NanoUI Resources" - set desc = "Force the client to redownload NanoUI Resources" - - // Close open NanoUIs. - nanomanager.close_user_uis(usr) - - // Re-load the assets. - var/datum/asset/assets = get_asset_datum(/datum/asset/nanoui) - assets.register() - - // Clear the user's cache so they get resent. - usr.client.cache = list() - - to_chat(usr, "Your NanoUI Resource files have been refreshed") - -/client/proc/view_runtimes() - set category = "Debug" - set name = "View Runtimes" - set desc = "Open the runtime Viewer" - - if(!check_rights(R_DEBUG)) - return - - error_cache.show_to(src) +/client/proc/Debug2() + set category = "Debug" + set name = "Debug-Game" + if(!check_rights(R_DEBUG)) return + + if(Debug2) + Debug2 = 0 + message_admins("[key_name(src)] toggled debugging off.") + log_admin("[key_name(src)] toggled debugging off.") + else + Debug2 = 1 + message_admins("[key_name(src)] toggled debugging on.") + log_admin("[key_name(src)] toggled debugging on.") + + feedback_add_details("admin_verb","DG2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + + +/* 21st Sept 2010 +Updated by Skie -- Still not perfect but better! +Stuff you can't do: +Call proc /mob/proc/make_dizzy() for some player +Because if you select a player mob as owner it tries to do the proc for +/mob/living/carbon/human/ instead. And that gives a run-time error. +But you can call procs that are of type /mob/living/carbon/human/proc/ for that player. +*/ + +/client/proc/callproc() + set category = "Debug" + set name = "Advanced ProcCall" + + if(!check_rights(R_PERMISSIONS)) + return + + if(1) return //TODO: config option + + spawn(0) + var/target = null + var/targetselected = 0 + var/lst[] // List reference + lst = new/list() // Make the list + var/returnval = null + var/class = null + + switch(alert("Proc owned by something?",,"Yes","No")) + if("Yes") + targetselected = 1 + class = input("Proc owned by...","Owner",null) as null|anything in list("Obj","Mob","Area or Turf","Client") + switch(class) + if("Obj") + target = input("Enter target:","Target",usr) as obj in world + if("Mob") + target = input("Enter target:","Target",usr) as mob in world + if("Area or Turf") + target = input("Enter target:","Target",usr.loc) as area|turf in world + if("Client") + var/list/keys = list() + for(var/client/C) + keys += C + target = input("Please, select a player!", "Selection", null, null) as null|anything in keys + else + return + if("No") + target = null + targetselected = 0 + + var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null + if(!procname) return + + var/argnum = input("Number of arguments","Number:",0) as num|null + if(!argnum && (argnum!=0)) return + + lst.len = argnum // Expand to right length + //TODO: make a list to store whether each argument was initialised as null. + //Reason: So we can abort the proccall if say, one of our arguments was a mob which no longer exists + //this will protect us from a fair few errors ~Carn + + var/i + for(i=1, iError: callproc(): owner of proc no longer exists.") + return + if(!hascall(target,procname)) + to_chat(usr, "Error: callproc(): target has no such call [procname].") + return + log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") + returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc + else + //this currently has no hascall protection. wasn't able to get it working. + log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") + returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc + + to_chat(usr, "[procname] returned: [returnval ? returnval : "null"]") + feedback_add_details("admin_verb","APC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/Cell() + set category = "Debug" + set name = "Air Status in Location" + if(!mob) + return + var/turf/T = mob.loc + + if (!( istype(T, /turf) )) + return + + var/datum/gas_mixture/env = T.return_air() + + var/t = "Coordinates: [T.x],[T.y],[T.z]\n" + t += "Temperature: [env.temperature]\n" + t += "Pressure: [env.return_pressure()]kPa\n" + for(var/g in env.gas) + t += "[g]: [env.gas[g]] / [env.gas[g] * R_IDEAL_GAS_EQUATION * env.temperature / env.volume]kPa\n" + + + usr.show_message(t, 1) + feedback_add_details("admin_verb","ASL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_robotize(mob/M in mob_list) + set category = "Fun" + set name = "Make Robot" + + if(!ticker) + alert("Wait until the game starts") + return + if(ishuman(M)) + log_admin("[key_name(src)] has robotized [M.key].") + spawn(10) + M:Robotize() + + else + alert("Invalid mob") + +/client/proc/cmd_admin_animalize(mob/M in mob_list) + set category = "Fun" + set name = "Make Simple Animal" + + if(!ticker) + alert("Wait until the game starts") + return + + if(!M) + alert("That mob doesn't seem to exist, close the panel and try again.") + return + + if(isnewplayer(M)) + alert("The mob must not be a new_player.") + return + + log_admin("[key_name(src)] has animalized [M.key].") + spawn(10) + M.Animalize() + + +/client/proc/makepAI(turf/T in mob_list) + set category = "Fun" + set name = "Make pAI" + set desc = "Specify a location to spawn a pAI device, then specify a key to play that pAI." + + var/list/available = list() + for(var/mob/C in mob_list) + if(C.key) + available.Add(C) + var/mob/choice = input("Choose a player to play the pAI", "Spawn pAI") in available + if(!choice) + return 0 + if(!isobserver(choice)) + var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank him out of them out of their body and place them in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No") + if(confirm != "Yes") + return 0 + var/obj/item/device/paicard/card = new(T) + var/mob/living/silicon/pai/pai = new(card) + pai.name = sanitize_safe(input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text, MAX_NAME_LEN) + pai.real_name = pai.name + pai.key = choice.key + card.setPersonality(pai) + for(var/datum/paiCandidate/candidate in paiController.pai_candidates) + if(candidate.key == choice.key) + paiController.pai_candidates.Remove(candidate) + feedback_add_details("admin_verb","MPAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_alienize(mob/M in mob_list) + set category = "Fun" + set name = "Make Alien" + + if(!ticker) + alert("Wait until the game starts") + return + if(ishuman(M)) + log_admin("[key_name(src)] has alienized [M.key].") + spawn(10) + M:Alienize() + feedback_add_details("admin_verb","MKAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] made [key_name(M)] into an alien.") + message_admins("\blue [key_name_admin(usr)] made [key_name(M)] into an alien.") + else + alert("Invalid mob") + +/client/proc/cmd_admin_slimeize(mob/M in mob_list) + set category = "Fun" + set name = "Make slime" + + if(!ticker) + alert("Wait until the game starts") + return + if(ishuman(M)) + log_admin("[key_name(src)] has slimeized [M.key].") + spawn(10) + M:slimeize() + feedback_add_details("admin_verb","MKMET") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] made [key_name(M)] into a slime.") + message_admins("\blue [key_name_admin(usr)] made [key_name(M)] into a slime.") + else + alert("Invalid mob") + +/client/proc/cmd_admin_blobize(mob/M in mob_list) + set category = "Fun" + set name = "Make Blob" + + if(!ticker) + alert("Wait until the game starts") + return + if(istype(M, /mob/living/carbon/human)) + log_admin("[key_name(src)] has blobized [M.key].") + var/mob/living/carbon/human/H = M + spawn(10) + H.Blobize() + + else + alert("Invalid mob") + +/* +/client/proc/cmd_admin_monkeyize(mob/M in world) + set category = "Fun" + set name = "Make Monkey" + + if(!ticker) + alert("Wait until the game starts") + return + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/target = M + log_admin("[key_name(src)] is attempting to monkeyize [M.key].") + spawn(10) + target.monkeyize() + else + alert("Invalid mob") + +/client/proc/cmd_admin_changelinginize(mob/M in world) + set category = "Fun" + set name = "Make Changeling" + + if(!ticker) + alert("Wait until the game starts") + return + if(istype(M, /mob/living/carbon/human)) + log_admin("[key_name(src)] has made [M.key] a changeling.") + spawn(10) + M.absorbed_dna[M.real_name] = M.dna.Clone() + M.make_changeling() + if(M.mind) + M.mind.special_role = "Changeling" + else + alert("Invalid mob") +*/ +/* +/client/proc/cmd_admin_abominize(mob/M in world) + set category = null + set name = "Make Abomination" + + to_chat(usr, "Ruby Mode disabled. Command aborted.") + return + if(!ticker) + alert("Wait until the game starts.") + return + if(istype(M, /mob/living/carbon/human)) + log_admin("[key_name(src)] has made [M.key] an abomination.") + + // spawn(10) + // M.make_abomination() + +*/ +/* +/client/proc/make_cultist(mob/M in world) // -- TLE, modified by Urist + set category = "Fun" + set name = "Make Cultist" + set desc = "Makes target a cultist" + if(!cultwords["travel"]) + runerandom() + if(M) + if(M.mind in ticker.mode.cult) + return + else + if(alert("Spawn that person a tome?",,"Yes","No")=="Yes") + to_chat(M, "\red 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. A tome, a message from your new master, appears on the ground.") + new /obj/item/weapon/book/tome(M.loc) + else + to_chat(M, "\red 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.") + var/glimpse=pick("1","2","3","4","5","6","7","8") + switch(glimpse) + if("1") + to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["travel"]] is travel...") + if("2") + to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["blood"]] is blood...") + if("3") + to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["join"]] is join...") + if("4") + to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["hell"]] is Hell...") + if("5") + to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["destroy"]] is destroy...") + if("6") + to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["technology"]] is technology...") + if("7") + to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["self"]] is self...") + if("8") + to_chat(M, "\red You remembered one thing from the glimpse... [cultwords["see"]] is see...") + + if(M.mind) + M.mind.special_role = "Cultist" + ticker.mode.cult += M.mind + to_chat(src, "Made [M] a cultist.") +*/ + +//TODO: merge the vievars version into this or something maybe mayhaps +/client/proc/cmd_debug_del_all() + set category = "Debug" + set name = "Del-All" + + // to prevent REALLY stupid deletions + var/blocked = list(/obj, /mob, /mob/living, /mob/living/carbon, /mob/living/carbon/human, /mob/dead, /mob/dead/observer, /mob/living/silicon, /mob/living/silicon/robot, /mob/living/silicon/ai) + var/hsbitem = input(usr, "Choose an object to delete.", "Delete:") as null|anything in typesof(/obj) + typesof(/mob) - blocked + if(hsbitem) + for(var/atom/O in world) + if(istype(O, hsbitem)) + qdel(O) + CHECK_TICK + log_admin("[key_name(src)] has deleted all instances of [hsbitem].") + message_admins("[key_name_admin(src)] has deleted all instances of [hsbitem].") + feedback_add_details("admin_verb","DELA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_debug_make_powernets() + set category = "Debug" + set name = "Make Powernets" + SSmachine.makepowernets() + log_admin("[key_name(src)] has remade the powernet. makepowernets() called.") + message_admins("[key_name_admin(src)] has remade the powernets. makepowernets() called.") + feedback_add_details("admin_verb","MPWN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/proc/cmd_debug_load_junkyard() + set category = "Debug" + set name = "Load Junkyard" + SSjunkyard.populate_junkyard() + + //todo: safe gate ref in map datum + for(var/obj/machinery/gateway/center/G in gateways_list) + if (G.name == "Junkyard Gateway") + G.toggleon() + + log_admin("[key_name(src)] pupulated junkyard. SSjunkyard.populate_junkyard() called.") + message_admins("[key_name_admin(src)] pupulated junkyard. SSjunkyard.populate_junkyard() called.") + feedback_add_details("admin_verb","PPJYD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + + +/client/proc/cmd_debug_tog_aliens() + set category = "Server" + set name = "Toggle Aliens" + + aliens_allowed = !aliens_allowed + log_admin("[key_name(src)] has turned aliens [aliens_allowed ? "on" : "off"].") + message_admins("[key_name_admin(src)] has turned aliens [aliens_allowed ? "on" : "off"].") + feedback_add_details("admin_verb","TAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_debug_tog_vcounter() + set category = "Server" + set name = "Toggle Visual Counters" + + visual_counter = !visual_counter + log_admin("[key_name(src)] has turned visual counters [visual_counter ? "on" : "off"].") + message_admins("[key_name_admin(src)] has turned visual counters [visual_counter ? "on" : "off"].") + feedback_add_details("admin_verb","TVC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_message_spam_control() + set category = "Server" + set name = "Global Message Cooldown" + + global_message_cooldown = !global_message_cooldown + log_admin("[key_name(src)] has turned global message cooldown [global_message_cooldown ? "on" : "off"].") + message_admins("[key_name_admin(src)] has turned global message cooldown [global_message_cooldown ? "on" : "off"].") + feedback_add_details("admin_verb","TGMC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_grantfullaccess(mob/M in mob_list) + set category = "Admin" + set name = "Grant Full Access" + + if (!ticker) + alert("Wait until the game starts") + return + if (istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if (H.wear_id) + var/obj/item/weapon/card/id/id = H.wear_id + if(istype(H.wear_id, /obj/item/device/pda)) + var/obj/item/device/pda/pda = H.wear_id + id = pda.id + id.icon_state = "gold" + id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access() + else + var/obj/item/weapon/card/id/id = new/obj/item/weapon/card/id(M); + id.icon_state = "gold" + id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access() + id.registered_name = H.real_name + id.assignment = "Captain" + id.name = "[id.registered_name]'s ID Card ([id.assignment])" + H.equip_to_slot_or_del(id, slot_wear_id) + H.update_inv_wear_id() + else + alert("Invalid mob") + feedback_add_details("admin_verb","GFA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(src)] has granted [M.key] full access.") + message_admins("\blue [key_name_admin(usr)] has granted [M.key] full access.") + +/client/proc/cmd_assume_direct_control(mob/M in mob_list) + set category = "Admin" + set name = "Assume direct control" + set desc = "Direct intervention." + + if(!check_rights(R_DEBUG|R_ADMIN)) + return + if(M.ckey) + if(alert("This mob is being controlled by [M.ckey]. Are you sure you wish to assume control of it? [M.ckey] will be made a ghost.",,"Yes","No") != "Yes") + return + else + var/mob/dead/observer/ghost = new/mob/dead/observer(M,1) + ghost.ckey = M.ckey + message_admins("\blue [key_name_admin(usr)] assumed direct control of [M].") + log_admin("[key_name(usr)] assumed direct control of [M].") + var/mob/adminmob = src.mob + M.ckey = src.ckey + if( isobserver(adminmob) ) + qdel(adminmob) + feedback_add_details("admin_verb","ADC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + + + + +/client/proc/cmd_switch_radio() + set category = "Debug" + set name = "Switch Radio Mode" + set desc = "Toggle between normal radios and experimental radios. Have a coder present if you do this." + + GLOBAL_RADIO_TYPE = !GLOBAL_RADIO_TYPE // toggle + log_admin("[key_name(src)] has turned the experimental radio system [GLOBAL_RADIO_TYPE ? "on" : "off"].") + message_admins("[key_name_admin(src)] has turned the experimental radio system [GLOBAL_RADIO_TYPE ? "on" : "off"].") + feedback_add_details("admin_verb","SRM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_areatest() + set category = "Mapping" + set name = "Test areas" + + var/list/areas_all = list() + var/list/areas_with_APC = list() + var/list/areas_with_air_alarm = list() + var/list/areas_with_RC = list() + var/list/areas_with_light = list() + var/list/areas_with_LS = list() + var/list/areas_with_intercom = list() + var/list/areas_with_camera = list() + + for(var/area/A in world) + if(!(A.type in areas_all)) + areas_all.Add(A.type) + + for(var/obj/machinery/power/apc/APC in machines) + var/area/A = get_area(APC) + if(!(A.type in areas_with_APC)) + areas_with_APC.Add(A.type) + + for(var/obj/machinery/alarm/alarm in machines) + var/area/A = get_area(alarm) + if(!(A.type in areas_with_air_alarm)) + areas_with_air_alarm.Add(A.type) + + for(var/obj/machinery/requests_console/RC in machines) + var/area/A = get_area(RC) + if(!(A.type in areas_with_RC)) + areas_with_RC.Add(A.type) + + for(var/obj/machinery/light/L in machines) + var/area/A = get_area(L) + if(!(A.type in areas_with_light)) + areas_with_light.Add(A.type) + + for(var/obj/machinery/light_switch/LS in machines) + var/area/A = get_area(LS) + if(!(A.type in areas_with_LS)) + areas_with_LS.Add(A.type) + + for(var/obj/item/device/radio/intercom/I in machines) + var/area/A = get_area(I) + if(!(A.type in areas_with_intercom)) + areas_with_intercom.Add(A.type) + + for(var/obj/machinery/camera/C in machines) + var/area/A = get_area(C) + if(!(A.type in areas_with_camera)) + areas_with_camera.Add(A.type) + + var/list/areas_without_APC = areas_all - areas_with_APC + var/list/areas_without_air_alarm = areas_all - areas_with_air_alarm + var/list/areas_without_RC = areas_all - areas_with_RC + var/list/areas_without_light = areas_all - areas_with_light + var/list/areas_without_LS = areas_all - areas_with_LS + var/list/areas_without_intercom = areas_all - areas_with_intercom + var/list/areas_without_camera = areas_all - areas_with_camera + + to_chat(world, "AREAS WITHOUT AN APC:") + for(var/areatype in areas_without_APC) + to_chat(world, "* [areatype]") + + to_chat(world, "AREAS WITHOUT AN AIR ALARM:") + for(var/areatype in areas_without_air_alarm) + to_chat(world, "* [areatype]") + + to_chat(world, "AREAS WITHOUT A REQUEST CONSOLE:") + for(var/areatype in areas_without_RC) + to_chat(world, "* [areatype]") + + to_chat(world, "AREAS WITHOUT ANY LIGHTS:") + for(var/areatype in areas_without_light) + to_chat(world, "* [areatype]") + + to_chat(world, "AREAS WITHOUT A LIGHT SWITCH:") + for(var/areatype in areas_without_LS) + to_chat(world, "* [areatype]") + + to_chat(world, "AREAS WITHOUT ANY INTERCOMS:") + for(var/areatype in areas_without_intercom) + to_chat(world, "* [areatype]") + + to_chat(world, "AREAS WITHOUT ANY CAMERAS:") + for(var/areatype in areas_without_camera) + to_chat(world, "* [areatype]") + +/client/proc/cmd_admin_dress(mob/living/carbon/human/M in mob_list) + set category = "Fun" + set name = "Select equipment" + if(!ishuman(M)) + alert("Invalid mob") + return + //log_admin("[key_name(src)] has alienized [M.key].") + var/list/dresspacks = list( + "strip", + "standard space gear", + "tournament standard red", + "tournament standard green", + "tournament gangster", + "tournament chef", + "tournament janitor", + "pirate", + "space pirate", + "soviet admiral", + "tunnel clown", + "masked killer", + "assassin", + "preparation", + "death commando", + "syndicate commando", + "special ops officer", + "blue wizard", + "red wizard", + "marisa wizard", + "emergency response team", + "nanotrasen representative", + "nanotrasen officer", + "nanotrasen captain", + "captain", + "hop", + "hos", + "cmo", + "rd", + "ce", + "warden", + "security officer", + "detective", + "doctor", + "paramedic", + "chemist", + "virologist", + "psychiatrist", + "engineer", + "atmos-tech", + "scientist", + "xenobiologist", + "xenoarchaeologist", + "roboticist", + "geneticist", + "janitor", + "chef", + "bartender", + "barber", + "botanist", + "qm", + "cargo", + "miner", + "librarian", + "agent", + "assistant", + "test subject", + "tourist", + "mime", + "clown" + ) + var/list/dresspacks_without_money = list( + "strip", + "blue wizard", + "red wizard", + "marisa wizard" + ) + var/dresscode = input("Select dress for [M]", "Robust quick dress shop") as null|anything in dresspacks + if (isnull(dresscode)) + return + feedback_add_details("admin_verb","SEQ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + for (var/obj/item/I in M) + if (istype(I, /obj/item/weapon/implant)) + continue + qdel(I) + switch(dresscode) + if ("strip") + //do nothing + if ("standard space gear") + 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/under/color/grey(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/globose(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/globose(M), slot_head) + var/obj/item/weapon/tank/jetpack/J = new /obj/item/weapon/tank/jetpack/oxygen(M) + M.equip_to_slot_or_del(J, slot_back) + J.toggle() + M.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(M), slot_wear_mask) + J.Topic(null, list("stat" = 1)) + if ("tournament standard red","tournament standard green") //we think stunning weapon is too overpowered to use it on tournaments. --rastaf0 + if (dresscode=="tournament standard red") + M.equip_to_slot_or_del(new /obj/item/clothing/under/color/red(M), slot_w_uniform) + else + M.equip_to_slot_or_del(new /obj/item/clothing/under/color/green(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/armor/vest(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/thunderdome(M), slot_head) + + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/destroyer(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_l_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/grenade/smokebomb(M), slot_r_store) + + + if ("tournament gangster") //gangster are supposed to fight each other. --rastaf0 + M.equip_to_slot_or_del(new /obj/item/clothing/under/det(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/storage/det_suit(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/clothing/head/det_hat(M), slot_head) + + M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_l_store) + + if ("tournament chef") //Steven Seagal FTW + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chef(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/chef(M), slot_wear_suit) + 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/head/chefhat(M), slot_head) + + M.equip_to_slot_or_del(new /obj/item/weapon/kitchen/rollingpin(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_l_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_r_store) + M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_s_store) + + if ("tournament janitor") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/janitor(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) + var/obj/item/weapon/storage/backpack/backpack = new(M) + for(var/obj/item/I in backpack) + qdel(I) + M.equip_to_slot_or_del(backpack, slot_back) + + M.equip_to_slot_or_del(new /obj/item/weapon/mop(M), slot_r_hand) + var/obj/item/weapon/reagent_containers/glass/bucket/bucket = new(M) + bucket.reagents.add_reagent("water", 70) + M.equip_to_slot_or_del(bucket, slot_l_hand) + + M.equip_to_slot_or_del(new /obj/item/weapon/grenade/chem_grenade/cleaner(M), slot_r_store) + M.equip_to_slot_or_del(new /obj/item/weapon/grenade/chem_grenade/cleaner(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/stack/tile/plasteel(M), slot_in_backpack) + + if ("pirate") + M.equip_to_slot_or_del(new /obj/item/clothing/under/pirate(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/head/bandana(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword/pirate(M), slot_r_hand) + + if ("space pirate") + M.equip_to_slot_or_del(new /obj/item/clothing/under/pirate(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/space/pirate(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/pirate(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses) + + M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword/pirate(M), slot_r_hand) + + if ("soviet soldier") + M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(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/head/ushanka(M), slot_head) + + if("tunnel clown")//Tunnel clowns rule! + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/clothing/head/chaplain_hood(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/chaplain_hoodie(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(M), slot_r_store) + + var/obj/item/weapon/card/id/W = new(M) + W.assignment = "Tunnel Clown!" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = get_all_accesses() + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + var/obj/item/weapon/twohanded/fireaxe/fire_axe = new(M) + M.equip_to_slot_or_del(fire_axe, slot_r_hand) + + if("masked killer") + M.equip_to_slot_or_del(new /obj/item/clothing/under/overalls(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/latex(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/clothing/head/welding(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/weapon/kitchenknife(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/weapon/scalpel(M), slot_r_store) + + var/obj/item/weapon/twohanded/fireaxe/fire_axe = new(M) + M.equip_to_slot_or_del(fire_axe, slot_r_hand) + + for(var/obj/item/carried_item in M.contents) + if(!istype(carried_item, /obj/item/weapon/implant))//If it's not an implant. + carried_item.add_blood(M)//Oh yes, there will be blood... + + if("assassin") + M.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket(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/gloves/black(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/wcoat(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(M), slot_l_store) + + var/obj/item/weapon/storage/secure/briefcase/sec_briefcase = new(M) + for(var/obj/item/briefcase_item in sec_briefcase) + qdel(briefcase_item) + for(var/i=3, i>0, i--) + sec_briefcase.contents += new /obj/item/weapon/spacecash/c1000 + sec_briefcase.contents += new /obj/item/weapon/gun/energy/crossbow + sec_briefcase.contents += new /obj/item/weapon/gun/projectile/revolver/mateba + sec_briefcase.contents += new /obj/item/ammo_box/a357 + sec_briefcase.contents += new /obj/item/weapon/plastique + M.equip_to_slot_or_del(sec_briefcase, slot_l_hand) + + var/obj/item/device/pda/heads/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Reaper" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/syndicate/W = new(M) + W.assignment = "Reaper" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = get_all_accesses() + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("preparation") + 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/jackboots(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) + var/obj/item/weapon/card/id/syndicate/W = new(M) + W.assignment = "Unknown" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = get_all_accesses() + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + if("death commando")//Was looking to add this for a while. + M.equip_death_commando() + + if("syndicate commando") + M.equip_syndicate_commando() + + if("nanotrasen representative") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom/representative(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/centcom(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/hop(M), slot_l_ear) + + var/obj/item/device/pda/heads/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "NanoTrasen Navy Representative" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + + M.equip_to_slot_or_del(pda, slot_r_store) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/weapon/clipboard(M), slot_belt) + + var/obj/item/weapon/card/id/centcom/W = new(M) + W.assignment = "NanoTrasen Navy Representative" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.icon_state = "centcom" + W.item_state = "id_inv" + W.access = get_all_accesses() + W.access += list("VIP Guest","Custodian","Thunderdome Overseer","Intel Officer","Medical Officer","Death Commando","Research Officer") + W.rank = "NanoTrasen Representative" + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + if("nanotrasen officer") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom/officer(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/centcom(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/head/beret/centcomofficer(M), slot_head) + + var/obj/item/device/pda/heads/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "NanoTrasen Navy Officer" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + + M.equip_to_slot_or_del(pda, slot_r_store) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy(M), slot_belt) + + var/obj/item/weapon/card/id/centcom/W = new(M) + W.assignment = "NanoTrasen Navy Officer" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = get_all_accesses() + W.access += get_all_centcom_access() + W.rank = "NanoTrasen Representative" + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + + if("nanotrasen captain") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom/captain(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/centcom(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/head/beret/centcomcaptain(M), slot_head) + + var/obj/item/device/pda/heads/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "NanoTrasen Navy Captain" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + + M.equip_to_slot_or_del(pda, slot_r_store) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy(M), slot_belt) + + var/obj/item/weapon/card/id/centcom/W = new(M) + W.assignment = "NanoTrasen Navy Captain" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = get_all_accesses() + W.access += get_all_centcom_access() + W.rank = "NanoTrasen Representative" + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + if("emergency response team") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/ert(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + + var/obj/item/weapon/card/id/ert/W = new(M) + W.assignment = "Emergency Response Team" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.icon_state = "centcom" + W.access = get_all_accesses() + W.access += get_all_centcom_access() + W.rank = "Emergency Response Team" + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + if("special ops officer") + M.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate/combat(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/swat/officer(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/cigarette/cigar/havana(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/deathsquad/beret(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle/M1911(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/weapon/lighter/zippo(M), slot_r_store) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + + var/obj/item/weapon/card/id/centcom/W = new(M) + W.assignment = "Special Operations Officer" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.icon_state = "centcom" + W.access = get_all_accesses() + W.access += get_all_centcom_access() + W.rank = "NanoTrasen Representative" + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + if("blue wizard") + M.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(M), slot_r_store) + M.equip_to_slot_or_del(new /obj/item/weapon/spellbook(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/staff(M), slot_l_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack) + + if("red wizard") + M.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/red(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/red(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(M), slot_r_store) + M.equip_to_slot_or_del(new /obj/item/weapon/spellbook(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/staff(M), slot_l_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack) + + if("marisa wizard") + M.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/marisa(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/marisa(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/marisa(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(M), slot_r_store) + M.equip_to_slot_or_del(new /obj/item/weapon/spellbook(M), slot_r_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/staff(M), slot_l_hand) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack) + if("soviet admiral") + M.equip_to_slot_or_del(new /obj/item/clothing/head/hgpiratecap(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/hgpirate(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform) + var/obj/item/weapon/card/id/W = new(M) + W.assignment = "Admiral" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = get_all_accesses() + W.access += get_all_centcom_access() + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("captain") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/captain(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/head/caphat(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) + + var/obj/item/device/pda/captain/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Captain" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/gold/W = new(M) + W.assignment = "Captain" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = get_all_accesses() + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + var/obj/item/weapon/implant/mindshield/loyalty/L = new(M) + START_PROCESSING(SSobj, L) + L.inject(M) + if("hop") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_personnel(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/hop(M), slot_l_ear) + + var/obj/item/device/pda/heads/hop/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Head of Personnel" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/silver/W = new(M) + W.assignment = "Head of Personnel" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers, + access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads, + access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, + access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer, + access_theatre, access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, + access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway, access_barber) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("hos") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/hos(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(M), slot_l_store) + + var/obj/item/device/pda/heads/hos/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Head of Security" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/secGold/W = new(M) + W.assignment = "Head of Security" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.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, access_detective) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + var/obj/item/weapon/implant/mindshield/loyalty/L = new(M) + L.inject(M) + START_PROCESSING(SSobj, L) + if("cmo") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_medical_officer(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/cmo(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/cmo(M), slot_l_ear) + + var/obj/item/device/pda/heads/cmo/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Chief Medical Officer" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/medGold/W = new(M) + W.assignment = "Chief Medical Officer" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.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_psychiatrist) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("rd") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/rd(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/research_director(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(M), slot_wear_suit) + + var/obj/item/device/pda/heads/rd/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Research Director" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/sciGold/W = new(M) + W.assignment = "Research Director" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, + access_tox_storage, access_teleporter, access_sec_doors, access_minisat, + access_research, access_robotics, access_xenobiology, access_ai_upload, + access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("ce") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chief_engineer(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/white(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) + + var/obj/item/device/pda/heads/ce/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Chief Engineer" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_l_store) + + var/obj/item/weapon/card/id/engGold/W = new(M) + W.assignment = "Chief Engineer" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.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_minisat, + access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("warden") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(M), slot_glasses) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(M), slot_l_ear) + + var/obj/item/device/pda/warden/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Warden" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_l_store) + + var/obj/item/weapon/card/id/sec/W = new(M) + W.assignment = "Warden" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("security officer") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/security(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(M), slot_r_store) + M.equip_to_slot_or_del(new /obj/item/device/flash(M), slot_l_store) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(M), slot_l_ear) + + var/obj/item/device/pda/security/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Security Officer" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_l_store) + + var/obj/item/weapon/card/id/sec/W = new(M) + W.assignment = "Security Officer" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("detective") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/det(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_suit(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/head/det_hat(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/device/detective_scanner(M), slot_r_hand) + + var/obj/item/device/pda/detective/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Detective" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/sec/W = new(M) + W.assignment = "Detective" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_security, access_sec_doors, access_detective, access_maint_tunnels, access_court) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("doctor") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + + var/obj/item/device/pda/medical/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Medical Doctor" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/med/W = new(M) + W.assignment = "Medical Doctor" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_medical, access_morgue, access_surgery) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("paramedic") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/fr_jacket(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + + var/obj/item/device/pda/medical/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Paramedic" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/med/W = new(M) + W.assignment = "Paramedic" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_medical, access_morgue, access_maint_tunnels, access_external_airlocks, access_security, access_engine_equip, access_research, access_mailsorting) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("chemist") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chemist(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/chemist(M), slot_wear_suit) + + var/obj/item/device/pda/chemist/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Chemist" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/med/W = new(M) + W.assignment = "Chemist" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_medical, access_chemistry) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("virologist") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/virologist(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/virologist(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) + + var/obj/item/device/pda/viro/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Virologist" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/med/W = new(M) + W.assignment = "Virologist" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_medical, access_virology) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("psychiatrist") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_med(M), slot_l_ear) + + var/obj/item/device/pda/medical/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Psychiatrist" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/med/W = new(M) + W.assignment = "Psychiatrist" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_medical, access_psychiatrist) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("engineer") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/clothing/head/hardhat/yellow(M), slot_head) + + var/obj/item/device/pda/engineering/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Station Egnineer" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_l_store) + + var/obj/item/weapon/card/id/eng/W = new(M) + W.assignment = "Station Engineer" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("atmos-tech") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_eng(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/atmospheric_technician(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/workboots(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/atmostech/(M), slot_belt) + + var/obj/item/device/pda/atmos/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Atmospheric Technician" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_l_store) + + var/obj/item/weapon/card/id/eng/W = new(M) + W.assignment = "Atmospheric Technician" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_atmospherics, access_maint_tunnels, access_emergency_storage, access_construction) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("scientist") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(M), slot_wear_suit) + + var/obj/item/device/pda/science/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Scientist" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/sci/W = new(M) + W.assignment = "Scientist" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_tox, access_tox_storage, access_research, access_xenoarch) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("xenoarchaeologist") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(M), slot_wear_suit) + + var/obj/item/device/pda/science/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Xenoarchaeologist" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/sci/W = new(M) + W.assignment = "Xenoarchaeologist" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_research, access_xenoarch) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("xenobiologist") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/scientist(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/science(M), slot_wear_suit) + + var/obj/item/device/pda/science/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Xenobiologist" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/sci/W = new(M) + W.assignment = "Xenobiologist" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_research, access_xenobiology) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("roboticist") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sci(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/roboticist(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/storage/labcoat(M), slot_wear_suit) + + var/obj/item/device/pda/roboticist/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Roboticist" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/sci/W = new(M) + W.assignment = "Roboticist" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_robotics, access_tech_storage, access_morgue, access_research) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("geneticist") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_medsci(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/geneticist(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/genetics(M), slot_wear_suit) + + var/obj/item/device/pda/geneticist/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Geneticist" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/med/W = new(M) + W.assignment = "Geneticist" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_medical, access_morgue, access_genetics, access_research) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("janitor") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/janitor(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/device/radio/headset(M), slot_l_ear) + + var/obj/item/device/pda/janitor/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Janitor" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/civ/W = new(M) + W.assignment = "Janitor" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_janitor, access_maint_tunnels) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("chef") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/chef(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/chef(M), slot_wear_suit) + 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/head/chefhat(M), slot_head) + + var/obj/item/device/pda/chef/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Chef" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/civ/W = new(M) + W.assignment = "Chef" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_kitchen) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("bartender") + 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/armor/vest(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/bartender(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + + var/obj/item/device/pda/bar/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Bartender" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/civ/W = new(M) + W.assignment = "Bartender" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_bar) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("barber") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/barber(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/wcoat(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(M), slot_shoes) + + var/obj/item/device/pda/barber/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Barber" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/civ/W = new(M) + W.assignment = "Barber" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_barber) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("botanist") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/hydroponics(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/gloves/botanic_leather(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/device/plant_analyzer(M), slot_s_store) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + + var/obj/item/device/pda/botanist/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Botanist" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/civ/W = new(M) + W.assignment = "Botanist" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_hydroponics, access_morgue) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("qm") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargo(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) + + var/obj/item/device/pda/cargo/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Quartermastert" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/cargoGold/W = new(M) + W.assignment = "Quartermaster" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mint, access_mining, access_mining_station) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("cargo") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_cargo(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/cargotech(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), slot_shoes) + + var/obj/item/device/pda/cargo/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Cargo Technician" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/cargo/W = new(M) + W.assignment = "Cargo Technician" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_maint_tunnels, access_cargo, access_cargo_bot, access_mailsorting) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("miner") + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/miner(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/device/radio/headset/headset_cargo(M), slot_l_ear) + + var/obj/item/device/pda/shaftminer/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Shaft Miner" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/cargo/W = new(M) + W.assignment = "Shaft Miner" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_mining, access_mint, access_mining_station, access_mailsorting) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("librarian") + M.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket/red(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/device/radio/headset(M), slot_l_ear) + + var/obj/item/device/pda/librarian/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Librarian" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/civ/W = new(M) + W.assignment = "Librarian" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_library) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("agent") + M.equip_to_slot_or_del(new /obj/item/device/radio/headset/headset_sec(M), slot_l_ear) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/internalaffairs(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/internalaffairs(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/big(M), slot_glasses) + + var/obj/item/device/pda/lawyer/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Internal Affairs Agent" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/civ/W = new(M) + W.assignment = "Internal Affairs Agent" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_lawyer, access_court, access_sec_doors) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + var/obj/item/weapon/implant/mindshield/loyalty/L = new(M) + L.inject(M) + START_PROCESSING(SSobj, L) + if("assistant") + M.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(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/device/radio/headset(M), slot_l_ear) + + var/obj/item/device/pda/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Assistant" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/W = new(M) + W.assignment = "Assistant" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_library) + if(config.assistant_maint) + W.access += access_maint_tunnels + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("test subject") + M.equip_to_slot_or_del(new /obj/item/clothing/under/fluff/jane_sidsuit(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/device/radio/headset(M), slot_l_ear) + + var/obj/item/device/pda/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Test Subject" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/W = new(M) + W.assignment = "Test Subject" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_library) + if(config.assistant_maint) + W.access += access_maint_tunnels + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + if("tourist") + M.equip_to_slot_or_del(new /obj/item/clothing/under/tourist(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/tourist(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear) + if("mime") + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/clothing/under/mime(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/device/pda/mime(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/mime(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/clothing/head/beret(M), slot_head) + M.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(M), slot_wear_suit) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M.back), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/toy/crayon/mime(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(M), slot_in_backpack) + + var/obj/item/device/pda/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Mime" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/mime/W = new(M) + W.assignment = "Mime" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_library, access_clown, access_theatre) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + if("clown") + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/clown(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(M.back), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(M), slot_w_uniform) + M.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(M), slot_shoes) + M.equip_to_slot_or_del(new /obj/item/device/pda/clown(M), slot_belt) + M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(M), slot_wear_mask) + M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/stamp/clown(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/toy/crayon/rainbow(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/fancy/crayons(M), slot_in_backpack) + M.equip_to_slot_or_del(new /obj/item/toy/waterflower(M), slot_in_backpack) + + var/obj/item/device/pda/pda = new(M) + pda.owner = M.real_name + pda.ownjob = "Clown" + pda.name = "PDA-[M.real_name] ([pda.ownjob])" + M.equip_to_slot_or_del(pda, slot_belt) + + var/obj/item/weapon/card/id/clown/W = new(M) + W.assignment = "Clown" + W.name = "[M.real_name]'s ID Card ([W.assignment])" + W.access = list(access_library, access_clown, access_theatre) + W.registered_name = M.real_name + M.equip_to_slot_or_del(W, slot_wear_id) + + if(!(dresscode in dresspacks_without_money) && M.mind) + if(M.mind.initial_account) + if(M.mind.initial_account.owner_name != M.real_name) + qdel(M.mind.initial_account) + M.mind.initial_account = null + create_random_account_and_store_in_mind(M) + //else do nothing + else + create_random_account_and_store_in_mind(M) + + M.regenerate_icons() + + log_admin("[key_name(usr)] changed the equipment of [key_name(M)] to [dresscode].") + message_admins("\blue [key_name_admin(usr)] changed the equipment of [key_name_admin(M)] to [dresscode]..") + return + +/client/proc/startSinglo() + + set category = "Debug" + set name = "Start Singularity" + set desc = "Sets up the singularity and all machines to get power flowing through the station." + + if(alert("Are you sure? This will start up the engine. Should only be used during debug!",,"Yes","No") != "Yes") + return + + for(var/obj/machinery/power/emitter/E in machines) + if(E.anchored) + E.active = 1 + + for(var/obj/machinery/field_generator/F in machines) + if(F.anchored) + F.var_edit_start = 1 + spawn(30) + for(var/obj/machinery/the_singularitygen/G in machines) + if(G.anchored) + var/obj/singularity/S = new /obj/singularity(get_turf(G), 50) + spawn(0) + qdel(G) + S.energy = 1750 + S.current_size = STAGE_FOUR + S.icon = 'icons/effects/224x224.dmi' + S.icon_state = "singularity_s7" + S.pixel_x = -96 + S.pixel_y = -96 + S.grav_pull = 0 + //S.consume_range = 3 + S.dissipate = 0 + //S.dissipate_delay = 10 + //S.dissipate_track = 0 + //S.dissipate_strength = 10 + + for(var/obj/machinery/power/rad_collector/Rad in machines) + if(Rad.anchored) + if(!Rad.P) + var/obj/item/weapon/tank/phoron/Phoron = new/obj/item/weapon/tank/phoron(Rad) + Phoron.air_contents.gas["phoron"] = 70 + Rad.drainratio = 0 + Rad.P = Phoron + Phoron.loc = Rad + + if(!Rad.active) + Rad.toggle_power() + + for(var/obj/machinery/power/smes/SMES in machines) + if(SMES.anchored) + SMES.chargemode = 1 + +/client/proc/setup_supermatter_engine() + set category = "Debug" + set name = "Setup supermatter" + set desc = "Sets up the supermatter engine." + + if(!check_rights(R_DEBUG)) + return + + var/response = alert("Are you sure? This will start up the engine. Should only be used during debug!",,"Setup Completely","Setup except coolant","No") + + if(response == "No") + return + + var/found_the_pump = 0 + var/obj/machinery/power/supermatter/SM + + for(var/obj/machinery/M in machines) + if(!M) + continue + if(!M.loc) + continue + if(!M.loc.loc) + continue + + if(istype(M,/obj/machinery/power/rad_collector)) + var/obj/machinery/power/rad_collector/Rad = M + Rad.anchored = 1 + Rad.connect_to_network() + + var/obj/item/weapon/tank/phoron/Phoron = new/obj/item/weapon/tank/phoron(Rad) + + Phoron.air_contents.gas["phoron"] = 29.1154 //This is a full tank if you filled it from a canister + Rad.P = Phoron + + Phoron.loc = Rad + + if(!Rad.active) + Rad.toggle_power() + Rad.update_icon() + + else if(istype(M,/obj/machinery/atmospherics/components/binary/pump)) //Turning on every pump. + var/obj/machinery/atmospherics/components/binary/pump/Pump = M + if(Pump.name == "Engine Feed" && response == "Setup Completely") + var/datum/gas_mixture/air2 = Pump.AIR2 + + found_the_pump = 1 + air2.gas["nitrogen"] = 3750 //The contents of 2 canisters. + air2.temperature = 50 + air2.update_values() + //Pump.on=1 + Pump.target_pressure = 4500 + Pump.update_icon() + + else if(istype(M,/obj/machinery/power/supermatter)) + SM = M + spawn(50) + SM.power = 320 + + else if(istype(M,/obj/machinery/power/smes)) //This is the SMES inside the engine room. We don't need much power. + var/obj/machinery/power/smes/SMES = M + SMES.chargemode = 1 + SMES.chargelevel = 200000 + SMES.output = 75000 + + if(!found_the_pump && response == "Setup Completely") + to_chat(src, "\red Unable to locate air supply to fill up with coolant, adding some coolant around the supermatter") + var/turf/simulated/T = SM.loc + T.zone.air.gas["nitrogen"] += 450 + T.zone.air.temperature = 50 + T.zone.air.update_values() + + + log_admin("[key_name(usr)] setup the supermatter engine [response == "Setup except coolant" ? "without coolant" : ""]") + message_admins("\blue [key_name_admin(usr)] setup the supermatter engine [response == "Setup except coolant" ? "without coolant": ""]") + return + + + +/client/proc/cmd_debug_mob_lists() + set category = "Debug" + set name = "Debug Mob Lists" + set desc = "For when you just gotta know." + + switch(input("Which list?") in list("Players","Admins","Mobs","Alive Mobs","Dead Mobs", "Clients", "Joined Clients")) + if("Players") + to_chat(usr, jointext(player_list,",")) + if("Admins") + to_chat(usr, jointext(admins,",")) + if("Mobs") + to_chat(usr, jointext(mob_list,",")) + if("Alive Mobs") + to_chat(usr, jointext(alive_mob_list,",")) + if("Dead Mobs") + to_chat(usr, jointext(dead_mob_list,",")) + if("Clients") + to_chat(usr, jointext(clients,",")) + if("Joined Clients") + to_chat(usr, jointext(joined_player_list,",")) + +/client/proc/cmd_display_del_log() + set category = "Debug" + set name = "Display del() Log" + set desc = "Display del's log of everything that's passed through it." + + var/list/dellog = list("List of things that have gone through qdel this round

                      ") + sortTim(SSgarbage.items, cmp=/proc/cmp_qdel_item_time, associative = TRUE) + for(var/path in SSgarbage.items) + var/datum/qdel_item/I = SSgarbage.items[path] + dellog += "
                    1. [path]
                        " + if (I.failures) + dellog += "
                      • Failures: [I.failures]
                      • " + dellog += "
                      • qdel() Count: [I.qdels]
                      • " + dellog += "
                      • Destroy() Cost: [I.destroy_time]ms
                      • " + if (I.hard_deletes) + dellog += "
                      • Total Hard Deletes [I.hard_deletes]
                      • " + dellog += "
                      • Time Spent Hard Deleting: [I.hard_delete_time]ms
                      • " + if (I.slept_destroy) + dellog += "
                      • Sleeps: [I.slept_destroy]
                      • " + if (I.no_hint) + dellog += "
                      • No hint: [I.no_hint]
                      • " + dellog += "
                    2. " + + dellog += "
                    " + + usr << browse(dellog.Join(), "window=dellog") + +/client/proc/cmd_display_init_log() + set category = "Debug" + set name = "Display Initialzie() Log" + set desc = "Displays a list of things that didn't handle Initialize() properly" + + if(!LAZYLEN(SSatoms.BadInitializeCalls)) + to_chat(usr, "There is no bad initializations found in log.") + else + usr << browse(replacetext(SSatoms.InitLog(), "\n", "
                    "), "window=initlog") + +// DNA2 - Admin Hax +/client/proc/cmd_admin_toggle_block(mob/M,block) + if(!ticker) + alert("Wait until the game starts") + return + if(istype(M, /mob/living/carbon)) + var/saved_key = M.key + M.dna.SetSEState(block,!M.dna.GetSEState(block)) + //domutcheck(M,null,MUTCHK_FORCED) //#Z2 + genemutcheck(M,block,null,MUTCHK_FORCED) //#Z2 + if(istype(M, /mob/living/carbon)) + M.update_mutations() + var/state="[M.dna.GetSEState(block)?"on":"off"]" + var/blockname=assigned_blocks[block] + message_admins("[key_name_admin(src)] has toggled [M.key]'s [blockname] block [state]!") + log_admin("[key_name(src)] has toggled [M.key]'s [blockname] block [state]!") + else + message_admins("[key_name_admin(src)] has toggled [saved_key]'s HULK block on!") + log_admin("[key_name(src)] has toggled [saved_key]'s HULK block on!") + else + alert("Invalid mob") + +/client/proc/reload_nanoui_resources() + set category = "Debug" + set name = "Reload NanoUI Resources" + set desc = "Force the client to redownload NanoUI Resources" + + // Close open NanoUIs. + nanomanager.close_user_uis(usr) + + // Re-load the assets. + var/datum/asset/assets = get_asset_datum(/datum/asset/nanoui) + assets.register() + + // Clear the user's cache so they get resent. + usr.client.cache = list() + + to_chat(usr, "Your NanoUI Resource files have been refreshed") + +/client/proc/view_runtimes() + set category = "Debug" + set name = "View Runtimes" + set desc = "Open the runtime Viewer" + + if(!check_rights(R_DEBUG)) + return + + error_cache.show_to(src) diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index a55457d2953b..3ca237774e3a 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -1,88 +1,88 @@ -/client/proc/fix_next_move() - set category = "Debug" - set name = "Unfreeze Everyone" - var/largest_move_time = 0 - var/largest_click_time = 0 - var/mob/largest_move_mob = null - var/mob/largest_click_mob = null - for(var/mob/M in world) - if(!M.client) - continue - if(M.next_move >= largest_move_time) - largest_move_mob = M - if(M.next_move > world.time) - largest_move_time = M.next_move - world.time - else - largest_move_time = 1 - if(M.next_click >= largest_click_time) - largest_click_mob = M - if(M.next_click > world.time) - largest_click_time = M.next_click - world.time - else - largest_click_time = 0 - log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] next_click = [M.next_click] world.time = [world.time]") - M.next_move = 1 - M.next_click = 0 - message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [largest_move_time/10] seconds!", 1) - message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [largest_click_time/10] seconds!", 1) - message_admins("world.time = [world.time]") - feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/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! - -/client/proc/reload_mentors() - set name = "Reload Mentors" - set category = "Debug" - - if(!check_rights(R_SERVER)) - return - - message_admins("[usr] manually reloaded Mentors") - world.load_mentors() +/client/proc/fix_next_move() + set category = "Debug" + set name = "Unfreeze Everyone" + var/largest_move_time = 0 + var/largest_click_time = 0 + var/mob/largest_move_mob = null + var/mob/largest_click_mob = null + for(var/mob/M in world) + if(!M.client) + continue + if(M.next_move >= largest_move_time) + largest_move_mob = M + if(M.next_move > world.time) + largest_move_time = M.next_move - world.time + else + largest_move_time = 1 + if(M.next_click >= largest_click_time) + largest_click_mob = M + if(M.next_click > world.time) + largest_click_time = M.next_click - world.time + else + largest_click_time = 0 + log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] next_click = [M.next_click] world.time = [world.time]") + M.next_move = 1 + M.next_click = 0 + message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [largest_move_time/10] seconds!", 1) + message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [largest_click_time/10] seconds!", 1) + message_admins("world.time = [world.time]") + feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/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! + +/client/proc/reload_mentors() + set name = "Reload Mentors" + set category = "Debug" + + if(!check_rights(R_SERVER)) + return + + message_admins("[usr] manually reloaded Mentors") + world.load_mentors() diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 29b9f87a81d6..ebfbde1b79d4 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -1,354 +1,354 @@ -//- 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) - qdel(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" - - var/list/obj/machinery/camera/CL = list() - - for(var/obj/machinery/camera/C in cameranet.cameras) - CL += C - - var/output = {"CAMERA ANNOMALITIES REPORT
                    -The following annomalities 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.dir in list(5,6,9,10) ) - 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(entity_ja(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 = 0 - else - intercom_range_display_status = 1 - - 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 orange(7,I)) - var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T) - if (!(F in view(7,I.loc))) - qdel(F) - feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -var/list/debug_verbs = list ( - /client/proc/do_not_use_these - ,/client/proc/camera_view - ,/client/proc/sec_camera_report - ,/client/proc/intercom_view - ,/client/proc/Cell - ,/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/startSinglo - ,/client/proc/set_fps //allows you to set the ticklag. - ,/client/proc/cmd_admin_grantfullaccess -// ,/client/proc/splash - ,/client/proc/cmd_admin_areatest - ,/client/proc/cmd_admin_rejuvenate - ,/datum/admins/proc/show_traitor_panel - ,/client/proc/forceEvent - ,/client/proc/disable_communication - ,/client/proc/disable_movement - ,/client/proc/Zone_Info - ,/client/proc/Test_ZAS_Connection - ,/client/proc/hide_debug_verbs - ,/client/proc/testZAScolors - ,/client/proc/testZAScolors_remove - ,/client/proc/setup_supermatter_engine - ) - - -/client/proc/enable_debug_verbs() - set category = "Debug" - set name = "Debug verbs" - - if(!check_rights(R_DEBUG)) return - - verbs += debug_verbs - - feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/hide_debug_verbs() - set category = "Debug" - set name = "Hide Debug verbs" - - if(!check_rights(R_DEBUG)) return - - verbs -= debug_verbs - - feedback_add_details("admin_verb","hDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/var/list/testZAScolors_turfs = list() -/client/var/list/testZAScolors_zones = list() -/client/var/usedZAScolors = 0 -/client/var/list/image/ZAScolors = list() - -/client/proc/recurse_zone(zone/Z, recurse_level =1) - testZAScolors_zones += Z - if(recurse_level > 10) - return - var/icon/yellow = new('icons/misc/debug_group.dmi', "yellow") - - for(var/turf/T in Z.contents) - images += image(yellow, T, "zasdebug", TURF_LAYER) - testZAScolors_turfs += T - for(var/connection_edge/zone/edge in Z.edges) - var/zone/connected = edge.get_connected_zone(Z) - if(connected in testZAScolors_zones) - continue - recurse_zone(connected,recurse_level+1) - - -/client/proc/testZAScolors() - set category = "ZAS" - set name = "Check ZAS connections" - - if(!check_rights(R_DEBUG)) return - testZAScolors_remove() - - var/turf/simulated/location = get_turf(usr) - - if(!istype(location, /turf/simulated)) // We're in space, let's not cause runtimes. - to_chat(usr, "\red this debug tool cannot be used from space") - return - - var/icon/red = new('icons/misc/debug_group.dmi', "red") //created here so we don't have to make thousands of these. - var/icon/green = new('icons/misc/debug_group.dmi', "green") - var/icon/blue = new('icons/misc/debug_group.dmi', "blue") - - if(!usedZAScolors) - to_chat(usr, "ZAS Test Colors") - to_chat(usr, "Green = Zone you are standing in") - to_chat(usr, "Blue = Connected zone to the zone you are standing in") - to_chat(usr, "Yellow = A zone that is connected but not one adjacent to your connected zone") - to_chat(usr, "Red = Not connected") - usedZAScolors = 1 - - testZAScolors_zones += location.zone - for(var/turf/T in location.zone.contents) - images += image(green, T,"zasdebug", TURF_LAYER) - testZAScolors_turfs += T - for(var/connection_edge/zone/edge in location.zone.edges) - var/zone/Z = edge.get_connected_zone(location.zone) - testZAScolors_zones += Z - for(var/turf/T in Z.contents) - images += image(blue, T,"zasdebug",TURF_LAYER) - testZAScolors_turfs += T - for(var/connection_edge/zone/z_edge in Z.edges) - var/zone/connected = z_edge.get_connected_zone(Z) - if(connected in testZAScolors_zones) - continue - recurse_zone(connected,1) - - for(var/turf/T in range(25,location)) - if(!istype(T)) - continue - if(T in testZAScolors_turfs) - continue - images += image(red, T, "zasdebug", TURF_LAYER) - testZAScolors_turfs += T - -/client/proc/testZAScolors_remove() - set category = "ZAS" - set name = "Remove ZAS connection colors" - - testZAScolors_turfs.Cut() - testZAScolors_zones.Cut() - - if(images.len) - for(var/image/i in images) - if(i.icon_state == "zasdebug") - images.Remove(i) - -/client/proc/count_objects_on_z_level() - set category = "Mapping" - set name = "Count Objects On Level" - var/num_level = input("Which z-level?","Level?") as null|num - if(!num_level) - return - - var/type_path = text2path(input("Which type path?","Path?") as null|text) - if(!type_path) - return - - var/count = 1 - - 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 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(world, "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! - - -var/global/prevent_airgroup_regroup = 0 - -//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, "\red 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, "\red 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) + qdel(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" + + var/list/obj/machinery/camera/CL = list() + + for(var/obj/machinery/camera/C in cameranet.cameras) + CL += C + + var/output = {"CAMERA ANNOMALITIES REPORT
                    +The following annomalities 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.dir in list(5,6,9,10) ) + 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(entity_ja(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 = 0 + else + intercom_range_display_status = 1 + + 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 orange(7,I)) + var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T) + if (!(F in view(7,I.loc))) + qdel(F) + feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +var/list/debug_verbs = list ( + /client/proc/do_not_use_these + ,/client/proc/camera_view + ,/client/proc/sec_camera_report + ,/client/proc/intercom_view + ,/client/proc/Cell + ,/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/startSinglo + ,/client/proc/set_fps //allows you to set the ticklag. + ,/client/proc/cmd_admin_grantfullaccess +// ,/client/proc/splash + ,/client/proc/cmd_admin_areatest + ,/client/proc/cmd_admin_rejuvenate + ,/datum/admins/proc/show_traitor_panel + ,/client/proc/forceEvent + ,/client/proc/disable_communication + ,/client/proc/disable_movement + ,/client/proc/Zone_Info + ,/client/proc/Test_ZAS_Connection + ,/client/proc/hide_debug_verbs + ,/client/proc/testZAScolors + ,/client/proc/testZAScolors_remove + ,/client/proc/setup_supermatter_engine + ) + + +/client/proc/enable_debug_verbs() + set category = "Debug" + set name = "Debug verbs" + + if(!check_rights(R_DEBUG)) return + + verbs += debug_verbs + + feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/hide_debug_verbs() + set category = "Debug" + set name = "Hide Debug verbs" + + if(!check_rights(R_DEBUG)) return + + verbs -= debug_verbs + + feedback_add_details("admin_verb","hDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/var/list/testZAScolors_turfs = list() +/client/var/list/testZAScolors_zones = list() +/client/var/usedZAScolors = 0 +/client/var/list/image/ZAScolors = list() + +/client/proc/recurse_zone(zone/Z, recurse_level =1) + testZAScolors_zones += Z + if(recurse_level > 10) + return + var/icon/yellow = new('icons/misc/debug_group.dmi', "yellow") + + for(var/turf/T in Z.contents) + images += image(yellow, T, "zasdebug", TURF_LAYER) + testZAScolors_turfs += T + for(var/connection_edge/zone/edge in Z.edges) + var/zone/connected = edge.get_connected_zone(Z) + if(connected in testZAScolors_zones) + continue + recurse_zone(connected,recurse_level+1) + + +/client/proc/testZAScolors() + set category = "ZAS" + set name = "Check ZAS connections" + + if(!check_rights(R_DEBUG)) return + testZAScolors_remove() + + var/turf/simulated/location = get_turf(usr) + + if(!istype(location, /turf/simulated)) // We're in space, let's not cause runtimes. + to_chat(usr, "\red this debug tool cannot be used from space") + return + + var/icon/red = new('icons/misc/debug_group.dmi', "red") //created here so we don't have to make thousands of these. + var/icon/green = new('icons/misc/debug_group.dmi', "green") + var/icon/blue = new('icons/misc/debug_group.dmi', "blue") + + if(!usedZAScolors) + to_chat(usr, "ZAS Test Colors") + to_chat(usr, "Green = Zone you are standing in") + to_chat(usr, "Blue = Connected zone to the zone you are standing in") + to_chat(usr, "Yellow = A zone that is connected but not one adjacent to your connected zone") + to_chat(usr, "Red = Not connected") + usedZAScolors = 1 + + testZAScolors_zones += location.zone + for(var/turf/T in location.zone.contents) + images += image(green, T,"zasdebug", TURF_LAYER) + testZAScolors_turfs += T + for(var/connection_edge/zone/edge in location.zone.edges) + var/zone/Z = edge.get_connected_zone(location.zone) + testZAScolors_zones += Z + for(var/turf/T in Z.contents) + images += image(blue, T,"zasdebug",TURF_LAYER) + testZAScolors_turfs += T + for(var/connection_edge/zone/z_edge in Z.edges) + var/zone/connected = z_edge.get_connected_zone(Z) + if(connected in testZAScolors_zones) + continue + recurse_zone(connected,1) + + for(var/turf/T in range(25,location)) + if(!istype(T)) + continue + if(T in testZAScolors_turfs) + continue + images += image(red, T, "zasdebug", TURF_LAYER) + testZAScolors_turfs += T + +/client/proc/testZAScolors_remove() + set category = "ZAS" + set name = "Remove ZAS connection colors" + + testZAScolors_turfs.Cut() + testZAScolors_zones.Cut() + + if(images.len) + for(var/image/i in images) + if(i.icon_state == "zasdebug") + images.Remove(i) + +/client/proc/count_objects_on_z_level() + set category = "Mapping" + set name = "Count Objects On Level" + var/num_level = input("Which z-level?","Level?") as null|num + if(!num_level) + return + + var/type_path = text2path(input("Which type path?","Path?") as null|text) + if(!type_path) + return + + var/count = 1 + + 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 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(world, "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! + + +var/global/prevent_airgroup_regroup = 0 + +//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, "\red 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, "\red 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 ca400f2b08d2..0e55945cfb6b 100644 --- a/code/modules/admin/verbs/massmodvar.dm +++ b/code/modules/admin/verbs/massmodvar.dm @@ -1,492 +1,492 @@ -/client/proc/cmd_mass_modify_object_variables(atom/A, 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(atom/O, var_name = "", method = 0) - if(!check_rights(R_VAREDIT)) return - - var/list/icons_modifying = list("icon", "icon_state", "resize") - var/list/locked = list("vars", "summon_type") - var/list/fully_locked = list("holder", "key", "ckey", "client", "player_next_age_tick", "player_ingame_age", "resize_rev", "step_x", "step_y") - - if(is_type_in_list(O, forbidden_varedit_object_types)) - to_chat(usr, "\red 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 in fully_locked) - to_chat(usr, "\red It is forbidden to edit this variable.") - return - - if((variable in locked) && !check_rights(R_DEBUG)) - return - - if((variable in icons_modifying) && !check_rights(R_DEBUG|R_EVENT)) - return - - if(isnull(var_value)) - to_chat(usr, "Unable to determine variable type.") - - else if(isnum(var_value)) - to_chat(usr, "Variable appears to be NUM.") - default = "num" - - else if(istext(var_value)) - to_chat(usr, "Variable appears to be TEXT.") - default = "text" - - else if(isloc(var_value)) - to_chat(usr, "Variable appears to be REFERENCE.") - default = "reference" - - else if(isicon(var_value)) - to_chat(usr, "Variable appears to be ICON.") - var_value = "[bicon(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)) - to_chat(usr, "Variable appears to be LIST.") - default = "list" - - else if(istype(var_value,/client)) - to_chat(usr, "Variable appears to be CLIENT.") - default = "cancel" - - else - to_chat(usr, "Variable appears to be 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) - 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 - - var/log_handled = FALSE - - switch(class) - - if("restore to default") - if(variable=="resize") - world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.resize_rev]")]" - log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.resize_rev]") - message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.resize_rev]") - log_handled = TRUE - O.vars[variable] = O.resize_rev - O.update_transform() - O.resize_rev = initial(O.resize_rev) - else - 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)) - if(variable=="resize") - M.vars[variable] = M.resize_rev - M.update_transform() - M.resize_rev = O.resize_rev - else - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /obj)) - for(var/obj/A in world) - if(istype(A, O.type)) - if(variable=="resize") - A.vars[variable] = A.resize_rev - A.update_transform() - A.resize_rev = O.resize_rev - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /turf)) - for(var/turf/A in world) - if(istype(A, O.type)) - if(variable=="resize") - A.vars[variable] = A.resize_rev - A.update_transform() - A.resize_rev = O.resize_rev - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if(M.type == O.type) - if(variable=="resize") - M.vars[variable] = M.resize_rev - M.update_transform() - M.resize_rev = O.resize_rev - else - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /obj)) - for(var/obj/A in world) - if(A.type == O.type) - if(variable=="resize") - A.vars[variable] = A.resize_rev - A.update_transform() - A.resize_rev = O.resize_rev - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /turf)) - for(var/turf/A in world) - if(A.type == O.type) - if(variable=="resize") - A.vars[variable] = A.resize_rev - A.update_transform() - A.resize_rev = O.resize_rev - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - 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(isnull(new_value)) - 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 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 world) - if(A.type == O.type) - A.vars[variable] = O.vars[variable] - - if("num") - var/new_value = input("Enter new number:","Num", O.vars[variable]) as num|null - if(isnull(new_value)) - return - - if(variable=="resize") - if(new_value == 0) - to_chat(usr, "Resize coefficient can't be equal 0") - return - world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[new_value]")]" - log_admin("[key_name(src)] modified [original_name]'s [variable] to [new_value]") - message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [new_value]") - log_handled = TRUE - else - O.vars[variable] = new_value - - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if(istype(M, O.type)) - switch(variable) - if("light_range") - M.set_light(new_value) - if("resize") - M.vars[variable] = new_value - M.update_transform() - else - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /obj)) - for(var/obj/A in world) - if(istype(A, O.type)) - switch(variable) - if("light_range") - A.set_light(new_value) - if("resize") - A.vars[variable] = new_value - A.update_transform() - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /turf)) - for(var/turf/A in world) - if(istype(A, O.type)) - switch(variable) - if("light_range") - A.set_light(new_value) - if("resize") - A.vars[variable] = new_value - A.update_transform() - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if(M.type == O.type) - switch(variable) - if("light_range") - M.set_light(new_value) - if("resize") - M.vars[variable] = new_value - M.update_transform() - else - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /obj)) - for(var/obj/A in world) - if(A.type == O.type) - switch(variable) - if("light_range") - A.set_light(new_value) - if("resize") - A.vars[variable] = new_value - A.update_transform() - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /turf)) - for(var/turf/A in world) - if(A.type == O.type) - switch(variable) - if("light_range") - A.set_light(new_value) - if("resize") - A.vars[variable] = new_value - A.update_transform() - else - A.vars[variable] = O.vars[variable] - CHECK_TICK - - if("type") - var/new_value - new_value = input("Enter type:", "Type", O.vars[variable]) as null|anything in typesof(/obj, /mob, /area, /turf) - if(isnull(new_value)) - 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] - CHECK_TICK - - else if(istype(O, /obj)) - for(var/obj/A in world) - if(istype(A, O.type) ) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /turf)) - for(var/turf/A in world) - if(istype(A, O.type)) - A.vars[variable] = O.vars[variable] - CHECK_TICK - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if(M.type == O.type) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /obj)) - for(var/obj/A in world) - if(A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /turf)) - for(var/turf/A in world) - if(A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - if("file") - var/new_value = input("Pick file:", "File", O.vars[variable]) as null|file - if(isnull(new_value)) - 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] - CHECK_TICK - - else if(istype(O.type, /obj)) - for(var/obj/A in world) - if(istype(A , O.type)) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O.type, /turf)) - for(var/turf/A in world) - if(istype(A , O.type)) - A.vars[variable] = O.vars[variable] - CHECK_TICK - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if(M.type == O.type) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O.type, /obj)) - for(var/obj/A in world) - if(A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O.type, /turf)) - for(var/turf/A in world) - if(A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - if("icon") - var/new_value = input("Pick icon:", "Icon", O.vars[variable]) as null|icon - if(isnull(new_value)) - 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] - CHECK_TICK - - else if(istype(O, /obj)) - for(var/obj/A in world) - if(istype(A, O.type)) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /turf)) - for(var/turf/A in world) - if(istype(A, O.type)) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if(M.type == O.type) - M.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /obj)) - for(var/obj/A in world) - if(A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - else if(istype(O, /turf)) - for(var/turf/A in world) - if(A.type == O.type) - A.vars[variable] = O.vars[variable] - CHECK_TICK - - if(!log_handled) - world.log << "### MassVarEdit by [src]: [O.type] [variable]=[html_encode("[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) +/client/proc/cmd_mass_modify_object_variables(atom/A, 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(atom/O, var_name = "", method = 0) + if(!check_rights(R_VAREDIT)) return + + var/list/icons_modifying = list("icon", "icon_state", "resize") + var/list/locked = list("vars", "summon_type") + var/list/fully_locked = list("holder", "key", "ckey", "client", "player_next_age_tick", "player_ingame_age", "resize_rev", "step_x", "step_y") + + if(is_type_in_list(O, forbidden_varedit_object_types)) + to_chat(usr, "\red 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 in fully_locked) + to_chat(usr, "\red It is forbidden to edit this variable.") + return + + if((variable in locked) && !check_rights(R_DEBUG)) + return + + if((variable in icons_modifying) && !check_rights(R_DEBUG|R_EVENT)) + return + + if(isnull(var_value)) + to_chat(usr, "Unable to determine variable type.") + + else if(isnum(var_value)) + to_chat(usr, "Variable appears to be NUM.") + default = "num" + + else if(istext(var_value)) + to_chat(usr, "Variable appears to be TEXT.") + default = "text" + + else if(isloc(var_value)) + to_chat(usr, "Variable appears to be REFERENCE.") + default = "reference" + + else if(isicon(var_value)) + to_chat(usr, "Variable appears to be ICON.") + var_value = "[bicon(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)) + to_chat(usr, "Variable appears to be LIST.") + default = "list" + + else if(istype(var_value,/client)) + to_chat(usr, "Variable appears to be CLIENT.") + default = "cancel" + + else + to_chat(usr, "Variable appears to be 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) + 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 + + var/log_handled = FALSE + + switch(class) + + if("restore to default") + if(variable=="resize") + world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.resize_rev]")]" + log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.resize_rev]") + message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.resize_rev]") + log_handled = TRUE + O.vars[variable] = O.resize_rev + O.update_transform() + O.resize_rev = initial(O.resize_rev) + else + 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)) + if(variable=="resize") + M.vars[variable] = M.resize_rev + M.update_transform() + M.resize_rev = O.resize_rev + else + M.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /obj)) + for(var/obj/A in world) + if(istype(A, O.type)) + if(variable=="resize") + A.vars[variable] = A.resize_rev + A.update_transform() + A.resize_rev = O.resize_rev + else + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /turf)) + for(var/turf/A in world) + if(istype(A, O.type)) + if(variable=="resize") + A.vars[variable] = A.resize_rev + A.update_transform() + A.resize_rev = O.resize_rev + else + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if(M.type == O.type) + if(variable=="resize") + M.vars[variable] = M.resize_rev + M.update_transform() + M.resize_rev = O.resize_rev + else + M.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /obj)) + for(var/obj/A in world) + if(A.type == O.type) + if(variable=="resize") + A.vars[variable] = A.resize_rev + A.update_transform() + A.resize_rev = O.resize_rev + else + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /turf)) + for(var/turf/A in world) + if(A.type == O.type) + if(variable=="resize") + A.vars[variable] = A.resize_rev + A.update_transform() + A.resize_rev = O.resize_rev + else + A.vars[variable] = O.vars[variable] + CHECK_TICK + + 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(isnull(new_value)) + 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 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 world) + if(A.type == O.type) + A.vars[variable] = O.vars[variable] + + if("num") + var/new_value = input("Enter new number:","Num", O.vars[variable]) as num|null + if(isnull(new_value)) + return + + if(variable=="resize") + if(new_value == 0) + to_chat(usr, "Resize coefficient can't be equal 0") + return + world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[new_value]")]" + log_admin("[key_name(src)] modified [original_name]'s [variable] to [new_value]") + message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [new_value]") + log_handled = TRUE + else + O.vars[variable] = new_value + + if(method) + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if(istype(M, O.type)) + switch(variable) + if("light_range") + M.set_light(new_value) + if("resize") + M.vars[variable] = new_value + M.update_transform() + else + M.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /obj)) + for(var/obj/A in world) + if(istype(A, O.type)) + switch(variable) + if("light_range") + A.set_light(new_value) + if("resize") + A.vars[variable] = new_value + A.update_transform() + else + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /turf)) + for(var/turf/A in world) + if(istype(A, O.type)) + switch(variable) + if("light_range") + A.set_light(new_value) + if("resize") + A.vars[variable] = new_value + A.update_transform() + else + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if(M.type == O.type) + switch(variable) + if("light_range") + M.set_light(new_value) + if("resize") + M.vars[variable] = new_value + M.update_transform() + else + M.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /obj)) + for(var/obj/A in world) + if(A.type == O.type) + switch(variable) + if("light_range") + A.set_light(new_value) + if("resize") + A.vars[variable] = new_value + A.update_transform() + else + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /turf)) + for(var/turf/A in world) + if(A.type == O.type) + switch(variable) + if("light_range") + A.set_light(new_value) + if("resize") + A.vars[variable] = new_value + A.update_transform() + else + A.vars[variable] = O.vars[variable] + CHECK_TICK + + if("type") + var/new_value + new_value = input("Enter type:", "Type", O.vars[variable]) as null|anything in typesof(/obj, /mob, /area, /turf) + if(isnull(new_value)) + 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] + CHECK_TICK + + else if(istype(O, /obj)) + for(var/obj/A in world) + if(istype(A, O.type) ) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /turf)) + for(var/turf/A in world) + if(istype(A, O.type)) + A.vars[variable] = O.vars[variable] + CHECK_TICK + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if(M.type == O.type) + M.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /obj)) + for(var/obj/A in world) + if(A.type == O.type) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /turf)) + for(var/turf/A in world) + if(A.type == O.type) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + if("file") + var/new_value = input("Pick file:", "File", O.vars[variable]) as null|file + if(isnull(new_value)) + 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] + CHECK_TICK + + else if(istype(O.type, /obj)) + for(var/obj/A in world) + if(istype(A , O.type)) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O.type, /turf)) + for(var/turf/A in world) + if(istype(A , O.type)) + A.vars[variable] = O.vars[variable] + CHECK_TICK + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if(M.type == O.type) + M.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O.type, /obj)) + for(var/obj/A in world) + if(A.type == O.type) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O.type, /turf)) + for(var/turf/A in world) + if(A.type == O.type) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + if("icon") + var/new_value = input("Pick icon:", "Icon", O.vars[variable]) as null|icon + if(isnull(new_value)) + 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] + CHECK_TICK + + else if(istype(O, /obj)) + for(var/obj/A in world) + if(istype(A, O.type)) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /turf)) + for(var/turf/A in world) + if(istype(A, O.type)) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else + if(istype(O, /mob)) + for(var/mob/M in mob_list) + if(M.type == O.type) + M.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /obj)) + for(var/obj/A in world) + if(A.type == O.type) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + else if(istype(O, /turf)) + for(var/turf/A in world) + if(A.type == O.type) + A.vars[variable] = O.vars[variable] + CHECK_TICK + + if(!log_handled) + world.log << "### MassVarEdit by [src]: [O.type] [variable]=[html_encode("[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) diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index 86e0bd64a750..483e0288e4ea 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -1,555 +1,555 @@ -var/list/forbidden_varedit_object_types = list( - /datum/admins, //Admins editing their own admin-power object? Yup, sounds like a good idea. - /datum/configuration, - /obj/machinery/blackbox_recorder, //Prevents people messing with feedback gathering - /datum/feedback_variable, //Prevents people messing with feedback gathering - /datum/timedevent, //Nope.avi - /datum/craft_or_build, - /datum/stack_recipe, - /datum/events, - ) - -/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 = sanitize(input("Enter new text:","Text") as null|text) - - 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(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 = sanitize(input("Enter new text:","Text") as text) - - 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(list/L) - if(!check_rights(R_VAREDIT)) - return - - if(!islist(L)) - to_chat(usr, "Still not a list") - return - - - var/list/locked = list("vars", "key", "ckey", "client", "virus", "viruses", "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)) - to_chat(usr, "Variable appears to be NUM.") - default = "num" - - else if(istext(variable)) - to_chat(usr, "Variable appears to be TEXT.") - default = "text" - - else if(isloc(variable)) - to_chat(usr, "Variable appears to be REFERENCE.") - default = "reference" - - else if(isicon(variable)) - to_chat(usr, "Variable appears to be ICON.") - variable = "[bicon(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)) - to_chat(usr, "Variable appears to be LIST.") - default = "list" - - else if(istype(variable,/client)) - to_chat(usr, "Variable appears to be CLIENT.") - default = "cancel" - - else - to_chat(usr, "Variable appears to be 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) - 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") - if(!islist(L[L.Find(variable)])) - if(alert("This is not a list. Would you like to create new list?",,"Yes","No") == "No") - return - L[L.Find(variable)] = list() - mod_list(L[L.Find(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") - L[L.Find(variable)] = sanitize(input("Enter new text:","Text") as text) - - if("num") - L[L.Find(variable)] = input("Enter new number:","Num") as num - - if("type") - L[L.Find(variable)] = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) - - if("reference") - L[L.Find(variable)] = input("Select reference:","Reference") as mob|obj|turf|area in world - - if("mob reference") - L[L.Find(variable)] = input("Select reference:","Reference") as mob in world - - if("file") - L[L.Find(variable)] = input("Pick file:","File") as file - - if("icon") - L[L.Find(variable)] = input("Pick icon:","Icon") as icon - - if("marked datum") - L[L.Find(variable)] = holder.marked_datum - - -/client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0) - if(!check_rights(R_VAREDIT)) return - - var/list/icons_modifying = list("resize") - var/list/locked = list("vars", "key", "ckey", "client", "virus", "viruses", "mutantrace", "player_ingame_age", "summon_type", "AI_Interact") - var/list/typechange_locked = list("player_next_age_tick","player_ingame_age") - var/list/fully_locked = list("holder", "player_next_age_tick", "resize_rev", "step_x", "step_y") - - if(is_type_in_list(O, forbidden_varedit_object_types)) - to_chat(usr, "\red 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)) - to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this atom ([O])") - return - - if(param_var_name in fully_locked) - to_chat(usr, "\red It is forbidden to edit this variable.") - return - - if(!autodetect_class && (param_var_name in typechange_locked)) - return - - if((param_var_name in locked) && !check_rights(R_DEBUG)) - return - - if((param_var_name in icons_modifying) && !check_rights(R_DEBUG|R_EVENT)) - 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)) - to_chat(usr, "Variable appears to be NUM.") - class = "num" - - else if(istext(var_value)) - to_chat(usr, "Variable appears to be TEXT.") - class = "text" - - else if(isloc(var_value)) - to_chat(usr, "Variable appears to be REFERENCE.") - class = "reference" - - else if(isicon(var_value)) - to_chat(usr, "Variable appears to be ICON.") - var_value = "[bicon(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)) - to_chat(usr, "Variable appears to be LIST.") - class = "list" - - else if(istype(var_value,/client)) - to_chat(usr, "Variable appears to be CLIENT.") - 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)) - to_chat(usr, "Unable to determine variable type.") - - else if(isnum(var_value)) - to_chat(usr, "Variable appears to be NUM.") - default = "num" - - else if(istext(var_value)) - to_chat(usr, "Variable appears to be TEXT.") - default = "text" - - else if(isloc(var_value)) - to_chat(usr, "Variable appears to be REFERENCE.") - default = "reference" - - else if(isicon(var_value)) - to_chat(usr, "Variable appears to be ICON.") - var_value = "[bicon(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)) - to_chat(usr, "Variable appears to be LIST.") - default = "list" - - else if(istype(var_value,/client)) - to_chat(usr, "Variable appears to be CLIENT.") - default = "cancel" - - else - to_chat(usr, "Variable appears to be 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) - 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" - - var/log_handled = FALSE - - switch(class) - - if("list") - if(!islist(O.vars[variable])) - if(alert("This is not a list. Would you like to create new list?",,"Yes","No") == "No") - return - O.vars[variable] = list() - mod_list(O.vars[variable]) - return - - if("restore to default") - if(variable=="resize") - world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.resize_rev]")]" - log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.resize_rev]") - message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.resize_rev]") - log_handled = TRUE - O.vars[variable] = O.resize_rev - O.update_transform() - O.resize_rev = initial(O.resize_rev) - else - O.vars[variable] = initial(O.vars[variable]) - - if("edit referenced object") - return .(O.vars[variable]) - - if("text") - var/var_new = sanitize(input("Enter new text:", "Text", O.vars[variable])) as null|text - if(isnull(var_new)) - return - O.vars[variable] = var_new - - if("num") - switch(variable) - if("light_range") - var/var_new = input("Enter new number:", "Num", O.vars[variable]) as null|num - if(isnull(var_new)) - return - O.set_light(var_new) - if("player_ingame_age") - var/var_new = input("Enter new number:", "Num", O.vars[variable]) as null|num - if(isnull(var_new) || var_new < 0) - return - O.vars[variable] = var_new - if(istype(O,/client)) - var/client/C = O - if(C) C.log_client_ingame_age_to_db() - if("stat") - var/var_new = input("Enter new number:", "Num", O.vars[variable]) as null|num - if(isnull(var_new)) - return - if((O.vars[variable] == DEAD) && (var_new < DEAD))//Bringing the dead back to life - dead_mob_list -= O - alive_mob_list += O - if((O.vars[variable] < DEAD) && (var_new == DEAD))//Kill him - alive_mob_list -= O - dead_mob_list += O - O.vars[variable] = var_new - if("resize") - var/var_new = input("Enter new coefficient: \n(object will be resized by multiplying this number)", "Num", O.vars[variable]) as null|num - if(isnull(var_new)) - return - if(var_new == 0) - to_chat(usr, "Resize coefficient can't be equal 0") - return - O.vars[variable] = var_new - world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.resize]")]" - log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.resize]") - message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.resize]") - log_handled = TRUE - O.update_transform() - else - var/var_new = input("Enter new number:", "Num", O.vars[variable]) as null|num - if(isnull(var_new)) - 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 - - if(!log_handled) - 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]]") +var/list/forbidden_varedit_object_types = list( + /datum/admins, //Admins editing their own admin-power object? Yup, sounds like a good idea. + /datum/configuration, + /obj/machinery/blackbox_recorder, //Prevents people messing with feedback gathering + /datum/feedback_variable, //Prevents people messing with feedback gathering + /datum/timedevent, //Nope.avi + /datum/craft_or_build, + /datum/stack_recipe, + /datum/events, + ) + +/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 = sanitize(input("Enter new text:","Text") as null|text) + + 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(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 = sanitize(input("Enter new text:","Text") as text) + + 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(list/L) + if(!check_rights(R_VAREDIT)) + return + + if(!islist(L)) + to_chat(usr, "Still not a list") + return + + + var/list/locked = list("vars", "key", "ckey", "client", "virus", "viruses", "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)) + to_chat(usr, "Variable appears to be NUM.") + default = "num" + + else if(istext(variable)) + to_chat(usr, "Variable appears to be TEXT.") + default = "text" + + else if(isloc(variable)) + to_chat(usr, "Variable appears to be REFERENCE.") + default = "reference" + + else if(isicon(variable)) + to_chat(usr, "Variable appears to be ICON.") + variable = "[bicon(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)) + to_chat(usr, "Variable appears to be LIST.") + default = "list" + + else if(istype(variable,/client)) + to_chat(usr, "Variable appears to be CLIENT.") + default = "cancel" + + else + to_chat(usr, "Variable appears to be 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) + 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") + if(!islist(L[L.Find(variable)])) + if(alert("This is not a list. Would you like to create new list?",,"Yes","No") == "No") + return + L[L.Find(variable)] = list() + mod_list(L[L.Find(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") + L[L.Find(variable)] = sanitize(input("Enter new text:","Text") as text) + + if("num") + L[L.Find(variable)] = input("Enter new number:","Num") as num + + if("type") + L[L.Find(variable)] = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) + + if("reference") + L[L.Find(variable)] = input("Select reference:","Reference") as mob|obj|turf|area in world + + if("mob reference") + L[L.Find(variable)] = input("Select reference:","Reference") as mob in world + + if("file") + L[L.Find(variable)] = input("Pick file:","File") as file + + if("icon") + L[L.Find(variable)] = input("Pick icon:","Icon") as icon + + if("marked datum") + L[L.Find(variable)] = holder.marked_datum + + +/client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0) + if(!check_rights(R_VAREDIT)) return + + var/list/icons_modifying = list("resize") + var/list/locked = list("vars", "key", "ckey", "client", "virus", "viruses", "mutantrace", "player_ingame_age", "summon_type", "AI_Interact") + var/list/typechange_locked = list("player_next_age_tick","player_ingame_age") + var/list/fully_locked = list("holder", "player_next_age_tick", "resize_rev", "step_x", "step_y") + + if(is_type_in_list(O, forbidden_varedit_object_types)) + to_chat(usr, "\red 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)) + to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this atom ([O])") + return + + if(param_var_name in fully_locked) + to_chat(usr, "\red It is forbidden to edit this variable.") + return + + if(!autodetect_class && (param_var_name in typechange_locked)) + return + + if((param_var_name in locked) && !check_rights(R_DEBUG)) + return + + if((param_var_name in icons_modifying) && !check_rights(R_DEBUG|R_EVENT)) + 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)) + to_chat(usr, "Variable appears to be NUM.") + class = "num" + + else if(istext(var_value)) + to_chat(usr, "Variable appears to be TEXT.") + class = "text" + + else if(isloc(var_value)) + to_chat(usr, "Variable appears to be REFERENCE.") + class = "reference" + + else if(isicon(var_value)) + to_chat(usr, "Variable appears to be ICON.") + var_value = "[bicon(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)) + to_chat(usr, "Variable appears to be LIST.") + class = "list" + + else if(istype(var_value,/client)) + to_chat(usr, "Variable appears to be CLIENT.") + 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)) + to_chat(usr, "Unable to determine variable type.") + + else if(isnum(var_value)) + to_chat(usr, "Variable appears to be NUM.") + default = "num" + + else if(istext(var_value)) + to_chat(usr, "Variable appears to be TEXT.") + default = "text" + + else if(isloc(var_value)) + to_chat(usr, "Variable appears to be REFERENCE.") + default = "reference" + + else if(isicon(var_value)) + to_chat(usr, "Variable appears to be ICON.") + var_value = "[bicon(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)) + to_chat(usr, "Variable appears to be LIST.") + default = "list" + + else if(istype(var_value,/client)) + to_chat(usr, "Variable appears to be CLIENT.") + default = "cancel" + + else + to_chat(usr, "Variable appears to be 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) + 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" + + var/log_handled = FALSE + + switch(class) + + if("list") + if(!islist(O.vars[variable])) + if(alert("This is not a list. Would you like to create new list?",,"Yes","No") == "No") + return + O.vars[variable] = list() + mod_list(O.vars[variable]) + return + + if("restore to default") + if(variable=="resize") + world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.resize_rev]")]" + log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.resize_rev]") + message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.resize_rev]") + log_handled = TRUE + O.vars[variable] = O.resize_rev + O.update_transform() + O.resize_rev = initial(O.resize_rev) + else + O.vars[variable] = initial(O.vars[variable]) + + if("edit referenced object") + return .(O.vars[variable]) + + if("text") + var/var_new = sanitize(input("Enter new text:", "Text", O.vars[variable])) as null|text + if(isnull(var_new)) + return + O.vars[variable] = var_new + + if("num") + switch(variable) + if("light_range") + var/var_new = input("Enter new number:", "Num", O.vars[variable]) as null|num + if(isnull(var_new)) + return + O.set_light(var_new) + if("player_ingame_age") + var/var_new = input("Enter new number:", "Num", O.vars[variable]) as null|num + if(isnull(var_new) || var_new < 0) + return + O.vars[variable] = var_new + if(istype(O,/client)) + var/client/C = O + if(C) C.log_client_ingame_age_to_db() + if("stat") + var/var_new = input("Enter new number:", "Num", O.vars[variable]) as null|num + if(isnull(var_new)) + return + if((O.vars[variable] == DEAD) && (var_new < DEAD))//Bringing the dead back to life + dead_mob_list -= O + alive_mob_list += O + if((O.vars[variable] < DEAD) && (var_new == DEAD))//Kill him + alive_mob_list -= O + dead_mob_list += O + O.vars[variable] = var_new + if("resize") + var/var_new = input("Enter new coefficient: \n(object will be resized by multiplying this number)", "Num", O.vars[variable]) as null|num + if(isnull(var_new)) + return + if(var_new == 0) + to_chat(usr, "Resize coefficient can't be equal 0") + return + O.vars[variable] = var_new + world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.resize]")]" + log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.resize]") + message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.resize]") + log_handled = TRUE + O.update_transform() + else + var/var_new = input("Enter new number:", "Num", O.vars[variable]) as null|num + if(isnull(var_new)) + 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 + + if(!log_handled) + 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]]") diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index ee032ade484e..6a22de2142be 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -1,633 +1,633 @@ -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 Gangsters
                    - Make Abductor Team (Requires Ghosts)
                    - "} -/* These dont work just yet - Ninja, aliens and deathsquad I have not looked into yet - Nuke team is getting a null mob returned from makebody() (runtime error: null.mind. Line 272) - - Make Nuke Team (Requires Ghosts)
                    - Make Space Ninja (Requires Ghosts)
                    - Make Aliens (Requires Ghosts)
                    - Make Deathsquad (Syndicate) (Requires Ghosts)
                    - "} -*/ - usr << browse(entity_ja(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() - var/mob/living/carbon/human/H = null - - for(var/mob/living/carbon/human/applicant in player_list) - if(ROLE_TRAITOR in applicant.client.prefs.be_role) - if(!applicant.stat) - if(applicant.mind) - if (!applicant.mind.special_role) - if(!jobban_isbanned(applicant, ROLE_TRAITOR) && !jobban_isbanned(applicant, "Syndicate") && !role_available_in_minutes(applicant, ROLE_TRAITOR)) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant - - if(candidates.len) - var/numTraitors = min(candidates.len, 3) - - for(var/i = 0, i300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - - sleep(300) - - if(candidates.len) - shuffle(candidates) - for(var/mob/i in candidates) - if(!i || !i.client) continue //Dont bother removing them from the list since we only grab one wizard - - theghost = i - break - - if(theghost) - var/mob/living/carbon/human/new_character=makeBody(theghost) - new_character.mind.make_Wizard() - return 1 - - return 0 - - -/datum/admins/proc/makeCult() - - var/datum/game_mode/cult/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(ROLE_CULTIST in applicant.client.prefs.be_role) - if(applicant.stat == CONSCIOUS) - if(applicant.mind) - if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, ROLE_CULTIST) && !jobban_isbanned(applicant, "Syndicate") && !role_available_in_minutes(applicant, ROLE_CULTIST)) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant - - if(candidates.len) - var/numCultists = min(candidates.len, 4) - - for(var/i = 0, i300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - - sleep(300) - - if(candidates.len) - var/numagents = 5 - var/agentcount = 0 - - for(var/i = 0, i300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - sleep(300) - - for(var/mob/dead/observer/G in candidates) - if(!G.key) - candidates.Remove(G) - - if(candidates.len) - var/numagents = 6 - //Spawns commandos and equips them. - for (var/obj/effect/landmark/L in /area/syndicate_mothership/elite_squad) - if(numagents<=0) - break - if (L.name == "Syndicate-Commando") - syndicate_leader_selected = numagents == 1?1:0 - - var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) - - - while((!theghost || !theghost.client) && candidates.len) - theghost = pick(candidates) - candidates.Remove(theghost) - - if(!theghost) - qdel(new_syndicate_commando) - break - - new_syndicate_commando.key = theghost.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. - - - to_chat(new_syndicate_commando, "\blue You are an Elite Syndicate. [!syndicate_leader_selected?"commando":"LEADER"] in the service of the Syndicate. \nYour current mission is: \red [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 - - -/datum/admins/proc/makeGangsters() - - var/datum/game_mode/gang/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(ROLE_REV in applicant.client.prefs.be_role) - if(!applicant.stat) - if(applicant.mind) - if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, ROLE_REV) && !jobban_isbanned(applicant, "Syndicate") && !role_available_in_minutes(applicant, ROLE_REV)) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant - - if(candidates.len >= 2) - H = pick(candidates) - H.mind.make_Gang("A") - candidates.Remove(H) - H = pick(candidates) - H.mind.make_Gang("B") - return 1 - - return 0 - - -/datum/admins/proc/makeBody(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) - if(new_character.gender == MALE) - new_character.real_name = "[pick(first_names_male)] [pick(last_names)]" - else - new_character.real_name = "[pick(first_names_female)] [pick(last_names)]" - new_character.name = new_character.real_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/time_passed = world.time - 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 player_list) - spawn(0) - switch(alert(G,"Do you wish to be considered for a vox raiding party arriving on the station?","Please answer in 30 seconds!","Yes","No")) - if("Yes") - if((world.time-time_passed)>300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - - sleep(300) //Debug. - - 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) - qdel(new_vox) - break - - new_vox.key = theghost.key - to_chat(new_vox, "\blue 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: \red [input]") - to_chat(new_vox, "\red 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, "Vox") - - new_vox.gender = pick(MALE, FEMALE) - new_vox.h_style = "Short Vox Quills" - new_vox.regenerate_icons() - - var/sounds = rand(2,10) - var/i = 0 - var/newname = "" - - while(i<=sounds) - i++ - newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) - - new_vox.real_name = capitalize(newname) - new_vox.name = new_vox.real_name - new_vox.age = rand(12,20) - - new_vox.dna.ready_dna(new_vox) // Creates DNA. - new_vox.dna.mutantrace = "vox" - new_vox.mind_initialize() - new_vox.mind.assigned_role = "MODE" - new_vox.mind.special_role = "Vox Raider" - new_vox.mutations |= NOCLONE //Stops the station crew from messing around with their DNA. - - //Now apply cortical stack. - var/obj/item/organ/external/BP = new_vox.bodyparts_by_name[BP_HEAD] - - //To avoid duplicates. - for(var/obj/item/weapon/implant/cortical/imp in new_vox.contents) - BP.implants -= imp - qdel(imp) - - var/obj/item/weapon/implant/cortical/I = new(new_vox) - I.imp_in = new_vox - I.implanted = 1 - BP.implants += I - I.part = BP - - if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist ) ) ) - var/datum/game_mode/heist/M = ticker.mode - M.cortical_stacks[new_vox.mind] = I - M.raiders[new_vox.mind] = I - - ticker.mode.traitors += new_vox.mind - new_vox.equip_vox_raider() - - return new_vox - -datum/admins/proc/makeAbductorTeam() - var/list/mob/dead/observer/candidates = list() - var/time_passed = world.time - - for(var/mob/dead/observer/G in player_list) - spawn(0) - switch(alert(G,"Do you wish to be considered for Abductor Team?","Please answer in 30 seconds!","Yes","No")) - if("Yes") - if((world.time-time_passed)>300)//If more than 30 game seconds passed. - return - candidates += G - if("No") - return - else - return - sleep(300) - - for(var/mob/dead/observer/G in candidates) - if(!G.key) - candidates.Remove(G) - - if(candidates.len >= 2) - var/number = ticker.mode.abductor_teams + 1 - - var/datum/game_mode/abduction/temp - if(ticker.mode.config_tag == "abduction") - temp = ticker.mode - else - temp = new - - var/agent_mind = pick(candidates) - candidates -= agent_mind - var/scientist_mind = pick(candidates) - - var/mob/living/carbon/human/agent=makeBody(agent_mind) - var/mob/living/carbon/human/scientist=makeBody(scientist_mind) - - agent_mind = agent.mind - scientist_mind = scientist.mind - - temp.scientists.len = number - temp.agents.len = number - temp.abductors.len = 2*number - temp.team_objectives.len = number - temp.team_names.len = number - temp.scientists[number] = scientist_mind - temp.agents[number] = agent_mind - temp.abductors = list(agent_mind,scientist_mind) - temp.make_abductor_team(number) - temp.post_setup_team(number) - ticker.mode.abductors += temp.abductors - ticker.mode.abductor_teams++ - - if(ticker.mode.config_tag != "abduction") - ticker.mode.abductors |= temp.abductors - - return 1 - else - return +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 Gangsters
                    + Make Abductor Team (Requires Ghosts)
                    + "} +/* These dont work just yet + Ninja, aliens and deathsquad I have not looked into yet + Nuke team is getting a null mob returned from makebody() (runtime error: null.mind. Line 272) + + Make Nuke Team (Requires Ghosts)
                    + Make Space Ninja (Requires Ghosts)
                    + Make Aliens (Requires Ghosts)
                    + Make Deathsquad (Syndicate) (Requires Ghosts)
                    + "} +*/ + usr << browse(entity_ja(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() + var/mob/living/carbon/human/H = null + + for(var/mob/living/carbon/human/applicant in player_list) + if(ROLE_TRAITOR in applicant.client.prefs.be_role) + if(!applicant.stat) + if(applicant.mind) + if (!applicant.mind.special_role) + if(!jobban_isbanned(applicant, ROLE_TRAITOR) && !jobban_isbanned(applicant, "Syndicate") && !role_available_in_minutes(applicant, ROLE_TRAITOR)) + if(!(applicant.job in temp.restricted_jobs)) + candidates += applicant + + if(candidates.len) + var/numTraitors = min(candidates.len, 3) + + for(var/i = 0, i300)//If more than 30 game seconds passed. + return + candidates += G + if("No") + return + else + return + + sleep(300) + + if(candidates.len) + shuffle(candidates) + for(var/mob/i in candidates) + if(!i || !i.client) continue //Dont bother removing them from the list since we only grab one wizard + + theghost = i + break + + if(theghost) + var/mob/living/carbon/human/new_character=makeBody(theghost) + new_character.mind.make_Wizard() + return 1 + + return 0 + + +/datum/admins/proc/makeCult() + + var/datum/game_mode/cult/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(ROLE_CULTIST in applicant.client.prefs.be_role) + if(applicant.stat == CONSCIOUS) + if(applicant.mind) + if(!applicant.mind.special_role) + if(!jobban_isbanned(applicant, ROLE_CULTIST) && !jobban_isbanned(applicant, "Syndicate") && !role_available_in_minutes(applicant, ROLE_CULTIST)) + if(!(applicant.job in temp.restricted_jobs)) + candidates += applicant + + if(candidates.len) + var/numCultists = min(candidates.len, 4) + + for(var/i = 0, i300)//If more than 30 game seconds passed. + return + candidates += G + if("No") + return + else + return + + sleep(300) + + if(candidates.len) + var/numagents = 5 + var/agentcount = 0 + + for(var/i = 0, i300)//If more than 30 game seconds passed. + return + candidates += G + if("No") + return + else + return + sleep(300) + + for(var/mob/dead/observer/G in candidates) + if(!G.key) + candidates.Remove(G) + + if(candidates.len) + var/numagents = 6 + //Spawns commandos and equips them. + for (var/obj/effect/landmark/L in /area/syndicate_mothership/elite_squad) + if(numagents<=0) + break + if (L.name == "Syndicate-Commando") + syndicate_leader_selected = numagents == 1?1:0 + + var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) + + + while((!theghost || !theghost.client) && candidates.len) + theghost = pick(candidates) + candidates.Remove(theghost) + + if(!theghost) + qdel(new_syndicate_commando) + break + + new_syndicate_commando.key = theghost.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. + + + to_chat(new_syndicate_commando, "\blue You are an Elite Syndicate. [!syndicate_leader_selected?"commando":"LEADER"] in the service of the Syndicate. \nYour current mission is: \red [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 + + +/datum/admins/proc/makeGangsters() + + var/datum/game_mode/gang/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(ROLE_REV in applicant.client.prefs.be_role) + if(!applicant.stat) + if(applicant.mind) + if(!applicant.mind.special_role) + if(!jobban_isbanned(applicant, ROLE_REV) && !jobban_isbanned(applicant, "Syndicate") && !role_available_in_minutes(applicant, ROLE_REV)) + if(!(applicant.job in temp.restricted_jobs)) + candidates += applicant + + if(candidates.len >= 2) + H = pick(candidates) + H.mind.make_Gang("A") + candidates.Remove(H) + H = pick(candidates) + H.mind.make_Gang("B") + return 1 + + return 0 + + +/datum/admins/proc/makeBody(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) + if(new_character.gender == MALE) + new_character.real_name = "[pick(first_names_male)] [pick(last_names)]" + else + new_character.real_name = "[pick(first_names_female)] [pick(last_names)]" + new_character.name = new_character.real_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/time_passed = world.time + 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 player_list) + spawn(0) + switch(alert(G,"Do you wish to be considered for a vox raiding party arriving on the station?","Please answer in 30 seconds!","Yes","No")) + if("Yes") + if((world.time-time_passed)>300)//If more than 30 game seconds passed. + return + candidates += G + if("No") + return + else + return + + sleep(300) //Debug. + + 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) + qdel(new_vox) + break + + new_vox.key = theghost.key + to_chat(new_vox, "\blue 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: \red [input]") + to_chat(new_vox, "\red 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, "Vox") + + new_vox.gender = pick(MALE, FEMALE) + new_vox.h_style = "Short Vox Quills" + new_vox.regenerate_icons() + + var/sounds = rand(2,10) + var/i = 0 + var/newname = "" + + while(i<=sounds) + i++ + newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) + + new_vox.real_name = capitalize(newname) + new_vox.name = new_vox.real_name + new_vox.age = rand(12,20) + + new_vox.dna.ready_dna(new_vox) // Creates DNA. + new_vox.dna.mutantrace = "vox" + new_vox.mind_initialize() + new_vox.mind.assigned_role = "MODE" + new_vox.mind.special_role = "Vox Raider" + new_vox.mutations |= NOCLONE //Stops the station crew from messing around with their DNA. + + //Now apply cortical stack. + var/obj/item/organ/external/BP = new_vox.bodyparts_by_name[BP_HEAD] + + //To avoid duplicates. + for(var/obj/item/weapon/implant/cortical/imp in new_vox.contents) + BP.implants -= imp + qdel(imp) + + var/obj/item/weapon/implant/cortical/I = new(new_vox) + I.imp_in = new_vox + I.implanted = 1 + BP.implants += I + I.part = BP + + if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist ) ) ) + var/datum/game_mode/heist/M = ticker.mode + M.cortical_stacks[new_vox.mind] = I + M.raiders[new_vox.mind] = I + + ticker.mode.traitors += new_vox.mind + new_vox.equip_vox_raider() + + return new_vox + +datum/admins/proc/makeAbductorTeam() + var/list/mob/dead/observer/candidates = list() + var/time_passed = world.time + + for(var/mob/dead/observer/G in player_list) + spawn(0) + switch(alert(G,"Do you wish to be considered for Abductor Team?","Please answer in 30 seconds!","Yes","No")) + if("Yes") + if((world.time-time_passed)>300)//If more than 30 game seconds passed. + return + candidates += G + if("No") + return + else + return + sleep(300) + + for(var/mob/dead/observer/G in candidates) + if(!G.key) + candidates.Remove(G) + + if(candidates.len >= 2) + var/number = ticker.mode.abductor_teams + 1 + + var/datum/game_mode/abduction/temp + if(ticker.mode.config_tag == "abduction") + temp = ticker.mode + else + temp = new + + var/agent_mind = pick(candidates) + candidates -= agent_mind + var/scientist_mind = pick(candidates) + + var/mob/living/carbon/human/agent=makeBody(agent_mind) + var/mob/living/carbon/human/scientist=makeBody(scientist_mind) + + agent_mind = agent.mind + scientist_mind = scientist.mind + + temp.scientists.len = number + temp.agents.len = number + temp.abductors.len = 2*number + temp.team_objectives.len = number + temp.team_names.len = number + temp.scientists[number] = scientist_mind + temp.agents[number] = agent_mind + temp.abductors = list(agent_mind,scientist_mind) + temp.make_abductor_team(number) + temp.post_setup_team(number) + ticker.mode.abductors += temp.abductors + ticker.mode.abductor_teams++ + + if(ticker.mode.config_tag != "abduction") + ticker.mode.abductors |= temp.abductors + + return 1 + else + return diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm index 2ac0bf399d85..13733d207a59 100644 --- a/code/modules/admin/verbs/onlyone.dm +++ b/code/modules/admin/verbs/onlyone.dm @@ -1,50 +1,50 @@ -/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 == DEAD || !(H.client)) continue - if(is_special_character(H)) continue - - ticker.mode.traitors += H.mind - H.mind.special_role = "traitor" - - 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) - 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 - qdel(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_l_ear) - 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("\blue [key_name_admin(usr)] used THERE CAN BE ONLY ONE!") - log_admin("[key_name(usr)] used there can be only one.") +/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 == DEAD || !(H.client)) continue + if(is_special_character(H)) continue + + ticker.mode.traitors += H.mind + H.mind.special_role = "traitor" + + 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) + 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 + qdel(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_l_ear) + 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("\blue [key_name_admin(usr)] used THERE CAN BE ONLY ONE!") + log_admin("[key_name(usr)] used there can be only one.") diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm index 72d3a02bdb61..5c90ea9b128c 100644 --- a/code/modules/admin/verbs/playsound.dm +++ b/code/modules/admin/verbs/playsound.dm @@ -1,71 +1,71 @@ -var/global/list/sounds_cache = list() - -/client/proc/play_sound(S as sound) - set category = "Fun" - set name = "Play Global Sound" - if(!check_rights(R_SOUNDS)) return - - var/sound/uploaded_sound = new()//sound(S, repeat = 0, wait = 1, channel = CHANNEL_ADMIN) - uploaded_sound.file = S - uploaded_sound.priority = 250 - uploaded_sound.channel = CHANNEL_ADMIN - uploaded_sound.wait = 1 - uploaded_sound.status = SOUND_STREAM - uploaded_sound.volume = 100 - - sounds_cache += S - - var/forced = FALSE - - switch(alert("Do you ready?\nSong: [S]\nDon't overuse forced play (or UNPEDALITY)! This is only for sound effects.",,"Play", "Forced", "Cancel")) - if("Forced") - forced = TRUE - if("Cancel") - return - - log_admin("[key_name(src)] played sound [S] [forced ? "FORCED" : ""]") - message_admins("[key_name_admin(src)] played sound [S] [forced ? "FORCED" : ""]") - - for(var/mob/M in player_list) - if(forced || M.client.prefs.toggles & SOUND_MIDI) - uploaded_sound.volume = M.client.adminSoundVolume - M.client << 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(S as sound) - set category = "Fun" - set name = "Play Local Sound" - if(!check_rights(R_SOUNDS)) return - - log_admin("[key_name(src)] played a local sound [S]") - message_admins("[key_name_admin(src)] played a local sound [S]") - playsound(get_turf_loc(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/play_server_sound() - set category = "Fun" - set name = "Play Server Sound" - if(!check_rights(R_SOUNDS)) return - - var/list/sounds = file2list("sound/serversound_list.txt"); - sounds += "--CANCEL--" - sounds += sounds_cache - - var/melody = input("Select a sound from the server to play", , "CANCEL") in sounds - - if(melody == "--CANCEL--") return - - play_sound(melody) - -/client/proc/stop_server_sound() - set category = "Fun" - set name = "Stop Global Sound" - if(!check_rights(R_SOUNDS)) - return - var/sound/sound = sound(null, repeat = 0, wait = 0, channel = CHANNEL_ADMIN) - for(var/mob/M in player_list) - M << sound - log_admin("[key_name(src)] has stopped the global sound.") - message_admins("[key_name_admin(src)] has stopped the global sound.") +var/global/list/sounds_cache = list() + +/client/proc/play_sound(S as sound) + set category = "Fun" + set name = "Play Global Sound" + if(!check_rights(R_SOUNDS)) return + + var/sound/uploaded_sound = new()//sound(S, repeat = 0, wait = 1, channel = CHANNEL_ADMIN) + uploaded_sound.file = S + uploaded_sound.priority = 250 + uploaded_sound.channel = CHANNEL_ADMIN + uploaded_sound.wait = 1 + uploaded_sound.status = SOUND_STREAM + uploaded_sound.volume = 100 + + sounds_cache += S + + var/forced = FALSE + + switch(alert("Do you ready?\nSong: [S]\nDon't overuse forced play (or UNPEDALITY)! This is only for sound effects.",,"Play", "Forced", "Cancel")) + if("Forced") + forced = TRUE + if("Cancel") + return + + log_admin("[key_name(src)] played sound [S] [forced ? "FORCED" : ""]") + message_admins("[key_name_admin(src)] played sound [S] [forced ? "FORCED" : ""]") + + for(var/mob/M in player_list) + if(forced || M.client.prefs.toggles & SOUND_MIDI) + uploaded_sound.volume = M.client.adminSoundVolume + M.client << 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(S as sound) + set category = "Fun" + set name = "Play Local Sound" + if(!check_rights(R_SOUNDS)) return + + log_admin("[key_name(src)] played a local sound [S]") + message_admins("[key_name_admin(src)] played a local sound [S]") + playsound(get_turf_loc(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/play_server_sound() + set category = "Fun" + set name = "Play Server Sound" + if(!check_rights(R_SOUNDS)) return + + var/list/sounds = file2list("sound/serversound_list.txt"); + sounds += "--CANCEL--" + sounds += sounds_cache + + var/melody = input("Select a sound from the server to play", , "CANCEL") in sounds + + if(melody == "--CANCEL--") return + + play_sound(melody) + +/client/proc/stop_server_sound() + set category = "Fun" + set name = "Stop Global Sound" + if(!check_rights(R_SOUNDS)) + return + var/sound/sound = sound(null, repeat = 0, wait = 0, channel = CHANNEL_ADMIN) + for(var/mob/M in player_list) + M << sound + log_admin("[key_name(src)] has stopped the global sound.") + message_admins("[key_name_admin(src)] has stopped the global sound.") diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index 945fdbac5110..a31d43d15eb2 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -1,57 +1,57 @@ -/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, "\red Speech is currently admin-disabled.") - return - - msg = sanitize(msg) - if(!msg) return - - if(usr.client) - if(usr.client.prefs.muted & MUTE_PRAY) - to_chat(usr, "\red You cannot pray (muted).") - return - if(src.client.handle_spam_prevention(msg,MUTE_PRAY)) - return - - var/mutable_appearance/cross = mutable_appearance('icons/obj/storage.dmi', "bible") - var/font_color = "purple" - var/prayer_type = "PRAYER" - var/deity - - if(usr.job == "Chaplain") - cross.icon_state = "kingyellow" - font_color = "blue" - prayer_type = "CHAPLAIN PRAYER" - if(ticker.Bible_deity_name) - deity = ticker.Bible_deity_name - else if(iscultist(usr)) - cross.icon_state = "tome" - font_color = "red" - prayer_type = "CULTIST PRAYER" - deity = "Nar'Sie" - - var/msg_tmp = msg - msg = "\blue [bicon(cross)] [prayer_type][deity ? " (to [deity])" : ""] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (CA) (SC): [msg]" - - for(var/client/C in admins) - if(C.prefs.chat_toggles & CHAT_PRAYER) - to_chat(C, msg) - to_chat(usr, "You pray to the gods: \"[msg_tmp]\"") - - feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - //log_admin("HELP: [key_name(src)]: [msg]") - -/proc/Centcomm_announce(text , mob/Sender , iamessage) - send2slack_custommsg("[key_name(Sender)] has made an Centcomm announcement", text, ":job_cap:") - text = "\blue CENTCOMM[iamessage ? " IA" : ""]:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [text]" - for(var/client/C in admins) - to_chat(C, text) - -/proc/Syndicate_announce(text , mob/Sender) - send2slack_custommsg("[key_name(Sender)] has made an Syndicate announcement", text, ":job_nuke:") - text = "\blue SYNDICATE:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [text]" - for(var/client/C in admins) - to_chat(C, text) +/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, "\red Speech is currently admin-disabled.") + return + + msg = sanitize(msg) + if(!msg) return + + if(usr.client) + if(usr.client.prefs.muted & MUTE_PRAY) + to_chat(usr, "\red You cannot pray (muted).") + return + if(src.client.handle_spam_prevention(msg,MUTE_PRAY)) + return + + var/mutable_appearance/cross = mutable_appearance('icons/obj/storage.dmi', "bible") + var/font_color = "purple" + var/prayer_type = "PRAYER" + var/deity + + if(usr.job == "Chaplain") + cross.icon_state = "kingyellow" + font_color = "blue" + prayer_type = "CHAPLAIN PRAYER" + if(ticker.Bible_deity_name) + deity = ticker.Bible_deity_name + else if(iscultist(usr)) + cross.icon_state = "tome" + font_color = "red" + prayer_type = "CULTIST PRAYER" + deity = "Nar'Sie" + + var/msg_tmp = msg + msg = "\blue [bicon(cross)] [prayer_type][deity ? " (to [deity])" : ""] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (CA) (SC): [msg]" + + for(var/client/C in admins) + if(C.prefs.chat_toggles & CHAT_PRAYER) + to_chat(C, msg) + to_chat(usr, "You pray to the gods: \"[msg_tmp]\"") + + feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + //log_admin("HELP: [key_name(src)]: [msg]") + +/proc/Centcomm_announce(text , mob/Sender , iamessage) + send2slack_custommsg("[key_name(Sender)] has made an Centcomm announcement", text, ":job_cap:") + text = "\blue CENTCOMM[iamessage ? " IA" : ""]:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [text]" + for(var/client/C in admins) + to_chat(C, text) + +/proc/Syndicate_announce(text , mob/Sender) + send2slack_custommsg("[key_name(Sender)] has made an Syndicate announcement", text, ":job_nuke:") + text = "\blue SYNDICATE:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [text]" + for(var/client/C in admins) + to_chat(C, text) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 285eb5c4909a..a0f02fa88d11 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1,1109 +1,1109 @@ -/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 - - for(var/obj/item/W in M) - M.drop_from_inventory(W) - - log_admin("[key_name(usr)] made [key_name(M)] drop everything!") - message_admins("[key_name_admin(usr)] made [key_name_admin(M)] drop everything!") - 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/orange(prisoner), slot_w_uniform) - prisoner.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(prisoner), slot_shoes) - spawn(50) - to_chat(M, "\red You have been sent to the prison station!") - log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.") - message_admins("\blue [key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.") - 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 = sanitize(input("Message:", text("Subtle PM to [M.key]")) as text) - - if (!msg) - return - if(usr) - if (usr.client) - if(usr.client.holder) - to_chat(M, "\bold You hear a voice in your head... \italic [msg]") - - log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]") - message_admins("\blue \bold SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]") - feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/cmd_mentor_check_new_players() //Allows mentors / admins to determine who the newer players are. - set category = "Admin" - set name = "Check new Players" - if(!holder) - to_chat(src, "Only staff members may use this command.") - - var/age = alert(src, "Age check", "Show accounts yonger then _____ days","7", "30" , "All") - - if(age == "All") - age = 9999999 - else - age = text2num(age) - - var/missing_ages = 0 - var/msg = "" - - for(var/client/C in clients) - if(C.player_age == "Requires database") - missing_ages = 1 - continue - if(C.player_age < age) - msg += {" - [key_name(C, 1)] [ADMIN_PP(C.mob)]:
                    - Days on server: [C.player_age]
                    - In-game minutes: [C.player_ingame_age] -
                    - "} - - if(missing_ages) - to_chat(src, "Some accounts did not have proper ages set in their clients. This function requires database to be present") - - if(msg != "") - src << browse(msg, "window=Player_age_check") - else - to_chat(src, "No matches for that age range found.") - - -/client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE - set category = "Special Verbs" - set name = "Global Narrate" - - if (!holder) - to_chat(src, "Only administrators may use this command.") - return - - var/msg = sanitize(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("\blue \bold GlobalNarrate: [key_name_admin(usr)] : [msg]
                    ") - 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(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 get_mob_with_client_list() - - if(!M) - return - - var/msg = sanitize(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("\blue \bold DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]
                    ") - 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_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 - to_chat(usr, "\blue 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"]") - 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) - to_chat(usr, "Error: cmd_admin_mute: This mob doesn't have a client tied to it.") - if(M.client.holder && (M.client.holder.rights & R_ADMIN) && !check_rights(R_PERMISSIONS)) - return - if(M.client.holder && (M.client.holder.rights & R_PERMISSIONS)) - to_chat(usr, "Error: cmd_admin_mute: You cannot mute an admin with permissions rights.") - return - if(!M.client) - 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_MENTORHELP) - mute_string = "mentorhelp and mentor PM" - 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].") - 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 - if(M.client.prefs.permamuted & mute_type) - M.client.prefs.permamuted &= ~mute_type - M.client.prefs.save_preferences() - else - muteunmute = "muted" - M.client.prefs.muted |= mute_type - if(alert("Would you like to make it permament?","Permamute?","Yes","No, round only") == "Yes") - muteunmute = "permamuted" - M.client.prefs.permamuted |= mute_type - M.client.prefs.save_preferences() - - - 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].") - 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) - 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.") - - 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") - world << sound('sound/AI/ionstorm.ogg') - - IonStorm(0) - 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 player_list) - if(M.stat != DEAD) continue //we are not dead! - if(!(ROLE_ALIEN in M.client.prefs.be_role)) continue //we don't want to be an alium - if(M.client.is_afk()) continue //we are afk - if(M.mind && M.mind.current && M.mind.current.stat != DEAD) continue //we have a live body we are tied to - 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("\blue [key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].") - 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(notify = 0,what = 2) - // what = 1, return ghosts ass list. - // what = 2, return mob list - - var/list/mobs = list() - var/list/ghosts = list() - var/list/sortmob = sortAtom(observer_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 - - 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("\blue 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") - - -/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, "\red The Administrator has disabled AntagHUD ") - config.antag_hud_allowed = 0 - to_chat(src, "\red 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, "\blue The Administrator has enabled AntagHUD ")// Notify all observers they can now use AntagHUD - config.antag_hud_allowed = 1 - action = "enabled" - to_chat(src, "\blue 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") - - - -/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()) - to_chat(g, "\blue The administrator has lifted restrictions on joining the round if you use AntagHUD") - action = "lifted restrictions" - config.antag_hud_restricted = 0 - to_chat(src, "\blue AntagHUD restrictions have been lifted") - else - for(var/mob/dead/observer/g in get_ghosts()) - to_chat(g, "\red The administrator has placed restrictions on joining the round if you use AntagHUD") - to_chat(g, "\red 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 - to_chat(src, "\red 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") - - - - -/* -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 = input(src, "Please specify which key will be respawned.", "Key", "") as null|anything in clients - 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 - to_chat(new_xeno, "You have been fully respawned. Enjoy the game.") - message_admins("\blue [key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.") - 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("\blue [key_name_admin(usr)] has respawned [new_monkey.key] as a filthy xeno.") - 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]") - for(var/datum/data/record/t in data_core.locked) - if(t.fields["id"]==id) - record_found = t//We shall now reference the record. - break - - if(record_found)//If they have a record we can determine a few things. - new_character.real_name = record_found.fields["name"] - new_character.gender = record_found.fields["sex"] - new_character.age = record_found.fields["age"] - new_character.b_type = record_found.fields["b_type"] - else - new_character.gender = 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) - if(new_character.gender == MALE) - new_character.real_name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) - else - new_character.real_name = capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names)) - 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 = "Test Subject"//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") - SSjob.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("Ninja") - new_character.equip_space_ninja() - new_character.internal = new_character.s_store - new_character.internals.icon_state = "internal1" - if(ninjastart.len == 0) - to_chat(new_character, "\red A proper starting location for you could not be found, please report this bug!") - to_chat(new_character, "\red Attempting to place at a carpspawn.") - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "carpspawn") - ninjastart.Add(L) - if(ninjastart.len == 0 && latejoin.len > 0) - to_chat(new_character, "\red Still no spawneable locations could be found. Defaulting to latejoin.") - new_character.loc = pick(latejoin) - else if (ninjastart.len == 0) - to_chat(new_character, "\red Still no spawneable locations could be found. Aborting.") - - 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("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) - if("AI") - new_character = new_character.AIize() - if(new_character.mind.special_role=="traitor") - call(/datum/game_mode/proc/add_law_zero)(new_character) - //Add aliens. - else - SSjob.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") - call(/mob/dead/new_player/proc/AnnounceArrival)(new_character, new_character.mind.assigned_role) - - message_admins("\blue [admin] has respawned [player_key] as [new_character.real_name].") - - 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) - to_chat(src, "Only administrators may use this command.") - return - var/input = sanitize(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 ai_list) - if (M.stat == DEAD) - to_chat(usr, "Upload failed. No signal is being detected from the AI.") - 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 ai_list) - to_chat(O, "\red " + input + "\red...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]") - - 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") - 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) - to_chat(src, "Only administrators may use this command.") - return - if(!check_rights(R_REJUVINATE)) return - if(!mob) - return - if(!istype(M)) - alert("Cannot revive a ghost") - return - if(config.allow_admin_rev) - M.revive() - - log_admin("[key_name(usr)] healed / revived [key_name(M)]") - message_admins("\red Admin [key_name_admin(usr)] healed / revived [key_name_admin(M)]!") - 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 = sanitize(input(usr, "Please enter anything you want. Anything. Serious.", "What?", "") as message|null, MAX_PAPER_MESSAGE_LEN, extra = FALSE) - var/customname = sanitize_safe(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 communications_list) - 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 = replacetext(input, "\n", "
                    ") - 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, "\red New NanoTrasen Update available at all communication consoles.") - - 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") - 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 view()) - 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])") - feedback_add_details("admin_verb","DEL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - 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(SSjob) - for(var/datum/job/job in SSjob.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])") - 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])") - 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)]") - - 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("\blue [key_name_admin(usr)] used gibself.") - 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) - to_chat(M, "\redYou have been banned by [usr.client.ckey].\nReason: [reason].") - to_chat(M, "\red This is a temporary ban, it will be removed in [mins] minutes.") - to_chat(M, "\red 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("\blue[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) - qdel(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, "\redYou have been banned by [usr.client.ckey].\nReason: [reason].") - to_chat(M, "\red This is a permanent ban.") - to_chat(M, "\red 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("\blue[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) - qdel(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/M as mob in mob_list) - set category = "Special Verbs" - set name = "Check Contents" - - var/list/L = M.get_contents() - for(var/t in L) - to_chat(usr, "[t]") - 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_phoron() - 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("\blue [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 || SSshuttle.location) - return - - if(!check_rights(R_ADMIN)) - return - - if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") - return - - if(SSshuttle.always_fake_recall) - var/choice = input("The shuttle will just return if you call it. What you want to do?") in list( - "Cancel shuttle call", - "Call it anyway", - "Call and allow it to fly to station") - switch(choice) - if("Cancel shuttle call") - return - if("Call and allow it to fly to station") - SSshuttle.always_fake_recall = FALSE - SSshuttle.fake_recall = 0 - log_admin("[key_name(usr)] disabled shuttle fake recall.") - message_admins("[key_name_admin(usr)] disabled shuttle fake recall.") - - var/type = alert(src, "It's emergency shuttle or crew transfer?", "Confirm", "Emergency", "Crew transfer") - - if(type == "Crew transfer") - SSshuttle.shuttlealert(1) - SSshuttle.incall() - captain_announce("A crew transfer has been initiated. The shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - else - var/eaccess = alert(src, "Grant acces to maints for everyone?", "Confirm", "Yes", "No") - SSshuttle.incall() - captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - world << sound('sound/AI/shuttlecalled.ogg') - - if(eaccess == "Yes") - make_maint_all_access(FALSE) - - 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("\blue [key_name_admin(usr)] admin-called the emergency shuttle.") - 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 || SSshuttle.location || SSshuttle.direction == 0) - return - - SSshuttle.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("\blue [key_name_admin(usr)] admin-recalled the emergency shuttle.") - - if(timer_maint_revoke_id) - deltimer(timer_maint_revoke_id) - timer_maint_revoke_id = 0 - timer_maint_revoke_id = addtimer(CALLBACK(GLOBAL_PROC, .proc/revoke_maint_all_access, FALSE), 600, TIMER_UNIQUE|TIMER_STOPPABLE) - - return - -/client/proc/admin_deny_shuttle() - set category = "Admin" - set name = "Toggle Deny Shuttle" - - if (!ticker) - return - - if(!check_rights(R_ADMIN)) - return - - SSshuttle.deny_shuttle = !SSshuttle.deny_shuttle - - log_admin("[key_name(src)] has [SSshuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.") - message_admins("[key_name_admin(usr)] has [SSshuttle.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("\red Attack Log for []", mob)) - 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) - 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.") - 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.") - - if(notifyplayers == "Yes") - to_chat(world, "\blue 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 - to_chat(usr, "Random events enabled") - message_admins("Admin [key_name_admin(usr)] has enabled random events.") - else - config.allow_random_events = 0 - to_chat(usr, "Random events disabled") - message_admins("Admin [key_name_admin(usr)] has disabled random events.") - feedback_add_details("admin_verb","TRE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - - -/client/proc/send_fax_message() - set name = "Send Fax Message" - set category = "Special Verbs" - - if(!check_rights(R_ADMIN)) - return - - var/sent_text = sanitize(input(usr, "Please, enter the text you want to send.", "What?", "") as message|null, MAX_PAPER_MESSAGE_LEN) - if(!sent_text) - return - - var/sent_name = sanitize_safe(input(usr, "Pick a title for the message.", "Title") as text) - if(!sent_name) - sent_name = "NanoTrasen Update" - if(sent_name == "Cancel") - return - - var/list/departments = alldepartments.Copy() - departments += "All" - var/department = input(usr, "Please, choose the destination department.") as null|anything in departments - if(!department) - return - - var/list/stamp_list = list("CentComm", "Syndicate", "Clown", "FakeCentComm", "None") - var/stamp_name = input(usr, "Please, choose the stamp you want to send with.") as null|anything in stamp_list - if(!stamp_name) - return - - var/stamp_type = null - if(stamp_name != "None") - stamp_type = text2path("/obj/item/weapon/stamp/[lowertext(stamp_name)]") - - var/stamp_text = null - if(stamp_type) - stamp_text = sanitize(input(usr, "Pick a message for stamp text (e.g. This paper has been stamped by the Central Compound Quantum Relay). In case of empty field there will be default stamp text.") as text) - - var/obj/item/weapon/paper/P = new - P.name = sent_name - P.info = sent_text - - if(stamp_type) - var/obj/item/weapon/stamp/S = new stamp_type - - if(stamp_text) - S.stamp_paper(P, stamp_text) - else - S.stamp_paper(P, use_stamp_by_message = TRUE) - - send_fax(usr, P, department) - - feedback_add_details("admin_verb","FAXMESS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - message_admins("Fax message was created by [key_name_admin(usr)] and sent to [department]") - send2slack_custommsg("Fax message was created by [key_name_admin(usr)] and sent to [department]: [sent_text]") +/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 + + for(var/obj/item/W in M) + M.drop_from_inventory(W) + + log_admin("[key_name(usr)] made [key_name(M)] drop everything!") + message_admins("[key_name_admin(usr)] made [key_name_admin(M)] drop everything!") + 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/orange(prisoner), slot_w_uniform) + prisoner.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(prisoner), slot_shoes) + spawn(50) + to_chat(M, "\red You have been sent to the prison station!") + log_admin("[key_name(usr)] sent [key_name(M)] to the prison station.") + message_admins("\blue [key_name_admin(usr)] sent [key_name_admin(M)] to the prison station.") + 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 = sanitize(input("Message:", text("Subtle PM to [M.key]")) as text) + + if (!msg) + return + if(usr) + if (usr.client) + if(usr.client.holder) + to_chat(M, "\bold You hear a voice in your head... \italic [msg]") + + log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]") + message_admins("\blue \bold SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] : [msg]") + feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_mentor_check_new_players() //Allows mentors / admins to determine who the newer players are. + set category = "Admin" + set name = "Check new Players" + if(!holder) + to_chat(src, "Only staff members may use this command.") + + var/age = alert(src, "Age check", "Show accounts yonger then _____ days","7", "30" , "All") + + if(age == "All") + age = 9999999 + else + age = text2num(age) + + var/missing_ages = 0 + var/msg = "" + + for(var/client/C in clients) + if(C.player_age == "Requires database") + missing_ages = 1 + continue + if(C.player_age < age) + msg += {" + [key_name(C, 1)] [ADMIN_PP(C.mob)]:
                    + Days on server: [C.player_age]
                    + In-game minutes: [C.player_ingame_age] +
                    + "} + + if(missing_ages) + to_chat(src, "Some accounts did not have proper ages set in their clients. This function requires database to be present") + + if(msg != "") + src << browse(msg, "window=Player_age_check") + else + to_chat(src, "No matches for that age range found.") + + +/client/proc/cmd_admin_world_narrate() // Allows administrators to fluff events a little easier -- TLE + set category = "Special Verbs" + set name = "Global Narrate" + + if (!holder) + to_chat(src, "Only administrators may use this command.") + return + + var/msg = sanitize(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("\blue \bold GlobalNarrate: [key_name_admin(usr)] : [msg]
                    ") + 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(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 get_mob_with_client_list() + + if(!M) + return + + var/msg = sanitize(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("\blue \bold DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]
                    ") + 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_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 + to_chat(usr, "\blue 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"]") + 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) + to_chat(usr, "Error: cmd_admin_mute: This mob doesn't have a client tied to it.") + if(M.client.holder && (M.client.holder.rights & R_ADMIN) && !check_rights(R_PERMISSIONS)) + return + if(M.client.holder && (M.client.holder.rights & R_PERMISSIONS)) + to_chat(usr, "Error: cmd_admin_mute: You cannot mute an admin with permissions rights.") + return + if(!M.client) + 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_MENTORHELP) + mute_string = "mentorhelp and mentor PM" + 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].") + 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 + if(M.client.prefs.permamuted & mute_type) + M.client.prefs.permamuted &= ~mute_type + M.client.prefs.save_preferences() + else + muteunmute = "muted" + M.client.prefs.muted |= mute_type + if(alert("Would you like to make it permament?","Permamute?","Yes","No, round only") == "Yes") + muteunmute = "permamuted" + M.client.prefs.permamuted |= mute_type + M.client.prefs.save_preferences() + + + 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].") + 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) + 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.") + + 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") + world << sound('sound/AI/ionstorm.ogg') + + IonStorm(0) + 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 player_list) + if(M.stat != DEAD) continue //we are not dead! + if(!(ROLE_ALIEN in M.client.prefs.be_role)) continue //we don't want to be an alium + if(M.client.is_afk()) continue //we are afk + if(M.mind && M.mind.current && M.mind.current.stat != DEAD) continue //we have a live body we are tied to + 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("\blue [key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].") + 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(notify = 0,what = 2) + // what = 1, return ghosts ass list. + // what = 2, return mob list + + var/list/mobs = list() + var/list/ghosts = list() + var/list/sortmob = sortAtom(observer_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 + + 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("\blue 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") + + +/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, "\red The Administrator has disabled AntagHUD ") + config.antag_hud_allowed = 0 + to_chat(src, "\red 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, "\blue The Administrator has enabled AntagHUD ")// Notify all observers they can now use AntagHUD + config.antag_hud_allowed = 1 + action = "enabled" + to_chat(src, "\blue 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") + + + +/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()) + to_chat(g, "\blue The administrator has lifted restrictions on joining the round if you use AntagHUD") + action = "lifted restrictions" + config.antag_hud_restricted = 0 + to_chat(src, "\blue AntagHUD restrictions have been lifted") + else + for(var/mob/dead/observer/g in get_ghosts()) + to_chat(g, "\red The administrator has placed restrictions on joining the round if you use AntagHUD") + to_chat(g, "\red 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 + to_chat(src, "\red 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") + + + + +/* +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 = input(src, "Please specify which key will be respawned.", "Key", "") as null|anything in clients + 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 + to_chat(new_xeno, "You have been fully respawned. Enjoy the game.") + message_admins("\blue [key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.") + 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("\blue [key_name_admin(usr)] has respawned [new_monkey.key] as a filthy xeno.") + 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]") + for(var/datum/data/record/t in data_core.locked) + if(t.fields["id"]==id) + record_found = t//We shall now reference the record. + break + + if(record_found)//If they have a record we can determine a few things. + new_character.real_name = record_found.fields["name"] + new_character.gender = record_found.fields["sex"] + new_character.age = record_found.fields["age"] + new_character.b_type = record_found.fields["b_type"] + else + new_character.gender = 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) + if(new_character.gender == MALE) + new_character.real_name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) + else + new_character.real_name = capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names)) + 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 = "Test Subject"//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") + SSjob.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("Ninja") + new_character.equip_space_ninja() + new_character.internal = new_character.s_store + new_character.internals.icon_state = "internal1" + if(ninjastart.len == 0) + to_chat(new_character, "\red A proper starting location for you could not be found, please report this bug!") + to_chat(new_character, "\red Attempting to place at a carpspawn.") + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == "carpspawn") + ninjastart.Add(L) + if(ninjastart.len == 0 && latejoin.len > 0) + to_chat(new_character, "\red Still no spawneable locations could be found. Defaulting to latejoin.") + new_character.loc = pick(latejoin) + else if (ninjastart.len == 0) + to_chat(new_character, "\red Still no spawneable locations could be found. Aborting.") + + 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("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) + if("AI") + new_character = new_character.AIize() + if(new_character.mind.special_role=="traitor") + call(/datum/game_mode/proc/add_law_zero)(new_character) + //Add aliens. + else + SSjob.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") + call(/mob/dead/new_player/proc/AnnounceArrival)(new_character, new_character.mind.assigned_role) + + message_admins("\blue [admin] has respawned [player_key] as [new_character.real_name].") + + 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) + to_chat(src, "Only administrators may use this command.") + return + var/input = sanitize(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 ai_list) + if (M.stat == DEAD) + to_chat(usr, "Upload failed. No signal is being detected from the AI.") + 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 ai_list) + to_chat(O, "\red " + input + "\red...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]") + + 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") + 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) + to_chat(src, "Only administrators may use this command.") + return + if(!check_rights(R_REJUVINATE)) return + if(!mob) + return + if(!istype(M)) + alert("Cannot revive a ghost") + return + if(config.allow_admin_rev) + M.revive() + + log_admin("[key_name(usr)] healed / revived [key_name(M)]") + message_admins("\red Admin [key_name_admin(usr)] healed / revived [key_name_admin(M)]!") + 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 = sanitize(input(usr, "Please enter anything you want. Anything. Serious.", "What?", "") as message|null, MAX_PAPER_MESSAGE_LEN, extra = FALSE) + var/customname = sanitize_safe(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 communications_list) + 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 = replacetext(input, "\n", "
                    ") + 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, "\red New NanoTrasen Update available at all communication consoles.") + + 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") + 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 view()) + 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])") + feedback_add_details("admin_verb","DEL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + 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(SSjob) + for(var/datum/job/job in SSjob.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])") + 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])") + 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)]") + + 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("\blue [key_name_admin(usr)] used gibself.") + 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) + to_chat(M, "\redYou have been banned by [usr.client.ckey].\nReason: [reason].") + to_chat(M, "\red This is a temporary ban, it will be removed in [mins] minutes.") + to_chat(M, "\red 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("\blue[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) + qdel(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, "\redYou have been banned by [usr.client.ckey].\nReason: [reason].") + to_chat(M, "\red This is a permanent ban.") + to_chat(M, "\red 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("\blue[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) + qdel(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/M as mob in mob_list) + set category = "Special Verbs" + set name = "Check Contents" + + var/list/L = M.get_contents() + for(var/t in L) + to_chat(usr, "[t]") + 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_phoron() + 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("\blue [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 || SSshuttle.location) + return + + if(!check_rights(R_ADMIN)) + return + + if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") + return + + if(SSshuttle.always_fake_recall) + var/choice = input("The shuttle will just return if you call it. What you want to do?") in list( + "Cancel shuttle call", + "Call it anyway", + "Call and allow it to fly to station") + switch(choice) + if("Cancel shuttle call") + return + if("Call and allow it to fly to station") + SSshuttle.always_fake_recall = FALSE + SSshuttle.fake_recall = 0 + log_admin("[key_name(usr)] disabled shuttle fake recall.") + message_admins("[key_name_admin(usr)] disabled shuttle fake recall.") + + var/type = alert(src, "It's emergency shuttle or crew transfer?", "Confirm", "Emergency", "Crew transfer") + + if(type == "Crew transfer") + SSshuttle.shuttlealert(1) + SSshuttle.incall() + captain_announce("A crew transfer has been initiated. The shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + else + var/eaccess = alert(src, "Grant acces to maints for everyone?", "Confirm", "Yes", "No") + SSshuttle.incall() + captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + world << sound('sound/AI/shuttlecalled.ogg') + + if(eaccess == "Yes") + make_maint_all_access(FALSE) + + 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("\blue [key_name_admin(usr)] admin-called the emergency shuttle.") + 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 || SSshuttle.location || SSshuttle.direction == 0) + return + + SSshuttle.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("\blue [key_name_admin(usr)] admin-recalled the emergency shuttle.") + + if(timer_maint_revoke_id) + deltimer(timer_maint_revoke_id) + timer_maint_revoke_id = 0 + timer_maint_revoke_id = addtimer(CALLBACK(GLOBAL_PROC, .proc/revoke_maint_all_access, FALSE), 600, TIMER_UNIQUE|TIMER_STOPPABLE) + + return + +/client/proc/admin_deny_shuttle() + set category = "Admin" + set name = "Toggle Deny Shuttle" + + if (!ticker) + return + + if(!check_rights(R_ADMIN)) + return + + SSshuttle.deny_shuttle = !SSshuttle.deny_shuttle + + log_admin("[key_name(src)] has [SSshuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.") + message_admins("[key_name_admin(usr)] has [SSshuttle.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("\red Attack Log for []", mob)) + 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) + 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.") + 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.") + + if(notifyplayers == "Yes") + to_chat(world, "\blue 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 + to_chat(usr, "Random events enabled") + message_admins("Admin [key_name_admin(usr)] has enabled random events.") + else + config.allow_random_events = 0 + to_chat(usr, "Random events disabled") + message_admins("Admin [key_name_admin(usr)] has disabled random events.") + feedback_add_details("admin_verb","TRE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + +/client/proc/send_fax_message() + set name = "Send Fax Message" + set category = "Special Verbs" + + if(!check_rights(R_ADMIN)) + return + + var/sent_text = sanitize(input(usr, "Please, enter the text you want to send.", "What?", "") as message|null, MAX_PAPER_MESSAGE_LEN) + if(!sent_text) + return + + var/sent_name = sanitize_safe(input(usr, "Pick a title for the message.", "Title") as text) + if(!sent_name) + sent_name = "NanoTrasen Update" + if(sent_name == "Cancel") + return + + var/list/departments = alldepartments.Copy() + departments += "All" + var/department = input(usr, "Please, choose the destination department.") as null|anything in departments + if(!department) + return + + var/list/stamp_list = list("CentComm", "Syndicate", "Clown", "FakeCentComm", "None") + var/stamp_name = input(usr, "Please, choose the stamp you want to send with.") as null|anything in stamp_list + if(!stamp_name) + return + + var/stamp_type = null + if(stamp_name != "None") + stamp_type = text2path("/obj/item/weapon/stamp/[lowertext(stamp_name)]") + + var/stamp_text = null + if(stamp_type) + stamp_text = sanitize(input(usr, "Pick a message for stamp text (e.g. This paper has been stamped by the Central Compound Quantum Relay). In case of empty field there will be default stamp text.") as text) + + var/obj/item/weapon/paper/P = new + P.name = sent_name + P.info = sent_text + + if(stamp_type) + var/obj/item/weapon/stamp/S = new stamp_type + + if(stamp_text) + S.stamp_paper(P, stamp_text) + else + S.stamp_paper(P, use_stamp_by_message = TRUE) + + send_fax(usr, P, department) + + feedback_add_details("admin_verb","FAXMESS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + message_admins("Fax message was created by [key_name_admin(usr)] and sent to [department]") + send2slack_custommsg("Fax message was created by [key_name_admin(usr)] and sent to [department]: [sent_text]") diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm index 6444f4eab9c7..53487f58ee6a 100644 --- a/code/modules/admin/verbs/striketeam.dm +++ b/code/modules/admin/verbs/striketeam.dm @@ -1,175 +1,175 @@ -//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) - to_chat(usr, "There are [(6000-world.time)/10] seconds remaining before it may be called.") - 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 = sanitize(input(src, "Please specify which mission the death commando squad shall undertake.", "Specify Mission", "")) - 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 (SSshuttle.direction == 1 && SSshuttle.online == 1) - SSshuttle.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 poi_list) - 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. - create_random_account_and_store_in_mind(new_commando) - if(nuke_code) - new_commando.mind.store_memory("Nuke Code: \red [nuke_code].") - new_commando.mind.store_memory("Mission: \red [input].") - - to_chat(new_commando, "\blue 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: \red[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) - qdel(L) - - message_admins("\blue [key_name_admin(usr)] has spawned a CentCom strike squad.") - 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) - 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_l_ear) - 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/swat(src), slot_shoes) - equip_to_slot_or_del(new /obj/item/clothing/suit/armor/swat(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/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_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/storage/box/flashbangs(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/device/flashlight(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/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/flashbang(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/revolver/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/mindshield/loyalty/L = new(src) - L.inject(src) - START_PROCESSING(SSobj, L) - - - - var/obj/item/weapon/card/id/W = new(src) - W.name = "[real_name]'s ID Card" - W.icon_state = "centcom" - W.access = get_all_accesses()//They get full station access. - W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)//Let's add their alloted CentCom access. - W.assignment = "Death Commando" - W.registered_name = real_name - equip_to_slot_or_del(W, slot_wear_id) - - return 1 +//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) + to_chat(usr, "There are [(6000-world.time)/10] seconds remaining before it may be called.") + 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 = sanitize(input(src, "Please specify which mission the death commando squad shall undertake.", "Specify Mission", "")) + 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 (SSshuttle.direction == 1 && SSshuttle.online == 1) + SSshuttle.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 poi_list) + 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. + create_random_account_and_store_in_mind(new_commando) + if(nuke_code) + new_commando.mind.store_memory("Nuke Code: \red [nuke_code].") + new_commando.mind.store_memory("Mission: \red [input].") + + to_chat(new_commando, "\blue 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: \red[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) + qdel(L) + + message_admins("\blue [key_name_admin(usr)] has spawned a CentCom strike squad.") + 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) + 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_l_ear) + 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/swat(src), slot_shoes) + equip_to_slot_or_del(new /obj/item/clothing/suit/armor/swat(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/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_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/storage/box/flashbangs(src), slot_in_backpack) + equip_to_slot_or_del(new /obj/item/device/flashlight(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/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/flashbang(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/revolver/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/mindshield/loyalty/L = new(src) + L.inject(src) + START_PROCESSING(SSobj, L) + + + + var/obj/item/weapon/card/id/W = new(src) + W.name = "[real_name]'s ID Card" + W.icon_state = "centcom" + W.access = get_all_accesses()//They get full station access. + W.access += list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)//Let's add their alloted CentCom access. + W.assignment = "Death Commando" + W.registered_name = real_name + equip_to_slot_or_del(W, slot_wear_id) + + return 1 diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm index f590a9939d38..b238f2266d21 100644 --- a/code/modules/admin/verbs/striketeam_syndicate.dm +++ b/code/modules/admin/verbs/striketeam_syndicate.dm @@ -1,178 +1,178 @@ -//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 = sanitize(input(src, "Please specify which mission the syndicate strike team shall undertake.", "Specify Mission", "")) - 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 (SSshuttle.direction == 1 && SSshuttle.online == 1) - SSshuttle.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 poi_list) - 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: \red [nuke_code].") - new_syndicate_commando.mind.store_memory("Mission: \red [input].") - - to_chat(new_syndicate_commando, "\blue You are an Elite Syndicate. [!syndicate_leader_selected?"commando":"LEADER"] in the service of the Syndicate. \nYour current mission is: \red[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) - qdel(L) - - message_admins("\blue [key_name_admin(usr)] has spawned a Syndicate strike squad.") - 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.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.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) - qdel(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_l_ear) - 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/elite(src), slot_wear_suit) - else - equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/elite/commander(src), slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(src), slot_gloves) - if (!syndicate_leader_selected) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/elite(src), slot_head) - else - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/elite/commander(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_box/magazine/sm45(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/automatic/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 +//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 = sanitize(input(src, "Please specify which mission the syndicate strike team shall undertake.", "Specify Mission", "")) + 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 (SSshuttle.direction == 1 && SSshuttle.online == 1) + SSshuttle.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 poi_list) + 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: \red [nuke_code].") + new_syndicate_commando.mind.store_memory("Mission: \red [input].") + + to_chat(new_syndicate_commando, "\blue You are an Elite Syndicate. [!syndicate_leader_selected?"commando":"LEADER"] in the service of the Syndicate. \nYour current mission is: \red[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) + qdel(L) + + message_admins("\blue [key_name_admin(usr)] has spawned a Syndicate strike squad.") + 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.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.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) + qdel(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_l_ear) + 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/elite(src), slot_wear_suit) + else + equip_to_slot_or_del(new /obj/item/clothing/suit/space/syndicate/elite/commander(src), slot_wear_suit) + equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(src), slot_gloves) + if (!syndicate_leader_selected) + equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/elite(src), slot_head) + else + equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/syndicate/elite/commander(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_box/magazine/sm45(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/automatic/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 diff --git a/code/modules/admin/verbs/tripAI.dm b/code/modules/admin/verbs/tripAI.dm index f2f777ce8c73..f832eff1ec2d 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) - to_chat(usr, "This option is currently only usable during pregame. This may change at a later date.") - return - - if(SSjob && ticker) - var/datum/job/job = SSjob.GetJob("AI") - if(!job) - to_chat(usr, "Unable to locate the AI job") - return - if(ticker.triai) - ticker.triai = 0 - to_chat(usr, "Only one AI will be spawned at round start.") - message_admins("\blue [key_name_admin(usr)] has toggled off triple AIs at round start.") - else - ticker.triai = 1 - to_chat(usr, "There will be an AI Triumvirate at round start.") - message_admins("\blue [key_name_admin(usr)] has toggled on triple AIs at round start.") - return +/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(SSjob && ticker) + var/datum/job/job = SSjob.GetJob("AI") + if(!job) + to_chat(usr, "Unable to locate the AI job") + return + if(ticker.triai) + ticker.triai = 0 + to_chat(usr, "Only one AI will be spawned at round start.") + message_admins("\blue [key_name_admin(usr)] has toggled off triple AIs at round start.") + else + ticker.triai = 1 + to_chat(usr, "There will be an AI Triumvirate at round start.") + message_admins("\blue [key_name_admin(usr)] has toggled on triple AIs at round start.") + return diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index cc08255149d0..46250119b3e1 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -1,146 +1,146 @@ -/obj/item/device/assembly - name = "assembly" - desc = "A small electronic device that should never exist." - icon = 'icons/obj/assemblies/new_assemblies.dmi' - icon_state = "" - flags = CONDUCT - w_class = 2.0 - m_amt = 100 - g_amt = 0 - w_amt = 0 - throwforce = 2 - throw_speed = 3 - throw_range = 10 - origin_tech = "magnets=1" - - 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 - -/obj/item/device/assembly/proc/activate() //What the device does when turned on - return - -/obj/item/device/assembly/proc/pulsed(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(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(obj/A, 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) //Called when attack_self is called - return - -/obj/item/device/assembly/hear_talk(mob/living/M, msg) //Called when someone speak - return - -/obj/item/device/assembly/proc/is_secured(mob/user) - if(!secured) - to_chat(user, "The [name] is unsecured!") - return 0 - return 1 - -/obj/item/device/assembly/process_cooldown() - cooldown-- - if(cooldown <= 0) return 0 - spawn(10) - process_cooldown() - return 1 - - -/obj/item/device/assembly/pulsed(radio = 0) - if(holder && (wires & WIRE_RECEIVE)) - activate() - if(radio && (wires & WIRE_RADIO_RECEIVE)) - activate() - return 1 - - -/obj/item/device/assembly/pulse(radio = 0) - if(holder && (wires & WIRE_PULSE)) - holder.process_activation(src, 1, 0) - if(holder && (wires & WIRE_PULSE_SPECIAL)) - holder.process_activation(src, 0, 1) -// 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(obj/item/device/assembly/A, mob/user) - holder = new/obj/item/device/assembly_holder(get_turf(src)) - if(holder.attach(A,src,user)) - to_chat(user, "\blue You attach \the [A] to \the [src]!") - return 1 - return 0 - - -/obj/item/device/assembly/attackby(obj/item/weapon/W, mob/user) - 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, "\blue \The [src] is ready!") - else - to_chat(user, "\blue \The [src] can now be attached!") - return - ..() - return - - -/obj/item/device/assembly/process() - STOP_PROCESSING(SSobj, src) - return - - -/obj/item/device/assembly/examine(mob/user) - ..() - if(src in view(1, user)) - 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) - if(!user) return 0 - user.set_machine(src) - interact(user) - return 1 - - -/obj/item/device/assembly/interact(mob/user) - return //HTML MENU FOR WIRES GOES HERE +/obj/item/device/assembly + name = "assembly" + desc = "A small electronic device that should never exist." + icon = 'icons/obj/assemblies/new_assemblies.dmi' + icon_state = "" + flags = CONDUCT + w_class = 2.0 + m_amt = 100 + g_amt = 0 + w_amt = 0 + throwforce = 2 + throw_speed = 3 + throw_range = 10 + origin_tech = "magnets=1" + + 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 + +/obj/item/device/assembly/proc/activate() //What the device does when turned on + return + +/obj/item/device/assembly/proc/pulsed(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(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(obj/A, 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) //Called when attack_self is called + return + +/obj/item/device/assembly/hear_talk(mob/living/M, msg) //Called when someone speak + return + +/obj/item/device/assembly/proc/is_secured(mob/user) + if(!secured) + to_chat(user, "The [name] is unsecured!") + return 0 + return 1 + +/obj/item/device/assembly/process_cooldown() + cooldown-- + if(cooldown <= 0) return 0 + spawn(10) + process_cooldown() + return 1 + + +/obj/item/device/assembly/pulsed(radio = 0) + if(holder && (wires & WIRE_RECEIVE)) + activate() + if(radio && (wires & WIRE_RADIO_RECEIVE)) + activate() + return 1 + + +/obj/item/device/assembly/pulse(radio = 0) + if(holder && (wires & WIRE_PULSE)) + holder.process_activation(src, 1, 0) + if(holder && (wires & WIRE_PULSE_SPECIAL)) + holder.process_activation(src, 0, 1) +// 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(obj/item/device/assembly/A, mob/user) + holder = new/obj/item/device/assembly_holder(get_turf(src)) + if(holder.attach(A,src,user)) + to_chat(user, "\blue You attach \the [A] to \the [src]!") + return 1 + return 0 + + +/obj/item/device/assembly/attackby(obj/item/weapon/W, mob/user) + 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, "\blue \The [src] is ready!") + else + to_chat(user, "\blue \The [src] can now be attached!") + return + ..() + return + + +/obj/item/device/assembly/process() + STOP_PROCESSING(SSobj, src) + return + + +/obj/item/device/assembly/examine(mob/user) + ..() + if(src in view(1, user)) + 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) + if(!user) return 0 + user.set_machine(src) + interact(user) + return 1 + + +/obj/item/device/assembly/interact(mob/user) + return //HTML MENU FOR WIRES GOES HERE diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index 5f2a56db6d92..f5865fc9f809 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -1,159 +1,159 @@ -/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 = CONDUCT //Copied this from old code, so this may or may not be necessary - 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 phoron tank - -/obj/item/device/onetankbomb/examine(mob/user) - ..() - user.examinate(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, mob/user) - 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 - - qdel(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] (JMP)") - 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]" - to_chat(user, "The hole has been closed.") - add_fingerprint(user) - ..() - -/obj/item/device/onetankbomb/attack_self(mob/user) //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("[bicon(src)] *beep* *beep*", "*beep* *beep*") - sleep(10) - if(!src) - return - if(status) - bombtank.ignite() //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) - if(bombassembly) - bombassembly.HasProximity(AM) - -/obj/item/device/onetankbomb/hear_talk(mob/living/M, msg) - if(bombassembly) - bombassembly.hear_talk(M, msg) - -// ---------- 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 - - var/obj/item/device/onetankbomb/R = new /obj/item/device/onetankbomb(loc) - - M.drop_item() //Remove the assembly from your hands - 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/ignite() //This happens when a bomb is told to explode - var/fuel_moles = air_contents.gas["phoron"] + air_contents.gas["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) - - 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) - - 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) - - else - ground_zero.assume_air(air_contents) - ground_zero.hotspot_expose(1000, 125) - - if(master) - qdel(master) - qdel(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) +/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 = CONDUCT //Copied this from old code, so this may or may not be necessary + 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 phoron tank + +/obj/item/device/onetankbomb/examine(mob/user) + ..() + user.examinate(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, mob/user) + 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 + + qdel(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] (JMP)") + 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]" + to_chat(user, "The hole has been closed.") + add_fingerprint(user) + ..() + +/obj/item/device/onetankbomb/attack_self(mob/user) //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("[bicon(src)] *beep* *beep*", "*beep* *beep*") + sleep(10) + if(!src) + return + if(status) + bombtank.ignite() //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) + if(bombassembly) + bombassembly.HasProximity(AM) + +/obj/item/device/onetankbomb/hear_talk(mob/living/M, msg) + if(bombassembly) + bombassembly.hear_talk(M, msg) + +// ---------- 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 + + var/obj/item/device/onetankbomb/R = new /obj/item/device/onetankbomb(loc) + + M.drop_item() //Remove the assembly from your hands + 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/ignite() //This happens when a bomb is told to explode + var/fuel_moles = air_contents.gas["phoron"] + air_contents.gas["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) + + 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) + + 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) + + else + ground_zero.assume_air(air_contents) + ground_zero.hotspot_expose(1000, 125) + + if(master) + qdel(master) + qdel(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) diff --git a/code/modules/assembly/helpers.dm b/code/modules/assembly/helpers.dm index feb125ded783..7763e988bee5 100644 --- a/code/modules/assembly/helpers.dm +++ b/code/modules/assembly/helpers.dm @@ -1,14 +1,14 @@ -/* -Name: IsSpecialAssembly -Desc: If true is an object that can be attached to an assembly holder but is a special thing like a phoron 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 +/* +Name: IsSpecialAssembly +Desc: If true is an object that can be attached to an assembly holder but is a special thing like a phoron 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 diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index 43438f2aa312..646d06072483 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -1,254 +1,254 @@ -/obj/item/device/assembly_holder - name = "Assembly" - icon = 'icons/obj/assemblies/new_assemblies.dmi' - icon_state = "holder" - item_state = "assembly" - flags = CONDUCT - 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(obj/item/device/D, obj/item/device/D2, mob/user) - return - -/obj/item/device/assembly_holder/proc/attach_special(obj/O, mob/user) - return - -/obj/item/device/assembly_holder/proc/process_activation(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/attach(obj/item/device/D, obj/item/device/D2, 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 - 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(obj/O, mob/user) - if(!O) return - if(!O.IsSpecialAssembly()) return 0 - - return - - -/obj/item/device/assembly_holder/update_icon() - overlays.Cut() - 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() - -/obj/item/device/assembly_holder/examine(mob/user) - ..() - if (src in view(1, user)) - if (src.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) - 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) - 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() - return - -/obj/item/device/assembly_holder/hear_talk(mob/living/M, msg, verb, datum/language/speaking) - if(a_left) - a_left.hear_talk(M,msg,verb,speaking) - if(a_right) - a_right.hear_talk(M,msg,verb,speaking) - - 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() - ..() - return - - -/obj/item/device/assembly_holder/attackby(obj/item/weapon/W, mob/user) - if(isscrewdriver(W)) - if(!a_left || !a_right) - to_chat(user, "\red BUG:Assembly part missing, please report this!") - return - a_left.toggle_secure() - a_right.toggle_secure() - secured = !secured - if(secured) - to_chat(user, "\blue \The [src] is ready!") - else - to_chat(user, "\blue \The [src] can now be taken apart!") - update_icon() - return - else if(W.IsSpecialAssembly()) - attach_special(W, user) - else - ..() - return - - -/obj/item/device/assembly_holder/attack_self(mob/user) - src.add_fingerprint(user) - if(src.secured) - if(!a_left || !a_right) - to_chat(user, "\red 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 - if(a_right) - a_right:holder = null - a_right.loc = T - qdel(src) - return - - -/obj/item/device/assembly_holder/process_activation(obj/D, normal = 1, special = 1) - if(!D) return 0 - if(!secured) - visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*") - if((normal) && (a_right) && (a_left)) - if(a_right != D) - a_right.pulsed(0) - if(a_left != D) - a_left.pulsed(0) - if(master) - master.receive_signal() - return 1 - -//********-Timer -/obj/item/device/assembly_holder/timer_igniter - name = "timer-igniter assembly" - -/obj/item/device/assembly_holder/timer_igniter/atom_init() - . = ..() - - 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 - START_PROCESSING(SSobj, 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.stat || 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 = CONDUCT + 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(obj/item/device/D, obj/item/device/D2, mob/user) + return + +/obj/item/device/assembly_holder/proc/attach_special(obj/O, mob/user) + return + +/obj/item/device/assembly_holder/proc/process_activation(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/attach(obj/item/device/D, obj/item/device/D2, 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 + 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(obj/O, mob/user) + if(!O) return + if(!O.IsSpecialAssembly()) return 0 + + return + + +/obj/item/device/assembly_holder/update_icon() + overlays.Cut() + 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() + +/obj/item/device/assembly_holder/examine(mob/user) + ..() + if (src in view(1, user)) + if (src.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) + 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) + 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() + return + +/obj/item/device/assembly_holder/hear_talk(mob/living/M, msg, verb, datum/language/speaking) + if(a_left) + a_left.hear_talk(M,msg,verb,speaking) + if(a_right) + a_right.hear_talk(M,msg,verb,speaking) + + 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() + ..() + return + + +/obj/item/device/assembly_holder/attackby(obj/item/weapon/W, mob/user) + if(isscrewdriver(W)) + if(!a_left || !a_right) + to_chat(user, "\red BUG:Assembly part missing, please report this!") + return + a_left.toggle_secure() + a_right.toggle_secure() + secured = !secured + if(secured) + to_chat(user, "\blue \The [src] is ready!") + else + to_chat(user, "\blue \The [src] can now be taken apart!") + update_icon() + return + else if(W.IsSpecialAssembly()) + attach_special(W, user) + else + ..() + return + + +/obj/item/device/assembly_holder/attack_self(mob/user) + src.add_fingerprint(user) + if(src.secured) + if(!a_left || !a_right) + to_chat(user, "\red 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 + if(a_right) + a_right:holder = null + a_right.loc = T + qdel(src) + return + + +/obj/item/device/assembly_holder/process_activation(obj/D, normal = 1, special = 1) + if(!D) return 0 + if(!secured) + visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*") + if((normal) && (a_right) && (a_left)) + if(a_right != D) + a_right.pulsed(0) + if(a_left != D) + a_left.pulsed(0) + if(master) + master.receive_signal() + return 1 + +//********-Timer +/obj/item/device/assembly_holder/timer_igniter + name = "timer-igniter assembly" + +/obj/item/device/assembly_holder/timer_igniter/atom_init() + . = ..() + + 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 + START_PROCESSING(SSobj, 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.stat || 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 26cae4c071ae..d6142e733f2f 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" - m_amt = 500 - g_amt = 50 - w_amt = 10 - 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) - 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) - 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" + m_amt = 500 + g_amt = 50 + w_amt = 10 + 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) + 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) + activate() + add_fingerprint(user) + return diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index db744a889a8e..24f70bb298a1 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -1,244 +1,244 @@ -/obj/item/device/assembly/infra - name = "infrared emitter" - desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted." - icon_state = "infrared" - m_amt = 1000 - g_amt = 500 - w_amt = 100 - origin_tech = "magnets=2" - - wires = WIRE_PULSE - - secured = 0 - - var/on = 0 - var/visible = 0 - var/obj/effect/beam/i_beam/first = null - var/obj/effect/beam/i_beam/last = null - - -/obj/item/device/assembly/infra/Destroy() - if(first) - qdel(first) - return ..() - -/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) - START_PROCESSING(SSobj, src) - else - on = 0 - if(first) - qdel(first) - STOP_PROCESSING(SSobj, src) - update_icon() - return secured - -/obj/item/device/assembly/infra/update_icon() - overlays.Cut() - 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(!on) - if(first) - qdel(first) - return - if(!secured) - return - if(first && last) - last.process() - return - var/turf/T = get_turf(src) - if(T && holder && isturf(holder.loc)) - var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam(T) - I.master = src - I.density = 1 - I.dir = dir - first = I - step(I, I.dir) - if(first) - I.density = 0 - I.vis_spread(visible) - I.limit = 8 - I.process() - -/obj/item/device/assembly/infra/attack_hand() - qdel(first) - ..() - return - -/obj/item/device/assembly/infra/Move() - var/t = dir - ..() - dir = t - qdel(first) - return - -/obj/item/device/assembly/infra/holder_movement() - if(!holder) - return 0 -// dir = holder.dir - qdel(first) - return 1 - -/obj/item/device/assembly/infra/proc/trigger_beam() - if((!secured)||(!on)||(cooldown > 0)) - return 0 - pulse(0) - if(!holder) - visible_message("[bicon(src)] *beep* *beep*") - cooldown = 2 - spawn(10) - process_cooldown() - var/time_pulse = time2text(world.realtime,"hh:mm:ss") - var/turf/T = get_turf(src) - lastsignalers.Add("[time_pulse] : [src] activated @ location ([T.x],[T.y],[T.z])") - message_admins("[src] activated @ location ([T.x],[T.y],[T.z]) (JMP)") - log_game("[src] activated @ location ([T.x],[T.y],[T.z])") - return - -/obj/item/device/assembly/infra/interact(mob/user)//TODO: change this this to the wire control panel - if(is_secured(user)) - user.set_machine(src) - var/dat = "Infrared Laser\nStatus: [on ? "On" : "Off"]
                    \nVisibility: [visible ? "Visible" : "Invisible"]
                    \n
                    " - dat += "

                    Refresh" - dat += "

                    Close" - user << browse(entity_ja(dat), "window=infra") - onclose(user, "infra") - return - -/obj/item/device/assembly/infra/Topic(href, href_list) - ..() - if(usr.incapacitated() || !in_range(loc, usr)) - usr << browse(null, "window=infra") - onclose(usr, "infra") - return - - if(href_list["state"]) - on = !(on) - update_icon() - var/time_start = time2text(world.realtime,"hh:mm:ss") - var/turf/T = get_turf(src) - if(usr) - lastsignalers.Add("[time_start] : [usr.key] set [src] [on?"On":"Off"] @ location ([T.x],[T.y],[T.z])") - message_admins("[key_name_admin(usr)] set [src] [on?"On":"Off"], location ([T.x],[T.y],[T.z]) (JMP)") - log_game("[usr.ckey]([usr]) set [src] [on?"On":"Off"], location ([T.x],[T.y],[T.z])") - else - lastsignalers.Add("[time_start] : (NO USER FOUND) set [src] [on?"On":"Off"] @ location ([T.x],[T.y],[T.z])") - message_admins("( NO USER FOUND) set [src] [on?"On":"Off"], location ([T.x],[T.y],[T.z])") - log_game("(NO USER FOUND) set [src] [on?"On":"Off"], location ([T.x],[T.y],[T.z])") - - if(href_list["visible"]) - visible = !(visible) - if(first) - first.vis_spread(visible) - - if(href_list["close"]) - usr << browse(null, "window=infra") - return - if(usr) - attack_self(usr) - -/obj/item/device/assembly/infra/verb/rotate()//This could likely be better - set name = "Rotate Infrared Laser" - set category = "Object" - set src in usr - - if(usr.incapacitated()) - return - - dir = turn(dir, 90) - return - - - -/***************************IBeam*********************************/ - -/obj/effect/beam/i_beam - name = "infrared beam" - icon = 'icons/obj/projectiles.dmi' - icon_state = "ibeam" - var/obj/effect/beam/i_beam/next = null - var/obj/effect/beam/i_beam/previous = null - var/obj/item/device/assembly/infra/master = null - var/limit = null - var/visible = 0 - var/left = null - anchored = 1 - -/obj/effect/beam/i_beam/proc/hit() - if(master) - master.trigger_beam() - qdel(src) - return - -/obj/effect/beam/i_beam/proc/vis_spread(v) - visible = v - if(next) - next.vis_spread(v) - -/obj/effect/beam/i_beam/process() - if((loc.density || !(master))) - qdel(src) - return - if(left > 0) - left-- - if(left < 1) - if(!(visible)) - invisibility = 101 - else - invisibility = 0 - else - invisibility = 0 - - if(!next && (limit > 0)) - var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam(loc) - I.master = master - I.density = 1 - I.dir = dir - I.previous = src - next = I - step(I, I.dir) - if(next) - I.density = 0 - I.vis_spread(visible) - I.limit = limit - 1 - master.last = I - I.process() - -/obj/effect/beam/i_beam/Bump() - qdel(src) - return - -/obj/effect/beam/i_beam/Bumped() - hit() - -/obj/effect/beam/i_beam/Crossed(atom/movable/AM as mob|obj) - if(istype(AM, /obj/effect/beam)) - return - hit() - -/obj/effect/beam/i_beam/Destroy() - if(master.first == src) - master.first = null - if(next) - qdel(next) - next = null - if(previous) - previous.next = null - master.last = previous - return ..() +/obj/item/device/assembly/infra + name = "infrared emitter" + desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted." + icon_state = "infrared" + m_amt = 1000 + g_amt = 500 + w_amt = 100 + origin_tech = "magnets=2" + + wires = WIRE_PULSE + + secured = 0 + + var/on = 0 + var/visible = 0 + var/obj/effect/beam/i_beam/first = null + var/obj/effect/beam/i_beam/last = null + + +/obj/item/device/assembly/infra/Destroy() + if(first) + qdel(first) + return ..() + +/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) + START_PROCESSING(SSobj, src) + else + on = 0 + if(first) + qdel(first) + STOP_PROCESSING(SSobj, src) + update_icon() + return secured + +/obj/item/device/assembly/infra/update_icon() + overlays.Cut() + 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(!on) + if(first) + qdel(first) + return + if(!secured) + return + if(first && last) + last.process() + return + var/turf/T = get_turf(src) + if(T && holder && isturf(holder.loc)) + var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam(T) + I.master = src + I.density = 1 + I.dir = dir + first = I + step(I, I.dir) + if(first) + I.density = 0 + I.vis_spread(visible) + I.limit = 8 + I.process() + +/obj/item/device/assembly/infra/attack_hand() + qdel(first) + ..() + return + +/obj/item/device/assembly/infra/Move() + var/t = dir + ..() + dir = t + qdel(first) + return + +/obj/item/device/assembly/infra/holder_movement() + if(!holder) + return 0 +// dir = holder.dir + qdel(first) + return 1 + +/obj/item/device/assembly/infra/proc/trigger_beam() + if((!secured)||(!on)||(cooldown > 0)) + return 0 + pulse(0) + if(!holder) + visible_message("[bicon(src)] *beep* *beep*") + cooldown = 2 + spawn(10) + process_cooldown() + var/time_pulse = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + lastsignalers.Add("[time_pulse] : [src] activated @ location ([T.x],[T.y],[T.z])") + message_admins("[src] activated @ location ([T.x],[T.y],[T.z]) (JMP)") + log_game("[src] activated @ location ([T.x],[T.y],[T.z])") + return + +/obj/item/device/assembly/infra/interact(mob/user)//TODO: change this this to the wire control panel + if(is_secured(user)) + user.set_machine(src) + var/dat = "Infrared Laser\nStatus: [on ? "On" : "Off"]
                    \nVisibility: [visible ? "Visible" : "Invisible"]
                    \n
                    " + dat += "

                    Refresh" + dat += "

                    Close" + user << browse(entity_ja(dat), "window=infra") + onclose(user, "infra") + return + +/obj/item/device/assembly/infra/Topic(href, href_list) + ..() + if(usr.incapacitated() || !in_range(loc, usr)) + usr << browse(null, "window=infra") + onclose(usr, "infra") + return + + if(href_list["state"]) + on = !(on) + update_icon() + var/time_start = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + if(usr) + lastsignalers.Add("[time_start] : [usr.key] set [src] [on?"On":"Off"] @ location ([T.x],[T.y],[T.z])") + message_admins("[key_name_admin(usr)] set [src] [on?"On":"Off"], location ([T.x],[T.y],[T.z]) (JMP)") + log_game("[usr.ckey]([usr]) set [src] [on?"On":"Off"], location ([T.x],[T.y],[T.z])") + else + lastsignalers.Add("[time_start] : (NO USER FOUND) set [src] [on?"On":"Off"] @ location ([T.x],[T.y],[T.z])") + message_admins("( NO USER FOUND) set [src] [on?"On":"Off"], location ([T.x],[T.y],[T.z])") + log_game("(NO USER FOUND) set [src] [on?"On":"Off"], location ([T.x],[T.y],[T.z])") + + if(href_list["visible"]) + visible = !(visible) + if(first) + first.vis_spread(visible) + + if(href_list["close"]) + usr << browse(null, "window=infra") + return + if(usr) + attack_self(usr) + +/obj/item/device/assembly/infra/verb/rotate()//This could likely be better + set name = "Rotate Infrared Laser" + set category = "Object" + set src in usr + + if(usr.incapacitated()) + return + + dir = turn(dir, 90) + return + + + +/***************************IBeam*********************************/ + +/obj/effect/beam/i_beam + name = "infrared beam" + icon = 'icons/obj/projectiles.dmi' + icon_state = "ibeam" + var/obj/effect/beam/i_beam/next = null + var/obj/effect/beam/i_beam/previous = null + var/obj/item/device/assembly/infra/master = null + var/limit = null + var/visible = 0 + var/left = null + anchored = 1 + +/obj/effect/beam/i_beam/proc/hit() + if(master) + master.trigger_beam() + qdel(src) + return + +/obj/effect/beam/i_beam/proc/vis_spread(v) + visible = v + if(next) + next.vis_spread(v) + +/obj/effect/beam/i_beam/process() + if((loc.density || !(master))) + qdel(src) + return + if(left > 0) + left-- + if(left < 1) + if(!(visible)) + invisibility = 101 + else + invisibility = 0 + else + invisibility = 0 + + if(!next && (limit > 0)) + var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam(loc) + I.master = master + I.density = 1 + I.dir = dir + I.previous = src + next = I + step(I, I.dir) + if(next) + I.density = 0 + I.vis_spread(visible) + I.limit = limit - 1 + master.last = I + I.process() + +/obj/effect/beam/i_beam/Bump() + qdel(src) + return + +/obj/effect/beam/i_beam/Bumped() + hit() + +/obj/effect/beam/i_beam/Crossed(atom/movable/AM as mob|obj) + if(istype(AM, /obj/effect/beam)) + return + hit() + +/obj/effect/beam/i_beam/Destroy() + if(master.first == src) + master.first = null + if(next) + qdel(next) + next = null + if(previous) + previous.next = null + master.last = previous + return ..() diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index a147797062df..9e509264a181 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -1,114 +1,114 @@ -/obj/item/device/assembly/mousetrap - name = "mousetrap" - desc = "A handy little spring-loaded trap for catching pesty rodents." - icon_state = "mousetrap" - m_amt = 100 - w_amt = 10 - origin_tech = "combat=1" - var/armed = 0 - -/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, type = "feet") - if(!armed) - return - var/obj/item/organ/external/BP = null - if(ishuman(target)) - var/mob/living/carbon/human/H = target - switch(type) - if("feet") - if(!H.shoes) - BP = H.bodyparts_by_name[pick(BP_L_LEG , BP_R_LEG)] - H.Weaken(3) - if(BP_L_ARM, BP_R_ARM) - if(!H.gloves) - BP = H.bodyparts_by_name[type] - H.Stun(3) - if(BP) - BP.take_damage(1, 0) - H.updatehealth() - else if(ismouse(target)) - var/mob/living/simple_animal/mouse/M = target - visible_message("\red SPLAT!") - M.splat() - playsound(target.loc, 'sound/effects/snap.ogg', 50, 1) - layer = MOB_LAYER - 0.2 - armed = 0 - update_icon() - pulse(0) - -/obj/item/device/assembly/mousetrap/attack_self(mob/living/user) - if(!armed) - to_chat(user, "You arm [src].") - else - if(((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50))) - triggered(user, user.hand ? BP_L_ARM : BP_R_ARM) - 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) - if(armed) - if(((user.getBrainLoss() >= 60 || CLUMSY in user.mutations)) && prob(50)) - user.SetNextMove(CLICK_CD_INTERACT) - triggered(user, user.hand ? BP_L_ARM : BP_R_ARM) - 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) - if(armed) - finder.visible_message("[finder] accidentally sets off [src], breaking their fingers.", \ - "You accidentally trigger [src]!") - triggered(finder, finder.hand ? BP_L_ARM : BP_R_ARM) - return 1 //end the search! - return 0 - -/obj/item/device/assembly/mousetrap/hitby(A) - 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.stat) - 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" + m_amt = 100 + w_amt = 10 + origin_tech = "combat=1" + var/armed = 0 + +/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, type = "feet") + if(!armed) + return + var/obj/item/organ/external/BP = null + if(ishuman(target)) + var/mob/living/carbon/human/H = target + switch(type) + if("feet") + if(!H.shoes) + BP = H.bodyparts_by_name[pick(BP_L_LEG , BP_R_LEG)] + H.Weaken(3) + if(BP_L_ARM, BP_R_ARM) + if(!H.gloves) + BP = H.bodyparts_by_name[type] + H.Stun(3) + if(BP) + BP.take_damage(1, 0) + H.updatehealth() + else if(ismouse(target)) + var/mob/living/simple_animal/mouse/M = target + visible_message("\red SPLAT!") + M.splat() + playsound(target.loc, 'sound/effects/snap.ogg', 50, 1) + layer = MOB_LAYER - 0.2 + armed = 0 + update_icon() + pulse(0) + +/obj/item/device/assembly/mousetrap/attack_self(mob/living/user) + if(!armed) + to_chat(user, "You arm [src].") + else + if(((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50))) + triggered(user, user.hand ? BP_L_ARM : BP_R_ARM) + 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) + if(armed) + if(((user.getBrainLoss() >= 60 || CLUMSY in user.mutations)) && prob(50)) + user.SetNextMove(CLICK_CD_INTERACT) + triggered(user, user.hand ? BP_L_ARM : BP_R_ARM) + 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) + if(armed) + finder.visible_message("[finder] accidentally sets off [src], breaking their fingers.", \ + "You accidentally trigger [src]!") + triggered(finder, finder.hand ? BP_L_ARM : BP_R_ARM) + return 1 //end the search! + return 0 + +/obj/item/device/assembly/mousetrap/hitby(A) + 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.stat) + 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 cf9a72ec3f68..ee4758a8a12f 100644 --- a/code/modules/assembly/proximity.dm +++ b/code/modules/assembly/proximity.dm @@ -1,175 +1,175 @@ -/obj/item/device/assembly/prox_sensor - name = "proximity sensor" - desc = "Used for scanning and alerting when someone enters a certain proximity." - icon_state = "prox" - m_amt = 800 - g_amt = 200 - w_amt = 50 - origin_tech = "magnets=1" - - wires = WIRE_PULSE - - secured = 0 - - var/scanning = 0 - var/timing = 0 - var/time = 10 - - var/range = 2 - -/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) - START_PROCESSING(SSobj, src) - else - scanning = 0 - timing = 0 - STOP_PROCESSING(SSobj, src) - update_icon() - return secured - -/obj/item/device/assembly/prox_sensor/HasProximity(atom/movable/AM) - if (istype(AM, /obj/effect/beam)) return - if (AM.move_speed < 12) sense() - return - -/obj/item/device/assembly/prox_sensor/proc/sense() - var/turf/mainloc = get_turf(src) -// if(scanning && cooldown <= 0) -// mainloc.visible_message("[bicon(src)] *boop* *boop*", "*boop* *boop*") - if((!holder && !secured)||(!scanning)||(cooldown > 0)) return 0 - pulse(0) - if(!holder) - mainloc.visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*") - cooldown = 2 - spawn(10) - process_cooldown() - -// var/time_pulse = time2text(world.realtime,"hh:mm:ss") -// var/turf/T = get_turf(src) -// lastsignalers.Add("[time_pulse] : [src] activated @ location ([T.x],[T.y],[T.z])") -// message_admins("[src] activated @ location ([T.x],[T.y],[T.z])",0,1) -// log_game("[src] activated @ location ([T.x],[T.y],[T.z])") - 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 = 10 - 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.Cut() - 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)//TODO: Change this to the wires thingy - if(!secured) - user.show_message("\red 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) - dat += "
                    [scanning?"Armed":"Unarmed"] (Movement sensor active when armed!)" - dat += "

                    Refresh" - dat += "

                    Close" - user << browse(entity_ja(dat), "window=prox") - onclose(user, "prox") - return - -/obj/item/device/assembly/prox_sensor/Topic(href, href_list) - ..() - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=prox") - onclose(usr, "prox") - return - - if(href_list["scanning"]) - toggle_scan() - var/time_scan = time2text(world.realtime,"hh:mm:ss") - var/turf/T = get_turf(src) - if(usr) - lastsignalers.Add("[time_scan] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : time set: [time]") - message_admins("[key_name_admin(usr)] used [src] , location ([T.x],[T.y],[T.z]) : time set: [time] (JMP)") - log_game("[usr.ckey]([usr]) used [src], location ([T.x],[T.y],[T.z]),time set: [time]") - else - lastsignalers.Add("[time_scan] : (NO USER FOUND) set [src] @ location ([T.x],[T.y],[T.z]) : time set: [time]") - message_admins("( NO USER FOUND) used [src], location ([T.x],[T.y],[T.z]) : time set: [time]") - log_game("(NO USER FOUND) used [src] , location ([T.x],[T.y],[T.z]),time set: [time]") - - if(href_list["time"]) - timing = text2num(href_list["time"]) - update_icon() - var/time_start = time2text(world.realtime,"hh:mm:ss") - var/turf/T = get_turf(src) - if(usr) - lastsignalers.Add("[time_start] : [usr.key] set [src] [timing?"On":"Off"] @ location ([T.x],[T.y],[T.z]) : time set: [time]") - message_admins("[key_name_admin(usr)] set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]) : time set: [time] (JMP)") - log_game("[usr.ckey]([usr]) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]),time set: [time]") - else - lastsignalers.Add("[time_start] : (NO USER FOUND) set [src] [timing?"On":"Off"] @ location ([T.x],[T.y],[T.z]) : time set: [time]") - message_admins("( NO USER FOUND) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]) : time set: [time]") - log_game("(NO USER FOUND) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]),time set: [time]") - - 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 = min(max(range, 1), 5) - - if(href_list["close"]) - usr << browse(null, "window=prox") - return - - if(usr) - attack_self(usr) - - return +/obj/item/device/assembly/prox_sensor + name = "proximity sensor" + desc = "Used for scanning and alerting when someone enters a certain proximity." + icon_state = "prox" + m_amt = 800 + g_amt = 200 + w_amt = 50 + origin_tech = "magnets=1" + + wires = WIRE_PULSE + + secured = 0 + + var/scanning = 0 + var/timing = 0 + var/time = 10 + + var/range = 2 + +/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) + START_PROCESSING(SSobj, src) + else + scanning = 0 + timing = 0 + STOP_PROCESSING(SSobj, src) + update_icon() + return secured + +/obj/item/device/assembly/prox_sensor/HasProximity(atom/movable/AM) + if (istype(AM, /obj/effect/beam)) return + if (AM.move_speed < 12) sense() + return + +/obj/item/device/assembly/prox_sensor/proc/sense() + var/turf/mainloc = get_turf(src) +// if(scanning && cooldown <= 0) +// mainloc.visible_message("[bicon(src)] *boop* *boop*", "*boop* *boop*") + if((!holder && !secured)||(!scanning)||(cooldown > 0)) return 0 + pulse(0) + if(!holder) + mainloc.visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*") + cooldown = 2 + spawn(10) + process_cooldown() + +// var/time_pulse = time2text(world.realtime,"hh:mm:ss") +// var/turf/T = get_turf(src) +// lastsignalers.Add("[time_pulse] : [src] activated @ location ([T.x],[T.y],[T.z])") +// message_admins("[src] activated @ location ([T.x],[T.y],[T.z])",0,1) +// log_game("[src] activated @ location ([T.x],[T.y],[T.z])") + 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 = 10 + 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.Cut() + 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)//TODO: Change this to the wires thingy + if(!secured) + user.show_message("\red 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) + dat += "
                    [scanning?"Armed":"Unarmed"] (Movement sensor active when armed!)" + dat += "

                    Refresh" + dat += "

                    Close" + user << browse(entity_ja(dat), "window=prox") + onclose(user, "prox") + return + +/obj/item/device/assembly/prox_sensor/Topic(href, href_list) + ..() + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + usr << browse(null, "window=prox") + onclose(usr, "prox") + return + + if(href_list["scanning"]) + toggle_scan() + var/time_scan = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + if(usr) + lastsignalers.Add("[time_scan] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : time set: [time]") + message_admins("[key_name_admin(usr)] used [src] , location ([T.x],[T.y],[T.z]) : time set: [time] (JMP)") + log_game("[usr.ckey]([usr]) used [src], location ([T.x],[T.y],[T.z]),time set: [time]") + else + lastsignalers.Add("[time_scan] : (NO USER FOUND) set [src] @ location ([T.x],[T.y],[T.z]) : time set: [time]") + message_admins("( NO USER FOUND) used [src], location ([T.x],[T.y],[T.z]) : time set: [time]") + log_game("(NO USER FOUND) used [src] , location ([T.x],[T.y],[T.z]),time set: [time]") + + if(href_list["time"]) + timing = text2num(href_list["time"]) + update_icon() + var/time_start = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + if(usr) + lastsignalers.Add("[time_start] : [usr.key] set [src] [timing?"On":"Off"] @ location ([T.x],[T.y],[T.z]) : time set: [time]") + message_admins("[key_name_admin(usr)] set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]) : time set: [time] (JMP)") + log_game("[usr.ckey]([usr]) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]),time set: [time]") + else + lastsignalers.Add("[time_start] : (NO USER FOUND) set [src] [timing?"On":"Off"] @ location ([T.x],[T.y],[T.z]) : time set: [time]") + message_admins("( NO USER FOUND) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]) : time set: [time]") + log_game("(NO USER FOUND) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]),time set: [time]") + + 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 = min(max(range, 1), 5) + + 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 067008dba570..52fa986d6aaf 100644 --- a/code/modules/assembly/shock_kit.dm +++ b/code/modules/assembly/shock_kit.dm @@ -1,45 +1,45 @@ -/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 = CONDUCT - -/obj/item/assembly/shock_kit/Destroy() - qdel(part1) - qdel(part2) - return ..() - -/obj/item/assembly/shock_kit/attackby(obj/item/weapon/W, mob/user) - 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 - qdel(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) - 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/stool/bed/chair/e_chair)) - var/obj/structure/stool/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 = CONDUCT + +/obj/item/assembly/shock_kit/Destroy() + qdel(part1) + qdel(part2) + return ..() + +/obj/item/assembly/shock_kit/attackby(obj/item/weapon/W, mob/user) + 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 + qdel(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) + 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/stool/bed/chair/e_chair)) + var/obj/structure/stool/bed/chair/e_chair/C = loc + C.shock() + return diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index 2d5c1a82b7a4..693eba0b47f2 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -1,210 +1,210 @@ -/obj/item/device/assembly/signaler - name = "remote signaling device" - desc = "Used to remotely activate devices." - icon_state = "signaller" - item_state = "signaler" - m_amt = 1000 - g_amt = 200 - w_amt = 100 - 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/airlock_wire = null - var/datum/wires/connected = null - var/datum/radio_frequency/radio_connection - var/deadman = 0 - -/obj/item/device/assembly/signaler/atom_init() - . = ..() - addtimer(CALLBACK(src, .proc/set_frequency, frequency), 40) - -/obj/item/device/assembly/signaler/Destroy() - if(radio_controller) - radio_controller.remove_object(src,frequency) - frequency = 0 - connected = null - return ..() - -/obj/item/device/assembly/signaler/activate() - if(cooldown > 0) - return FALSE - cooldown = 2 - addtimer(CALLBACK(src, .proc/process_cooldown), 10) - signal() - return TRUE - -/obj/item/device/assembly/signaler/update_icon() - if(holder) - holder.update_icon() - return - -/obj/item/device/assembly/signaler/interact(mob/user, 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(entity_ja(dat), "window=radio") - onclose(user, "radio") - return - - -/obj/item/device/assembly/signaler/Topic(href, href_list) - ..() - - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=radio") - onclose(usr, "radio") - return - - if (href_list["freq"]) - var/new_frequency = (frequency + text2num(href_list["freq"])) - if(new_frequency < 1200 || new_frequency > 1600) - 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) - - return - - -/obj/item/device/assembly/signaler/proc/signal() - if(!radio_connection) return - - var/datum/signal/signal = new - 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) - lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") - message_admins("[key_name_admin(usr)] used [src], location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code] (JMP)") - log_game("[usr.ckey]([usr]) used [src], location ([T.x],[T.y],[T.z]),frequency: [format_frequency(frequency)], code:[code]") - else - lastsignalers.Add("[time] : (\red NO USER FOUND) used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") - message_admins("(\red NO USER FOUND) used [src], location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") - log_game("(NO USER FOUND) used [src], location ([T.x],[T.y],[T.z]),frequency: [format_frequency(frequency)], code:[code]") - - return - -/* - for(var/obj/item/device/assembly/signaler/S in not_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(radio = 0) - if(connected && wires) - connected.pulse_signaler(src) - else if(holder) - holder.process_activation(src, 1, 0) - else - ..(radio) - return 1 - - -/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("[bicon(src)] *beep* *beep*", 3, "*beep* *beep*", 2) - return - - -/obj/item/device/assembly/signaler/proc/set_frequency(new_frequency) - if(!frequency) - return - if(!radio_controller) - sleep(20) - if(!radio_controller) - return - 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(!deadman) - STOP_PROCESSING(SSobj, src) - var/mob/M = src.loc - if(!M || !ismob(M)) - if(prob(5)) - signal() - deadman = 0 - STOP_PROCESSING(SSobj, 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!" - deadman = 1 - START_PROCESSING(SSobj, src) - usr.visible_message("\red [usr] moves their finger over [src]'s signal button...") - -// Embedded signaller used in anomalies. -/obj/item/device/assembly/signaler/anomaly - name = "anomaly core" - desc = "The neutralized core of an anomaly. It'd probably be valuable for research." - icon_state = "anomaly core" - item_state = "electronic" - -/obj/item/device/assembly/signaler/anomaly/receive_signal(datum/signal/signal) - if(!signal) - return 0 - if(signal.encryption != code) - return 0 - for(var/obj/effect/anomaly/A in orange(0, src)) - A.anomalyNeutralize() - -/obj/item/device/assembly/signaler/anomaly/attack_self() - return +/obj/item/device/assembly/signaler + name = "remote signaling device" + desc = "Used to remotely activate devices." + icon_state = "signaller" + item_state = "signaler" + m_amt = 1000 + g_amt = 200 + w_amt = 100 + 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/airlock_wire = null + var/datum/wires/connected = null + var/datum/radio_frequency/radio_connection + var/deadman = 0 + +/obj/item/device/assembly/signaler/atom_init() + . = ..() + addtimer(CALLBACK(src, .proc/set_frequency, frequency), 40) + +/obj/item/device/assembly/signaler/Destroy() + if(radio_controller) + radio_controller.remove_object(src,frequency) + frequency = 0 + connected = null + return ..() + +/obj/item/device/assembly/signaler/activate() + if(cooldown > 0) + return FALSE + cooldown = 2 + addtimer(CALLBACK(src, .proc/process_cooldown), 10) + signal() + return TRUE + +/obj/item/device/assembly/signaler/update_icon() + if(holder) + holder.update_icon() + return + +/obj/item/device/assembly/signaler/interact(mob/user, 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(entity_ja(dat), "window=radio") + onclose(user, "radio") + return + + +/obj/item/device/assembly/signaler/Topic(href, href_list) + ..() + + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + usr << browse(null, "window=radio") + onclose(usr, "radio") + return + + if (href_list["freq"]) + var/new_frequency = (frequency + text2num(href_list["freq"])) + if(new_frequency < 1200 || new_frequency > 1600) + 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) + + return + + +/obj/item/device/assembly/signaler/proc/signal() + if(!radio_connection) return + + var/datum/signal/signal = new + 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) + lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + message_admins("[key_name_admin(usr)] used [src], location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code] (JMP)") + log_game("[usr.ckey]([usr]) used [src], location ([T.x],[T.y],[T.z]),frequency: [format_frequency(frequency)], code:[code]") + else + lastsignalers.Add("[time] : (\red NO USER FOUND) used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + message_admins("(\red NO USER FOUND) used [src], location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + log_game("(NO USER FOUND) used [src], location ([T.x],[T.y],[T.z]),frequency: [format_frequency(frequency)], code:[code]") + + return + +/* + for(var/obj/item/device/assembly/signaler/S in not_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(radio = 0) + if(connected && wires) + connected.pulse_signaler(src) + else if(holder) + holder.process_activation(src, 1, 0) + else + ..(radio) + return 1 + + +/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("[bicon(src)] *beep* *beep*", 3, "*beep* *beep*", 2) + return + + +/obj/item/device/assembly/signaler/proc/set_frequency(new_frequency) + if(!frequency) + return + if(!radio_controller) + sleep(20) + if(!radio_controller) + return + 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(!deadman) + STOP_PROCESSING(SSobj, src) + var/mob/M = src.loc + if(!M || !ismob(M)) + if(prob(5)) + signal() + deadman = 0 + STOP_PROCESSING(SSobj, 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!" + deadman = 1 + START_PROCESSING(SSobj, src) + usr.visible_message("\red [usr] moves their finger over [src]'s signal button...") + +// Embedded signaller used in anomalies. +/obj/item/device/assembly/signaler/anomaly + name = "anomaly core" + desc = "The neutralized core of an anomaly. It'd probably be valuable for research." + icon_state = "anomaly core" + item_state = "electronic" + +/obj/item/device/assembly/signaler/anomaly/receive_signal(datum/signal/signal) + if(!signal) + return 0 + if(signal.encryption != code) + return 0 + for(var/obj/effect/anomaly/A in orange(0, src)) + A.anomalyNeutralize() + +/obj/item/device/assembly/signaler/anomaly/attack_self() + return diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm index a4310ae6b812..ee0e39a6c1ce 100644 --- a/code/modules/assembly/timer.dm +++ b/code/modules/assembly/timer.dm @@ -1,124 +1,124 @@ -/obj/item/device/assembly/timer - name = "timer" - desc = "Used to time things. Works well with contraptions which has to count down. Tick tock." - icon_state = "timer" - m_amt = 500 - g_amt = 50 - w_amt = 10 - origin_tech = "magnets=1" - - wires = WIRE_PULSE - - secured = 0 - - var/timing = 0 - var/time = 10 - -/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) - START_PROCESSING(SSobj, src) - else - timing = 0 - STOP_PROCESSING(SSobj, src) - update_icon() - return secured - - -/obj/item/device/assembly/timer/proc/timer_end() - if(!secured) return 0 - pulse(0) - if(!holder) - visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*") - cooldown = 2 - spawn(10) - process_cooldown() - - - var/time_pulse = time2text(world.realtime,"hh:mm:ss") - var/turf/T = get_turf(src) - lastsignalers.Add("[time_pulse] : [src] activated @ location ([T.x],[T.y],[T.z])") - message_admins("[src] activated @ location ([T.x],[T.y],[T.z]) (JMP)") - log_game("[src] activated @ location ([T.x],[T.y],[T.z])") - return - - -/obj/item/device/assembly/timer/process() - if(timing && (time > 0)) - time-- - if(timing && time <= 0) - timing = 0 - timer_end() - time = 10 - return - - -/obj/item/device/assembly/timer/update_icon() - overlays.Cut() - 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)//TODO: Have this use the wires - if(!secured) - user.show_message("\red 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) - dat += "

                    Refresh" - dat += "

                    Close" - user << browse(entity_ja(dat), "window=timer") - onclose(user, "timer") - return - - -/obj/item/device/assembly/timer/Topic(href, href_list) - ..() - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=timer") - onclose(usr, "timer") - return - - if(href_list["time"]) - timing = text2num(href_list["time"]) - var/time_start = time2text(world.realtime,"hh:mm:ss") - var/turf/T = get_turf(src) - if(usr) - lastsignalers.Add("[time_start] : [usr.key] set [src] [timing?"On":"Off"] @ location ([T.x],[T.y],[T.z]) : time set: [time]") - message_admins("[key_name_admin(usr)] set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]) : time set: [time] (JMP)") - log_game("[usr.ckey]([usr]) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]),time set: [time]") - else - lastsignalers.Add("[time_start] : (NO USER FOUND) set [src] [timing?"On":"Off"] @ location ([T.x],[T.y],[T.z]) : time set: [time]") - message_admins("( NO USER FOUND) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]) : time set: [time]",0,1) - log_game("(NO USER FOUND) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]),time set: [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["close"]) - usr << browse(null, "window=timer") - return - - if(usr) - attack_self(usr) - - return +/obj/item/device/assembly/timer + name = "timer" + desc = "Used to time things. Works well with contraptions which has to count down. Tick tock." + icon_state = "timer" + m_amt = 500 + g_amt = 50 + w_amt = 10 + origin_tech = "magnets=1" + + wires = WIRE_PULSE + + secured = 0 + + var/timing = 0 + var/time = 10 + +/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) + START_PROCESSING(SSobj, src) + else + timing = 0 + STOP_PROCESSING(SSobj, src) + update_icon() + return secured + + +/obj/item/device/assembly/timer/proc/timer_end() + if(!secured) return 0 + pulse(0) + if(!holder) + visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*") + cooldown = 2 + spawn(10) + process_cooldown() + + + var/time_pulse = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + lastsignalers.Add("[time_pulse] : [src] activated @ location ([T.x],[T.y],[T.z])") + message_admins("[src] activated @ location ([T.x],[T.y],[T.z]) (JMP)") + log_game("[src] activated @ location ([T.x],[T.y],[T.z])") + return + + +/obj/item/device/assembly/timer/process() + if(timing && (time > 0)) + time-- + if(timing && time <= 0) + timing = 0 + timer_end() + time = 10 + return + + +/obj/item/device/assembly/timer/update_icon() + overlays.Cut() + 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)//TODO: Have this use the wires + if(!secured) + user.show_message("\red 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) + dat += "

                    Refresh" + dat += "

                    Close" + user << browse(entity_ja(dat), "window=timer") + onclose(user, "timer") + return + + +/obj/item/device/assembly/timer/Topic(href, href_list) + ..() + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + usr << browse(null, "window=timer") + onclose(usr, "timer") + return + + if(href_list["time"]) + timing = text2num(href_list["time"]) + var/time_start = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + if(usr) + lastsignalers.Add("[time_start] : [usr.key] set [src] [timing?"On":"Off"] @ location ([T.x],[T.y],[T.z]) : time set: [time]") + message_admins("[key_name_admin(usr)] set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]) : time set: [time] (JMP)") + log_game("[usr.ckey]([usr]) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]),time set: [time]") + else + lastsignalers.Add("[time_start] : (NO USER FOUND) set [src] [timing?"On":"Off"] @ location ([T.x],[T.y],[T.z]) : time set: [time]") + message_admins("( NO USER FOUND) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]) : time set: [time]",0,1) + log_game("(NO USER FOUND) set [src] [timing?"On":"Off"], location ([T.x],[T.y],[T.z]),time set: [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["close"]) + usr << browse(null, "window=timer") + return + + if(usr) + attack_self(usr) + + return diff --git a/code/modules/awaymissions/bluespaceartillery.dm b/code/modules/awaymissions/bluespaceartillery.dm index c6b960b2b0f9..c4bb1ca63b09 100644 --- a/code/modules/awaymissions/bluespaceartillery.dm +++ b/code/modules/awaymissions/bluespaceartillery.dm @@ -1,73 +1,73 @@ - -/obj/machinery/artillerycontrol - var/reload = 180 - var/intensity = 1 - name = "bluespace artillery control" - icon_state = "control_boxp1" - icon = 'icons/obj/machines/particle_accelerator2.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/ui_interact(mob/user) - var/dat = "Bluespace Artillery Control:
                    " - dat += "Locked on
                    " - dat += "Charge progress: [reload]/180:
                    " - dat += "The Bluespace Artillery in mode : [intensity ? "Destroy" : "Hurt"]
                    " - dat += "Open Fire
                    " - dat += "Deployment of weapon authorized by
                    Nanotrasen Naval Command

                    Remember, friendly fire is grounds for termination of your contract and life.
                    " - user << browse(entity_ja(dat), "window=scroll") - onclose(user, "scroll") - -/obj/machinery/artillerycontrol/Topic(href, href_list) - . = ..() - if(!.) - return - if( href_list["toggle"] ) - intensity = !intensity - if(href_list["fire"]) - if(src.reload < (intensity ? 180 : 90)) - return FALSE - var/A - A = input("Area to jump bombard", "Open Fire", A) in teleportlocs - var/area/thearea = teleportlocs[A] - var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - if(!istype(T,/turf/simulated/wall) && !istype(T, /turf/simulated/wall/r_wall) && !istype(T, /turf/space)) - L+=T - var/loc = pick(L) - if(loc) - if(intensity) - command_alert("Bluespace artillery fire detected in [thearea.name]. Brace for impact.") - message_admins("[key_name_admin(usr)] has launched an artillery strike at [thearea.name].") - explosion(loc,2,5,11) - else - explosion(loc,2,1,0) - reload -= (intensity ? 180 : 90) - else - to_chat(usr,"There already everything is destroyed") - -/*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)*/ + +/obj/machinery/artillerycontrol + var/reload = 180 + var/intensity = 1 + name = "bluespace artillery control" + icon_state = "control_boxp1" + icon = 'icons/obj/machines/particle_accelerator2.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/ui_interact(mob/user) + var/dat = "Bluespace Artillery Control:
                    " + dat += "Locked on
                    " + dat += "Charge progress: [reload]/180:
                    " + dat += "The Bluespace Artillery in mode : [intensity ? "Destroy" : "Hurt"]
                    " + dat += "Open Fire
                    " + dat += "Deployment of weapon authorized by
                    Nanotrasen Naval Command

                    Remember, friendly fire is grounds for termination of your contract and life.
                    " + user << browse(entity_ja(dat), "window=scroll") + onclose(user, "scroll") + +/obj/machinery/artillerycontrol/Topic(href, href_list) + . = ..() + if(!.) + return + if( href_list["toggle"] ) + intensity = !intensity + if(href_list["fire"]) + if(src.reload < (intensity ? 180 : 90)) + return FALSE + var/A + A = input("Area to jump bombard", "Open Fire", A) in teleportlocs + var/area/thearea = teleportlocs[A] + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + if(!istype(T,/turf/simulated/wall) && !istype(T, /turf/simulated/wall/r_wall) && !istype(T, /turf/space)) + L+=T + var/loc = pick(L) + if(loc) + if(intensity) + command_alert("Bluespace artillery fire detected in [thearea.name]. Brace for impact.") + message_admins("[key_name_admin(usr)] has launched an artillery strike at [thearea.name].") + explosion(loc,2,5,11) + else + explosion(loc,2,1,0) + reload -= (intensity ? 180 : 90) + else + to_chat(usr,"There already everything is destroyed") + +/*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)*/ diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 95f96ed54297..1370e169ff2c 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -1,234 +1,234 @@ -//These are meant for spawning on maps, namely Away Missions. - -//If someone can do this in a neater way, be my guest-Kor - -//To do: Allow corpses to appear mangled, bloody, etc. Allow customizing the bodies appearance (they're all bald and white right now). - -/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/atom_init() - . = ..() - 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 (src.loc) - M.dna.mutantrace = mutantrace - M.real_name = src.name - M.death(1) //Kills the new mob - 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_l_ear) - 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/coloured - 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/yellow - corpseid = 1 - corpseidjob = "Station Engineer" - corpseidaccess = "Station Engineer" - -/obj/effect/landmark/corpse/engineer/rig - corpsesuit = /obj/item/clothing/suit/space/rig/engineering - corpsemask = /obj/item/clothing/mask/breath - corpsehelmet = /obj/item/clothing/head/helmet/space/rig/engineering - -/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/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_cargo - 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" +//These are meant for spawning on maps, namely Away Missions. + +//If someone can do this in a neater way, be my guest-Kor + +//To do: Allow corpses to appear mangled, bloody, etc. Allow customizing the bodies appearance (they're all bald and white right now). + +/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/atom_init() + . = ..() + 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 (src.loc) + M.dna.mutantrace = mutantrace + M.real_name = src.name + M.death(1) //Kills the new mob + 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_l_ear) + 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/coloured + 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/yellow + corpseid = 1 + corpseidjob = "Station Engineer" + corpseidaccess = "Station Engineer" + +/obj/effect/landmark/corpse/engineer/rig + corpsesuit = /obj/item/clothing/suit/space/rig/engineering + corpsemask = /obj/item/clothing/mask/breath + corpsehelmet = /obj/item/clothing/head/helmet/space/rig/engineering + +/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/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_cargo + 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" diff --git a/code/modules/awaymissions/exile.dm b/code/modules/awaymissions/exile.dm index b8563b23719d..52695adaa47f 100644 --- a/code/modules/awaymissions/exile.dm +++ b/code/modules/awaymissions/exile.dm @@ -1,43 +1,43 @@ -//////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/atom_init() - imp = new /obj/item/weapon/implant/exile(src) - . = ..() - update() - - -/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" - - -/obj/item/weapon/implantcase/exile/atom_init() - imp = new /obj/item/weapon/implant/exile(src) - . = ..() - - -/obj/structure/closet/secure_closet/exile - name = "Exile Implants" - req_access = list(access_hos) - -/obj/structure/closet/secure_closet/exile/PopulateContents() - new /obj/item/weapon/implanter/exile(src) - for (var/i in 1 to 5) - 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/atom_init() + imp = new /obj/item/weapon/implant/exile(src) + . = ..() + update() + + +/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" + + +/obj/item/weapon/implantcase/exile/atom_init() + imp = new /obj/item/weapon/implant/exile(src) + . = ..() + + +/obj/structure/closet/secure_closet/exile + name = "Exile Implants" + req_access = list(access_hos) + +/obj/structure/closet/secure_closet/exile/PopulateContents() + new /obj/item/weapon/implanter/exile(src) + for (var/i in 1 to 5) + new /obj/item/weapon/implantcase/exile(src) diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm index d9bcef42f256..9cab94d23c86 100644 --- a/code/modules/awaymissions/gateway.dm +++ b/code/modules/awaymissions/gateway.dm @@ -1,245 +1,245 @@ -/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 = TRUE - anchored = TRUE - - var/active = TRUE // on away missions you should activate gateway from start, or place "awaystart" landmarks somewhere - var/hacked = FALSE - var/static/obj/transit_loc = null - -/obj/machinery/gateway/atom_init() - ..() - update_icon() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/gateway/atom_init_late() - if(dir & SOUTH) - density = FALSE - if(!transit_loc) - transit_loc = locate(/obj/effect/landmark/gateway_transit) in landmarks_list - -/obj/machinery/gateway/update_icon() - icon_state = active ? "on" : "off" - if(hacked) - icon_state += "_s" - -/obj/machinery/gateway/Destroy() - if(hacked) - return QDEL_HINT_LETMELIVE - return ..() - -//this is da important part wot makes things go -/obj/machinery/gateway/center - name = "Unknown Gateway" - density = TRUE - icon_state = "offcenter" - - use_power = 1 - idle_power_usage = 50 - active_power_usage = 5000 - - //warping vars - var/list/linked = list() - var/ready = FALSE //have we got all the parts for a gateway? - var/blocked = FALSE // used in gateway_locker to allow/disallow entering to gateway while hacked - var/atom/destination = null - - var/block_exile_implant = TRUE - -/obj/machinery/gateway/center/atom_init() - . = ..() - -/obj/machinery/gateway/center/atom_init_late() - detect() - gateways_list += src - - if(active) - for(var/obj/machinery/gateway/G in linked) - G.active = 1 - G.update_icon() - -/obj/machinery/gateway/center/update_icon() - icon_state = active ? "on" : "off" - icon_state += "center" - if(hacked) - icon_state += "_s" - -/obj/machinery/gateway/center/process() - if((stat & NOPOWER) && active) - toggleoff() - -/obj/machinery/gateway/center/proc/detect() // now this checked only at the start. It's okay if it continues to work without some parts... right? - 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 = FALSE - toggleoff() - break - - if(linked.len == 8) - ready = TRUE - -/obj/machinery/gateway/center/proc/toggleon(mob/user) - if(!ready) - to_chat(user, "Error: Integrity check failed.") - return - - if(!destination) - to_chat(user, "Warning: No destination found, recalibration required.") - - for(var/obj/machinery/gateway/G in linked) - G.active = TRUE - G.update_icon() - playsound(src, 'sound/machines/gateway/gateway_open.ogg', 100, 2) - active = TRUE - update_icon() - - use_power = 2 - START_PROCESSING(SSmachine, src) - -/obj/machinery/gateway/center/proc/toggleoff() - for(var/obj/machinery/gateway/G in linked) - G.active = FALSE - G.update_icon() - playsound(src, 'sound/machines/gateway/gateway_close.ogg', 100, 2) - active = FALSE - update_icon() - - use_power = 1 - STOP_PROCESSING(SSmachine, src) - -/obj/machinery/gateway/center/proc/calibrate(user) - if(hacked) - to_chat(user, "Error: Recalibration failed..") - return - var/list/destinations_choice = list() - for(var/obj/machinery/gateway/center/G in gateways_list) - if(G.active && ready && powered() && src != G) - destinations_choice[G.name] = G - - //away gates always should be able to allow pass on station - var/atom/station_gate = locate(/obj/machinery/gateway/center/station/) - if(station_gate && !(station_gate in destinations_choice) && !istype(src,/obj/machinery/gateway/center/station)) - destinations_choice[station_gate.name] = station_gate - - if(length(awaydestinations)) - destinations_choice["Unstable destination"] = pick(awaydestinations) - - destinations_choice["None"] = null - - var/user_pick = input(user, "Select a destination from the following candidates:","Gateway Destination",null) as null|anything in destinations_choice - - if(user_pick && destinations_choice[user_pick]) - destination = destinations_choice[user_pick] - to_chat(user, "Recalibration successful!.") - -/obj/machinery/gateway/center/attack_hand(mob/user) - user.SetNextMove(CLICK_CD_INTERACT) - . = ..() - - if(.) - return - - if(!active && powered()) - toggleon(user) - return - - toggleoff() - -// okay, here's a good teleporting stuff -/obj/machinery/gateway/center/Bumped(atom/movable/M) - if(!ready || !active) - return - - if(hacked && blocked) - if(ismob(M)) - to_chat(M, "Gateway Matter reacts strangely to your Touching") - return - - if(!destination) - to_chat(M, "Error: No destination set, calibration required.") - return - - if(block_exile_implant && iscarbon(M)) - 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, "The gate has detected your exile implant and is blocking your entry.") - return - - M.dir = SOUTH - enter_to_transit(M, get_step(destination.loc, SOUTH)) - use_power(1000) - -/obj/machinery/gateway/center/attackby(obj/item/device/W, mob/user) - if(istype(W,/obj/item/device/multitool)) - calibrate(user) - else - ..() - -/obj/machinery/gateway/proc/enter_to_transit(atom/movable/entered, turf/target) - playsound(src, 'sound/machines/gateway/gateway_enter.ogg', 100, 2) - entered.freeze_movement = TRUE - entered.forceMove(transit_loc.loc) - if(isliving(entered)) - var/mob/living/M = entered - M.Stun(10, 1, 1, 1) - var/obj/screen/cinematic = new /obj/screen{icon='icons/effects/gateway_entry.dmi'; icon_state="entry"; layer=21; mouse_opacity=0; screen_loc="1,0"; } (src) - if(M.client) - M.client.screen += cinematic - M.playsound_local(M.loc, 'sound/machines/gateway/gateway_transit.ogg', 100, 2) - addtimer(CALLBACK(src, .proc/exit_from_transit, entered, target, cinematic), 100) - else - addtimer(CALLBACK(src, .proc/exit_from_transit, entered, target), 100) - -/obj/machinery/gateway/proc/exit_from_transit(atom/movable/entered, turf/target, obj/screen/cinematic) - if(isliving(entered)) - var/mob/living/M = entered - if(M.client) - cinematic.icon_state = "exit" - flick("exit", cinematic) - sleep(12) - M.client.screen -= cinematic - qdel(cinematic) - M.AdjustStunned(-10, 1, 1, 0) - entered.freeze_movement = FALSE - entered.forceMove(target) - playsound(target, 'sound/machines/gateway/gateway_enter.ogg', 100, 2) - -/obj/effect/landmark/gateway_transit - -/obj/effect/landmark/gateway_transit/Crossed(atom/movable/AM) - if(!AM.freeze_movement) - qdel(AM) // THIS IS BLUESPACE FELLAS - -/* station gate tweaks */ -/obj/machinery/gateway/center/station/ - name = "NSS Exodus Gateway" - block_exile_implant = FALSE - -/obj/machinery/gateway/center/station/process() - ..() - if(active && !config.gateway_enabled) - toggleoff() - -/obj/machinery/gateway/center/station/calibrate(user) - if(!config.gateway_enabled) - to_chat(user, "Error: Remote activation required, make a request to the CentComm for this.") - return - ..() - -/obj/machinery/gateway/center/station/toggleon(mob/user) - if(!config.gateway_enabled) - to_chat(user, "Error: Remote activation required, make a request to the CentComm for this.") - return - ..() +/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 = TRUE + anchored = TRUE + + var/active = TRUE // on away missions you should activate gateway from start, or place "awaystart" landmarks somewhere + var/hacked = FALSE + var/static/obj/transit_loc = null + +/obj/machinery/gateway/atom_init() + ..() + update_icon() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/gateway/atom_init_late() + if(dir & SOUTH) + density = FALSE + if(!transit_loc) + transit_loc = locate(/obj/effect/landmark/gateway_transit) in landmarks_list + +/obj/machinery/gateway/update_icon() + icon_state = active ? "on" : "off" + if(hacked) + icon_state += "_s" + +/obj/machinery/gateway/Destroy() + if(hacked) + return QDEL_HINT_LETMELIVE + return ..() + +//this is da important part wot makes things go +/obj/machinery/gateway/center + name = "Unknown Gateway" + density = TRUE + icon_state = "offcenter" + + use_power = 1 + idle_power_usage = 50 + active_power_usage = 5000 + + //warping vars + var/list/linked = list() + var/ready = FALSE //have we got all the parts for a gateway? + var/blocked = FALSE // used in gateway_locker to allow/disallow entering to gateway while hacked + var/atom/destination = null + + var/block_exile_implant = TRUE + +/obj/machinery/gateway/center/atom_init() + . = ..() + +/obj/machinery/gateway/center/atom_init_late() + detect() + gateways_list += src + + if(active) + for(var/obj/machinery/gateway/G in linked) + G.active = 1 + G.update_icon() + +/obj/machinery/gateway/center/update_icon() + icon_state = active ? "on" : "off" + icon_state += "center" + if(hacked) + icon_state += "_s" + +/obj/machinery/gateway/center/process() + if((stat & NOPOWER) && active) + toggleoff() + +/obj/machinery/gateway/center/proc/detect() // now this checked only at the start. It's okay if it continues to work without some parts... right? + 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 = FALSE + toggleoff() + break + + if(linked.len == 8) + ready = TRUE + +/obj/machinery/gateway/center/proc/toggleon(mob/user) + if(!ready) + to_chat(user, "Error: Integrity check failed.") + return + + if(!destination) + to_chat(user, "Warning: No destination found, recalibration required.") + + for(var/obj/machinery/gateway/G in linked) + G.active = TRUE + G.update_icon() + playsound(src, 'sound/machines/gateway/gateway_open.ogg', 100, 2) + active = TRUE + update_icon() + + use_power = 2 + START_PROCESSING(SSmachine, src) + +/obj/machinery/gateway/center/proc/toggleoff() + for(var/obj/machinery/gateway/G in linked) + G.active = FALSE + G.update_icon() + playsound(src, 'sound/machines/gateway/gateway_close.ogg', 100, 2) + active = FALSE + update_icon() + + use_power = 1 + STOP_PROCESSING(SSmachine, src) + +/obj/machinery/gateway/center/proc/calibrate(user) + if(hacked) + to_chat(user, "Error: Recalibration failed..") + return + var/list/destinations_choice = list() + for(var/obj/machinery/gateway/center/G in gateways_list) + if(G.active && ready && powered() && src != G) + destinations_choice[G.name] = G + + //away gates always should be able to allow pass on station + var/atom/station_gate = locate(/obj/machinery/gateway/center/station/) + if(station_gate && !(station_gate in destinations_choice) && !istype(src,/obj/machinery/gateway/center/station)) + destinations_choice[station_gate.name] = station_gate + + if(length(awaydestinations)) + destinations_choice["Unstable destination"] = pick(awaydestinations) + + destinations_choice["None"] = null + + var/user_pick = input(user, "Select a destination from the following candidates:","Gateway Destination",null) as null|anything in destinations_choice + + if(user_pick && destinations_choice[user_pick]) + destination = destinations_choice[user_pick] + to_chat(user, "Recalibration successful!.") + +/obj/machinery/gateway/center/attack_hand(mob/user) + user.SetNextMove(CLICK_CD_INTERACT) + . = ..() + + if(.) + return + + if(!active && powered()) + toggleon(user) + return + + toggleoff() + +// okay, here's a good teleporting stuff +/obj/machinery/gateway/center/Bumped(atom/movable/M) + if(!ready || !active) + return + + if(hacked && blocked) + if(ismob(M)) + to_chat(M, "Gateway Matter reacts strangely to your Touching") + return + + if(!destination) + to_chat(M, "Error: No destination set, calibration required.") + return + + if(block_exile_implant && iscarbon(M)) + 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, "The gate has detected your exile implant and is blocking your entry.") + return + + M.dir = SOUTH + enter_to_transit(M, get_step(destination.loc, SOUTH)) + use_power(1000) + +/obj/machinery/gateway/center/attackby(obj/item/device/W, mob/user) + if(istype(W,/obj/item/device/multitool)) + calibrate(user) + else + ..() + +/obj/machinery/gateway/proc/enter_to_transit(atom/movable/entered, turf/target) + playsound(src, 'sound/machines/gateway/gateway_enter.ogg', 100, 2) + entered.freeze_movement = TRUE + entered.forceMove(transit_loc.loc) + if(isliving(entered)) + var/mob/living/M = entered + M.Stun(10, 1, 1, 1) + var/obj/screen/cinematic = new /obj/screen{icon='icons/effects/gateway_entry.dmi'; icon_state="entry"; layer=21; mouse_opacity=0; screen_loc="1,0"; } (src) + if(M.client) + M.client.screen += cinematic + M.playsound_local(M.loc, 'sound/machines/gateway/gateway_transit.ogg', 100, 2) + addtimer(CALLBACK(src, .proc/exit_from_transit, entered, target, cinematic), 100) + else + addtimer(CALLBACK(src, .proc/exit_from_transit, entered, target), 100) + +/obj/machinery/gateway/proc/exit_from_transit(atom/movable/entered, turf/target, obj/screen/cinematic) + if(isliving(entered)) + var/mob/living/M = entered + if(M.client) + cinematic.icon_state = "exit" + flick("exit", cinematic) + sleep(12) + M.client.screen -= cinematic + qdel(cinematic) + M.AdjustStunned(-10, 1, 1, 0) + entered.freeze_movement = FALSE + entered.forceMove(target) + playsound(target, 'sound/machines/gateway/gateway_enter.ogg', 100, 2) + +/obj/effect/landmark/gateway_transit + +/obj/effect/landmark/gateway_transit/Crossed(atom/movable/AM) + if(!AM.freeze_movement) + qdel(AM) // THIS IS BLUESPACE FELLAS + +/* station gate tweaks */ +/obj/machinery/gateway/center/station/ + name = "NSS Exodus Gateway" + block_exile_implant = FALSE + +/obj/machinery/gateway/center/station/process() + ..() + if(active && !config.gateway_enabled) + toggleoff() + +/obj/machinery/gateway/center/station/calibrate(user) + if(!config.gateway_enabled) + to_chat(user, "Error: Remote activation required, make a request to the CentComm for this.") + return + ..() + +/obj/machinery/gateway/center/station/toggleon(mob/user) + if(!config.gateway_enabled) + to_chat(user, "Error: Remote activation required, make a request to the CentComm for this.") + return + ..() diff --git a/code/modules/awaymissions/loot.dm b/code/modules/awaymissions/loot.dm index d2d0bb1e97b8..78b785aae3b9 100644 --- a/code/modules/awaymissions/loot.dm +++ b/code/modules/awaymissions/loot.dm @@ -1,25 +1,25 @@ -/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/atom_init() - . = ..() - 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/atom_init() + . = ..() + 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 57f85d099423..ea7894fc288a 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() - return +/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 diff --git a/code/modules/awaymissions/trigger.dm b/code/modules/awaymissions/trigger.dm index 36ff850007c5..a2dfb08f55a3 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) - 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) - 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) +/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) + 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) + 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/cargo/packs.dm b/code/modules/cargo/packs.dm index 823a524ec04c..6293b966045d 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -1,1481 +1,1481 @@ -//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 hacked. -//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("Operations","Security","Hospitality","Engineering","Medical / Science","Hydroponics","Mining","Supply","Miscellaneous") - -datum/supply_pack - var/name = "Crate" - var/group = "Operations" - var/true_manifest = "" - var/hidden = FALSE - var/contraband = FALSE - var/cost = 700 // Minimum cost, or infinite points are possible. - var/access = FALSE - var/list/contains = null - var/crate_name = "crate" - var/crate_type = /obj/structure/closet/crate - var/dangerous = FALSE // Should we message admins? - var/special = FALSE //Event/Station Goals/Admin enabled packs - var/special_enabled = FALSE - var/amount = 0 - -datum/supply_pack/New() - true_manifest += "
                      " - for(var/path in contains) - if(!path) - continue - var/atom/movable/AM = path - true_manifest += "
                    • [initial(AM.name)]
                    • " - true_manifest += "
                    " - -/datum/supply_pack/proc/generate(turf/T) - var/obj/structure/closet/crate/C = new crate_type(T) - C.name = crate_name - if(access) - C.req_access = list(access) - - fill(C) - - return C - -/datum/supply_pack/proc/fill(obj/structure/closet/crate/C) - for(var/item in contains) - var/n_item = new item(C) - if(amount && (istype(n_item, /obj/item/stack/sheet) || istype(n_item, /obj/item/stack/tile))) - var/obj/item/stack/sheet/n_sheet = n_item - n_sheet.set_amount(amount) - -//---------------------------------------------- -//-----------------OPERATIONS------------------- -//---------------------------------------------- - -/datum/supply_pack/mule - name = "MULEbot Crate" - contains = list(/obj/machinery/bot/mulebot) - cost = 2000 - crate_type = /obj/structure/largecrate/mule - crate_name = "MULEbot Crate" - group = "Operations" - -/datum/supply_pack/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/weapon/packageWrap, - /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/weapon/wrapping_paper, - /obj/item/weapon/wrapping_paper, - /obj/item/weapon/wrapping_paper) - cost = 1000 - crate_name = "Arts and Crafts crate" - group = "Operations" - -/datum/supply_pack/price_scanner - name = "Export scanners" - contains = list(/obj/item/device/export_scanner, - /obj/item/device/export_scanner) - cost = 1000 - crate_name = "Export scanners crate" - group = "Operations" - -//---------------------------------------------- -//-----------------SECURITY--------------------- -//---------------------------------------------- - -/datum/supply_pack/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) - cost = 1750 - crate_name = "Special Ops crate" - group = "Security" - hidden = TRUE - -/datum/supply_pack/weapons - name = "Weapons crate" - contains = list(/obj/item/weapon/melee/baton, - /obj/item/weapon/melee/baton, - /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) - cost = 3000 - crate_type = /obj/structure/closet/crate/secure/weapon - crate_name = "Weapons crate" - access = access_brig - group = "Security" - -/datum/supply_pack/eweapons - name = "Experimental weapons crate" - contains = list(/obj/item/weapon/flamethrower/full, - /obj/item/weapon/tank/phoron, - /obj/item/weapon/tank/phoron, - /obj/item/weapon/tank/phoron) - cost = 1750 - crate_type = /obj/structure/closet/crate/secure/weapon - crate_name = "Experimental weapons crate" - access = access_heads - group = "Security" - -/datum/supply_pack/armor - name = "Armor crate" - contains = list(/obj/item/clothing/head/helmet, - /obj/item/clothing/head/helmet, - /obj/item/clothing/suit/storage/flak, - /obj/item/clothing/suit/storage/flak) - cost = 1500 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Armor crate" - access = access_brig - group = "Security" - -/datum/supply_pack/riot - name = "Riot gear crate" - contains = list(/obj/item/weapon/melee/baton, - /obj/item/weapon/melee/baton, - /obj/item/weapon/melee/baton, - /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) - cost = 6000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Riot gear crate" - access = access_armory - group = "Security" - -/datum/supply_pack/mind_shields - name = "Mind shields implant crate" - contains = list (/obj/item/weapon/storage/lockbox/mind_shields) - cost = 5000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Mind shields implant crate" - access = access_armory - group = "Security" - -/datum/supply_pack/loyalty - name = "Loyalty implant crate" - contains = list (/obj/item/weapon/storage/lockbox/loyalty) - cost = 8000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Loyalty implant crate" - access = access_armory - group = "Security" - -/datum/supply_pack/ballistic - name = "Ballistic gear crate" - contains = list(/obj/item/clothing/suit/storage/flak/bulletproof, - /obj/item/clothing/suit/storage/flak/bulletproof, - /obj/item/clothing/head/helmet/bulletproof, - /obj/item/clothing/head/helmet/bulletproof, - /obj/item/weapon/gun/projectile/shotgun/combat, - /obj/item/weapon/gun/projectile/shotgun/combat) - cost = 5000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Ballistic gear crate" - access = access_armory - group = "Security" - -/datum/supply_pack/erifle - name = "Energy marksman crate" - contains = list(/obj/item/clothing/suit/armor/laserproof, - /obj/item/clothing/suit/armor/laserproof, - /obj/item/clothing/head/helmet/laserproof, - /obj/item/clothing/head/helmet/laserproof, - /obj/item/weapon/gun/energy/sniperrifle, - /obj/item/weapon/gun/energy/sniperrifle) - cost = 5000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Energy marksman crate" - access = access_armory - group = "Security" - -/datum/supply_pack/shotgunammo_beanbag - name = "Shotgun shells (Beanbag)" - contains = list(/obj/item/weapon/storage/box/shotgun/beanbag) - cost = 1000 - crate_name = "Shotgun shells (Beanbag)" - group = "Security" - -/datum/supply_pack/shotgunammo_slug - name = "Shotgun shells (slug)" - contains = list(/obj/item/weapon/storage/box/shotgun/slug) - cost = 2000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Shotgun shells (slug)" - access = access_armory - group = "Security" - -/datum/supply_pack/shotgunammo_buckshot - name = "Shotgun shells (buckshot)" - contains = list(/obj/item/weapon/storage/box/shotgun/buckshot) - cost = 2500 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Shotgun shells (buckshot)" - access = access_armory - group = "Security" - -/datum/supply_pack/r4046 - name = "40x46mm rubber grenades" - contains = list(/obj/item/weapon/storage/box/r4046, - /obj/item/weapon/storage/box/r4046) - cost = 2000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "40x46mm rubber grenades" - access = access_armory - group = "Security" - -/datum/supply_pack/m79 - name = "m79 grenade launcher" - contains = list(/obj/item/weapon/gun/projectile/m79, - /obj/item/weapon/storage/box/r4046) - cost = 3000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "m79 grenade launcher" - access = access_armory - group = "Security" - - -/datum/supply_pack/expenergy - name = "Experimental energy gear crate" - contains = list(/obj/item/clothing/suit/armor/laserproof, - /obj/item/clothing/suit/armor/laserproof, - /obj/item/clothing/head/helmet/laserproof, - /obj/item/clothing/head/helmet/laserproof, - /obj/item/weapon/gun/energy/gun, - /obj/item/weapon/gun/energy/gun) - cost = 5000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Experimental energy gear crate" - access = access_armory - group = "Security" - -/datum/supply_pack/exparmor - name = "Experimental armor crate" - contains = list(/obj/item/clothing/suit/armor/laserproof, - /obj/item/clothing/head/helmet/laserproof, - /obj/item/clothing/suit/storage/flak/bulletproof, - /obj/item/clothing/head/helmet/bulletproof, - /obj/item/clothing/head/helmet/riot, - /obj/item/clothing/suit/armor/riot) - cost = 3500 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Experimental armor crate" - access = access_armory - group = "Security" - -/datum/supply_pack/securitybarriers - name = "Security barrier crate" - contains = list(/obj/machinery/deployable/barrier, - /obj/machinery/deployable/barrier, - /obj/machinery/deployable/barrier, - /obj/machinery/deployable/barrier) - cost = 2000 - crate_type = /obj/structure/closet/crate/secure/gear - crate_name = "Security barrier crate" - group = "Security" - -/datum/supply_pack/securitywallshield - name = "Wall shield Generators" - contains = list(/obj/machinery/shieldwallgen, - /obj/machinery/shieldwallgen, - /obj/machinery/shieldwallgen, - /obj/machinery/shieldwallgen) - cost = 2000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "wall shield generators crate" - access = access_teleporter - group = "Security" - -//---------------------------------------------- -//-----------------HOSPITALITY------------------ -//---------------------------------------------- - -/datum/supply_pack/vending_bar - name = "Bartending supply crate" - contains = list(/obj/item/weapon/vending_refill/boozeomat) - cost = 1500 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "bartending supply crate" - group = "Hospitality" - -/datum/supply_pack/vending_coffee - name = "Hotdrinks supply crate" - contains = list(/obj/item/weapon/vending_refill/coffee, - /obj/item/weapon/vending_refill/coffee, - /obj/item/weapon/vending_refill/coffee) - cost = 1500 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "hotdrinks supply crate" - group = "Hospitality" - -/datum/supply_pack/vending_snack - name = "Snack supply crate" - contains = list(/obj/item/weapon/vending_refill/snack, - /obj/item/weapon/vending_refill/snack, - /obj/item/weapon/vending_refill/snack) - cost = 1500 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "snack supply crate" - group = "Hospitality" - -/datum/supply_pack/vending_cola - name = "Softdrinks supply crate" - contains = list(/obj/item/weapon/vending_refill/cola, - /obj/item/weapon/vending_refill/cola, - /obj/item/weapon/vending_refill/cola) - cost = 1500 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "softdrinks supply crate" - group = "Hospitality" - -/datum/supply_pack/vending_cigarette - name = "Cigarette supply crate" - contains = list(/obj/item/weapon/vending_refill/cigarette, - /obj/item/weapon/vending_refill/cigarette, - /obj/item/weapon/vending_refill/cigarette) - cost = 1500 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "cigarette supply crate" - group = "Hospitality" - -/datum/supply_pack/vending_barber - name = "Barbershop supply crate" - contains = list(/obj/item/weapon/vending_refill/barbervend, - /obj/item/weapon/vending_refill/barbervend, - /obj/item/weapon/vending_refill/barbervend) - cost = 1500 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "barbershop supply crate" - group = "Hospitality" - -/datum/supply_pack/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/flask/barflask, - /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/bottle/ale, - /obj/item/weapon/reagent_containers/food/drinks/bottle/ale, - /obj/item/weapon/reagent_containers/food/drinks/bottle/beer, - /obj/item/weapon/reagent_containers/food/drinks/bottle/beer, - /obj/item/weapon/reagent_containers/food/drinks/bottle/beer, - /obj/item/weapon/reagent_containers/food/drinks/bottle/beer) - cost = 2000 - crate_type = /obj/structure/closet/crate - crate_name = "Party equipment" - group = "Hospitality" - -//---------------------------------------------- -//-----------------ENGINEERING------------------ -//---------------------------------------------- - -/datum/supply_pack/internals - name = "Internals crate" - contains = list(/obj/item/clothing/mask/gas/coloured, - /obj/item/clothing/mask/gas/coloured, - /obj/item/clothing/mask/gas/coloured, - /obj/item/weapon/tank/air, - /obj/item/weapon/tank/air, - /obj/item/weapon/tank/air) - cost = 1000 - crate_type = /obj/structure/closet/crate/internals - crate_name = "Internals crate" - group = "Engineering" - -/datum/supply_pack/sleeping_agent - name = "Canister: \[N2O\]" - contains = list(/obj/machinery/portable_atmospherics/canister/sleeping_agent) - cost = 4000 - crate_type = /obj/structure/largecrate - crate_name = "N2O crate" - group = "Engineering" - -/datum/supply_pack/oxygen - name = "Canister: \[O2\]" - contains = list(/obj/machinery/portable_atmospherics/canister/oxygen) - cost = 3000 - crate_type = /obj/structure/largecrate - crate_name = "O2 crate" - group = "Engineering" - -/datum/supply_pack/nitrogen - name = "Canister: \[N2\]" - contains = list(/obj/machinery/portable_atmospherics/canister/nitrogen) - cost = 2000 - crate_type = /obj/structure/largecrate - crate_name = "N2 crate" - group = "Engineering" - -/datum/supply_pack/air - name = "Canister \[Air\]" - contains = list(/obj/machinery/portable_atmospherics/canister/air) - cost = 2000 - crate_type = /obj/structure/largecrate - crate_name = "Air crate" - group = "Engineering" - -/datum/supply_pack/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/coloured, - /obj/item/clothing/mask/gas/coloured, - /obj/item/clothing/mask/gas/coloured, - /obj/item/clothing/mask/gas/coloured, - /obj/item/clothing/mask/gas/coloured) - cost = 3500 - crate_type = /obj/structure/closet/crate/internals - crate_name = "Emergency crate" - group = "Engineering" - -/datum/supply_pack/inflatable - name = "Inflatable barriers" - contains = list(/obj/item/weapon/storage/briefcase/inflatable, - /obj/item/weapon/storage/briefcase/inflatable, - /obj/item/weapon/storage/briefcase/inflatable) - cost = 2000 - crate_type = /obj/structure/closet/crate/engi - crate_name = "Inflatable Barrier Crate" - group = "Engineering" - -/datum/supply_pack/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 = 1000 - crate_type = /obj/structure/closet/crate - crate_name = "Replacement lights" - group = "Engineering" - -/datum/supply_pack/metal50 - name = "50 metal sheets" - contains = list(/obj/item/stack/sheet/metal) - amount = 50 - cost = 1000 - crate_type = /obj/structure/closet/crate/engi - crate_name = "Metal sheets crate" - group = "Engineering" - -/datum/supply_pack/glass50 - name = "50 glass sheets" - contains = list(/obj/item/stack/sheet/glass) - amount = 50 - cost = 1000 - crate_type = /obj/structure/closet/crate/engi - crate_name = "Glass sheets crate" - group = "Engineering" - -/datum/supply_pack/wood50 - name = "50 wooden planks" - contains = list(/obj/item/stack/sheet/wood) - amount = 50 - cost = 1000 - crate_type = /obj/structure/closet/crate/engi - crate_name = "Wooden planks crate" - group = "Engineering" - -/datum/supply_pack/carpets - name = "Random carpets" - contains = list(/obj/item/stack/tile/carpet, /obj/item/stack/tile/carpet/black, /obj/item/stack/tile/carpet/purple, /obj/item/stack/tile/carpet/orange, /obj/item/stack/tile/carpet/green, - /obj/item/stack/tile/carpet/blue, /obj/item/stack/tile/carpet/blue2, /obj/item/stack/tile/carpet/red, /obj/item/stack/tile/carpet/cyan - ) - amount = 50 - cost = 2500 - crate_type = /obj/structure/closet/crate - crate_name = "Carpet crate" - group = "Engineering" - var/num_contained = 4 // 4 random carpets per crate - -/datum/supply_pack/carpets/fill(obj/structure/closet/crate/C) - var/list/L = contains.Copy() - var/item - if(num_contained <= L.len) - for(var/i in 1 to num_contained) - item = pick_n_take(L) - var/n_item = new item(C) - if(istype(n_item, /obj/item/stack/tile)) - var/obj/item/stack/sheet/n_sheet = n_item - n_sheet.set_amount(amount) - else - for(var/i in 1 to num_contained) - item = pick(L) - var/n_item = new item(C) - if(istype(n_item, /obj/item/stack/tile)) - var/obj/item/stack/sheet/n_sheet = n_item - n_sheet.set_amount(amount) - -/datum/supply_pack/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/stock_parts/cell, - /obj/item/weapon/stock_parts/cell, - /obj/item/weapon/stock_parts/cell/high, - /obj/item/weapon/stock_parts/cell/high) - cost = 1500 - crate_type = /obj/structure/closet/crate/engi - crate_name = "Electrical maintenance crate" - group = "Engineering" - -/datum/supply_pack/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/yellow) - cost = 1000 - crate_type = /obj/structure/closet/crate/engi - crate_name = "Mechanical maintenance crate" - group = "Engineering" - -/datum/supply_pack/fueltank - name = "Fuel tank crate" - contains = list(/obj/structure/reagent_dispensers/fueltank) - cost = 800 - crate_type = /obj/structure/largecrate - crate_name = "fuel tank crate" - group = "Engineering" - -/datum/supply_pack/solar - name = "Solar Pack crate" - contains = list(/obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/solar_assembly, - /obj/item/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 = 2000 - crate_type = /obj/structure/closet/crate/engi - crate_name = "Solar pack crate" - group = "Engineering" - -/datum/supply_pack/engine - name = "Emitter crate" - contains = list(/obj/machinery/power/emitter, - /obj/machinery/power/emitter) - cost = 1000 - crate_type = /obj/structure/closet/crate/secure/engisec - crate_name = "Emitter crate" - access = access_ce - group = "Engineering" - -/datum/supply_pack/engine/field_gen - name = "Field Generator crate" - contains = list(/obj/machinery/field_generator, - /obj/machinery/field_generator) - crate_type = /obj/structure/closet/crate/engi - crate_name = "Field Generator crate" - -/datum/supply_pack/engine/sing_gen - name = "Singularity Generator crate" - contains = list(/obj/machinery/the_singularitygen) - crate_type = /obj/structure/closet/crate/engi - crate_name = "Singularity Generator crate" - -/datum/supply_pack/engine/collector - name = "Collector crate" - contains = list(/obj/machinery/power/rad_collector, - /obj/machinery/power/rad_collector, - /obj/machinery/power/rad_collector) - crate_type = /obj/structure/closet/crate/engi - crate_name = "Collector crate" - -/datum/supply_pack/engine/PA - name = "Particle Accelerator crate" - cost = 4000 - 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) - crate_type = /obj/structure/closet/crate/engi - crate_name = "Particle Accelerator crate" - -/datum/supply_pack/mecha_ripley - name = "Circuit Crate (\"Ripley\" APLU)" - contains = list(/obj/item/weapon/book/manual/wiki/guide_to_exosuits, - /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 = 3000 - crate_type = /obj/structure/closet/crate/secure/scisecurecrate - crate_name = "APLU \"Ripley\" Circuit Crate" - access = access_robotics - group = "Engineering" - -/datum/supply_pack/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 = 2500 - crate_type = /obj/structure/closet/crate/secure/scisecurecrate - crate_name = "\"Odysseus\" Circuit Crate" - access = access_robotics - group = "Engineering" - -/datum/supply_pack/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/stock_parts/cell/high, - /obj/item/weapon/stock_parts/cell/high) - cost = 1000 - crate_type = /obj/structure/closet/crate/secure/scisecurecrate - crate_name = "Robotics assembly" - access = access_robotics - group = "Engineering" - -/datum/supply_pack/shield_gen - contains = list(/obj/item/weapon/circuitboard/shield_gen) - name = "Bubble shield generator circuitry" - cost = 5000 - crate_type = /obj/structure/closet/crate/secure/engisec - crate_name = "bubble shield generator circuitry crate" - group = "Engineering" - access = access_ce - -/datum/supply_pack/shield_gen_ex - contains = list(/obj/item/weapon/circuitboard/shield_gen_ex) - name = "Hull shield generator circuitry" - cost = 5000 - crate_type = /obj/structure/closet/crate/secure/engisec - crate_name = "hull shield generator circuitry crate" - group = "Engineering" - access = access_ce - -/datum/supply_pack/shield_cap - contains = list(/obj/item/weapon/circuitboard/shield_cap) - name = "Bubble shield capacitor circuitry" - cost = 5000 - crate_type = /obj/structure/closet/crate/secure/engisec - crate_name = "shield capacitor circuitry crate" - group = "Engineering" - access = access_ce - -/datum/supply_pack/smbig - name = "Supermatter Core" - contains = list(/obj/machinery/power/supermatter) - cost = 5000 - crate_type = /obj/structure/closet/crate/secure/woodseccrate - crate_name = "Supermatter crate (CAUTION)" - group = "Engineering" - access = access_ce - -/*/datum/supply_pack/teg // teg currently were broken for a long time ago, so no point to have it in-game until fixed. - contains = list(/obj/machinery/power/generator) - name = "Mark I Thermoelectric Generator" - cost = 7500 - crate_type = /obj/structure/closet/crate/secure/large - crate_name = "Mk1 TEG crate" - group = "Engineering" - access = access_engine*/ - -/*/datum/supply_pack/circulator - contains = list(/obj/machinery/atmospherics/components/binary/circulator) - name = "Binary atmospheric circulator" - cost = 6000 - crate_type = /obj/structure/closet/crate/secure/large - crate_name = "Atmospheric circulator crate" - group = "Engineering" - access = access_engine*/ - -/datum/supply_pack/air_dispenser - contains = list(/obj/machinery/pipedispenser/orderable) - name = "Pipe Dispenser" - cost = 3500 - crate_type = /obj/structure/closet/crate/secure/large - crate_name = "Pipe Dispenser Crate" - group = "Engineering" - access = access_atmospherics - -/datum/supply_pack/disposals_dispenser - contains = list(/obj/machinery/pipedispenser/disposal/orderable) - name = "Disposals Pipe Dispenser" - cost = 3500 - crate_type = /obj/structure/closet/crate/secure/large - crate_name = "Disposal Dispenser Crate" - group = "Engineering" - access = access_atmospherics - -//---------------------------------------------- -//------------MEDICAL / SCIENCE----------------- -//---------------------------------------------- - -/datum/supply_pack/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/storage/firstaid/adv, - /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/box/autoinjectors, - /obj/item/weapon/storage/firstaid/small_firstaid_kit/civilian, - /obj/item/weapon/storage/firstaid/small_firstaid_kit/civilian, - /obj/item/weapon/storage/firstaid/small_firstaid_kit/space) - cost = 1000 - crate_type = /obj/structure/closet/crate/medical - crate_name = "Medical crate" - group = "Medical / Science" - -/datum/supply_pack/virus - name = "Virus sample crate" - contains = list(/obj/item/weapon/virusdish/random, - /obj/item/weapon/virusdish/random, - /obj/item/weapon/virusdish/random, - /obj/item/weapon/virusdish/random) - cost = 2500 - crate_type = /obj/structure/closet/crate/secure/medical - crate_name = "Virus sample crate" - access = access_cmo - group = "Medical / Science" - -/datum/supply_pack/coolanttank - name = "Coolant tank crate" - contains = list(/obj/structure/reagent_dispensers/coolanttank) - cost = 1600 - crate_type = /obj/structure/largecrate - crate_name = "Coolant tank crate" - group = "Medical / Science" - -/datum/supply_pack/phoron - name = "Phoron assembly crate" - contains = list(/obj/item/weapon/tank/phoron, - /obj/item/weapon/tank/phoron, - /obj/item/weapon/tank/phoron, - /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 = 1000 - crate_type = /obj/structure/closet/crate/secure/scisecurecrate - crate_name = "Phoron assembly crate" - access = access_tox_storage - group = "Medical / Science" - -/datum/supply_pack/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 = 2500 - crate_type = /obj/structure/closet/crate/secure/medical - crate_name = "Surgery crate" - access = access_medical - group = "Medical / Science" - -/datum/supply_pack/sterile - name = "Sterile equipment crate" - contains = list(/obj/item/clothing/under/rank/medical/green, - /obj/item/clothing/under/rank/medical/green, - /obj/item/clothing/head/surgery/green, - /obj/item/clothing/head/surgery/green, - /obj/item/weapon/storage/box/masks, - /obj/item/weapon/storage/box/gloves) - cost = 1500 - crate_type = /obj/structure/closet/crate - crate_name = "Sterile equipment crate" - group = "Medical / Science" - -/datum/supply_pack/bloodpacks - name = "Blood Pack Variety Crate" - cost = 3500 - contains = list(/obj/item/weapon/reagent_containers/blood/empty, - /obj/item/weapon/reagent_containers/blood/empty, - /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) - crate_type = /obj/structure/closet/crate/freezer - crate_name = "blood freezer" - group = "Medical / Science" - -/datum/supply_pack/iv_drip - name = "IV Drip Crate" - cost = 1000 - contains = list(/obj/machinery/iv_drip) - crate_type = /obj/structure/closet/crate/medical - crate_name = "iv drip crate" - group = "Medical / Science" - -/datum/supply_pack/body_bags - name = "Body Bags Crate" - cost = 1000 - contains = list(/obj/item/weapon/storage/box/bodybags, - /obj/item/weapon/storage/box/bodybags, - /obj/item/weapon/storage/box/bodybags) - crate_name = "body bags crate" - group = "Medical / Science" - -/datum/supply_pack/suspension_gen - name = "Suspension Field Generetor Crate" - cost = 3000 - contains = list(/obj/machinery/suspension_gen) - crate_type = /obj/structure/closet/crate/secure/scisecurecrate - crate_name = "Suspension Field Generetor Crate" - access = access_research - group = "Medical / Science" - -/datum/supply_pack/floodlight - name = "Emergency Floodlight Crate" - cost = 2000 - contains = list(/obj/machinery/floodlight, - /obj/machinery/floodlight) - crate_type = /obj/structure/closet/crate/scicrate - crate name = "Emergency Floodlight Crate" - group = "Medical / Science" - -//---------------------------------------------- -//-----------------HYDROPONICS------------------ -//---------------------------------------------- - -/datum/supply_pack/monkey - name = "Monkey crate" - contains = list (/obj/item/weapon/storage/box/monkeycubes) - cost = 2000 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "Monkey crate" - group = "Hydroponics" - -/datum/supply_pack/farwa - name = "Farwa crate" - contains = list (/obj/item/weapon/storage/box/monkeycubes/farwacubes) - cost = 3000 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "Farwa crate" - group = "Hydroponics" - -/datum/supply_pack/skrell - name = "Neaera crate" - contains = list (/obj/item/weapon/storage/box/monkeycubes/neaeracubes) - cost = 3000 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "Neaera crate" - group = "Hydroponics" - -/datum/supply_pack/stok - name = "Stok crate" - contains = list (/obj/item/weapon/storage/box/monkeycubes/stokcubes) - cost = 3000 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "Stok crate" - group = "Hydroponics" - -/datum/supply_pack/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/device/plant_analyzer, - /obj/item/clothing/gloves/botanic_leather, - /obj/item/clothing/suit/apron) // Updated with new things - cost = 1500 - crate_type = /obj/structure/closet/crate/hydroponics - crate_name = "Hydroponics crate" - access = access_hydroponics - group = "Hydroponics" - -//farm animals - useless and annoying, but potentially a good source of food -/datum/supply_pack/cow - name = "Cow crate" - cost = 3000 - crate_type = /obj/structure/closet/critter/cow - crate_name = "Cow crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_pack/goat - name = "Goat crate" - cost = 2500 - crate_type = /obj/structure/closet/critter/goat - crate_name = "Goat crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_pack/chicken - name = "Chicken crate" - cost = 2000 - crate_type = /obj/structure/closet/critter/chick - crate_name = "Chicken crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_pack/corgi - name = "Corgi crate" - cost = 5000 - crate_type = /obj/structure/closet/critter/corgi - crate_name = "Corgi crate" - group = "Hydroponics" - -/datum/supply_pack/shiba - name = "Shiba crate" - cost = 4000 - crate_type = /obj/structure/closet/critter/shiba - crate_name = "Shiba crate" - group = "Hydroponics" - -/datum/supply_pack/cat - name = "Cat crate" - cost = 4000 - crate_type = /obj/structure/closet/critter/cat - crate_name = "Cat crate" - group = "Hydroponics" - -/datum/supply_pack/pug - name = "Pug crate" - cost = 5000 - crate_type = /obj/structure/closet/critter/pug - crate_name = "Pug crate" - group = "Hydroponics" - -/datum/supply_pack/pig - name = "Pig crate" - cost = 3000 - crate_type = /obj/structure/closet/critter/pig - crate_name = "Pig crate" - group = "Hydroponics" - -/datum/supply_pack/turkey - name = "Turkey crate" - cost = 2000 - crate_type = /obj/structure/closet/critter/turkey - crate_name = "Turkey crate" - group = "Hydroponics" - -/datum/supply_pack/goose - name = "Goose crate" - cost = 2500 - crate_type = /obj/structure/closet/critter/goose - crate_name = "Goose crate" - group = "Hydroponics" - -/datum/supply_pack/seal - name = "Seal crate" - cost = 3000 - crate_type = /obj/structure/closet/critter/seal - crate_name = "Seal crate" - group = "Hydroponics" - -/datum/supply_pack/walrus - name = "Walrus crate" - cost = 3500 - crate_type = /obj/structure/closet/critter/walrus - crate_name = "Walrus crate" - group = "Hydroponics" - -/datum/supply_pack/seeds - name = "Seeds crate" - contains = list(/obj/item/seeds/chiliseed, - /obj/item/seeds/berryseed, - /obj/item/seeds/cornseed, - /obj/item/seeds/eggplantseed, - /obj/item/seeds/tomatoseed, - /obj/item/seeds/appleseed, - /obj/item/seeds/soyaseed, - /obj/item/seeds/wheatseed, - /obj/item/seeds/carrotseed, - /obj/item/seeds/harebell, - /obj/item/seeds/lemonseed, - /obj/item/seeds/orangeseed, - /obj/item/seeds/grassseed, - /obj/item/seeds/sunflowerseed, - /obj/item/seeds/chantermycelium, - /obj/item/seeds/potatoseed, - /obj/item/seeds/sugarcaneseed) - cost = 1000 - crate_type = /obj/structure/closet/crate/hydroponics - crate_name = "Seeds crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_pack/weedcontrol - name = "Weed control crate" - contains = list(/obj/item/weapon/scythe, - /obj/item/clothing/mask/gas/coloured, - /obj/item/weapon/grenade/chem_grenade/antiweed, - /obj/item/weapon/grenade/chem_grenade/antiweed) - cost = 2000 - crate_type = /obj/structure/closet/crate/secure/hydrosec - crate_name = "Weed control crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_pack/exoticseeds - name = "Exotic seeds crate" - contains = list(/obj/item/seeds/nettleseed, - /obj/item/seeds/replicapod, - /obj/item/seeds/replicapod, - /obj/item/seeds/replicapod, - /obj/item/seeds/plumpmycelium, - /obj/item/seeds/libertymycelium, - /obj/item/seeds/amanitamycelium, - /obj/item/seeds/reishimycelium, - /obj/item/seeds/bananaseed, - /obj/item/seeds/riceseed, - /obj/item/seeds/eggplantseed, - /obj/item/seeds/limeseed, - /obj/item/seeds/grapeseed, - /obj/item/seeds/eggyseed) - cost = 1500 - crate_type = /obj/structure/closet/crate/hydroponics - crate_name = "Exotic Seeds crate" - access = access_hydroponics - group = "Hydroponics" - -/datum/supply_pack/watertank - name = "Water tank crate" - contains = list(/obj/structure/reagent_dispensers/watertank) - cost = 800 - crate_type = /obj/structure/largecrate - crate_name = "Water tank crate" - group = "Hydroponics" - -/datum/supply_pack/bee_keeper - name = "Beekeeping crate" - contains = list(/obj/item/beezeez, - /obj/item/weapon/bee_net, - /obj/item/apiary, - /obj/item/queen_bee) - cost = 4000 - contraband = TRUE - crate_type = /obj/structure/closet/crate/hydroponics - crate_name = "Beekeeping crate" - access = access_hydroponics - group = "Hydroponics" - -//---------------------------------------------- -//--------------------MINING-------------------- -//---------------------------------------------- - -/datum/supply_pack/mining - name = "Mining Explosives Crate" - contains = list(/obj/item/weapon/mining_charge, - /obj/item/weapon/mining_charge, - /obj/item/weapon/mining_charge, - /obj/item/weapon/mining_charge, - /obj/item/weapon/mining_charge, - /obj/item/weapon/mining_charge, - /obj/item/weapon/mining_charge, - /obj/item/weapon/mining_charge, - /obj/item/weapon/mining_charge, - /obj/item/weapon/mining_charge,) - cost = 1500 - crate_type = /obj/structure/closet/crate/secure/gear - crate_name = "Mining Explosives Crate" - access = access_mining - group = "Mining" - -/datum/supply_pack/mining_drill - name = "Drill Crate" - contains = list(/obj/machinery/mining/drill) - cost = 3000 - crate_type = /obj/structure/closet/crate/secure/large - crate_name = "Drill Crate" - access = access_mining - group = "Mining" - -/datum/supply_pack/mining_brace - name = "Brace Crate" - contains = list(/obj/machinery/mining/brace) - cost = 1500 - crate_type = /obj/structure/closet/crate/secure/large - crate_name = "Brace Crate" - access = access_mining - group = "Mining" - -/datum/supply_pack/mining_supply - name = "Mining Supply Crate" - contains = list(/obj/item/weapon/mining_scanner/improved, - /obj/item/weapon/storage/firstaid/small_firstaid_kit/space, - /obj/item/weapon/storage/firstaid/small_firstaid_kit/space, - /obj/item/weapon/reagent_containers/spray/cleaner, - /obj/item/weapon/storage/box/autoinjector/stimpack, - /obj/item/device/flashlight/lantern, - /obj/item/weapon/pickaxe/drill/jackhammer) - cost = 3000 - crate_type = /obj/structure/closet/crate/secure/gear - crate_name = "Mining Supply Crate" - access = access_mining - group = "Mining" - -//---------------------------------------------- -//--------------------SUPPLY-------------------- -//---------------------------------------------- - -/datum/supply_pack/food - name = "Kitchen supply crate" - contains = list(/obj/item/weapon/reagent_containers/food/condiment/flour, - /obj/item/weapon/reagent_containers/food/condiment/flour, - /obj/item/weapon/reagent_containers/food/condiment/flour, - /obj/item/weapon/reagent_containers/food/condiment/flour, - /obj/item/weapon/reagent_containers/food/drinks/milk, - /obj/item/weapon/reagent_containers/food/drinks/milk, - /obj/item/weapon/storage/fancy/egg_box, - /obj/item/weapon/reagent_containers/food/snacks/tofu, - /obj/item/weapon/reagent_containers/food/snacks/tofu, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/grown/banana, - /obj/item/weapon/reagent_containers/food/snacks/grown/banana) - cost = 1000 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "Food crate" - group = "Supply" - -/datum/supply_pack/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 = 1000 - crate_name = "Toner cartridges" - group = "Supply" - -/datum/supply_pack/vest - name = "Vest Crate" - contains = list(/obj/item/clothing/accessory/storage/brown_vest, - /obj/item/clothing/accessory/storage/brown_vest, - /obj/item/clothing/accessory/storage/black_vest) - cost = 4000 - crate_name = "Vest Crate" - group = "Supply" - -/datum/supply_pack/misc/posters - name = "Corporate Posters Crate" - contains = list(/obj/item/weapon/poster/legit, - /obj/item/weapon/poster/legit, - /obj/item/weapon/poster/legit, - /obj/item/weapon/poster/legit, - /obj/item/weapon/poster/legit) - cost = 800 - crate_name = "Corporate Posters Crate" - group = "Supply" - -/datum/supply_pack/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/advanced, - /obj/item/weapon/holosign_creator, - /obj/item/weapon/caution, - /obj/item/weapon/caution, - /obj/item/weapon/caution, - /obj/item/weapon/reagent_containers/watertank_backpack/janitor, - /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 = 1000 - crate_name = "Janitorial supplies" - group = "Supply" - -/datum/supply_pack/boxes - name = "Empty boxes" - 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 = 1000 - crate_name = "Empty box crate" - group = "Supply" - -/datum/supply_pack/barber - name = "Barber supplies" - contains = list(/obj/item/weapon/storage/box/hairdyes, - /obj/item/weapon/reagent_containers/spray/hair_color_spray, - /obj/item/weapon/reagent_containers/glass/bottle/hair_growth_accelerator, - /obj/item/weapon/scissors, - /obj/item/weapon/razor) - cost = 1000 - crate_name = "Barber supplies" - group = "Supply" - -//---------------------------------------------- -//--------------MISCELLANEOUS------------------- -//---------------------------------------------- - -/datum/supply_pack/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 = 2000 - crate_name = "Wizard costume crate" - group = "Miscellaneous" - -/datum/supply_pack/conveyor - name = "Conveyor Assembly Crate" - contains = list(/obj/item/conveyor_construct, - /obj/item/conveyor_construct, - /obj/item/conveyor_construct, - /obj/item/conveyor_construct, - /obj/item/conveyor_construct, - /obj/item/conveyor_construct, - /obj/item/conveyor_switch_construct, - /obj/item/weapon/paper/conveyor) - cost = 1500 - crate_name = "conveyor assembly crate" - group = "Miscellaneous" - -/datum/supply_pack/formal_wear - contains = list(/obj/item/clothing/head/bowler, - /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/under/lawyer/bluesuit, - /obj/item/clothing/under/lawyer/purpsuit, - /obj/item/clothing/shoes/black, - /obj/item/clothing/shoes/black, - /obj/item/clothing/shoes/leather, - /obj/item/clothing/suit/wcoat, - /obj/item/clothing/under/suit_jacket/charcoal, - /obj/item/clothing/under/suit_jacket/navy, - /obj/item/clothing/under/suit_jacket/burgundy, - /obj/item/clothing/under/suit_jacket/checkered, - /obj/item/clothing/under/suit_jacket/tan) - name = "Formalwear closet" - cost = 3000 - crate_type = /obj/structure/closet - crate_name = "Formalwear for the best occasions." - group = "Miscellaneous" - -/datum/supply_pack/eftpos - contains = list(/obj/item/device/eftpos) - name = "EFTPOS scanner" - cost = 1000 - crate_name = "EFTPOS crate" - group = "Miscellaneous" - -//---------------------------------------------- -//-----------------RANDOMISED------------------- -//---------------------------------------------- - -/datum/supply_pack/randomised - name = "Collectable Hats Crate!" - cost = 20000 - var/num_contained = 4 //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) - crate_name = "Collectable hats crate! Brought to you by Bass.inc!" - group = "Miscellaneous" - -/datum/supply_pack/randomised/fill(obj/structure/closet/crate/C) - var/list/L = contains.Copy() - var/item - if(num_contained <= L.len) - for(var/i in 1 to num_contained) - item = pick_n_take(L) - new item(C) - else - for(var/i in 1 to num_contained) - item = pick(L) - new item(C) - -/datum/supply_pack/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/poster/contraband, - /obj/item/weapon/reagent_containers/food/drinks/bottle/pwine) - name = "Contraband crate" - cost = 3000 - crate_type = /obj/structure/closet/crate - crate_name = "Unlabeled crate" - contraband = TRUE - group = "Operations" - -/datum/supply_pack/randomised/toys - num_contained = 5 - contains = list(/obj/item/toy/spinningtoy, - /obj/item/toy/sword, - /obj/item/toy/owl, - /obj/item/toy/griffin, - /obj/item/toy/nuke, - /obj/item/toy/minimeteor, - /obj/item/toy/carpplushie, - /obj/item/toy/crossbow, - /obj/item/toy/katana) - name = "Toy Crate" - cost = 5000 // or play the arcade machines ya lazy bum - crate_name ="Toy crate" - group = "Miscellaneous" - -/datum/supply_pack/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 = 1500 - crate_type = /obj/structure/closet/crate/freezer - crate_name = "Pizza crate" - group = "Hospitality" - -/datum/supply_pack/randomised/costume - num_contained = 2 - contains = list(/obj/item/clothing/suit/pirate, - /obj/item/clothing/suit/judgerobe, - /obj/item/clothing/suit/wcoat, - /obj/item/clothing/suit/hastur, - /obj/item/clothing/suit/holidaypriest, - /obj/item/clothing/suit/nun, - /obj/item/clothing/suit/imperium_monk, - /obj/item/clothing/suit/ianshirt, - /obj/item/clothing/under/gimmick/rank/captain/suit, - /obj/item/clothing/under/gimmick/rank/head_of_personnel/suit, - /obj/item/clothing/under/lawyer/purpsuit, - /obj/item/clothing/under/rank/mailman, - /obj/item/clothing/under/dress/dress_saloon, - /obj/item/clothing/suit/suspenders, - /obj/item/clothing/suit/storage/labcoat/mad, - /obj/item/clothing/suit/bio_suit/plaguedoctorsuit, - /obj/item/clothing/under/schoolgirl, - /obj/item/clothing/under/owl, - /obj/item/clothing/under/waiter, - /obj/item/clothing/under/gladiator, - /obj/item/clothing/under/soviet, - /obj/item/clothing/under/scratch, - /obj/item/clothing/under/wedding/bride_white, - /obj/item/clothing/suit/chef, - /obj/item/clothing/suit/apron/overalls, - /obj/item/clothing/under/redcoat, - /obj/item/clothing/under/kilt) - name = "Costumes crate" - cost = 1000 - crate_type = /obj/structure/closet/crate/secure - crate_name = "Actor Costumes" - access = access_theatre - group = "Miscellaneous" +//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 hacked. +//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("Operations","Security","Hospitality","Engineering","Medical / Science","Hydroponics","Mining","Supply","Miscellaneous") + +datum/supply_pack + var/name = "Crate" + var/group = "Operations" + var/true_manifest = "" + var/hidden = FALSE + var/contraband = FALSE + var/cost = 700 // Minimum cost, or infinite points are possible. + var/access = FALSE + var/list/contains = null + var/crate_name = "crate" + var/crate_type = /obj/structure/closet/crate + var/dangerous = FALSE // Should we message admins? + var/special = FALSE //Event/Station Goals/Admin enabled packs + var/special_enabled = FALSE + var/amount = 0 + +datum/supply_pack/New() + true_manifest += "
                      " + for(var/path in contains) + if(!path) + continue + var/atom/movable/AM = path + true_manifest += "
                    • [initial(AM.name)]
                    • " + true_manifest += "
                    " + +/datum/supply_pack/proc/generate(turf/T) + var/obj/structure/closet/crate/C = new crate_type(T) + C.name = crate_name + if(access) + C.req_access = list(access) + + fill(C) + + return C + +/datum/supply_pack/proc/fill(obj/structure/closet/crate/C) + for(var/item in contains) + var/n_item = new item(C) + if(amount && (istype(n_item, /obj/item/stack/sheet) || istype(n_item, /obj/item/stack/tile))) + var/obj/item/stack/sheet/n_sheet = n_item + n_sheet.set_amount(amount) + +//---------------------------------------------- +//-----------------OPERATIONS------------------- +//---------------------------------------------- + +/datum/supply_pack/mule + name = "MULEbot Crate" + contains = list(/obj/machinery/bot/mulebot) + cost = 2000 + crate_type = /obj/structure/largecrate/mule + crate_name = "MULEbot Crate" + group = "Operations" + +/datum/supply_pack/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/weapon/packageWrap, + /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/weapon/wrapping_paper, + /obj/item/weapon/wrapping_paper, + /obj/item/weapon/wrapping_paper) + cost = 1000 + crate_name = "Arts and Crafts crate" + group = "Operations" + +/datum/supply_pack/price_scanner + name = "Export scanners" + contains = list(/obj/item/device/export_scanner, + /obj/item/device/export_scanner) + cost = 1000 + crate_name = "Export scanners crate" + group = "Operations" + +//---------------------------------------------- +//-----------------SECURITY--------------------- +//---------------------------------------------- + +/datum/supply_pack/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) + cost = 1750 + crate_name = "Special Ops crate" + group = "Security" + hidden = TRUE + +/datum/supply_pack/weapons + name = "Weapons crate" + contains = list(/obj/item/weapon/melee/baton, + /obj/item/weapon/melee/baton, + /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) + cost = 3000 + crate_type = /obj/structure/closet/crate/secure/weapon + crate_name = "Weapons crate" + access = access_brig + group = "Security" + +/datum/supply_pack/eweapons + name = "Experimental weapons crate" + contains = list(/obj/item/weapon/flamethrower/full, + /obj/item/weapon/tank/phoron, + /obj/item/weapon/tank/phoron, + /obj/item/weapon/tank/phoron) + cost = 1750 + crate_type = /obj/structure/closet/crate/secure/weapon + crate_name = "Experimental weapons crate" + access = access_heads + group = "Security" + +/datum/supply_pack/armor + name = "Armor crate" + contains = list(/obj/item/clothing/head/helmet, + /obj/item/clothing/head/helmet, + /obj/item/clothing/suit/storage/flak, + /obj/item/clothing/suit/storage/flak) + cost = 1500 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Armor crate" + access = access_brig + group = "Security" + +/datum/supply_pack/riot + name = "Riot gear crate" + contains = list(/obj/item/weapon/melee/baton, + /obj/item/weapon/melee/baton, + /obj/item/weapon/melee/baton, + /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) + cost = 6000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Riot gear crate" + access = access_armory + group = "Security" + +/datum/supply_pack/mind_shields + name = "Mind shields implant crate" + contains = list (/obj/item/weapon/storage/lockbox/mind_shields) + cost = 5000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Mind shields implant crate" + access = access_armory + group = "Security" + +/datum/supply_pack/loyalty + name = "Loyalty implant crate" + contains = list (/obj/item/weapon/storage/lockbox/loyalty) + cost = 8000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Loyalty implant crate" + access = access_armory + group = "Security" + +/datum/supply_pack/ballistic + name = "Ballistic gear crate" + contains = list(/obj/item/clothing/suit/storage/flak/bulletproof, + /obj/item/clothing/suit/storage/flak/bulletproof, + /obj/item/clothing/head/helmet/bulletproof, + /obj/item/clothing/head/helmet/bulletproof, + /obj/item/weapon/gun/projectile/shotgun/combat, + /obj/item/weapon/gun/projectile/shotgun/combat) + cost = 5000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Ballistic gear crate" + access = access_armory + group = "Security" + +/datum/supply_pack/erifle + name = "Energy marksman crate" + contains = list(/obj/item/clothing/suit/armor/laserproof, + /obj/item/clothing/suit/armor/laserproof, + /obj/item/clothing/head/helmet/laserproof, + /obj/item/clothing/head/helmet/laserproof, + /obj/item/weapon/gun/energy/sniperrifle, + /obj/item/weapon/gun/energy/sniperrifle) + cost = 5000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Energy marksman crate" + access = access_armory + group = "Security" + +/datum/supply_pack/shotgunammo_beanbag + name = "Shotgun shells (Beanbag)" + contains = list(/obj/item/weapon/storage/box/shotgun/beanbag) + cost = 1000 + crate_name = "Shotgun shells (Beanbag)" + group = "Security" + +/datum/supply_pack/shotgunammo_slug + name = "Shotgun shells (slug)" + contains = list(/obj/item/weapon/storage/box/shotgun/slug) + cost = 2000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Shotgun shells (slug)" + access = access_armory + group = "Security" + +/datum/supply_pack/shotgunammo_buckshot + name = "Shotgun shells (buckshot)" + contains = list(/obj/item/weapon/storage/box/shotgun/buckshot) + cost = 2500 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Shotgun shells (buckshot)" + access = access_armory + group = "Security" + +/datum/supply_pack/r4046 + name = "40x46mm rubber grenades" + contains = list(/obj/item/weapon/storage/box/r4046, + /obj/item/weapon/storage/box/r4046) + cost = 2000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "40x46mm rubber grenades" + access = access_armory + group = "Security" + +/datum/supply_pack/m79 + name = "m79 grenade launcher" + contains = list(/obj/item/weapon/gun/projectile/m79, + /obj/item/weapon/storage/box/r4046) + cost = 3000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "m79 grenade launcher" + access = access_armory + group = "Security" + + +/datum/supply_pack/expenergy + name = "Experimental energy gear crate" + contains = list(/obj/item/clothing/suit/armor/laserproof, + /obj/item/clothing/suit/armor/laserproof, + /obj/item/clothing/head/helmet/laserproof, + /obj/item/clothing/head/helmet/laserproof, + /obj/item/weapon/gun/energy/gun, + /obj/item/weapon/gun/energy/gun) + cost = 5000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Experimental energy gear crate" + access = access_armory + group = "Security" + +/datum/supply_pack/exparmor + name = "Experimental armor crate" + contains = list(/obj/item/clothing/suit/armor/laserproof, + /obj/item/clothing/head/helmet/laserproof, + /obj/item/clothing/suit/storage/flak/bulletproof, + /obj/item/clothing/head/helmet/bulletproof, + /obj/item/clothing/head/helmet/riot, + /obj/item/clothing/suit/armor/riot) + cost = 3500 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Experimental armor crate" + access = access_armory + group = "Security" + +/datum/supply_pack/securitybarriers + name = "Security barrier crate" + contains = list(/obj/machinery/deployable/barrier, + /obj/machinery/deployable/barrier, + /obj/machinery/deployable/barrier, + /obj/machinery/deployable/barrier) + cost = 2000 + crate_type = /obj/structure/closet/crate/secure/gear + crate_name = "Security barrier crate" + group = "Security" + +/datum/supply_pack/securitywallshield + name = "Wall shield Generators" + contains = list(/obj/machinery/shieldwallgen, + /obj/machinery/shieldwallgen, + /obj/machinery/shieldwallgen, + /obj/machinery/shieldwallgen) + cost = 2000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "wall shield generators crate" + access = access_teleporter + group = "Security" + +//---------------------------------------------- +//-----------------HOSPITALITY------------------ +//---------------------------------------------- + +/datum/supply_pack/vending_bar + name = "Bartending supply crate" + contains = list(/obj/item/weapon/vending_refill/boozeomat) + cost = 1500 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "bartending supply crate" + group = "Hospitality" + +/datum/supply_pack/vending_coffee + name = "Hotdrinks supply crate" + contains = list(/obj/item/weapon/vending_refill/coffee, + /obj/item/weapon/vending_refill/coffee, + /obj/item/weapon/vending_refill/coffee) + cost = 1500 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "hotdrinks supply crate" + group = "Hospitality" + +/datum/supply_pack/vending_snack + name = "Snack supply crate" + contains = list(/obj/item/weapon/vending_refill/snack, + /obj/item/weapon/vending_refill/snack, + /obj/item/weapon/vending_refill/snack) + cost = 1500 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "snack supply crate" + group = "Hospitality" + +/datum/supply_pack/vending_cola + name = "Softdrinks supply crate" + contains = list(/obj/item/weapon/vending_refill/cola, + /obj/item/weapon/vending_refill/cola, + /obj/item/weapon/vending_refill/cola) + cost = 1500 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "softdrinks supply crate" + group = "Hospitality" + +/datum/supply_pack/vending_cigarette + name = "Cigarette supply crate" + contains = list(/obj/item/weapon/vending_refill/cigarette, + /obj/item/weapon/vending_refill/cigarette, + /obj/item/weapon/vending_refill/cigarette) + cost = 1500 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "cigarette supply crate" + group = "Hospitality" + +/datum/supply_pack/vending_barber + name = "Barbershop supply crate" + contains = list(/obj/item/weapon/vending_refill/barbervend, + /obj/item/weapon/vending_refill/barbervend, + /obj/item/weapon/vending_refill/barbervend) + cost = 1500 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "barbershop supply crate" + group = "Hospitality" + +/datum/supply_pack/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/flask/barflask, + /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/bottle/ale, + /obj/item/weapon/reagent_containers/food/drinks/bottle/ale, + /obj/item/weapon/reagent_containers/food/drinks/bottle/beer, + /obj/item/weapon/reagent_containers/food/drinks/bottle/beer, + /obj/item/weapon/reagent_containers/food/drinks/bottle/beer, + /obj/item/weapon/reagent_containers/food/drinks/bottle/beer) + cost = 2000 + crate_type = /obj/structure/closet/crate + crate_name = "Party equipment" + group = "Hospitality" + +//---------------------------------------------- +//-----------------ENGINEERING------------------ +//---------------------------------------------- + +/datum/supply_pack/internals + name = "Internals crate" + contains = list(/obj/item/clothing/mask/gas/coloured, + /obj/item/clothing/mask/gas/coloured, + /obj/item/clothing/mask/gas/coloured, + /obj/item/weapon/tank/air, + /obj/item/weapon/tank/air, + /obj/item/weapon/tank/air) + cost = 1000 + crate_type = /obj/structure/closet/crate/internals + crate_name = "Internals crate" + group = "Engineering" + +/datum/supply_pack/sleeping_agent + name = "Canister: \[N2O\]" + contains = list(/obj/machinery/portable_atmospherics/canister/sleeping_agent) + cost = 4000 + crate_type = /obj/structure/largecrate + crate_name = "N2O crate" + group = "Engineering" + +/datum/supply_pack/oxygen + name = "Canister: \[O2\]" + contains = list(/obj/machinery/portable_atmospherics/canister/oxygen) + cost = 3000 + crate_type = /obj/structure/largecrate + crate_name = "O2 crate" + group = "Engineering" + +/datum/supply_pack/nitrogen + name = "Canister: \[N2\]" + contains = list(/obj/machinery/portable_atmospherics/canister/nitrogen) + cost = 2000 + crate_type = /obj/structure/largecrate + crate_name = "N2 crate" + group = "Engineering" + +/datum/supply_pack/air + name = "Canister \[Air\]" + contains = list(/obj/machinery/portable_atmospherics/canister/air) + cost = 2000 + crate_type = /obj/structure/largecrate + crate_name = "Air crate" + group = "Engineering" + +/datum/supply_pack/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/coloured, + /obj/item/clothing/mask/gas/coloured, + /obj/item/clothing/mask/gas/coloured, + /obj/item/clothing/mask/gas/coloured, + /obj/item/clothing/mask/gas/coloured) + cost = 3500 + crate_type = /obj/structure/closet/crate/internals + crate_name = "Emergency crate" + group = "Engineering" + +/datum/supply_pack/inflatable + name = "Inflatable barriers" + contains = list(/obj/item/weapon/storage/briefcase/inflatable, + /obj/item/weapon/storage/briefcase/inflatable, + /obj/item/weapon/storage/briefcase/inflatable) + cost = 2000 + crate_type = /obj/structure/closet/crate/engi + crate_name = "Inflatable Barrier Crate" + group = "Engineering" + +/datum/supply_pack/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 = 1000 + crate_type = /obj/structure/closet/crate + crate_name = "Replacement lights" + group = "Engineering" + +/datum/supply_pack/metal50 + name = "50 metal sheets" + contains = list(/obj/item/stack/sheet/metal) + amount = 50 + cost = 1000 + crate_type = /obj/structure/closet/crate/engi + crate_name = "Metal sheets crate" + group = "Engineering" + +/datum/supply_pack/glass50 + name = "50 glass sheets" + contains = list(/obj/item/stack/sheet/glass) + amount = 50 + cost = 1000 + crate_type = /obj/structure/closet/crate/engi + crate_name = "Glass sheets crate" + group = "Engineering" + +/datum/supply_pack/wood50 + name = "50 wooden planks" + contains = list(/obj/item/stack/sheet/wood) + amount = 50 + cost = 1000 + crate_type = /obj/structure/closet/crate/engi + crate_name = "Wooden planks crate" + group = "Engineering" + +/datum/supply_pack/carpets + name = "Random carpets" + contains = list(/obj/item/stack/tile/carpet, /obj/item/stack/tile/carpet/black, /obj/item/stack/tile/carpet/purple, /obj/item/stack/tile/carpet/orange, /obj/item/stack/tile/carpet/green, + /obj/item/stack/tile/carpet/blue, /obj/item/stack/tile/carpet/blue2, /obj/item/stack/tile/carpet/red, /obj/item/stack/tile/carpet/cyan + ) + amount = 50 + cost = 2500 + crate_type = /obj/structure/closet/crate + crate_name = "Carpet crate" + group = "Engineering" + var/num_contained = 4 // 4 random carpets per crate + +/datum/supply_pack/carpets/fill(obj/structure/closet/crate/C) + var/list/L = contains.Copy() + var/item + if(num_contained <= L.len) + for(var/i in 1 to num_contained) + item = pick_n_take(L) + var/n_item = new item(C) + if(istype(n_item, /obj/item/stack/tile)) + var/obj/item/stack/sheet/n_sheet = n_item + n_sheet.set_amount(amount) + else + for(var/i in 1 to num_contained) + item = pick(L) + var/n_item = new item(C) + if(istype(n_item, /obj/item/stack/tile)) + var/obj/item/stack/sheet/n_sheet = n_item + n_sheet.set_amount(amount) + +/datum/supply_pack/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/stock_parts/cell, + /obj/item/weapon/stock_parts/cell, + /obj/item/weapon/stock_parts/cell/high, + /obj/item/weapon/stock_parts/cell/high) + cost = 1500 + crate_type = /obj/structure/closet/crate/engi + crate_name = "Electrical maintenance crate" + group = "Engineering" + +/datum/supply_pack/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/yellow) + cost = 1000 + crate_type = /obj/structure/closet/crate/engi + crate_name = "Mechanical maintenance crate" + group = "Engineering" + +/datum/supply_pack/fueltank + name = "Fuel tank crate" + contains = list(/obj/structure/reagent_dispensers/fueltank) + cost = 800 + crate_type = /obj/structure/largecrate + crate_name = "fuel tank crate" + group = "Engineering" + +/datum/supply_pack/solar + name = "Solar Pack crate" + contains = list(/obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/solar_assembly, + /obj/item/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 = 2000 + crate_type = /obj/structure/closet/crate/engi + crate_name = "Solar pack crate" + group = "Engineering" + +/datum/supply_pack/engine + name = "Emitter crate" + contains = list(/obj/machinery/power/emitter, + /obj/machinery/power/emitter) + cost = 1000 + crate_type = /obj/structure/closet/crate/secure/engisec + crate_name = "Emitter crate" + access = access_ce + group = "Engineering" + +/datum/supply_pack/engine/field_gen + name = "Field Generator crate" + contains = list(/obj/machinery/field_generator, + /obj/machinery/field_generator) + crate_type = /obj/structure/closet/crate/engi + crate_name = "Field Generator crate" + +/datum/supply_pack/engine/sing_gen + name = "Singularity Generator crate" + contains = list(/obj/machinery/the_singularitygen) + crate_type = /obj/structure/closet/crate/engi + crate_name = "Singularity Generator crate" + +/datum/supply_pack/engine/collector + name = "Collector crate" + contains = list(/obj/machinery/power/rad_collector, + /obj/machinery/power/rad_collector, + /obj/machinery/power/rad_collector) + crate_type = /obj/structure/closet/crate/engi + crate_name = "Collector crate" + +/datum/supply_pack/engine/PA + name = "Particle Accelerator crate" + cost = 4000 + 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) + crate_type = /obj/structure/closet/crate/engi + crate_name = "Particle Accelerator crate" + +/datum/supply_pack/mecha_ripley + name = "Circuit Crate (\"Ripley\" APLU)" + contains = list(/obj/item/weapon/book/manual/wiki/guide_to_exosuits, + /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 = 3000 + crate_type = /obj/structure/closet/crate/secure/scisecurecrate + crate_name = "APLU \"Ripley\" Circuit Crate" + access = access_robotics + group = "Engineering" + +/datum/supply_pack/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 = 2500 + crate_type = /obj/structure/closet/crate/secure/scisecurecrate + crate_name = "\"Odysseus\" Circuit Crate" + access = access_robotics + group = "Engineering" + +/datum/supply_pack/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/stock_parts/cell/high, + /obj/item/weapon/stock_parts/cell/high) + cost = 1000 + crate_type = /obj/structure/closet/crate/secure/scisecurecrate + crate_name = "Robotics assembly" + access = access_robotics + group = "Engineering" + +/datum/supply_pack/shield_gen + contains = list(/obj/item/weapon/circuitboard/shield_gen) + name = "Bubble shield generator circuitry" + cost = 5000 + crate_type = /obj/structure/closet/crate/secure/engisec + crate_name = "bubble shield generator circuitry crate" + group = "Engineering" + access = access_ce + +/datum/supply_pack/shield_gen_ex + contains = list(/obj/item/weapon/circuitboard/shield_gen_ex) + name = "Hull shield generator circuitry" + cost = 5000 + crate_type = /obj/structure/closet/crate/secure/engisec + crate_name = "hull shield generator circuitry crate" + group = "Engineering" + access = access_ce + +/datum/supply_pack/shield_cap + contains = list(/obj/item/weapon/circuitboard/shield_cap) + name = "Bubble shield capacitor circuitry" + cost = 5000 + crate_type = /obj/structure/closet/crate/secure/engisec + crate_name = "shield capacitor circuitry crate" + group = "Engineering" + access = access_ce + +/datum/supply_pack/smbig + name = "Supermatter Core" + contains = list(/obj/machinery/power/supermatter) + cost = 5000 + crate_type = /obj/structure/closet/crate/secure/woodseccrate + crate_name = "Supermatter crate (CAUTION)" + group = "Engineering" + access = access_ce + +/*/datum/supply_pack/teg // teg currently were broken for a long time ago, so no point to have it in-game until fixed. + contains = list(/obj/machinery/power/generator) + name = "Mark I Thermoelectric Generator" + cost = 7500 + crate_type = /obj/structure/closet/crate/secure/large + crate_name = "Mk1 TEG crate" + group = "Engineering" + access = access_engine*/ + +/*/datum/supply_pack/circulator + contains = list(/obj/machinery/atmospherics/components/binary/circulator) + name = "Binary atmospheric circulator" + cost = 6000 + crate_type = /obj/structure/closet/crate/secure/large + crate_name = "Atmospheric circulator crate" + group = "Engineering" + access = access_engine*/ + +/datum/supply_pack/air_dispenser + contains = list(/obj/machinery/pipedispenser/orderable) + name = "Pipe Dispenser" + cost = 3500 + crate_type = /obj/structure/closet/crate/secure/large + crate_name = "Pipe Dispenser Crate" + group = "Engineering" + access = access_atmospherics + +/datum/supply_pack/disposals_dispenser + contains = list(/obj/machinery/pipedispenser/disposal/orderable) + name = "Disposals Pipe Dispenser" + cost = 3500 + crate_type = /obj/structure/closet/crate/secure/large + crate_name = "Disposal Dispenser Crate" + group = "Engineering" + access = access_atmospherics + +//---------------------------------------------- +//------------MEDICAL / SCIENCE----------------- +//---------------------------------------------- + +/datum/supply_pack/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/storage/firstaid/adv, + /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/box/autoinjectors, + /obj/item/weapon/storage/firstaid/small_firstaid_kit/civilian, + /obj/item/weapon/storage/firstaid/small_firstaid_kit/civilian, + /obj/item/weapon/storage/firstaid/small_firstaid_kit/space) + cost = 1000 + crate_type = /obj/structure/closet/crate/medical + crate_name = "Medical crate" + group = "Medical / Science" + +/datum/supply_pack/virus + name = "Virus sample crate" + contains = list(/obj/item/weapon/virusdish/random, + /obj/item/weapon/virusdish/random, + /obj/item/weapon/virusdish/random, + /obj/item/weapon/virusdish/random) + cost = 2500 + crate_type = /obj/structure/closet/crate/secure/medical + crate_name = "Virus sample crate" + access = access_cmo + group = "Medical / Science" + +/datum/supply_pack/coolanttank + name = "Coolant tank crate" + contains = list(/obj/structure/reagent_dispensers/coolanttank) + cost = 1600 + crate_type = /obj/structure/largecrate + crate_name = "Coolant tank crate" + group = "Medical / Science" + +/datum/supply_pack/phoron + name = "Phoron assembly crate" + contains = list(/obj/item/weapon/tank/phoron, + /obj/item/weapon/tank/phoron, + /obj/item/weapon/tank/phoron, + /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 = 1000 + crate_type = /obj/structure/closet/crate/secure/scisecurecrate + crate_name = "Phoron assembly crate" + access = access_tox_storage + group = "Medical / Science" + +/datum/supply_pack/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 = 2500 + crate_type = /obj/structure/closet/crate/secure/medical + crate_name = "Surgery crate" + access = access_medical + group = "Medical / Science" + +/datum/supply_pack/sterile + name = "Sterile equipment crate" + contains = list(/obj/item/clothing/under/rank/medical/green, + /obj/item/clothing/under/rank/medical/green, + /obj/item/clothing/head/surgery/green, + /obj/item/clothing/head/surgery/green, + /obj/item/weapon/storage/box/masks, + /obj/item/weapon/storage/box/gloves) + cost = 1500 + crate_type = /obj/structure/closet/crate + crate_name = "Sterile equipment crate" + group = "Medical / Science" + +/datum/supply_pack/bloodpacks + name = "Blood Pack Variety Crate" + cost = 3500 + contains = list(/obj/item/weapon/reagent_containers/blood/empty, + /obj/item/weapon/reagent_containers/blood/empty, + /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) + crate_type = /obj/structure/closet/crate/freezer + crate_name = "blood freezer" + group = "Medical / Science" + +/datum/supply_pack/iv_drip + name = "IV Drip Crate" + cost = 1000 + contains = list(/obj/machinery/iv_drip) + crate_type = /obj/structure/closet/crate/medical + crate_name = "iv drip crate" + group = "Medical / Science" + +/datum/supply_pack/body_bags + name = "Body Bags Crate" + cost = 1000 + contains = list(/obj/item/weapon/storage/box/bodybags, + /obj/item/weapon/storage/box/bodybags, + /obj/item/weapon/storage/box/bodybags) + crate_name = "body bags crate" + group = "Medical / Science" + +/datum/supply_pack/suspension_gen + name = "Suspension Field Generetor Crate" + cost = 3000 + contains = list(/obj/machinery/suspension_gen) + crate_type = /obj/structure/closet/crate/secure/scisecurecrate + crate_name = "Suspension Field Generetor Crate" + access = access_research + group = "Medical / Science" + +/datum/supply_pack/floodlight + name = "Emergency Floodlight Crate" + cost = 2000 + contains = list(/obj/machinery/floodlight, + /obj/machinery/floodlight) + crate_type = /obj/structure/closet/crate/scicrate + crate name = "Emergency Floodlight Crate" + group = "Medical / Science" + +//---------------------------------------------- +//-----------------HYDROPONICS------------------ +//---------------------------------------------- + +/datum/supply_pack/monkey + name = "Monkey crate" + contains = list (/obj/item/weapon/storage/box/monkeycubes) + cost = 2000 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "Monkey crate" + group = "Hydroponics" + +/datum/supply_pack/farwa + name = "Farwa crate" + contains = list (/obj/item/weapon/storage/box/monkeycubes/farwacubes) + cost = 3000 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "Farwa crate" + group = "Hydroponics" + +/datum/supply_pack/skrell + name = "Neaera crate" + contains = list (/obj/item/weapon/storage/box/monkeycubes/neaeracubes) + cost = 3000 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "Neaera crate" + group = "Hydroponics" + +/datum/supply_pack/stok + name = "Stok crate" + contains = list (/obj/item/weapon/storage/box/monkeycubes/stokcubes) + cost = 3000 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "Stok crate" + group = "Hydroponics" + +/datum/supply_pack/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/device/plant_analyzer, + /obj/item/clothing/gloves/botanic_leather, + /obj/item/clothing/suit/apron) // Updated with new things + cost = 1500 + crate_type = /obj/structure/closet/crate/hydroponics + crate_name = "Hydroponics crate" + access = access_hydroponics + group = "Hydroponics" + +//farm animals - useless and annoying, but potentially a good source of food +/datum/supply_pack/cow + name = "Cow crate" + cost = 3000 + crate_type = /obj/structure/closet/critter/cow + crate_name = "Cow crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_pack/goat + name = "Goat crate" + cost = 2500 + crate_type = /obj/structure/closet/critter/goat + crate_name = "Goat crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_pack/chicken + name = "Chicken crate" + cost = 2000 + crate_type = /obj/structure/closet/critter/chick + crate_name = "Chicken crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_pack/corgi + name = "Corgi crate" + cost = 5000 + crate_type = /obj/structure/closet/critter/corgi + crate_name = "Corgi crate" + group = "Hydroponics" + +/datum/supply_pack/shiba + name = "Shiba crate" + cost = 4000 + crate_type = /obj/structure/closet/critter/shiba + crate_name = "Shiba crate" + group = "Hydroponics" + +/datum/supply_pack/cat + name = "Cat crate" + cost = 4000 + crate_type = /obj/structure/closet/critter/cat + crate_name = "Cat crate" + group = "Hydroponics" + +/datum/supply_pack/pug + name = "Pug crate" + cost = 5000 + crate_type = /obj/structure/closet/critter/pug + crate_name = "Pug crate" + group = "Hydroponics" + +/datum/supply_pack/pig + name = "Pig crate" + cost = 3000 + crate_type = /obj/structure/closet/critter/pig + crate_name = "Pig crate" + group = "Hydroponics" + +/datum/supply_pack/turkey + name = "Turkey crate" + cost = 2000 + crate_type = /obj/structure/closet/critter/turkey + crate_name = "Turkey crate" + group = "Hydroponics" + +/datum/supply_pack/goose + name = "Goose crate" + cost = 2500 + crate_type = /obj/structure/closet/critter/goose + crate_name = "Goose crate" + group = "Hydroponics" + +/datum/supply_pack/seal + name = "Seal crate" + cost = 3000 + crate_type = /obj/structure/closet/critter/seal + crate_name = "Seal crate" + group = "Hydroponics" + +/datum/supply_pack/walrus + name = "Walrus crate" + cost = 3500 + crate_type = /obj/structure/closet/critter/walrus + crate_name = "Walrus crate" + group = "Hydroponics" + +/datum/supply_pack/seeds + name = "Seeds crate" + contains = list(/obj/item/seeds/chiliseed, + /obj/item/seeds/berryseed, + /obj/item/seeds/cornseed, + /obj/item/seeds/eggplantseed, + /obj/item/seeds/tomatoseed, + /obj/item/seeds/appleseed, + /obj/item/seeds/soyaseed, + /obj/item/seeds/wheatseed, + /obj/item/seeds/carrotseed, + /obj/item/seeds/harebell, + /obj/item/seeds/lemonseed, + /obj/item/seeds/orangeseed, + /obj/item/seeds/grassseed, + /obj/item/seeds/sunflowerseed, + /obj/item/seeds/chantermycelium, + /obj/item/seeds/potatoseed, + /obj/item/seeds/sugarcaneseed) + cost = 1000 + crate_type = /obj/structure/closet/crate/hydroponics + crate_name = "Seeds crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_pack/weedcontrol + name = "Weed control crate" + contains = list(/obj/item/weapon/scythe, + /obj/item/clothing/mask/gas/coloured, + /obj/item/weapon/grenade/chem_grenade/antiweed, + /obj/item/weapon/grenade/chem_grenade/antiweed) + cost = 2000 + crate_type = /obj/structure/closet/crate/secure/hydrosec + crate_name = "Weed control crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_pack/exoticseeds + name = "Exotic seeds crate" + contains = list(/obj/item/seeds/nettleseed, + /obj/item/seeds/replicapod, + /obj/item/seeds/replicapod, + /obj/item/seeds/replicapod, + /obj/item/seeds/plumpmycelium, + /obj/item/seeds/libertymycelium, + /obj/item/seeds/amanitamycelium, + /obj/item/seeds/reishimycelium, + /obj/item/seeds/bananaseed, + /obj/item/seeds/riceseed, + /obj/item/seeds/eggplantseed, + /obj/item/seeds/limeseed, + /obj/item/seeds/grapeseed, + /obj/item/seeds/eggyseed) + cost = 1500 + crate_type = /obj/structure/closet/crate/hydroponics + crate_name = "Exotic Seeds crate" + access = access_hydroponics + group = "Hydroponics" + +/datum/supply_pack/watertank + name = "Water tank crate" + contains = list(/obj/structure/reagent_dispensers/watertank) + cost = 800 + crate_type = /obj/structure/largecrate + crate_name = "Water tank crate" + group = "Hydroponics" + +/datum/supply_pack/bee_keeper + name = "Beekeeping crate" + contains = list(/obj/item/beezeez, + /obj/item/weapon/bee_net, + /obj/item/apiary, + /obj/item/queen_bee) + cost = 4000 + contraband = TRUE + crate_type = /obj/structure/closet/crate/hydroponics + crate_name = "Beekeeping crate" + access = access_hydroponics + group = "Hydroponics" + +//---------------------------------------------- +//--------------------MINING-------------------- +//---------------------------------------------- + +/datum/supply_pack/mining + name = "Mining Explosives Crate" + contains = list(/obj/item/weapon/mining_charge, + /obj/item/weapon/mining_charge, + /obj/item/weapon/mining_charge, + /obj/item/weapon/mining_charge, + /obj/item/weapon/mining_charge, + /obj/item/weapon/mining_charge, + /obj/item/weapon/mining_charge, + /obj/item/weapon/mining_charge, + /obj/item/weapon/mining_charge, + /obj/item/weapon/mining_charge,) + cost = 1500 + crate_type = /obj/structure/closet/crate/secure/gear + crate_name = "Mining Explosives Crate" + access = access_mining + group = "Mining" + +/datum/supply_pack/mining_drill + name = "Drill Crate" + contains = list(/obj/machinery/mining/drill) + cost = 3000 + crate_type = /obj/structure/closet/crate/secure/large + crate_name = "Drill Crate" + access = access_mining + group = "Mining" + +/datum/supply_pack/mining_brace + name = "Brace Crate" + contains = list(/obj/machinery/mining/brace) + cost = 1500 + crate_type = /obj/structure/closet/crate/secure/large + crate_name = "Brace Crate" + access = access_mining + group = "Mining" + +/datum/supply_pack/mining_supply + name = "Mining Supply Crate" + contains = list(/obj/item/weapon/mining_scanner/improved, + /obj/item/weapon/storage/firstaid/small_firstaid_kit/space, + /obj/item/weapon/storage/firstaid/small_firstaid_kit/space, + /obj/item/weapon/reagent_containers/spray/cleaner, + /obj/item/weapon/storage/box/autoinjector/stimpack, + /obj/item/device/flashlight/lantern, + /obj/item/weapon/pickaxe/drill/jackhammer) + cost = 3000 + crate_type = /obj/structure/closet/crate/secure/gear + crate_name = "Mining Supply Crate" + access = access_mining + group = "Mining" + +//---------------------------------------------- +//--------------------SUPPLY-------------------- +//---------------------------------------------- + +/datum/supply_pack/food + name = "Kitchen supply crate" + contains = list(/obj/item/weapon/reagent_containers/food/condiment/flour, + /obj/item/weapon/reagent_containers/food/condiment/flour, + /obj/item/weapon/reagent_containers/food/condiment/flour, + /obj/item/weapon/reagent_containers/food/condiment/flour, + /obj/item/weapon/reagent_containers/food/drinks/milk, + /obj/item/weapon/reagent_containers/food/drinks/milk, + /obj/item/weapon/storage/fancy/egg_box, + /obj/item/weapon/reagent_containers/food/snacks/tofu, + /obj/item/weapon/reagent_containers/food/snacks/tofu, + /obj/item/weapon/reagent_containers/food/snacks/meat, + /obj/item/weapon/reagent_containers/food/snacks/meat, + /obj/item/weapon/reagent_containers/food/snacks/grown/banana, + /obj/item/weapon/reagent_containers/food/snacks/grown/banana) + cost = 1000 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "Food crate" + group = "Supply" + +/datum/supply_pack/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 = 1000 + crate_name = "Toner cartridges" + group = "Supply" + +/datum/supply_pack/vest + name = "Vest Crate" + contains = list(/obj/item/clothing/accessory/storage/brown_vest, + /obj/item/clothing/accessory/storage/brown_vest, + /obj/item/clothing/accessory/storage/black_vest) + cost = 4000 + crate_name = "Vest Crate" + group = "Supply" + +/datum/supply_pack/misc/posters + name = "Corporate Posters Crate" + contains = list(/obj/item/weapon/poster/legit, + /obj/item/weapon/poster/legit, + /obj/item/weapon/poster/legit, + /obj/item/weapon/poster/legit, + /obj/item/weapon/poster/legit) + cost = 800 + crate_name = "Corporate Posters Crate" + group = "Supply" + +/datum/supply_pack/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/advanced, + /obj/item/weapon/holosign_creator, + /obj/item/weapon/caution, + /obj/item/weapon/caution, + /obj/item/weapon/caution, + /obj/item/weapon/reagent_containers/watertank_backpack/janitor, + /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 = 1000 + crate_name = "Janitorial supplies" + group = "Supply" + +/datum/supply_pack/boxes + name = "Empty boxes" + 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 = 1000 + crate_name = "Empty box crate" + group = "Supply" + +/datum/supply_pack/barber + name = "Barber supplies" + contains = list(/obj/item/weapon/storage/box/hairdyes, + /obj/item/weapon/reagent_containers/spray/hair_color_spray, + /obj/item/weapon/reagent_containers/glass/bottle/hair_growth_accelerator, + /obj/item/weapon/scissors, + /obj/item/weapon/razor) + cost = 1000 + crate_name = "Barber supplies" + group = "Supply" + +//---------------------------------------------- +//--------------MISCELLANEOUS------------------- +//---------------------------------------------- + +/datum/supply_pack/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 = 2000 + crate_name = "Wizard costume crate" + group = "Miscellaneous" + +/datum/supply_pack/conveyor + name = "Conveyor Assembly Crate" + contains = list(/obj/item/conveyor_construct, + /obj/item/conveyor_construct, + /obj/item/conveyor_construct, + /obj/item/conveyor_construct, + /obj/item/conveyor_construct, + /obj/item/conveyor_construct, + /obj/item/conveyor_switch_construct, + /obj/item/weapon/paper/conveyor) + cost = 1500 + crate_name = "conveyor assembly crate" + group = "Miscellaneous" + +/datum/supply_pack/formal_wear + contains = list(/obj/item/clothing/head/bowler, + /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/under/lawyer/bluesuit, + /obj/item/clothing/under/lawyer/purpsuit, + /obj/item/clothing/shoes/black, + /obj/item/clothing/shoes/black, + /obj/item/clothing/shoes/leather, + /obj/item/clothing/suit/wcoat, + /obj/item/clothing/under/suit_jacket/charcoal, + /obj/item/clothing/under/suit_jacket/navy, + /obj/item/clothing/under/suit_jacket/burgundy, + /obj/item/clothing/under/suit_jacket/checkered, + /obj/item/clothing/under/suit_jacket/tan) + name = "Formalwear closet" + cost = 3000 + crate_type = /obj/structure/closet + crate_name = "Formalwear for the best occasions." + group = "Miscellaneous" + +/datum/supply_pack/eftpos + contains = list(/obj/item/device/eftpos) + name = "EFTPOS scanner" + cost = 1000 + crate_name = "EFTPOS crate" + group = "Miscellaneous" + +//---------------------------------------------- +//-----------------RANDOMISED------------------- +//---------------------------------------------- + +/datum/supply_pack/randomised + name = "Collectable Hats Crate!" + cost = 20000 + var/num_contained = 4 //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) + crate_name = "Collectable hats crate! Brought to you by Bass.inc!" + group = "Miscellaneous" + +/datum/supply_pack/randomised/fill(obj/structure/closet/crate/C) + var/list/L = contains.Copy() + var/item + if(num_contained <= L.len) + for(var/i in 1 to num_contained) + item = pick_n_take(L) + new item(C) + else + for(var/i in 1 to num_contained) + item = pick(L) + new item(C) + +/datum/supply_pack/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/poster/contraband, + /obj/item/weapon/reagent_containers/food/drinks/bottle/pwine) + name = "Contraband crate" + cost = 3000 + crate_type = /obj/structure/closet/crate + crate_name = "Unlabeled crate" + contraband = TRUE + group = "Operations" + +/datum/supply_pack/randomised/toys + num_contained = 5 + contains = list(/obj/item/toy/spinningtoy, + /obj/item/toy/sword, + /obj/item/toy/owl, + /obj/item/toy/griffin, + /obj/item/toy/nuke, + /obj/item/toy/minimeteor, + /obj/item/toy/carpplushie, + /obj/item/toy/crossbow, + /obj/item/toy/katana) + name = "Toy Crate" + cost = 5000 // or play the arcade machines ya lazy bum + crate_name ="Toy crate" + group = "Miscellaneous" + +/datum/supply_pack/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 = 1500 + crate_type = /obj/structure/closet/crate/freezer + crate_name = "Pizza crate" + group = "Hospitality" + +/datum/supply_pack/randomised/costume + num_contained = 2 + contains = list(/obj/item/clothing/suit/pirate, + /obj/item/clothing/suit/judgerobe, + /obj/item/clothing/suit/wcoat, + /obj/item/clothing/suit/hastur, + /obj/item/clothing/suit/holidaypriest, + /obj/item/clothing/suit/nun, + /obj/item/clothing/suit/imperium_monk, + /obj/item/clothing/suit/ianshirt, + /obj/item/clothing/under/gimmick/rank/captain/suit, + /obj/item/clothing/under/gimmick/rank/head_of_personnel/suit, + /obj/item/clothing/under/lawyer/purpsuit, + /obj/item/clothing/under/rank/mailman, + /obj/item/clothing/under/dress/dress_saloon, + /obj/item/clothing/suit/suspenders, + /obj/item/clothing/suit/storage/labcoat/mad, + /obj/item/clothing/suit/bio_suit/plaguedoctorsuit, + /obj/item/clothing/under/schoolgirl, + /obj/item/clothing/under/owl, + /obj/item/clothing/under/waiter, + /obj/item/clothing/under/gladiator, + /obj/item/clothing/under/soviet, + /obj/item/clothing/under/scratch, + /obj/item/clothing/under/wedding/bride_white, + /obj/item/clothing/suit/chef, + /obj/item/clothing/suit/apron/overalls, + /obj/item/clothing/under/redcoat, + /obj/item/clothing/under/kilt) + name = "Costumes crate" + cost = 1000 + crate_type = /obj/structure/closet/crate/secure + crate_name = "Actor Costumes" + access = access_theatre + group = "Miscellaneous" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 75f1be76223d..ab5d599d5c28 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1,385 +1,385 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -var/list/preferences_datums = list() - -var/const/MAX_SAVE_SLOTS = 10 - -//used for alternate_option -#define GET_RANDOM_JOB 0 -#define BE_ASSISTANT 1 -#define RETURN_TO_LOBBY 2 - -#define MAX_GEAR_COST 5 -#define MAX_GEAR_COST_SUPPORTER MAX_GEAR_COST+3 -/datum/preferences - var/client/parent - //doohickeys for savefiles - var/path - var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used - var/savefile_version = 0 - - //non-preference stuff - var/permamuted = 0 - var/muted = 0 - var/last_ip - var/last_id - var/menu_type = "general" - var/submenu_type = "body" - var/list/ignore_question = list() //For roles which getting player_saves with question system - - //account data - var/list/cid_list = list() - var/ignore_cid_warning = 0 - - //game-preferences - var/UI_style = "White" - var/UI_style_color = "#ffffff" - var/UI_style_alpha = 255 - var/aooccolor = "#b82e00" - var/ooccolor = "#002eb8" - var/toggles = TOGGLES_DEFAULT - var/chat_toggles = TOGGLES_DEFAULT_CHAT - var/ghost_orbit = GHOST_ORBIT_CIRCLE - var/lastchangelog = "" //Saved changlog filesize to detect if there was a change - - //antag preferences - var/list/be_role = list() - var/uplinklocation = "PDA" - - //character preferences - var/real_name //our character's name - var/be_random_name = 0 //whether we are a random name 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/undershirt = 1 //undershirt type - var/socks = 1 //socks 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 tone - var/r_skin = 0 //Skin color - var/g_skin = 0 //Skin color - var/b_skin = 0 //Skin color - var/r_eyes = 0 //Eye color - var/g_eyes = 0 //Eye color - var/b_eyes = 0 //Eye color - var/species = HUMAN - var/language = "None" //Secondary language - - //Some faction information. - var/home_system = "None" //System of birth. - var/citizenship = "None" //Current home system. - var/faction = "None" //Antag faction/general associated faction. - var/religion = "None" //Religious association. - var/nanotrasen_relation = "Neutral" - - //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 - - // 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 = "" - - // Quirk list - var/list/positive_quirks = list() - var/list/negative_quirks = list() - var/list/neutral_quirks = list() - var/list/all_quirks = list() - var/list/character_quirks = list() - - // OOC Metadata: - var/metadata = "" - var/slot_name = "" - - // Whether or not to use randomized character slots - var/randomslot = 0 - // jukebox volume - var/volume = 100 - var/parallax = PARALLAX_HIGH - var/ambientocclusion = TRUE - var/parallax_theme = PARALLAX_THEME_CLASSIC - - //custom loadout - var/list/gear = list() - var/gear_tab = "General" - var/list/custom_items = list() - -/datum/preferences/New(client/C) - parent = C - b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") - if(istype(C)) - if(!IsGuestKey(C.key)) - load_path(C.ckey) - if(load_preferences()) - if(load_character()) - return - gender = pick(MALE, FEMALE) - real_name = random_name(gender) - -/datum/preferences/proc/ShowChoices(mob/user) - if(!user || !user.client) return - update_preview_icon() - - var/dat = "
                    " - dat += "" - dat += "" - dat += "" - dat += "" - - if(path) - dat += "" - else - dat += "Please create an account to save your preferences." - - dat += "

                    " - switch(menu_type) - if("general") - dat += ShowGeneral(user) - if("occupation") - dat += ShowOccupation(user) - if("roles") - dat += ShowRoles(user) - if("glob") - dat += ShowGlobal(user) - if("load_slot") - dat += ShowLoadSlot(user) - if("loadout") - dat += ShowCustomLoadout(user) - if("quirks") - dat += ShowQuirks(user) - if("fluff") - dat += ShowFluffMenu(user) - - dat += "" - - winshow(user, "preferences_window", TRUE) - user << browse(entity_ja(dat), "window=preferences_browser") - -/datum/preferences/proc/process_link(mob/user, list/href_list) - if(!user) - return - - if(href_list["preference"] == "close") - user << browse(null, "window=preferences_window") - var/client/C = user.client - if(C) - C.clear_character_previews() - return - - if(!isnewplayer(user)) - return - - switch(href_list["preference"]) - if("save") - save_preferences() - save_character() - - if("reload") - load_preferences() - load_character() - - if("changeslot") - load_character(text2num(href_list["num"])) - - if("general") - menu_type = "general" - - if("occupation") - menu_type = "occupation" - - if("roles") - menu_type = "roles" - - if("glob") - menu_type = "glob" - - if("loadout") - menu_type = "loadout" - - if("quirks") - menu_type = "quirks" - - if("fluff") - menu_type = "fluff" - - if("load_slot") - if(!IsGuestKey(user.key)) - menu_type = "load_slot" - switch(menu_type) - if("general") - process_link_general(user, href_list) - - if("occupation") - process_link_occupation(user, href_list) - - if("roles") - process_link_roles(user, href_list) - - if("glob") - process_link_glob(user, href_list) - - if("loadout") - process_link_loadout(user, href_list) - - if("quirks") - process_link_quirks(user, href_list) - - if("fluff") - process_link_fluff(user, href_list) - return 1 - - ShowChoices(user) - return 1 - -/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1) - if(be_random_name) - real_name = random_name(gender) - - if(config.humans_need_surnames) - 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.metadata = metadata - character.med_record = med_record - character.sec_record = sec_record - character.gen_record = gen_record - - character.gender = 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.r_skin = r_skin - character.g_skin = g_skin - character.b_skin = b_skin - - character.s_tone = s_tone - - character.h_style = h_style - character.f_style = f_style - - character.home_system = home_system - character.citizenship = citizenship - character.personal_faction = faction - character.religion = religion - - // Destroy/cyborgize bodyparts & organs - - for(var/name in organ_data) - var/obj/item/organ/external/BP = character.bodyparts_by_name[name] - var/obj/item/organ/internal/IO = character.organs_by_name[name] - var/status = organ_data[name] - - if(status == "amputated") - BP.amputated = 1 - BP.status |= ORGAN_DESTROYED - BP.destspawn = 1 - if(status == "cyborg") - BP.status |= ORGAN_ROBOT - if(status == "assisted") - IO.mechassist() - else if(status == "mechanical") - IO.mechanize() - - else continue - - // Wheelchair necessary? - var/obj/item/organ/external/l_leg = character.bodyparts_by_name[BP_L_LEG] - var/obj/item/organ/external/r_leg = character.bodyparts_by_name[BP_R_LEG] - if((!l_leg || l_leg.status & ORGAN_DESTROYED) && (!r_leg || r_leg.status & ORGAN_DESTROYED)) // TODO cane if its only single leg. - var/obj/structure/stool/bed/chair/wheelchair/W = new /obj/structure/stool/bed/chair/wheelchair (character.loc) - character.buckled = W - character.update_canmove() - W.dir = character.dir - W.buckled_mob = character - W.add_fingerprint(character) - - 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(undershirt > undershirt_t.len || undershirt < 1) - undershirt = 0 - character.undershirt = undershirt - - if(socks > socks_t.len || socks < 1) - socks = 0 - - character.socks = socks - - 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.gender = MALE - - if(icon_updates) - character.update_body() - character.update_hair() - +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 + +var/list/preferences_datums = list() + +var/const/MAX_SAVE_SLOTS = 10 + +//used for alternate_option +#define GET_RANDOM_JOB 0 +#define BE_ASSISTANT 1 +#define RETURN_TO_LOBBY 2 + +#define MAX_GEAR_COST 5 +#define MAX_GEAR_COST_SUPPORTER MAX_GEAR_COST+3 +/datum/preferences + var/client/parent + //doohickeys for savefiles + var/path + var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used + var/savefile_version = 0 + + //non-preference stuff + var/permamuted = 0 + var/muted = 0 + var/last_ip + var/last_id + var/menu_type = "general" + var/submenu_type = "body" + var/list/ignore_question = list() //For roles which getting player_saves with question system + + //account data + var/list/cid_list = list() + var/ignore_cid_warning = 0 + + //game-preferences + var/UI_style = "White" + var/UI_style_color = "#ffffff" + var/UI_style_alpha = 255 + var/aooccolor = "#b82e00" + var/ooccolor = "#002eb8" + var/toggles = TOGGLES_DEFAULT + var/chat_toggles = TOGGLES_DEFAULT_CHAT + var/ghost_orbit = GHOST_ORBIT_CIRCLE + var/lastchangelog = "" //Saved changlog filesize to detect if there was a change + + //antag preferences + var/list/be_role = list() + var/uplinklocation = "PDA" + + //character preferences + var/real_name //our character's name + var/be_random_name = 0 //whether we are a random name 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/undershirt = 1 //undershirt type + var/socks = 1 //socks 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 tone + var/r_skin = 0 //Skin color + var/g_skin = 0 //Skin color + var/b_skin = 0 //Skin color + var/r_eyes = 0 //Eye color + var/g_eyes = 0 //Eye color + var/b_eyes = 0 //Eye color + var/species = HUMAN + var/language = "None" //Secondary language + + //Some faction information. + var/home_system = "None" //System of birth. + var/citizenship = "None" //Current home system. + var/faction = "None" //Antag faction/general associated faction. + var/religion = "None" //Religious association. + var/nanotrasen_relation = "Neutral" + + //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 + + // 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 = "" + + // Quirk list + var/list/positive_quirks = list() + var/list/negative_quirks = list() + var/list/neutral_quirks = list() + var/list/all_quirks = list() + var/list/character_quirks = list() + + // OOC Metadata: + var/metadata = "" + var/slot_name = "" + + // Whether or not to use randomized character slots + var/randomslot = 0 + // jukebox volume + var/volume = 100 + var/parallax = PARALLAX_HIGH + var/ambientocclusion = TRUE + var/parallax_theme = PARALLAX_THEME_CLASSIC + + //custom loadout + var/list/gear = list() + var/gear_tab = "General" + var/list/custom_items = list() + +/datum/preferences/New(client/C) + parent = C + b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") + if(istype(C)) + if(!IsGuestKey(C.key)) + load_path(C.ckey) + if(load_preferences()) + if(load_character()) + return + gender = pick(MALE, FEMALE) + real_name = random_name(gender) + +/datum/preferences/proc/ShowChoices(mob/user) + if(!user || !user.client) return + update_preview_icon() + + var/dat = "
                    " + dat += "" + dat += "" + dat += "" + dat += "" + + if(path) + dat += "" + else + dat += "Please create an account to save your preferences." + + dat += "

                    " + switch(menu_type) + if("general") + dat += ShowGeneral(user) + if("occupation") + dat += ShowOccupation(user) + if("roles") + dat += ShowRoles(user) + if("glob") + dat += ShowGlobal(user) + if("load_slot") + dat += ShowLoadSlot(user) + if("loadout") + dat += ShowCustomLoadout(user) + if("quirks") + dat += ShowQuirks(user) + if("fluff") + dat += ShowFluffMenu(user) + + dat += "" + + winshow(user, "preferences_window", TRUE) + user << browse(entity_ja(dat), "window=preferences_browser") + +/datum/preferences/proc/process_link(mob/user, list/href_list) + if(!user) + return + + if(href_list["preference"] == "close") + user << browse(null, "window=preferences_window") + var/client/C = user.client + if(C) + C.clear_character_previews() + return + + if(!isnewplayer(user)) + return + + switch(href_list["preference"]) + if("save") + save_preferences() + save_character() + + if("reload") + load_preferences() + load_character() + + if("changeslot") + load_character(text2num(href_list["num"])) + + if("general") + menu_type = "general" + + if("occupation") + menu_type = "occupation" + + if("roles") + menu_type = "roles" + + if("glob") + menu_type = "glob" + + if("loadout") + menu_type = "loadout" + + if("quirks") + menu_type = "quirks" + + if("fluff") + menu_type = "fluff" + + if("load_slot") + if(!IsGuestKey(user.key)) + menu_type = "load_slot" + switch(menu_type) + if("general") + process_link_general(user, href_list) + + if("occupation") + process_link_occupation(user, href_list) + + if("roles") + process_link_roles(user, href_list) + + if("glob") + process_link_glob(user, href_list) + + if("loadout") + process_link_loadout(user, href_list) + + if("quirks") + process_link_quirks(user, href_list) + + if("fluff") + process_link_fluff(user, href_list) + return 1 + + ShowChoices(user) + return 1 + +/datum/preferences/proc/copy_to(mob/living/carbon/human/character, icon_updates = 1) + if(be_random_name) + real_name = random_name(gender) + + if(config.humans_need_surnames) + 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.metadata = metadata + character.med_record = med_record + character.sec_record = sec_record + character.gen_record = gen_record + + character.gender = 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.r_skin = r_skin + character.g_skin = g_skin + character.b_skin = b_skin + + character.s_tone = s_tone + + character.h_style = h_style + character.f_style = f_style + + character.home_system = home_system + character.citizenship = citizenship + character.personal_faction = faction + character.religion = religion + + // Destroy/cyborgize bodyparts & organs + + for(var/name in organ_data) + var/obj/item/organ/external/BP = character.bodyparts_by_name[name] + var/obj/item/organ/internal/IO = character.organs_by_name[name] + var/status = organ_data[name] + + if(status == "amputated") + BP.amputated = 1 + BP.status |= ORGAN_DESTROYED + BP.destspawn = 1 + if(status == "cyborg") + BP.status |= ORGAN_ROBOT + if(status == "assisted") + IO.mechassist() + else if(status == "mechanical") + IO.mechanize() + + else continue + + // Wheelchair necessary? + var/obj/item/organ/external/l_leg = character.bodyparts_by_name[BP_L_LEG] + var/obj/item/organ/external/r_leg = character.bodyparts_by_name[BP_R_LEG] + if((!l_leg || l_leg.status & ORGAN_DESTROYED) && (!r_leg || r_leg.status & ORGAN_DESTROYED)) // TODO cane if its only single leg. + var/obj/structure/stool/bed/chair/wheelchair/W = new /obj/structure/stool/bed/chair/wheelchair (character.loc) + character.buckled = W + character.update_canmove() + W.dir = character.dir + W.buckled_mob = character + W.add_fingerprint(character) + + 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(undershirt > undershirt_t.len || undershirt < 1) + undershirt = 0 + character.undershirt = undershirt + + if(socks > socks_t.len || socks < 1) + socks = 0 + + character.socks = socks + + 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.gender = MALE + + if(icon_updates) + character.update_body() + character.update_hair() + diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index e920cbda8012..05e29fd33b00 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -1,448 +1,448 @@ -//This is the lowest supported version, anything below this is completely obsolete and the entire savefile will be wiped. -#define SAVEFILE_VERSION_MIN 8 - -//This is the current version, anything below this will attempt to update (if it's not obsolete) -#define SAVEFILE_VERSION_MAX 21 - -/* -SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn - This proc checks if the current directory of the savefile S needs updating - It is to be used by the load_character and load_preferences procs. - (S.cd=="/" is preferences, S.cd=="/character[integer]" is a character slot, etc) - if the current directory's version is below SAVEFILE_VERSION_MIN it will simply wipe everything in that directory - (if we're at root "/" then it'll just wipe the entire savefile, for instance.) - if its version is below SAVEFILE_VERSION_MAX but above the minimum, it will load data but later call the - respective update_preferences() or update_character() proc. - Those procs allow coders to specify format changes so users do not lose their setups and have to redo them again. - Failing all that, the standard sanity checks are performed. They simply check the data is suitable, reverting to - initial() values if necessary. -*/ - -#define SAVEFILE_UP_TO_DATE -1 // everything is okay, nothing to update. -#define SAVEFILE_TOO_OLD -2 // savefile is too old, all data will be wiped. - -/datum/preferences/proc/savefile_needs_update(savefile/S) - S["version"] >> savefile_version - - if(isnull(savefile_version)) // By the time this feature added, we don't have separate "version" value for characters, so let's set it. - savefile_version = 8 // Don't touch this magic number. - - if(savefile_version < SAVEFILE_VERSION_MIN) - S.dir.Cut() - return SAVEFILE_TOO_OLD - - if(savefile_version < SAVEFILE_VERSION_MAX) - return savefile_version - - return SAVEFILE_UP_TO_DATE - -/datum/preferences/proc/update_preferences(current_version, savefile/S) - /* JUST AN EXAMPLE for future updates. - if(current_version < 10) - toggles |= MEMBER_PUBLIC - */ - if(current_version < 15) - S["warns"] << null - S["warnbans"] << null - - if(current_version < 16) - S["aooccolor"] << S["ooccolor"] - aooccolor = ooccolor - -/datum/preferences/proc/update_character(current_version, savefile/S) - if(current_version < 17) - for(var/organ_name in organ_data) - if(organ_name in list("r_hand", "l_hand", "r_foot", "l_foot")) - organ_data -= organ_name - S["organ_data"] -= organ_name - if(current_version < 18) - ResetJobs() - - if(language && species && language != "None") - if(!istext(language)) - var/atom/A = language - language = A.name - - var/datum/language/lang = all_languages[language] - if(!(species in lang.allowed_species)) - language = "None" - S["language"] << language - - if(current_version < 21) - S["disabilities"] << null - - all_quirks = list() - positive_quirks = list() - negative_quirks = list() - neutral_quirks = list() - - S["all_quirks"] << all_quirks - S["positive_quirks"] << positive_quirks - S["negative_quirks"] << negative_quirks - S["neutral_quirks"] << neutral_quirks - - -/datum/preferences/proc/load_path(ckey, filename = "preferences.sav") - if(!ckey) - return - path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/[filename]" - -/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 = "/" - - var/needs_update = savefile_needs_update(S) - if(needs_update == SAVEFILE_TOO_OLD) // fatal, can't load any data - return 0 - - //Account data - S["cid_list"] >> cid_list - S["ignore_cid_warning"] >> ignore_cid_warning - - //General preferences - S["ooccolor"] >> ooccolor - S["aooccolor"] >> aooccolor - S["lastchangelog"] >> lastchangelog - S["UI_style"] >> UI_style - S["UI_style_color"] >> UI_style_color - S["UI_style_alpha"] >> UI_style_alpha - S["default_slot"] >> default_slot - S["chat_toggles"] >> chat_toggles - S["toggles"] >> toggles - S["ghost_orbit"] >> ghost_orbit - S["randomslot"] >> randomslot - S["permamuted"] >> permamuted - S["permamuted"] >> muted - S["parallax"] >> parallax - S["parallax_theme"] >> parallax_theme - S["ambientocclusion"] >> ambientocclusion - - //*** FOR FUTURE UPDATES, SO YOU KNOW WHAT TO DO ***// - //try to fix any outdated data if necessary - if(needs_update >= 0) - update_preferences(needs_update, S) // needs_update = savefile_version if we need an update (positive integer) - - //Sanitize - ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) - aooccolor = sanitize_hexcolor(aooccolor, initial(aooccolor)) - lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) - UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style)) - default_slot = sanitize_integer(default_slot, 1, MAX_SAVE_SLOTS, initial(default_slot)) - toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) - chat_toggles = sanitize_integer(chat_toggles, 0, 65535, initial(chat_toggles)) - ghost_orbit = sanitize_inlist(ghost_orbit, ghost_orbits, initial(ghost_orbit)) - randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot)) - 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)) - parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, PARALLAX_HIGH) - parallax_theme = sanitize_text(parallax_theme, initial(parallax_theme)) - ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion)) - if(!cid_list) - cid_list = list() - ignore_cid_warning = sanitize_integer(ignore_cid_warning, 0, 1, initial(ignore_cid_warning)) - 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_MAX - - //Account data - S["cid_list"] << cid_list - S["ignore_cid_warning"] << ignore_cid_warning - - //general preferences - S["ooccolor"] << ooccolor - S["aooccolor"] << aooccolor - S["lastchangelog"] << lastchangelog - S["UI_style"] << UI_style - S["UI_style_color"] << UI_style_color - S["UI_style_alpha"] << UI_style_alpha - S["default_slot"] << default_slot - S["toggles"] << toggles - S["chat_toggles"] << chat_toggles - S["ghost_orbit"] << ghost_orbit - S["randomslot"] << randomslot - S["permamuted"] << permamuted - S["parallax"] << parallax - S["parallax_theme"] << parallax_theme - S["ambientocclusion"] << ambientocclusion - return 1 - -/datum/preferences/proc/load_saved_character(dir) - var/savefile/S = new /savefile(path) - if(!S) - return 0 - S.cd = dir - - var/needs_update = savefile_needs_update(S) - if(needs_update == SAVEFILE_TOO_OLD) // fatal, can't load any data - return 0 - - //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["skin_red"] >> r_skin - S["skin_green"] >> g_skin - S["skin_blue"] >> b_skin - S["hair_style_name"] >> h_style - S["facial_style_name"] >> f_style - S["eyes_red"] >> r_eyes - S["eyes_green"] >> g_eyes - S["eyes_blue"] >> b_eyes - S["underwear"] >> underwear - S["undershirt"] >> undershirt - S["socks"] >> socks - 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 - - //Traits - S["all_quirks"] >> all_quirks - S["positive_quirks"] >> positive_quirks - S["negative_quirks"] >> negative_quirks - S["neutral_quirks"] >> neutral_quirks - - //Miscellaneous - S["flavor_text"] >> flavor_text - S["med_record"] >> med_record - S["sec_record"] >> sec_record - S["gen_record"] >> gen_record - S["be_role"] >> be_role - S["player_alt_titles"] >> player_alt_titles - S["organ_data"] >> organ_data - S["gear"] >> gear - S["custom_items"] >> custom_items - - S["nanotrasen_relation"] >> nanotrasen_relation - S["home_system"] >> home_system - S["citizenship"] >> citizenship - S["faction"] >> faction - S["religion"] >> religion - - S["uplinklocation"] >> uplinklocation - - - //*** FOR FUTURE UPDATES, SO YOU KNOW WHAT TO DO ***// - //try to fix any outdated data if necessary - if(needs_update >= 0) - update_character(needs_update, S) // needs_update == savefile_version if we need an update (positive integer) - - //Sanitize - metadata = sanitize_text(metadata, initial(metadata)) - real_name = sanitize_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) - if(!gear) gear = list() - if(!custom_items) custom_items = list() - 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)) - r_skin = sanitize_integer(r_skin, 0, 255, initial(r_skin)) - g_skin = sanitize_integer(g_skin, 0, 255, initial(g_skin)) - b_skin = sanitize_integer(b_skin, 0, 255, initial(b_skin)) - h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style)) - f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style)) - r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes)) - g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes)) - b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes)) - underwear = sanitize_integer(underwear, 1, underwear_m.len, initial(underwear)) - undershirt = sanitize_integer(undershirt, 1, undershirt_t.len, initial(undershirt)) - socks = sanitize_integer(socks, 1, socks_t.len, initial(socks)) - 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)) - - all_quirks = SANITIZE_LIST(all_quirks) - positive_quirks = SANITIZE_LIST(positive_quirks) - negative_quirks = SANITIZE_LIST(negative_quirks) - neutral_quirks = SANITIZE_LIST(neutral_quirks) - - if(!player_alt_titles) player_alt_titles = new() - if(!organ_data) src.organ_data = list() - if(!be_role) src.be_role = list() - - if(!home_system) home_system = "None" - if(!citizenship) citizenship = "None" - if(!faction) faction = "None" - if(!religion) religion = "None" - -/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 to MAX_SAVE_SLOTS) - 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_saved_character(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_saved_character(S.cd) - - 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]" - - S["version"] << SAVEFILE_VERSION_MAX // load_character will sanitize any bad data, so assume up-to-date. - - //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 - 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["skin_red"] << r_skin - S["skin_green"] << g_skin - S["skin_blue"] << b_skin - S["hair_style_name"] << h_style - S["facial_style_name"] << f_style - S["eyes_red"] << r_eyes - S["eyes_green"] << g_eyes - S["eyes_blue"] << b_eyes - S["underwear"] << underwear - S["undershirt"] << undershirt - S["socks"] << socks - 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 - - //Traits - S["all_quirks"] << all_quirks - S["positive_quirks"] << positive_quirks - S["negative_quirks"] << negative_quirks - S["neutral_quirks"] << neutral_quirks - - //Miscellaneous - S["flavor_text"] << flavor_text - S["med_record"] << med_record - S["sec_record"] << sec_record - S["gen_record"] << gen_record - S["be_role"] << be_role - S["player_alt_titles"] << player_alt_titles - S["organ_data"] << organ_data - S["gear"] << gear - S["custom_items"] << custom_items - - S["nanotrasen_relation"] << nanotrasen_relation - S["home_system"] << home_system - S["citizenship"] << citizenship - S["faction"] << faction - S["religion"] << religion - S["uplinklocation"] << uplinklocation - - return 1 - -#undef SAVEFILE_TOO_OLD -#undef SAVEFILE_UP_TO_DATE -#undef SAVEFILE_VERSION_MAX -#undef SAVEFILE_VERSION_MIN +//This is the lowest supported version, anything below this is completely obsolete and the entire savefile will be wiped. +#define SAVEFILE_VERSION_MIN 8 + +//This is the current version, anything below this will attempt to update (if it's not obsolete) +#define SAVEFILE_VERSION_MAX 21 + +/* +SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn + This proc checks if the current directory of the savefile S needs updating + It is to be used by the load_character and load_preferences procs. + (S.cd=="/" is preferences, S.cd=="/character[integer]" is a character slot, etc) + if the current directory's version is below SAVEFILE_VERSION_MIN it will simply wipe everything in that directory + (if we're at root "/" then it'll just wipe the entire savefile, for instance.) + if its version is below SAVEFILE_VERSION_MAX but above the minimum, it will load data but later call the + respective update_preferences() or update_character() proc. + Those procs allow coders to specify format changes so users do not lose their setups and have to redo them again. + Failing all that, the standard sanity checks are performed. They simply check the data is suitable, reverting to + initial() values if necessary. +*/ + +#define SAVEFILE_UP_TO_DATE -1 // everything is okay, nothing to update. +#define SAVEFILE_TOO_OLD -2 // savefile is too old, all data will be wiped. + +/datum/preferences/proc/savefile_needs_update(savefile/S) + S["version"] >> savefile_version + + if(isnull(savefile_version)) // By the time this feature added, we don't have separate "version" value for characters, so let's set it. + savefile_version = 8 // Don't touch this magic number. + + if(savefile_version < SAVEFILE_VERSION_MIN) + S.dir.Cut() + return SAVEFILE_TOO_OLD + + if(savefile_version < SAVEFILE_VERSION_MAX) + return savefile_version + + return SAVEFILE_UP_TO_DATE + +/datum/preferences/proc/update_preferences(current_version, savefile/S) + /* JUST AN EXAMPLE for future updates. + if(current_version < 10) + toggles |= MEMBER_PUBLIC + */ + if(current_version < 15) + S["warns"] << null + S["warnbans"] << null + + if(current_version < 16) + S["aooccolor"] << S["ooccolor"] + aooccolor = ooccolor + +/datum/preferences/proc/update_character(current_version, savefile/S) + if(current_version < 17) + for(var/organ_name in organ_data) + if(organ_name in list("r_hand", "l_hand", "r_foot", "l_foot")) + organ_data -= organ_name + S["organ_data"] -= organ_name + if(current_version < 18) + ResetJobs() + + if(language && species && language != "None") + if(!istext(language)) + var/atom/A = language + language = A.name + + var/datum/language/lang = all_languages[language] + if(!(species in lang.allowed_species)) + language = "None" + S["language"] << language + + if(current_version < 21) + S["disabilities"] << null + + all_quirks = list() + positive_quirks = list() + negative_quirks = list() + neutral_quirks = list() + + S["all_quirks"] << all_quirks + S["positive_quirks"] << positive_quirks + S["negative_quirks"] << negative_quirks + S["neutral_quirks"] << neutral_quirks + + +/datum/preferences/proc/load_path(ckey, filename = "preferences.sav") + if(!ckey) + return + path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/[filename]" + +/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 = "/" + + var/needs_update = savefile_needs_update(S) + if(needs_update == SAVEFILE_TOO_OLD) // fatal, can't load any data + return 0 + + //Account data + S["cid_list"] >> cid_list + S["ignore_cid_warning"] >> ignore_cid_warning + + //General preferences + S["ooccolor"] >> ooccolor + S["aooccolor"] >> aooccolor + S["lastchangelog"] >> lastchangelog + S["UI_style"] >> UI_style + S["UI_style_color"] >> UI_style_color + S["UI_style_alpha"] >> UI_style_alpha + S["default_slot"] >> default_slot + S["chat_toggles"] >> chat_toggles + S["toggles"] >> toggles + S["ghost_orbit"] >> ghost_orbit + S["randomslot"] >> randomslot + S["permamuted"] >> permamuted + S["permamuted"] >> muted + S["parallax"] >> parallax + S["parallax_theme"] >> parallax_theme + S["ambientocclusion"] >> ambientocclusion + + //*** FOR FUTURE UPDATES, SO YOU KNOW WHAT TO DO ***// + //try to fix any outdated data if necessary + if(needs_update >= 0) + update_preferences(needs_update, S) // needs_update = savefile_version if we need an update (positive integer) + + //Sanitize + ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor)) + aooccolor = sanitize_hexcolor(aooccolor, initial(aooccolor)) + lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) + UI_style = sanitize_inlist(UI_style, list("White", "Midnight","Orange","old"), initial(UI_style)) + default_slot = sanitize_integer(default_slot, 1, MAX_SAVE_SLOTS, initial(default_slot)) + toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) + chat_toggles = sanitize_integer(chat_toggles, 0, 65535, initial(chat_toggles)) + ghost_orbit = sanitize_inlist(ghost_orbit, ghost_orbits, initial(ghost_orbit)) + randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot)) + 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)) + parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, PARALLAX_HIGH) + parallax_theme = sanitize_text(parallax_theme, initial(parallax_theme)) + ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion)) + if(!cid_list) + cid_list = list() + ignore_cid_warning = sanitize_integer(ignore_cid_warning, 0, 1, initial(ignore_cid_warning)) + 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_MAX + + //Account data + S["cid_list"] << cid_list + S["ignore_cid_warning"] << ignore_cid_warning + + //general preferences + S["ooccolor"] << ooccolor + S["aooccolor"] << aooccolor + S["lastchangelog"] << lastchangelog + S["UI_style"] << UI_style + S["UI_style_color"] << UI_style_color + S["UI_style_alpha"] << UI_style_alpha + S["default_slot"] << default_slot + S["toggles"] << toggles + S["chat_toggles"] << chat_toggles + S["ghost_orbit"] << ghost_orbit + S["randomslot"] << randomslot + S["permamuted"] << permamuted + S["parallax"] << parallax + S["parallax_theme"] << parallax_theme + S["ambientocclusion"] << ambientocclusion + return 1 + +/datum/preferences/proc/load_saved_character(dir) + var/savefile/S = new /savefile(path) + if(!S) + return 0 + S.cd = dir + + var/needs_update = savefile_needs_update(S) + if(needs_update == SAVEFILE_TOO_OLD) // fatal, can't load any data + return 0 + + //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["skin_red"] >> r_skin + S["skin_green"] >> g_skin + S["skin_blue"] >> b_skin + S["hair_style_name"] >> h_style + S["facial_style_name"] >> f_style + S["eyes_red"] >> r_eyes + S["eyes_green"] >> g_eyes + S["eyes_blue"] >> b_eyes + S["underwear"] >> underwear + S["undershirt"] >> undershirt + S["socks"] >> socks + 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 + + //Traits + S["all_quirks"] >> all_quirks + S["positive_quirks"] >> positive_quirks + S["negative_quirks"] >> negative_quirks + S["neutral_quirks"] >> neutral_quirks + + //Miscellaneous + S["flavor_text"] >> flavor_text + S["med_record"] >> med_record + S["sec_record"] >> sec_record + S["gen_record"] >> gen_record + S["be_role"] >> be_role + S["player_alt_titles"] >> player_alt_titles + S["organ_data"] >> organ_data + S["gear"] >> gear + S["custom_items"] >> custom_items + + S["nanotrasen_relation"] >> nanotrasen_relation + S["home_system"] >> home_system + S["citizenship"] >> citizenship + S["faction"] >> faction + S["religion"] >> religion + + S["uplinklocation"] >> uplinklocation + + + //*** FOR FUTURE UPDATES, SO YOU KNOW WHAT TO DO ***// + //try to fix any outdated data if necessary + if(needs_update >= 0) + update_character(needs_update, S) // needs_update == savefile_version if we need an update (positive integer) + + //Sanitize + metadata = sanitize_text(metadata, initial(metadata)) + real_name = sanitize_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) + if(!gear) gear = list() + if(!custom_items) custom_items = list() + 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)) + r_skin = sanitize_integer(r_skin, 0, 255, initial(r_skin)) + g_skin = sanitize_integer(g_skin, 0, 255, initial(g_skin)) + b_skin = sanitize_integer(b_skin, 0, 255, initial(b_skin)) + h_style = sanitize_inlist(h_style, hair_styles_list, initial(h_style)) + f_style = sanitize_inlist(f_style, facial_hair_styles_list, initial(f_style)) + r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes)) + g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes)) + b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes)) + underwear = sanitize_integer(underwear, 1, underwear_m.len, initial(underwear)) + undershirt = sanitize_integer(undershirt, 1, undershirt_t.len, initial(undershirt)) + socks = sanitize_integer(socks, 1, socks_t.len, initial(socks)) + 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)) + + all_quirks = SANITIZE_LIST(all_quirks) + positive_quirks = SANITIZE_LIST(positive_quirks) + negative_quirks = SANITIZE_LIST(negative_quirks) + neutral_quirks = SANITIZE_LIST(neutral_quirks) + + if(!player_alt_titles) player_alt_titles = new() + if(!organ_data) src.organ_data = list() + if(!be_role) src.be_role = list() + + if(!home_system) home_system = "None" + if(!citizenship) citizenship = "None" + if(!faction) faction = "None" + if(!religion) religion = "None" + +/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 to MAX_SAVE_SLOTS) + 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_saved_character(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_saved_character(S.cd) + + 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]" + + S["version"] << SAVEFILE_VERSION_MAX // load_character will sanitize any bad data, so assume up-to-date. + + //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 + 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["skin_red"] << r_skin + S["skin_green"] << g_skin + S["skin_blue"] << b_skin + S["hair_style_name"] << h_style + S["facial_style_name"] << f_style + S["eyes_red"] << r_eyes + S["eyes_green"] << g_eyes + S["eyes_blue"] << b_eyes + S["underwear"] << underwear + S["undershirt"] << undershirt + S["socks"] << socks + 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 + + //Traits + S["all_quirks"] << all_quirks + S["positive_quirks"] << positive_quirks + S["negative_quirks"] << negative_quirks + S["neutral_quirks"] << neutral_quirks + + //Miscellaneous + S["flavor_text"] << flavor_text + S["med_record"] << med_record + S["sec_record"] << sec_record + S["gen_record"] << gen_record + S["be_role"] << be_role + S["player_alt_titles"] << player_alt_titles + S["organ_data"] << organ_data + S["gear"] << gear + S["custom_items"] << custom_items + + S["nanotrasen_relation"] << nanotrasen_relation + S["home_system"] << home_system + S["citizenship"] << citizenship + S["faction"] << faction + S["religion"] << religion + S["uplinklocation"] << uplinklocation + + return 1 + +#undef SAVEFILE_TOO_OLD +#undef SAVEFILE_UP_TO_DATE +#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 838821648a0e..390be4cf19ba 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -1,309 +1,309 @@ -//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.chat_toggles ^= CHAT_GHOSTEARS - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].") - prefs.save_preferences() - 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.chat_toggles ^= CHAT_GHOSTSIGHT - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].") - prefs.save_preferences() - 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_npc() - set name = "Show/Hide GhostNPCsSpeech" - set category = "Preferences" - set desc = ".Toggle Between seeing all non-player mobs speech, and only speech of nearby non-player mobs." - prefs.chat_toggles ^= CHAT_GHOSTNPC - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTNPC) ? "see all non-player mobs speech in the world" : "only see speech from nearby non-player mobs"].") - prefs.save_preferences() - feedback_add_details("admin_verb","TGN") - -/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.chat_toggles ^= CHAT_GHOSTRADIO - to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"].") - prefs.save_preferences() - feedback_add_details("admin_verb","TGR") - -/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.chat_toggles ^= CHAT_RADIO - prefs.save_preferences() - to_chat(usr, "You will [(prefs.chat_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() - 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.chat_toggles ^= CHAT_DEAD - prefs.save_preferences() - - if(src.holder) - to_chat(src, "You will [(prefs.chat_toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.") - else - to_chat(src, "As a ghost, you will [(prefs.chat_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.chat_toggles ^= CHAT_PRAYER - prefs.save_preferences() - to_chat(src, "You will [(prefs.chat_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() - if(prefs.toggles & SOUND_LOBBY) - to_chat(src, "You will now hear music in the game lobby.") - if(isnewplayer(mob)) - playtitlemusic() - else - to_chat(src, "You will no longer hear music in the game lobby.") - if(isnewplayer(mob)) - 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() - if(prefs.toggles & SOUND_MIDI) - to_chat(src, "You will now hear any sounds uploaded by admins.") - var/sound/break_sound = sound(null, repeat = 0, wait = 0, channel = CHANNEL_ADMIN) - - break_sound.priority = 250 - src << break_sound //breaks the client's sound output on channel CHANNEL_ADMIN - else - 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.chat_toggles ^= CHAT_OOC - prefs.save_preferences() - to_chat(src, "You will [(prefs.chat_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.chat_toggles ^= CHAT_LOOC - prefs.save_preferences() - - to_chat(src, "You will [(prefs.chat_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() - if(prefs.toggles & SOUND_AMBIENCE) - to_chat(src, "You will now hear ambient sounds.") - else - to_chat(src, "You will no longer hear ambient sounds.") - src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1) - 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/toggle_be_role(role in special_roles) - set name = "Toggle SpecialRole Candidacy" - set category = "Preferences" - set desc = "Toggles which special roles you would like to be a candidate for, during events." - var/role_type = role - if(!role_type) return - if(role_type in prefs.be_role) - prefs.be_role -= role_type - else - prefs.be_role += role_type - prefs.save_preferences() - to_chat(src, "You will [(role_type in prefs.be_role) ? "now" : "no longer"] be considered for [role] events (where possible).") - feedback_add_details("admin_verb","TBeSpecial") //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) - - 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 - - - - 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() - to_chat(usr, "UI was saved") - -/client/verb/toggle_anim_attacks() - set name = "Show/Hide Melee Animations" - set category = "Preferences" - set desc = "Toggles seeing melee attack animations." - prefs.toggles ^= SHOW_ANIMATIONS - prefs.save_preferences() - to_chat(src, "You will [(prefs.toggles & SHOW_ANIMATIONS) ? "now" : "no longer"] see melee attack animations.") - feedback_add_details("admin_verb","MAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggle_progress_bar() - set name = "Show/Hide Progress Bar" - set category = "Preferences" - set desc = "Toggles visibility of progress bars." - prefs.toggles ^= SHOW_PROGBAR - prefs.save_preferences() - to_chat(src, "You will [(prefs.toggles & SHOW_PROGBAR) ? "now" : "no longer"] see progress bars.") - feedback_add_details("admin_verb","PRB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/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() - to_chat(src, "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() - -var/global/list/ghost_orbits = list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOST_ORBIT_SQUARE,GHOST_ORBIT_HEXAGON,GHOST_ORBIT_PENTAGON) - -/client/verb/pick_ghost_orbit() - set name = "Choose Ghost Orbit" - set category = "Preferences" - set desc = "Choose your preferred ghostly orbit." - - var/new_orbit = input(src, "Choose your ghostly orbit:") as null|anything in ghost_orbits - if(new_orbit) - prefs.ghost_orbit = new_orbit - prefs.save_preferences() - if(istype(mob, /mob/dead/observer)) - var/mob/dead/observer/O = mob - O.ghost_orbit = new_orbit - -/client/verb/set_ckey_show() - set name = "Show/Hide Ckey" - set desc = "Toggle between showing your Ckey in LOOC and dead chat." - set category = "Preferences" - prefs.chat_toggles ^= CHAT_CKEY - prefs.save_preferences() - to_chat(src, "You will [(prefs.chat_toggles & CHAT_CKEY) ? "now" : "no longer"] show your ckey in LOOC and deadchat.") - feedback_add_details("admin_verb","SC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/verb/toggle_ambient_occlusion() - set name = "Toggle Ambient Occlusion" - set category = "Preferences" - set desc = "Toggle ambient occlusion." - - prefs.ambientocclusion = !prefs.ambientocclusion - to_chat(src, "Ambient Occlusion: [prefs.ambientocclusion ? "Enabled" : "Disabled"].") - prefs.save_preferences() - if(screen && screen.len) - var/obj/screen/plane_master/game_world/PM = locate() in screen - PM.backdrop(mob) - feedback_add_details("admin_verb","TAC") - -/client/verb/set_parallax_quality() - set name = "Set Parallax Quality" - set category = "Preferences" - set desc = "Set space parallax quality." - - var/new_setting = input(src, "Parallax quality:") as null|anything in list("Disable", "Low", "Medium", "High", "Insane") - if(!new_setting) - return - - switch(new_setting) - if("Disable") - prefs.parallax = PARALLAX_DISABLE - if("Low") - prefs.parallax = PARALLAX_LOW - if("Medium") - prefs.parallax = PARALLAX_MED - if("High") - prefs.parallax = PARALLAX_HIGH - if("Insane") - prefs.parallax = PARALLAX_INSANE - - to_chat(src, "Parallax (Fancy Space): [new_setting].") - prefs.save_preferences() - feedback_add_details("admin_verb","TPX") - - if (mob && mob.hud_used) - mob.hud_used.update_parallax_pref() - -/client/verb/set_parallax_theme() - set name = "Set Parallax Theme" - set category = "Preferences" - set desc = "Set space parallax theme." - - var/new_setting = input(src, "Parallax theme:") as null|anything in list(PARALLAX_THEME_CLASSIC, PARALLAX_THEME_TG) - if(!new_setting) - return - - prefs.parallax_theme = new_setting - to_chat(src, "Parallax theme: [new_setting].") - prefs.save_preferences() - feedback_add_details("admin_verb","SPX") - - if (mob && mob.hud_used) - mob.hud_used.update_parallax_pref() +//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.chat_toggles ^= CHAT_GHOSTEARS + to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].") + prefs.save_preferences() + 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.chat_toggles ^= CHAT_GHOSTSIGHT + to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].") + prefs.save_preferences() + 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_npc() + set name = "Show/Hide GhostNPCsSpeech" + set category = "Preferences" + set desc = ".Toggle Between seeing all non-player mobs speech, and only speech of nearby non-player mobs." + prefs.chat_toggles ^= CHAT_GHOSTNPC + to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTNPC) ? "see all non-player mobs speech in the world" : "only see speech from nearby non-player mobs"].") + prefs.save_preferences() + feedback_add_details("admin_verb","TGN") + +/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.chat_toggles ^= CHAT_GHOSTRADIO + to_chat(src, "As a ghost, you will now [(prefs.chat_toggles & CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"].") + prefs.save_preferences() + feedback_add_details("admin_verb","TGR") + +/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.chat_toggles ^= CHAT_RADIO + prefs.save_preferences() + to_chat(usr, "You will [(prefs.chat_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() + 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.chat_toggles ^= CHAT_DEAD + prefs.save_preferences() + + if(src.holder) + to_chat(src, "You will [(prefs.chat_toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.") + else + to_chat(src, "As a ghost, you will [(prefs.chat_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.chat_toggles ^= CHAT_PRAYER + prefs.save_preferences() + to_chat(src, "You will [(prefs.chat_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() + if(prefs.toggles & SOUND_LOBBY) + to_chat(src, "You will now hear music in the game lobby.") + if(isnewplayer(mob)) + playtitlemusic() + else + to_chat(src, "You will no longer hear music in the game lobby.") + if(isnewplayer(mob)) + 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() + if(prefs.toggles & SOUND_MIDI) + to_chat(src, "You will now hear any sounds uploaded by admins.") + var/sound/break_sound = sound(null, repeat = 0, wait = 0, channel = CHANNEL_ADMIN) + + break_sound.priority = 250 + src << break_sound //breaks the client's sound output on channel CHANNEL_ADMIN + else + 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.chat_toggles ^= CHAT_OOC + prefs.save_preferences() + to_chat(src, "You will [(prefs.chat_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.chat_toggles ^= CHAT_LOOC + prefs.save_preferences() + + to_chat(src, "You will [(prefs.chat_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() + if(prefs.toggles & SOUND_AMBIENCE) + to_chat(src, "You will now hear ambient sounds.") + else + to_chat(src, "You will no longer hear ambient sounds.") + src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1) + 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/toggle_be_role(role in special_roles) + set name = "Toggle SpecialRole Candidacy" + set category = "Preferences" + set desc = "Toggles which special roles you would like to be a candidate for, during events." + var/role_type = role + if(!role_type) return + if(role_type in prefs.be_role) + prefs.be_role -= role_type + else + prefs.be_role += role_type + prefs.save_preferences() + to_chat(src, "You will [(role_type in prefs.be_role) ? "now" : "no longer"] be considered for [role] events (where possible).") + feedback_add_details("admin_verb","TBeSpecial") //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) + + 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 + + + + 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() + to_chat(usr, "UI was saved") + +/client/verb/toggle_anim_attacks() + set name = "Show/Hide Melee Animations" + set category = "Preferences" + set desc = "Toggles seeing melee attack animations." + prefs.toggles ^= SHOW_ANIMATIONS + prefs.save_preferences() + to_chat(src, "You will [(prefs.toggles & SHOW_ANIMATIONS) ? "now" : "no longer"] see melee attack animations.") + feedback_add_details("admin_verb","MAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/verb/toggle_progress_bar() + set name = "Show/Hide Progress Bar" + set category = "Preferences" + set desc = "Toggles visibility of progress bars." + prefs.toggles ^= SHOW_PROGBAR + prefs.save_preferences() + to_chat(src, "You will [(prefs.toggles & SHOW_PROGBAR) ? "now" : "no longer"] see progress bars.") + feedback_add_details("admin_verb","PRB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/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() + to_chat(src, "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() + +var/global/list/ghost_orbits = list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOST_ORBIT_SQUARE,GHOST_ORBIT_HEXAGON,GHOST_ORBIT_PENTAGON) + +/client/verb/pick_ghost_orbit() + set name = "Choose Ghost Orbit" + set category = "Preferences" + set desc = "Choose your preferred ghostly orbit." + + var/new_orbit = input(src, "Choose your ghostly orbit:") as null|anything in ghost_orbits + if(new_orbit) + prefs.ghost_orbit = new_orbit + prefs.save_preferences() + if(istype(mob, /mob/dead/observer)) + var/mob/dead/observer/O = mob + O.ghost_orbit = new_orbit + +/client/verb/set_ckey_show() + set name = "Show/Hide Ckey" + set desc = "Toggle between showing your Ckey in LOOC and dead chat." + set category = "Preferences" + prefs.chat_toggles ^= CHAT_CKEY + prefs.save_preferences() + to_chat(src, "You will [(prefs.chat_toggles & CHAT_CKEY) ? "now" : "no longer"] show your ckey in LOOC and deadchat.") + feedback_add_details("admin_verb","SC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/verb/toggle_ambient_occlusion() + set name = "Toggle Ambient Occlusion" + set category = "Preferences" + set desc = "Toggle ambient occlusion." + + prefs.ambientocclusion = !prefs.ambientocclusion + to_chat(src, "Ambient Occlusion: [prefs.ambientocclusion ? "Enabled" : "Disabled"].") + prefs.save_preferences() + if(screen && screen.len) + var/obj/screen/plane_master/game_world/PM = locate() in screen + PM.backdrop(mob) + feedback_add_details("admin_verb","TAC") + +/client/verb/set_parallax_quality() + set name = "Set Parallax Quality" + set category = "Preferences" + set desc = "Set space parallax quality." + + var/new_setting = input(src, "Parallax quality:") as null|anything in list("Disable", "Low", "Medium", "High", "Insane") + if(!new_setting) + return + + switch(new_setting) + if("Disable") + prefs.parallax = PARALLAX_DISABLE + if("Low") + prefs.parallax = PARALLAX_LOW + if("Medium") + prefs.parallax = PARALLAX_MED + if("High") + prefs.parallax = PARALLAX_HIGH + if("Insane") + prefs.parallax = PARALLAX_INSANE + + to_chat(src, "Parallax (Fancy Space): [new_setting].") + prefs.save_preferences() + feedback_add_details("admin_verb","TPX") + + if (mob && mob.hud_used) + mob.hud_used.update_parallax_pref() + +/client/verb/set_parallax_theme() + set name = "Set Parallax Theme" + set category = "Preferences" + set desc = "Set space parallax theme." + + var/new_setting = input(src, "Parallax theme:") as null|anything in list(PARALLAX_THEME_CLASSIC, PARALLAX_THEME_TG) + if(!new_setting) + return + + prefs.parallax_theme = new_setting + to_chat(src, "Parallax theme: [new_setting].") + prefs.save_preferences() + feedback_add_details("admin_verb","SPX") + + if (mob && mob.hud_used) + mob.hud_used.update_parallax_pref() diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index b5c01d93e406..2db5a4160d26 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -1,593 +1,593 @@ - -/obj/item/clothing - name = "clothing" - var/list/species_restricted = null //Only these species can wear this kit. - var/equip_time = 0 - var/equipping = 0 - var/rig_restrict_helmet = 0 // Stops the user from equipping a rig helmet without attaching it to the suit first. - var/gang //Is this a gang outfit? - - /* - Sprites used when the clothing item is refit. This is done by setting icon_override. - For best results, if this is set then sprite_sheets should be null and vice versa, but that is by no means necessary. - Ideally, sprite_sheets_refit should be used for "hard" clothing items that can't change shape very well to fit the wearer (e.g. helmets, hardsuits), - while sprite_sheets should be used for "flexible" clothing items that do not need to be refitted (e.g. vox wearing jumpsuits). - */ - var/list/sprite_sheets_refit = null - lefthand_file = 'icons/mob/inhands/clothing_lefthand.dmi' - righthand_file = 'icons/mob/inhands/clothing_righthand.dmi' - -//BS12: Species-restricted clothing check. -/obj/item/clothing/mob_can_equip(M, slot) - - //if we can't equip the item anyway, don't bother with species_restricted (cuts down on spam) - if (!..()) - return 0 - - if(species_restricted && istype(M,/mob/living/carbon/human)) - - var/wearable = null - var/exclusive = null - var/mob/living/carbon/human/H = M - - if("exclude" in species_restricted) - exclusive = 1 - - if(H.species) - if(exclusive) - if(!(H.species.name in species_restricted)) - wearable = 1 - else - if(H.species.name in species_restricted) - wearable = 1 - - if(!wearable && (slot != 15 && slot != 16)) //Pockets. - to_chat(M, "\red Your species cannot wear [src].") - return 0 - - return 1 - -/obj/item/clothing/proc/refit_for_species(target_species) - //Set species_restricted list - switch(target_species) - if(HUMAN , SKRELL) //humanoid bodytypes - species_restricted = list("exclude" , UNATHI , TAJARAN , DIONA , VOX) - else - species_restricted = list(target_species) - - //Set icon - if (sprite_sheets_refit && (target_species in sprite_sheets_refit)) - icon_override = sprite_sheets_refit[target_species] - else - icon_override = initial(icon_override) - - //Set icon - if (sprite_sheets_obj && (target_species in sprite_sheets_obj)) - icon = sprite_sheets_obj[target_species] - else - icon = initial(icon) - -/obj/item/clothing/head/helmet/refit_for_species(target_species) - //Set species_restricted list - switch(target_species) - if(SKRELL) - species_restricted = list("exclude" , UNATHI , TAJARAN , DIONA , VOX) - if(HUMAN) - species_restricted = list("exclude" , SKRELL , UNATHI , TAJARAN , DIONA , VOX) - else - species_restricted = list(target_species) - - //Set icon - if (sprite_sheets_refit && (target_species in sprite_sheets_refit)) - icon_override = sprite_sheets_refit[target_species] - else - icon_override = initial(icon_override) - - //Set icon - if (sprite_sheets_obj && (target_species in sprite_sheets_obj)) - icon = sprite_sheets_obj[target_species] - else - icon = initial(icon) - -//Ears: headsets, earmuffs and tiny objects -/obj/item/clothing/ears - name = "ears" - w_class = 1.0 - throwforce = 2 - slot_flags = SLOT_EARS - -/obj/item/clothing/ears/attack_hand(mob/user) - if (!user) return - - if (src.loc != user || !istype(user,/mob/living/carbon/human)) - ..() - return - - var/mob/living/carbon/human/H = user - if(H.l_ear != src && H.r_ear != src) - ..() - return - - if(!canremove) - return - - var/obj/item/clothing/ears/O - if(slot_flags & SLOT_TWOEARS ) - O = (H.l_ear == src ? H.r_ear : H.l_ear) - user.u_equip(O) - if(!istype(src,/obj/item/clothing/ears/offear)) - qdel(O) - O = src - else - O = src - - user.u_equip(src) - - if (O) - user.put_in_hands(O) - O.add_fingerprint(user) - - if(istype(src,/obj/item/clothing/ears/offear)) - qdel(src) - -/obj/item/clothing/ears/offear - name = "Other ear" - w_class = 5.0 - icon = 'icons/mob/screen1_Midnight.dmi' - icon_state = "block" - slot_flags = SLOT_EARS | SLOT_TWOEARS - -/obj/item/clothing/ears/offear/atom_init() - . = ..() - var/obj/O = loc - name = O.name - desc = O.desc - icon = O.icon - icon_state = O.icon_state - dir = O.dir - -/obj/item/clothing/ears/earmuffs - name = "earmuffs" - desc = "Protects your hearing from loud noises, and quiet ones as well." - icon_state = "earmuffs" - item_state = "earmuffs" - slot_flags = SLOT_EARS | SLOT_TWOEARS - -//Glasses -/obj/item/clothing/glasses - name = "glasses" - icon = 'icons/obj/clothing/glasses.dmi' - w_class = 2.0 - flags = GLASSESCOVERSEYES - slot_flags = SLOT_EYES - var/vision_flags = 0 - var/darkness_view = 0//Base human is 2 - var/invisa_view = 0 - sprite_sheets = list(VOX = 'icons/mob/species/vox/eyes.dmi') -/* -SEE_SELF // can see self, no matter what -SEE_MOBS // can see all mobs, no matter what -SEE_OBJS // can see all objs, no matter what -SEE_TURFS // can see all turfs (and areas), no matter what -SEE_PIXELS// if an object is located on an unlit area, but some of its pixels are - // in a lit area (via pixel_x,y or smooth movement), can see those pixels -BLIND // can't see anything -*/ - - -//Gloves -/obj/item/clothing/gloves - name = "gloves" - gender = PLURAL //Carn: for grammarically correct text-parsing - w_class = 2.0 - icon = 'icons/obj/clothing/gloves.dmi' - siemens_coefficient = 0.9 - var/wired = FALSE - var/obj/item/weapon/stock_parts/cell/cell = 0 - var/clipped = FALSE - var/protect_fingers = TRUE // Are we gonna get hurt when searching in the trash piles - body_parts_covered = ARMS - slot_flags = SLOT_GLOVES - attack_verb = list("challenged") - species_restricted = list("exclude" , UNATHI , TAJARAN) - sprite_sheets = list(VOX = 'icons/mob/species/vox/gloves.dmi') - -/obj/item/clothing/gloves/emp_act(severity) - if(cell) - //why is this not part of the powercell code? - cell.charge -= 1000 / severity - if (cell.charge < 0) - cell.charge = 0 - if(cell.reliability != 100 && prob(50/severity)) - cell.reliability -= 10 / severity - ..() - -// Called just before an attack_hand(), in mob/UnarmedAttack() -/obj/item/clothing/gloves/proc/Touch(atom/A, proximity) - return 0 // return 1 to cancel attack_hand() - -//Head -/obj/item/clothing/head - name = "head" - icon = 'icons/obj/clothing/hats.dmi' - body_parts_covered = HEAD - slot_flags = SLOT_HEAD - w_class = 2.0 - sprite_sheets = list(VOX = 'icons/mob/species/vox/head.dmi') - var/blockTracking = 0 - - -//Mask -/obj/item/clothing/mask - name = "mask" - icon = 'icons/obj/clothing/masks.dmi' - slot_flags = SLOT_MASK - body_parts_covered = FACE|EYES - sprite_sheets = list(VOX = 'icons/mob/species/vox/masks.dmi') - -/obj/item/clothing/proc/speechModification(message) - return message - -//Shoes -/obj/item/clothing/shoes - name = "shoes" - icon = 'icons/obj/clothing/shoes.dmi' - desc = "Comfortable-looking shoes." - gender = PLURAL //Carn: for grammarically correct text-parsing - siemens_coefficient = 0.9 - body_parts_covered = LEGS - slot_flags = SLOT_FEET - var/clipped_status = NO_CLIPPING - - permeability_coefficient = 0.50 - slowdown = SHOES_SLOWDOWN - species_restricted = list("exclude" , UNATHI , TAJARAN) - var/footstep = 1 //used for squeeks whilst walking(tc) - sprite_sheets = list(VOX = 'icons/mob/species/vox/shoes.dmi') - -//Cutting shoes -/obj/item/clothing/shoes/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel)) - switch(clipped_status) - if(CLIPPABLE) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) - user.visible_message("[user] cuts the toe caps off of [src].","You cut the toe caps off of [src].") - - name = "mangled [name]" - desc = "[desc]
                    They have the toe caps cut off of them." - if("exclude" in species_restricted) - species_restricted -= UNATHI - species_restricted -= TAJARAN - src.icon_state += "_cut" - user.update_inv_shoes() - clipped_status = CLIPPED - if(NO_CLIPPING) - to_chat(user, "You have no idea of how to clip [src]!") - if(CLIPPED) - to_chat(user, "[src] have already been clipped!") - else - ..() - -/obj/item/proc/negates_gravity() - return 0 - -//Suit -/obj/item/clothing/suit - icon = 'icons/obj/clothing/suits.dmi' - name = "suit" - var/fire_resist = T0C+100 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - allowed = list(/obj/item/weapon/tank/emergency_oxygen) - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - slot_flags = SLOT_OCLOTHING - var/blood_overlay_type = "suit" - siemens_coefficient = 0.9 - w_class = 3 - sprite_sheets = list(VOX = 'icons/mob/species/vox/suit.dmi') - -/obj/item/clothing/proc/attack_reaction(mob/living/carbon/human/H, reaction_type, mob/living/carbon/human/T = null) - return - -//Spacesuit -//Note: Everything in modules/clothing/spacesuits should have the entire suit grouped together. -// Meaning the the suit is defined directly after the corrisponding helmet. Just like below! -/obj/item/clothing/head/helmet/space - name = "space helmet" - icon_state = "space" - desc = "A special helmet designed for work in a hazardous, low-pressure environment." - flags = HEADCOVERSEYES | BLOCKHAIR | HEADCOVERSMOUTH | THICKMATERIAL | PHORONGUARD - flags_pressure = STOPS_PRESSUREDMAGE - item_state = "space" - permeability_coefficient = 0.01 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50) - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - body_parts_covered = HEAD|FACE|EYES - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0.2 - species_restricted = list("exclude" , DIONA , VOX) - sprite_sheets = list(VOX = 'icons/mob/species/vox/head.dmi') - -/obj/item/clothing/suit/space - name = "space suit" - desc = "A suit that protects against low pressure environments. \"NSS EXODUS\" is written in large block letters on the back." - icon_state = "space" - item_state = "s_suit" - w_class = 4//bulky item - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.02 - flags = THICKMATERIAL | PHORONGUARD - flags_pressure = STOPS_PRESSUREDMAGE - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit) - slowdown = 3 - equip_time = 100 // Bone White - time to equip/unequip. see /obj/item/attack_hand (items.dm) and /obj/item/clothing/mob_can_equip (clothing.dm) - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS - min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0.2 - species_restricted = list("exclude" , DIONA , VOX) - - var/list/supporting_limbs //If not-null, automatically splints breaks. Checked when removing the suit. - -/obj/item/clothing/suit/space/equipped(mob/M) - check_limb_support() - ..() - -/obj/item/clothing/suit/space/dropped() - check_limb_support() - ..() - -// Some space suits are equipped with reactive membranes that support -// broken limbs - at the time of writing, only the ninja suit, but -// I can see it being useful for other suits as we expand them. ~ Z -// The actual splinting occurs in /obj/item/organ/external/proc/fracture() -/obj/item/clothing/suit/space/proc/check_limb_support() - - // If this isn't set, then we don't need to care. - if(!supporting_limbs || !supporting_limbs.len) - return - - var/mob/living/carbon/human/H = src.loc - - // If the holder isn't human, or the holder IS and is wearing the suit, it keeps supporting the limbs. - if(!istype(H) || H.wear_suit == src) - return - - // Otherwise, remove the splints. - for(var/obj/item/organ/external/BP in supporting_limbs) - BP.status &= ~ORGAN_SPLINTED - supporting_limbs = list() - -//Under clothing -/obj/item/clothing/under - icon = 'icons/obj/clothing/uniforms.dmi' - name = "under" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - permeability_coefficient = 0.90 - slot_flags = SLOT_ICLOTHING - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - w_class = 3 - var/has_sensor = 1//For the crew computer 2 = unable to change mode - var/sensor_mode = 0 - /* - 1 = Report living/dead - 2 = Report detailed damages - 3 = Report location - */ - var/list/accessories = list() - var/displays_id = 1 - var/rolled_down = 0 - var/basecolor - sprite_sheets = list(VOX = 'icons/mob/species/vox/uniform.dmi') - -/obj/item/clothing/under/emp_act(severity) - ..() - if(accessories.len) - for(var/obj/item/clothing/accessory/A in accessories) - A.emp_act(severity) - -/obj/item/clothing/under/proc/can_attach_accessory(obj/item/clothing/accessory/A) - if(istype(A)) - . = TRUE - else - return FALSE - if(accessories.len && (A.slot in list("utility","armband"))) - for(var/obj/item/clothing/accessory/AC in accessories) - if (AC.slot == A.slot) - return FALSE - -/obj/item/clothing/under/verb/removetie() - set name = "Remove Accessory" - set category = "Object" - set src in usr - handle_accessories_removal() - -/obj/item/clothing/under/proc/handle_accessories_removal() - if(!isliving(usr)) - return - if(usr.incapacitated()) - return - if(!Adjacent(usr)) - return - if(!accessories.len) - return - if(!istype(usr, /mob/living)) - return - - var/obj/item/clothing/accessory/A - if(accessories.len > 1) - A = input("Select an accessory to remove from [src]") as null|anything in accessories - else - A = accessories[1] - remove_accessory(usr, A) - -/obj/item/clothing/under/proc/remove_accessory(mob/user, obj/item/clothing/accessory/A) - if(QDELETED(A) || !(A in accessories)) - return - if(!isliving(user)) - return - if(user.incapacitated()) - return - if(!Adjacent(user)) - return - A.on_removed(user) - accessories -= A - to_chat(user, "You remove [A] from [src].") - if(istype(loc, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = loc - H.update_inv_w_uniform() - action_button_name = null - -/obj/item/clothing/under/attackby(obj/item/I, mob/user) - if(I.sharp && !ishuman(loc)) //you can cut only clothes lying on the floor - for (var/i in 1 to 3) - new /obj/item/stack/medical/bruise_pack/rags(get_turf(src), null, null, crit_fail) - qdel(src) - return - - if(istype(I, /obj/item/clothing/accessory)) - var/obj/item/clothing/accessory/A = I - if(can_attach_accessory(A)) - user.drop_item() - accessories += A - A.on_attached(src, user) - - if(istype(loc, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = loc - H.update_inv_w_uniform() - action_button_name = "Use inventory." - return - else - to_chat(user, "You cannot attach more accessories of this type to [src].") - - if(accessories.len) - for(var/obj/item/clothing/accessory/A in accessories) - A.attackby(I, user) - return - - ..() - -/obj/item/clothing/under/AltClick() - handle_accessories_removal() - -/obj/item/clothing/under/attack_hand(mob/user) - //only forward to the attached accessory if the clothing is equipped (not in a storage) - if(accessories.len && loc == user) - for(var/obj/item/clothing/accessory/A in accessories) - A.attack_hand(user) - return - - if ((ishuman(usr) || ismonkey(usr)) && loc == user) //make it harder to accidentally undress yourself - return - - ..() - -//This is to ensure people can take off suits when there is an attached accessory -/obj/item/clothing/under/MouseDrop(obj/over_object) - if (ishuman(usr) || ismonkey(usr)) - var/mob/M = usr - //makes sure that the clothing is equipped so that we can't drag it into our hand from miles away. - if (!(src.loc == usr)) - return - if (!over_object) - return - - if (!( usr.restrained() ) && !( usr.stat )) - switch(over_object.name) - if("r_hand") - if(!M.unEquip(src)) - return - M.put_in_r_hand(src) - if("l_hand") - if(!M.unEquip(src)) - return - M.put_in_l_hand(src) - src.add_fingerprint(usr) - return - return - -/obj/item/clothing/under/examine(mob/user) - ..() - switch(src.sensor_mode) - if(0) - to_chat(user, "Its sensors appear to be disabled.") - if(1) - to_chat(user, "Its binary life sensors appear to be enabled.") - if(2) - to_chat(user, "Its vital tracker appears to be enabled.") - if(3) - to_chat(user, "Its vital tracker and tracking beacon appear to be enabled.") - - for(var/obj/item/clothing/accessory/A in accessories) - to_chat(user, "[bicon(A)] \A [A] is attached to it.") - -/obj/item/clothing/under/proc/set_sensors(mob/usr) - var/mob/M = usr - if (istype(M, /mob/dead/)) return - if (usr.stat || usr.restrained()) return - if(has_sensor >= 2) - to_chat(usr, "The controls are locked.") - return 0 - if(has_sensor <= 0) - to_chat(usr, "This suit does not have any sensors.") - return 0 - - var/list/modes = list("Off", "Binary sensors", "Vitals tracker", "Tracking beacon") - var/switchMode = input("Select a sensor mode:", "Suit Sensor Mode", modes[sensor_mode + 1]) in modes - if(get_dist(usr, src) > 1) - to_chat(usr, "You have moved too far away.") - return - sensor_mode = modes.Find(switchMode) - 1 - - if (src.loc == usr) - switch(sensor_mode) - if(0) - to_chat(usr, "You disable your suit's remote sensing equipment.") - if(1) - to_chat(usr, "Your suit will now report whether you are live or dead.") - if(2) - to_chat(usr, "Your suit will now report your vital lifesigns.") - if(3) - to_chat(usr, "Your suit will now report your vital lifesigns as well as your coordinate position.") - else if (istype(src.loc, /mob)) - switch(sensor_mode) - if(0) - for(var/mob/V in viewers(usr, 1)) - V.show_message("\red [usr] disables [src.loc]'s remote sensing equipment.", 1) - if(1) - for(var/mob/V in viewers(usr, 1)) - V.show_message("[usr] turns [src.loc]'s remote sensors to binary.", 1) - if(2) - for(var/mob/V in viewers(usr, 1)) - V.show_message("[usr] sets [src.loc]'s sensors to track vitals.", 1) - if(3) - for(var/mob/V in viewers(usr, 1)) - V.show_message("[usr] sets [src.loc]'s sensors to maximum.", 1) - -/obj/item/clothing/under/verb/toggle() - set name = "Toggle Suit Sensors" - set category = "Object" - set src in usr - set_sensors(usr) - ..() - -/obj/item/clothing/under/verb/rollsuit() - set name = "Roll Down Jumpsuit" - set category = "Object" - set src in usr - if(!istype(usr, /mob/living)) return - if(usr.stat) return - - if(copytext(item_color,-2) != "_d") - basecolor = item_color - if(basecolor + "_d_s" in icon_states('icons/mob/uniform.dmi')) - item_color = item_color == "[basecolor]" ? "[basecolor]_d" : "[basecolor]" - usr.update_inv_w_uniform() - else - to_chat(usr, "You cannot roll down the uniform!") - -/obj/item/clothing/under/rank/atom_init() - sensor_mode = pick(0,1,2,3) - . = ..() + +/obj/item/clothing + name = "clothing" + var/list/species_restricted = null //Only these species can wear this kit. + var/equip_time = 0 + var/equipping = 0 + var/rig_restrict_helmet = 0 // Stops the user from equipping a rig helmet without attaching it to the suit first. + var/gang //Is this a gang outfit? + + /* + Sprites used when the clothing item is refit. This is done by setting icon_override. + For best results, if this is set then sprite_sheets should be null and vice versa, but that is by no means necessary. + Ideally, sprite_sheets_refit should be used for "hard" clothing items that can't change shape very well to fit the wearer (e.g. helmets, hardsuits), + while sprite_sheets should be used for "flexible" clothing items that do not need to be refitted (e.g. vox wearing jumpsuits). + */ + var/list/sprite_sheets_refit = null + lefthand_file = 'icons/mob/inhands/clothing_lefthand.dmi' + righthand_file = 'icons/mob/inhands/clothing_righthand.dmi' + +//BS12: Species-restricted clothing check. +/obj/item/clothing/mob_can_equip(M, slot) + + //if we can't equip the item anyway, don't bother with species_restricted (cuts down on spam) + if (!..()) + return 0 + + if(species_restricted && istype(M,/mob/living/carbon/human)) + + var/wearable = null + var/exclusive = null + var/mob/living/carbon/human/H = M + + if("exclude" in species_restricted) + exclusive = 1 + + if(H.species) + if(exclusive) + if(!(H.species.name in species_restricted)) + wearable = 1 + else + if(H.species.name in species_restricted) + wearable = 1 + + if(!wearable && (slot != 15 && slot != 16)) //Pockets. + to_chat(M, "\red Your species cannot wear [src].") + return 0 + + return 1 + +/obj/item/clothing/proc/refit_for_species(target_species) + //Set species_restricted list + switch(target_species) + if(HUMAN , SKRELL) //humanoid bodytypes + species_restricted = list("exclude" , UNATHI , TAJARAN , DIONA , VOX) + else + species_restricted = list(target_species) + + //Set icon + if (sprite_sheets_refit && (target_species in sprite_sheets_refit)) + icon_override = sprite_sheets_refit[target_species] + else + icon_override = initial(icon_override) + + //Set icon + if (sprite_sheets_obj && (target_species in sprite_sheets_obj)) + icon = sprite_sheets_obj[target_species] + else + icon = initial(icon) + +/obj/item/clothing/head/helmet/refit_for_species(target_species) + //Set species_restricted list + switch(target_species) + if(SKRELL) + species_restricted = list("exclude" , UNATHI , TAJARAN , DIONA , VOX) + if(HUMAN) + species_restricted = list("exclude" , SKRELL , UNATHI , TAJARAN , DIONA , VOX) + else + species_restricted = list(target_species) + + //Set icon + if (sprite_sheets_refit && (target_species in sprite_sheets_refit)) + icon_override = sprite_sheets_refit[target_species] + else + icon_override = initial(icon_override) + + //Set icon + if (sprite_sheets_obj && (target_species in sprite_sheets_obj)) + icon = sprite_sheets_obj[target_species] + else + icon = initial(icon) + +//Ears: headsets, earmuffs and tiny objects +/obj/item/clothing/ears + name = "ears" + w_class = 1.0 + throwforce = 2 + slot_flags = SLOT_EARS + +/obj/item/clothing/ears/attack_hand(mob/user) + if (!user) return + + if (src.loc != user || !istype(user,/mob/living/carbon/human)) + ..() + return + + var/mob/living/carbon/human/H = user + if(H.l_ear != src && H.r_ear != src) + ..() + return + + if(!canremove) + return + + var/obj/item/clothing/ears/O + if(slot_flags & SLOT_TWOEARS ) + O = (H.l_ear == src ? H.r_ear : H.l_ear) + user.u_equip(O) + if(!istype(src,/obj/item/clothing/ears/offear)) + qdel(O) + O = src + else + O = src + + user.u_equip(src) + + if (O) + user.put_in_hands(O) + O.add_fingerprint(user) + + if(istype(src,/obj/item/clothing/ears/offear)) + qdel(src) + +/obj/item/clothing/ears/offear + name = "Other ear" + w_class = 5.0 + icon = 'icons/mob/screen1_Midnight.dmi' + icon_state = "block" + slot_flags = SLOT_EARS | SLOT_TWOEARS + +/obj/item/clothing/ears/offear/atom_init() + . = ..() + var/obj/O = loc + name = O.name + desc = O.desc + icon = O.icon + icon_state = O.icon_state + dir = O.dir + +/obj/item/clothing/ears/earmuffs + name = "earmuffs" + desc = "Protects your hearing from loud noises, and quiet ones as well." + icon_state = "earmuffs" + item_state = "earmuffs" + slot_flags = SLOT_EARS | SLOT_TWOEARS + +//Glasses +/obj/item/clothing/glasses + name = "glasses" + icon = 'icons/obj/clothing/glasses.dmi' + w_class = 2.0 + flags = GLASSESCOVERSEYES + slot_flags = SLOT_EYES + var/vision_flags = 0 + var/darkness_view = 0//Base human is 2 + var/invisa_view = 0 + sprite_sheets = list(VOX = 'icons/mob/species/vox/eyes.dmi') +/* +SEE_SELF // can see self, no matter what +SEE_MOBS // can see all mobs, no matter what +SEE_OBJS // can see all objs, no matter what +SEE_TURFS // can see all turfs (and areas), no matter what +SEE_PIXELS// if an object is located on an unlit area, but some of its pixels are + // in a lit area (via pixel_x,y or smooth movement), can see those pixels +BLIND // can't see anything +*/ + + +//Gloves +/obj/item/clothing/gloves + name = "gloves" + gender = PLURAL //Carn: for grammarically correct text-parsing + w_class = 2.0 + icon = 'icons/obj/clothing/gloves.dmi' + siemens_coefficient = 0.9 + var/wired = FALSE + var/obj/item/weapon/stock_parts/cell/cell = 0 + var/clipped = FALSE + var/protect_fingers = TRUE // Are we gonna get hurt when searching in the trash piles + body_parts_covered = ARMS + slot_flags = SLOT_GLOVES + attack_verb = list("challenged") + species_restricted = list("exclude" , UNATHI , TAJARAN) + sprite_sheets = list(VOX = 'icons/mob/species/vox/gloves.dmi') + +/obj/item/clothing/gloves/emp_act(severity) + if(cell) + //why is this not part of the powercell code? + cell.charge -= 1000 / severity + if (cell.charge < 0) + cell.charge = 0 + if(cell.reliability != 100 && prob(50/severity)) + cell.reliability -= 10 / severity + ..() + +// Called just before an attack_hand(), in mob/UnarmedAttack() +/obj/item/clothing/gloves/proc/Touch(atom/A, proximity) + return 0 // return 1 to cancel attack_hand() + +//Head +/obj/item/clothing/head + name = "head" + icon = 'icons/obj/clothing/hats.dmi' + body_parts_covered = HEAD + slot_flags = SLOT_HEAD + w_class = 2.0 + sprite_sheets = list(VOX = 'icons/mob/species/vox/head.dmi') + var/blockTracking = 0 + + +//Mask +/obj/item/clothing/mask + name = "mask" + icon = 'icons/obj/clothing/masks.dmi' + slot_flags = SLOT_MASK + body_parts_covered = FACE|EYES + sprite_sheets = list(VOX = 'icons/mob/species/vox/masks.dmi') + +/obj/item/clothing/proc/speechModification(message) + return message + +//Shoes +/obj/item/clothing/shoes + name = "shoes" + icon = 'icons/obj/clothing/shoes.dmi' + desc = "Comfortable-looking shoes." + gender = PLURAL //Carn: for grammarically correct text-parsing + siemens_coefficient = 0.9 + body_parts_covered = LEGS + slot_flags = SLOT_FEET + var/clipped_status = NO_CLIPPING + + permeability_coefficient = 0.50 + slowdown = SHOES_SLOWDOWN + species_restricted = list("exclude" , UNATHI , TAJARAN) + var/footstep = 1 //used for squeeks whilst walking(tc) + sprite_sheets = list(VOX = 'icons/mob/species/vox/shoes.dmi') + +//Cutting shoes +/obj/item/clothing/shoes/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel)) + switch(clipped_status) + if(CLIPPABLE) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + user.visible_message("[user] cuts the toe caps off of [src].","You cut the toe caps off of [src].") + + name = "mangled [name]" + desc = "[desc]
                    They have the toe caps cut off of them." + if("exclude" in species_restricted) + species_restricted -= UNATHI + species_restricted -= TAJARAN + src.icon_state += "_cut" + user.update_inv_shoes() + clipped_status = CLIPPED + if(NO_CLIPPING) + to_chat(user, "You have no idea of how to clip [src]!") + if(CLIPPED) + to_chat(user, "[src] have already been clipped!") + else + ..() + +/obj/item/proc/negates_gravity() + return 0 + +//Suit +/obj/item/clothing/suit + icon = 'icons/obj/clothing/suits.dmi' + name = "suit" + var/fire_resist = T0C+100 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + allowed = list(/obj/item/weapon/tank/emergency_oxygen) + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + slot_flags = SLOT_OCLOTHING + var/blood_overlay_type = "suit" + siemens_coefficient = 0.9 + w_class = 3 + sprite_sheets = list(VOX = 'icons/mob/species/vox/suit.dmi') + +/obj/item/clothing/proc/attack_reaction(mob/living/carbon/human/H, reaction_type, mob/living/carbon/human/T = null) + return + +//Spacesuit +//Note: Everything in modules/clothing/spacesuits should have the entire suit grouped together. +// Meaning the the suit is defined directly after the corrisponding helmet. Just like below! +/obj/item/clothing/head/helmet/space + name = "space helmet" + icon_state = "space" + desc = "A special helmet designed for work in a hazardous, low-pressure environment." + flags = HEADCOVERSEYES | BLOCKHAIR | HEADCOVERSMOUTH | THICKMATERIAL | PHORONGUARD + flags_pressure = STOPS_PRESSUREDMAGE + item_state = "space" + permeability_coefficient = 0.01 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50) + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + body_parts_covered = HEAD|FACE|EYES + cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.2 + species_restricted = list("exclude" , DIONA , VOX) + sprite_sheets = list(VOX = 'icons/mob/species/vox/head.dmi') + +/obj/item/clothing/suit/space + name = "space suit" + desc = "A suit that protects against low pressure environments. \"NSS EXODUS\" is written in large block letters on the back." + icon_state = "space" + item_state = "s_suit" + w_class = 4//bulky item + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.02 + flags = THICKMATERIAL | PHORONGUARD + flags_pressure = STOPS_PRESSUREDMAGE + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit) + slowdown = 3 + equip_time = 100 // Bone White - time to equip/unequip. see /obj/item/attack_hand (items.dm) and /obj/item/clothing/mob_can_equip (clothing.dm) + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50) + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.2 + species_restricted = list("exclude" , DIONA , VOX) + + var/list/supporting_limbs //If not-null, automatically splints breaks. Checked when removing the suit. + +/obj/item/clothing/suit/space/equipped(mob/M) + check_limb_support() + ..() + +/obj/item/clothing/suit/space/dropped() + check_limb_support() + ..() + +// Some space suits are equipped with reactive membranes that support +// broken limbs - at the time of writing, only the ninja suit, but +// I can see it being useful for other suits as we expand them. ~ Z +// The actual splinting occurs in /obj/item/organ/external/proc/fracture() +/obj/item/clothing/suit/space/proc/check_limb_support() + + // If this isn't set, then we don't need to care. + if(!supporting_limbs || !supporting_limbs.len) + return + + var/mob/living/carbon/human/H = src.loc + + // If the holder isn't human, or the holder IS and is wearing the suit, it keeps supporting the limbs. + if(!istype(H) || H.wear_suit == src) + return + + // Otherwise, remove the splints. + for(var/obj/item/organ/external/BP in supporting_limbs) + BP.status &= ~ORGAN_SPLINTED + supporting_limbs = list() + +//Under clothing +/obj/item/clothing/under + icon = 'icons/obj/clothing/uniforms.dmi' + name = "under" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + permeability_coefficient = 0.90 + slot_flags = SLOT_ICLOTHING + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + w_class = 3 + var/has_sensor = 1//For the crew computer 2 = unable to change mode + var/sensor_mode = 0 + /* + 1 = Report living/dead + 2 = Report detailed damages + 3 = Report location + */ + var/list/accessories = list() + var/displays_id = 1 + var/rolled_down = 0 + var/basecolor + sprite_sheets = list(VOX = 'icons/mob/species/vox/uniform.dmi') + +/obj/item/clothing/under/emp_act(severity) + ..() + if(accessories.len) + for(var/obj/item/clothing/accessory/A in accessories) + A.emp_act(severity) + +/obj/item/clothing/under/proc/can_attach_accessory(obj/item/clothing/accessory/A) + if(istype(A)) + . = TRUE + else + return FALSE + if(accessories.len && (A.slot in list("utility","armband"))) + for(var/obj/item/clothing/accessory/AC in accessories) + if (AC.slot == A.slot) + return FALSE + +/obj/item/clothing/under/verb/removetie() + set name = "Remove Accessory" + set category = "Object" + set src in usr + handle_accessories_removal() + +/obj/item/clothing/under/proc/handle_accessories_removal() + if(!isliving(usr)) + return + if(usr.incapacitated()) + return + if(!Adjacent(usr)) + return + if(!accessories.len) + return + if(!istype(usr, /mob/living)) + return + + var/obj/item/clothing/accessory/A + if(accessories.len > 1) + A = input("Select an accessory to remove from [src]") as null|anything in accessories + else + A = accessories[1] + remove_accessory(usr, A) + +/obj/item/clothing/under/proc/remove_accessory(mob/user, obj/item/clothing/accessory/A) + if(QDELETED(A) || !(A in accessories)) + return + if(!isliving(user)) + return + if(user.incapacitated()) + return + if(!Adjacent(user)) + return + A.on_removed(user) + accessories -= A + to_chat(user, "You remove [A] from [src].") + if(istype(loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = loc + H.update_inv_w_uniform() + action_button_name = null + +/obj/item/clothing/under/attackby(obj/item/I, mob/user) + if(I.sharp && !ishuman(loc)) //you can cut only clothes lying on the floor + for (var/i in 1 to 3) + new /obj/item/stack/medical/bruise_pack/rags(get_turf(src), null, null, crit_fail) + qdel(src) + return + + if(istype(I, /obj/item/clothing/accessory)) + var/obj/item/clothing/accessory/A = I + if(can_attach_accessory(A)) + user.drop_item() + accessories += A + A.on_attached(src, user) + + if(istype(loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = loc + H.update_inv_w_uniform() + action_button_name = "Use inventory." + return + else + to_chat(user, "You cannot attach more accessories of this type to [src].") + + if(accessories.len) + for(var/obj/item/clothing/accessory/A in accessories) + A.attackby(I, user) + return + + ..() + +/obj/item/clothing/under/AltClick() + handle_accessories_removal() + +/obj/item/clothing/under/attack_hand(mob/user) + //only forward to the attached accessory if the clothing is equipped (not in a storage) + if(accessories.len && loc == user) + for(var/obj/item/clothing/accessory/A in accessories) + A.attack_hand(user) + return + + if ((ishuman(usr) || ismonkey(usr)) && loc == user) //make it harder to accidentally undress yourself + return + + ..() + +//This is to ensure people can take off suits when there is an attached accessory +/obj/item/clothing/under/MouseDrop(obj/over_object) + if (ishuman(usr) || ismonkey(usr)) + var/mob/M = usr + //makes sure that the clothing is equipped so that we can't drag it into our hand from miles away. + if (!(src.loc == usr)) + return + if (!over_object) + return + + if (!( usr.restrained() ) && !( usr.stat )) + switch(over_object.name) + if("r_hand") + if(!M.unEquip(src)) + return + M.put_in_r_hand(src) + if("l_hand") + if(!M.unEquip(src)) + return + M.put_in_l_hand(src) + src.add_fingerprint(usr) + return + return + +/obj/item/clothing/under/examine(mob/user) + ..() + switch(src.sensor_mode) + if(0) + to_chat(user, "Its sensors appear to be disabled.") + if(1) + to_chat(user, "Its binary life sensors appear to be enabled.") + if(2) + to_chat(user, "Its vital tracker appears to be enabled.") + if(3) + to_chat(user, "Its vital tracker and tracking beacon appear to be enabled.") + + for(var/obj/item/clothing/accessory/A in accessories) + to_chat(user, "[bicon(A)] \A [A] is attached to it.") + +/obj/item/clothing/under/proc/set_sensors(mob/usr) + var/mob/M = usr + if (istype(M, /mob/dead/)) return + if (usr.stat || usr.restrained()) return + if(has_sensor >= 2) + to_chat(usr, "The controls are locked.") + return 0 + if(has_sensor <= 0) + to_chat(usr, "This suit does not have any sensors.") + return 0 + + var/list/modes = list("Off", "Binary sensors", "Vitals tracker", "Tracking beacon") + var/switchMode = input("Select a sensor mode:", "Suit Sensor Mode", modes[sensor_mode + 1]) in modes + if(get_dist(usr, src) > 1) + to_chat(usr, "You have moved too far away.") + return + sensor_mode = modes.Find(switchMode) - 1 + + if (src.loc == usr) + switch(sensor_mode) + if(0) + to_chat(usr, "You disable your suit's remote sensing equipment.") + if(1) + to_chat(usr, "Your suit will now report whether you are live or dead.") + if(2) + to_chat(usr, "Your suit will now report your vital lifesigns.") + if(3) + to_chat(usr, "Your suit will now report your vital lifesigns as well as your coordinate position.") + else if (istype(src.loc, /mob)) + switch(sensor_mode) + if(0) + for(var/mob/V in viewers(usr, 1)) + V.show_message("\red [usr] disables [src.loc]'s remote sensing equipment.", 1) + if(1) + for(var/mob/V in viewers(usr, 1)) + V.show_message("[usr] turns [src.loc]'s remote sensors to binary.", 1) + if(2) + for(var/mob/V in viewers(usr, 1)) + V.show_message("[usr] sets [src.loc]'s sensors to track vitals.", 1) + if(3) + for(var/mob/V in viewers(usr, 1)) + V.show_message("[usr] sets [src.loc]'s sensors to maximum.", 1) + +/obj/item/clothing/under/verb/toggle() + set name = "Toggle Suit Sensors" + set category = "Object" + set src in usr + set_sensors(usr) + ..() + +/obj/item/clothing/under/verb/rollsuit() + set name = "Roll Down Jumpsuit" + set category = "Object" + set src in usr + if(!istype(usr, /mob/living)) return + if(usr.stat) return + + if(copytext(item_color,-2) != "_d") + basecolor = item_color + if(basecolor + "_d_s" in icon_states('icons/mob/uniform.dmi')) + item_color = item_color == "[basecolor]" ? "[basecolor]_d" : "[basecolor]" + usr.update_inv_w_uniform() + else + to_chat(usr, "You cannot roll down the uniform!") + +/obj/item/clothing/under/rank/atom_init() + sensor_mode = pick(0,1,2,3) + . = ..() diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 50a7df5af5fd..24720e0fd5cf 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -1,355 +1,355 @@ - -/obj/item/clothing/glasses - name = "glasses" - icon = 'icons/obj/clothing/glasses.dmi' - //w_class = 2.0 - //flags = GLASSESCOVERSEYES - //slot_flags = SLOT_EYES - //var/vision_flags = 0 - //var/darkness_view = 0//Base human is 2 - //var/invisa_view = 0 - var/prescription = 0 - body_parts_covered = EYES - var/toggleable = 0 - var/off_state = "degoggles" - var/active = 1 - var/activation_sound = 'sound/items/buttonclick.ogg' - -/obj/item/clothing/glasses/attack_self(mob/user) - if(toggleable) - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - if(active) - active = 0 - icon_state = off_state - vision_flags = 0 - to_chat(usr, "You deactivate the optical matrix on the [src].") - else - active = 1 - icon_state = initial(icon_state) - vision_flags = initial(vision_flags) - to_chat(usr, "You activate the optical matrix on the [src].") - playsound(src.loc, activation_sound, 10, 0) - H.update_inv_glasses() - H.update_sight() - -/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" - action_button_name = "Toggle Goggles" - origin_tech = "magnets=2;engineering=2" - toggleable = 1 - vision_flags = SEE_TURFS - -/obj/item/clothing/glasses/meson/prescription - name = "prescription mesons" - desc = "Optical Meson Scanner with prescription lenses." - prescription = 1 - -/obj/item/clothing/glasses/science - name = "science goggles" - desc = "The goggles do nothing!" - icon_state = "purple" - item_state = "glasses" - action_button_name = "Toggle Goggles" - toggleable = 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" -// darkness_view = 3 -// vision_flags = SEE_SELF - darkness_view = 7 - toggleable = 1 - action_button_name = "Toggle Goggles" - active = 1 - off_state = "night" - activation_sound = 'sound/effects/glasses_on.ogg' - -/obj/item/clothing/glasses/eyepatch - name = "eyepatch" - desc = "Yarr." - icon_state = "eyepatch" - item_state = "eyepatch" - body_parts_covered = 0 - -/obj/item/clothing/glasses/monocle - name = "monocle" - desc = "Such a dapper eyepiece!" - icon_state = "monocle" - item_state = "headset" // lol - body_parts_covered = 0 - -/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" - toggleable = 1 - action_button_name = "Toggle Goggles" - vision_flags = SEE_OBJS - -/obj/item/clothing/glasses/aviator_orange - name = "aviator glasses" - desc = "Stylish glasses with orange lenses" - icon_state = "aviators_orange" - -/obj/item/clothing/glasses/aviator_black - name = "aviator glasses" - desc = "Stylish glasses with black lenses" - icon_state = "aviators_black" - -/obj/item/clothing/glasses/aviator_red - name = "aviator glasses" - desc = "Stylish glasses with red lenses" - icon_state = "aviators_red" - -/obj/item/clothing/glasses/aviator_mirror - name = "aviator glasses" - desc = "Stylish glasses with transparent lenses" - icon_state = "aviators_mirror" - -/obj/item/clothing/glasses/jerusalem - name = "Jerusalem glasses" - desc = "Here you can see a small inscription: I hate it here" - icon_state = "spider_jerusalem" - -/obj/item/clothing/glasses/regular - name = "prescription glasses" - desc = "Made by Nerd. Co." - icon_state = "glasses" - item_state = "glasses" - prescription = 1 - body_parts_covered = 0 - -/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/threedglasses - desc = "A long time ago, people used these glasses to makes images from screens threedimensional." - name = "3D glasses" - icon_state = "3d" - item_state = "3d" - body_parts_covered = 0 - -/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" - body_parts_covered = 0 - -/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" - darkness_view = -1 - -/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" - action_button_name = "Flip Welding Goggles" - var/up = 0 - -/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 - - if(usr.canmove && !usr.stat && !usr.restrained()) - if(src.up) - src.up = !src.up - src.flags |= GLASSESCOVERSEYES - flags_inv |= HIDEEYES - body_parts_covered |= EYES - icon_state = initial(icon_state) - to_chat(usr, "You flip \the [src] down to protect your eyes.") - else - src.up = !src.up - src.flags &= ~HEADCOVERSEYES - flags_inv &= ~HIDEEYES - body_parts_covered &= ~EYES - icon_state = "[initial(icon_state)]up" - to_chat(usr, "You push \the [src] up out of your face.") - - usr.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." - icon_state = "rwelding-g" - item_state = "rwelding-g" - -/obj/item/clothing/glasses/sunglasses/blindfold - name = "blindfold" - desc = "Covers the eyes, preventing sight." - icon_state = "blindfold" - item_state = "blindfold" - //vision_flags = BLIND // This flag is only supposed to be used if it causes permanent blindness, not temporary because of glasses - -/obj/item/clothing/glasses/sunglasses/blindfold/white - name = "blind personnel blindfold" - desc = "Indicates that the wearer suffers from blindness." - icon_state = "blindfoldwhite" - item_state = "blindfoldwhite" - var/colored_before = FALSE - -/obj/item/clothing/glasses/sunglasses/blindfold/white/equipped(mob/living/carbon/human/user, slot) - if(ishuman(user) && slot == slot_glasses) - update_icon(user) - ..() - -/obj/item/clothing/glasses/sunglasses/blindfold/white/update_icon(mob/living/carbon/human/user) - if(ishuman(user) && !colored_before) - colored_before = TRUE - color = rgb(user.r_eyes, user.g_eyes, user.b_eyes) - -/obj/item/clothing/glasses/sunglasses/prescription - name = "prescription sunglasses" - prescription = 1 - -/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" - -/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 - -/obj/item/clothing/glasses/sunglasses/sechud/atom_init() - . = ..() - hud = new/obj/item/clothing/glasses/hud/security(src) - -/obj/item/clothing/glasses/sunglasses/sechud/tactical - name = "tactical HUD" - desc = "Flash-resistant goggles with inbuilt combat and security information." - icon_state = "swatgoggles" - -/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 - invisa_view = 2 - toggleable = 1 - action_button_name = "Toggle Goggles" - -/obj/item/clothing/glasses/thermal/emp_act(severity) - if(istype(src.loc, /mob/living/carbon/human)) - var/mob/living/carbon/human/M = src.loc - to_chat(M, "\red 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" - -/obj/item/clothing/glasses/thermal/monocle - name = "thermoncle" - desc = "A monocle thermal." - icon_state = "thermoncle" - flags = null //doesn't protect eyes because it's a monocle, duh - body_parts_covered = 0 - toggleable = 1 - off_state = "thermoncle_off" - action_button_name = "Toggle Monocle" - -/obj/item/clothing/glasses/thermal/eyepatch - name = "optical thermal eyepatch" - desc = "An eyepatch with built-in thermal optics." - icon_state = "eyepatch" - item_state = "eyepatch" - body_parts_covered = 0 - toggleable = 0 - action_button_name = null - -/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" - -/obj/item/clothing/glasses/thermal/hos_thermals - name = "augmented shades" - desc = "Polarized bioneural eyewear, designed to augment your vision." - icon_state = "hos_shades" - item_state = "hos_shades" - toggleable = 0 - action_button_name = null - -/obj/item/clothing/glasses/rosas_eyepatch - name = "white eyepatch" - icon_state = "rosas_eye" - -/obj/item/clothing/glasses/hud/health/night - name = "night vision health scanner HUD" - desc = "An advanced medical head-up display that allows doctors to find patients in complete darkness." - icon_state = "healthhudnight" - darkness_view = 7 - -/obj/item/clothing/glasses/gar - name = "gar glasses" - icon_state = "gar" - item_state = "gar" - -/obj/item/clothing/glasses/sunglasses/gar - name = "gar sunglasses" - icon_state = "garb" - item_state = "garb" - -/obj/item/clothing/glasses/meson/gar - name = "gar meson scanner" - icon_state = "garm" - item_state = "garm" - toggleable = 0 - action_button_name = null - -/obj/item/clothing/glasses/sunglasses/sechud/gar - name = "gar HUDsunglasses" - icon_state = "gars" - item_state = "gars" - -/obj/item/clothing/glasses/sunglasses/gar/super - name = "supergar sunglasses" - icon_state = "supergarb" - item_state = "supergarb" - -/obj/item/clothing/glasses/sunglasses/sechud/gar/super - name = "supergar HUDSunglasses" - icon_state = "supergars" - item_state = "supergars" - -/obj/item/clothing/glasses/gar/super - name = "supergar glasses" - icon_state = "supergar" - item_state = "supergar" - toggleable = 0 + +/obj/item/clothing/glasses + name = "glasses" + icon = 'icons/obj/clothing/glasses.dmi' + //w_class = 2.0 + //flags = GLASSESCOVERSEYES + //slot_flags = SLOT_EYES + //var/vision_flags = 0 + //var/darkness_view = 0//Base human is 2 + //var/invisa_view = 0 + var/prescription = 0 + body_parts_covered = EYES + var/toggleable = 0 + var/off_state = "degoggles" + var/active = 1 + var/activation_sound = 'sound/items/buttonclick.ogg' + +/obj/item/clothing/glasses/attack_self(mob/user) + if(toggleable) + if(ishuman(usr)) + var/mob/living/carbon/human/H = usr + if(active) + active = 0 + icon_state = off_state + vision_flags = 0 + to_chat(usr, "You deactivate the optical matrix on the [src].") + else + active = 1 + icon_state = initial(icon_state) + vision_flags = initial(vision_flags) + to_chat(usr, "You activate the optical matrix on the [src].") + playsound(src.loc, activation_sound, 10, 0) + H.update_inv_glasses() + H.update_sight() + +/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" + action_button_name = "Toggle Goggles" + origin_tech = "magnets=2;engineering=2" + toggleable = 1 + vision_flags = SEE_TURFS + +/obj/item/clothing/glasses/meson/prescription + name = "prescription mesons" + desc = "Optical Meson Scanner with prescription lenses." + prescription = 1 + +/obj/item/clothing/glasses/science + name = "science goggles" + desc = "The goggles do nothing!" + icon_state = "purple" + item_state = "glasses" + action_button_name = "Toggle Goggles" + toggleable = 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" +// darkness_view = 3 +// vision_flags = SEE_SELF + darkness_view = 7 + toggleable = 1 + action_button_name = "Toggle Goggles" + active = 1 + off_state = "night" + activation_sound = 'sound/effects/glasses_on.ogg' + +/obj/item/clothing/glasses/eyepatch + name = "eyepatch" + desc = "Yarr." + icon_state = "eyepatch" + item_state = "eyepatch" + body_parts_covered = 0 + +/obj/item/clothing/glasses/monocle + name = "monocle" + desc = "Such a dapper eyepiece!" + icon_state = "monocle" + item_state = "headset" // lol + body_parts_covered = 0 + +/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" + toggleable = 1 + action_button_name = "Toggle Goggles" + vision_flags = SEE_OBJS + +/obj/item/clothing/glasses/aviator_orange + name = "aviator glasses" + desc = "Stylish glasses with orange lenses" + icon_state = "aviators_orange" + +/obj/item/clothing/glasses/aviator_black + name = "aviator glasses" + desc = "Stylish glasses with black lenses" + icon_state = "aviators_black" + +/obj/item/clothing/glasses/aviator_red + name = "aviator glasses" + desc = "Stylish glasses with red lenses" + icon_state = "aviators_red" + +/obj/item/clothing/glasses/aviator_mirror + name = "aviator glasses" + desc = "Stylish glasses with transparent lenses" + icon_state = "aviators_mirror" + +/obj/item/clothing/glasses/jerusalem + name = "Jerusalem glasses" + desc = "Here you can see a small inscription: I hate it here" + icon_state = "spider_jerusalem" + +/obj/item/clothing/glasses/regular + name = "prescription glasses" + desc = "Made by Nerd. Co." + icon_state = "glasses" + item_state = "glasses" + prescription = 1 + body_parts_covered = 0 + +/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/threedglasses + desc = "A long time ago, people used these glasses to makes images from screens threedimensional." + name = "3D glasses" + icon_state = "3d" + item_state = "3d" + body_parts_covered = 0 + +/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" + body_parts_covered = 0 + +/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" + darkness_view = -1 + +/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" + action_button_name = "Flip Welding Goggles" + var/up = 0 + +/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 + + if(usr.canmove && !usr.stat && !usr.restrained()) + if(src.up) + src.up = !src.up + src.flags |= GLASSESCOVERSEYES + flags_inv |= HIDEEYES + body_parts_covered |= EYES + icon_state = initial(icon_state) + to_chat(usr, "You flip \the [src] down to protect your eyes.") + else + src.up = !src.up + src.flags &= ~HEADCOVERSEYES + flags_inv &= ~HIDEEYES + body_parts_covered &= ~EYES + icon_state = "[initial(icon_state)]up" + to_chat(usr, "You push \the [src] up out of your face.") + + usr.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." + icon_state = "rwelding-g" + item_state = "rwelding-g" + +/obj/item/clothing/glasses/sunglasses/blindfold + name = "blindfold" + desc = "Covers the eyes, preventing sight." + icon_state = "blindfold" + item_state = "blindfold" + //vision_flags = BLIND // This flag is only supposed to be used if it causes permanent blindness, not temporary because of glasses + +/obj/item/clothing/glasses/sunglasses/blindfold/white + name = "blind personnel blindfold" + desc = "Indicates that the wearer suffers from blindness." + icon_state = "blindfoldwhite" + item_state = "blindfoldwhite" + var/colored_before = FALSE + +/obj/item/clothing/glasses/sunglasses/blindfold/white/equipped(mob/living/carbon/human/user, slot) + if(ishuman(user) && slot == slot_glasses) + update_icon(user) + ..() + +/obj/item/clothing/glasses/sunglasses/blindfold/white/update_icon(mob/living/carbon/human/user) + if(ishuman(user) && !colored_before) + colored_before = TRUE + color = rgb(user.r_eyes, user.g_eyes, user.b_eyes) + +/obj/item/clothing/glasses/sunglasses/prescription + name = "prescription sunglasses" + prescription = 1 + +/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" + +/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 + +/obj/item/clothing/glasses/sunglasses/sechud/atom_init() + . = ..() + hud = new/obj/item/clothing/glasses/hud/security(src) + +/obj/item/clothing/glasses/sunglasses/sechud/tactical + name = "tactical HUD" + desc = "Flash-resistant goggles with inbuilt combat and security information." + icon_state = "swatgoggles" + +/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 + invisa_view = 2 + toggleable = 1 + action_button_name = "Toggle Goggles" + +/obj/item/clothing/glasses/thermal/emp_act(severity) + if(istype(src.loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/M = src.loc + to_chat(M, "\red 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" + +/obj/item/clothing/glasses/thermal/monocle + name = "thermoncle" + desc = "A monocle thermal." + icon_state = "thermoncle" + flags = null //doesn't protect eyes because it's a monocle, duh + body_parts_covered = 0 + toggleable = 1 + off_state = "thermoncle_off" + action_button_name = "Toggle Monocle" + +/obj/item/clothing/glasses/thermal/eyepatch + name = "optical thermal eyepatch" + desc = "An eyepatch with built-in thermal optics." + icon_state = "eyepatch" + item_state = "eyepatch" + body_parts_covered = 0 + toggleable = 0 + action_button_name = null + +/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" + +/obj/item/clothing/glasses/thermal/hos_thermals + name = "augmented shades" + desc = "Polarized bioneural eyewear, designed to augment your vision." + icon_state = "hos_shades" + item_state = "hos_shades" + toggleable = 0 + action_button_name = null + +/obj/item/clothing/glasses/rosas_eyepatch + name = "white eyepatch" + icon_state = "rosas_eye" + +/obj/item/clothing/glasses/hud/health/night + name = "night vision health scanner HUD" + desc = "An advanced medical head-up display that allows doctors to find patients in complete darkness." + icon_state = "healthhudnight" + darkness_view = 7 + +/obj/item/clothing/glasses/gar + name = "gar glasses" + icon_state = "gar" + item_state = "gar" + +/obj/item/clothing/glasses/sunglasses/gar + name = "gar sunglasses" + icon_state = "garb" + item_state = "garb" + +/obj/item/clothing/glasses/meson/gar + name = "gar meson scanner" + icon_state = "garm" + item_state = "garm" + toggleable = 0 + action_button_name = null + +/obj/item/clothing/glasses/sunglasses/sechud/gar + name = "gar HUDsunglasses" + icon_state = "gars" + item_state = "gars" + +/obj/item/clothing/glasses/sunglasses/gar/super + name = "supergar sunglasses" + icon_state = "supergarb" + item_state = "supergarb" + +/obj/item/clothing/glasses/sunglasses/sechud/gar/super + name = "supergar HUDSunglasses" + icon_state = "supergars" + item_state = "supergars" + +/obj/item/clothing/glasses/gar/super + name = "supergar glasses" + icon_state = "supergar" + item_state = "supergar" + toggleable = 0 diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index e68e1d911db7..92fc6b3a0cd0 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -1,74 +1,74 @@ -/obj/item/clothing/glasses/hud - name = "HUD" - desc = "A heads-up display that provides important info in (almost) real time." - flags = null //doesn't protect eyes because it's a monocle, duh - origin_tech = "magnets=3;biotech=2" - var/fixtime = 0 - var/list/icon/current = list() //the current hud icons - -/obj/item/clothing/glasses/hud/proc/process_hud(mob/M) - return - - -/obj/item/clothing/glasses/sunglasses/hud/secmed - name = "mixed HUD" - desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status and health status." - icon_state = "secmedhud" - body_parts_covered = 0 - var/fixtime = 0 - - -/obj/item/clothing/glasses/sunglasses/hud/secmed/proc/process_hud(mob/M) - if(crit_fail) - if(fixtime < world.time) - crit_fail=0 - process_med_hud(M, 1, crit_fail = crit_fail) - process_sec_hud(M, 1, crit_fail = crit_fail) - -/obj/item/clothing/glasses/hud/emp_act(severity) - if(!crit_fail) - crit_fail = 1 - fixtime = world.time + 900 / severity - -/obj/item/clothing/glasses/hud/health - name = "health scanner HUD" - desc = "A heads-up display that scans the humans in view and provides accurate data about their health status." - icon_state = "healthhud" - body_parts_covered = 0 - - -/obj/item/clothing/glasses/hud/health/process_hud(mob/M) - check_integrity() - process_med_hud(M, 1, crit_fail = crit_fail) - -/obj/item/clothing/glasses/hud/security - name = "security HUD" - desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status and security records." - icon_state = "securityhud" - body_parts_covered = 0 - var/global/list/jobs[0] - -/obj/item/clothing/glasses/hud/security/jensenshades - name = "augmented shades" - desc = "Polarized bioneural eyewear, designed to augment your vision." - icon_state = "hos_shades" - item_state = "hos_shades" - vision_flags = SEE_MOBS - invisa_view = 3 - -/obj/item/clothing/glasses/hud/security/process_hud(mob/M) - check_integrity() - process_sec_hud(M, 1, crit_fail = crit_fail) - -/obj/item/clothing/glasses/hud/broken/process_hud(mob/M) - process_broken_hud(M, 1) - -/obj/item/clothing/glasses/hud/proc/check_integrity() - if(crit_fail) - if(fixtime < world.time) - crit_fail=0 - -/obj/item/clothing/glasses/hud/emp_act(severity) - if(!crit_fail) - crit_fail = 1 +/obj/item/clothing/glasses/hud + name = "HUD" + desc = "A heads-up display that provides important info in (almost) real time." + flags = null //doesn't protect eyes because it's a monocle, duh + origin_tech = "magnets=3;biotech=2" + var/fixtime = 0 + var/list/icon/current = list() //the current hud icons + +/obj/item/clothing/glasses/hud/proc/process_hud(mob/M) + return + + +/obj/item/clothing/glasses/sunglasses/hud/secmed + name = "mixed HUD" + desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status and health status." + icon_state = "secmedhud" + body_parts_covered = 0 + var/fixtime = 0 + + +/obj/item/clothing/glasses/sunglasses/hud/secmed/proc/process_hud(mob/M) + if(crit_fail) + if(fixtime < world.time) + crit_fail=0 + process_med_hud(M, 1, crit_fail = crit_fail) + process_sec_hud(M, 1, crit_fail = crit_fail) + +/obj/item/clothing/glasses/hud/emp_act(severity) + if(!crit_fail) + crit_fail = 1 + fixtime = world.time + 900 / severity + +/obj/item/clothing/glasses/hud/health + name = "health scanner HUD" + desc = "A heads-up display that scans the humans in view and provides accurate data about their health status." + icon_state = "healthhud" + body_parts_covered = 0 + + +/obj/item/clothing/glasses/hud/health/process_hud(mob/M) + check_integrity() + process_med_hud(M, 1, crit_fail = crit_fail) + +/obj/item/clothing/glasses/hud/security + name = "security HUD" + desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status and security records." + icon_state = "securityhud" + body_parts_covered = 0 + var/global/list/jobs[0] + +/obj/item/clothing/glasses/hud/security/jensenshades + name = "augmented shades" + desc = "Polarized bioneural eyewear, designed to augment your vision." + icon_state = "hos_shades" + item_state = "hos_shades" + vision_flags = SEE_MOBS + invisa_view = 3 + +/obj/item/clothing/glasses/hud/security/process_hud(mob/M) + check_integrity() + process_sec_hud(M, 1, crit_fail = crit_fail) + +/obj/item/clothing/glasses/hud/broken/process_hud(mob/M) + process_broken_hud(M, 1) + +/obj/item/clothing/glasses/hud/proc/check_integrity() + if(crit_fail) + if(fixtime < world.time) + crit_fail=0 + +/obj/item/clothing/glasses/hud/emp_act(severity) + if(!crit_fail) + crit_fail = 1 fixtime = world.time + 900 / severity \ No newline at end of file diff --git a/code/modules/clothing/gloves/boxing.dm b/code/modules/clothing/gloves/boxing.dm index 7a81ab5ba148..c499d6646d92 100644 --- a/code/modules/clothing/gloves/boxing.dm +++ b/code/modules/clothing/gloves/boxing.dm @@ -1,27 +1,27 @@ -/obj/item/clothing/gloves/boxing - name = "boxing gloves" - desc = "Because you really needed another excuse to punch your crewmates." - icon_state = "boxing" - item_state = "boxing" - -/obj/item/clothing/gloves/boxing/green - icon_state = "boxinggreen" - item_state = "boxinggreen" - -/obj/item/clothing/gloves/boxing/blue - icon_state = "boxingblue" - item_state = "boxingblue" - -/obj/item/clothing/gloves/boxing/yellow - icon_state = "boxingyellow" - item_state = "boxingyellow" - -/obj/item/clothing/gloves/white - name = "white gloves" - desc = "These look pretty fancy." - icon_state = "latex" - item_state = "lgloves" - item_color="mime" - -/obj/item/clothing/gloves/white/redcoat - item_color = "redcoat" //Exists for washing machines. Is not different from white gloves in any way. +/obj/item/clothing/gloves/boxing + name = "boxing gloves" + desc = "Because you really needed another excuse to punch your crewmates." + icon_state = "boxing" + item_state = "boxing" + +/obj/item/clothing/gloves/boxing/green + icon_state = "boxinggreen" + item_state = "boxinggreen" + +/obj/item/clothing/gloves/boxing/blue + icon_state = "boxingblue" + item_state = "boxingblue" + +/obj/item/clothing/gloves/boxing/yellow + icon_state = "boxingyellow" + item_state = "boxingyellow" + +/obj/item/clothing/gloves/white + name = "white gloves" + desc = "These look pretty fancy." + icon_state = "latex" + item_state = "lgloves" + item_color="mime" + +/obj/item/clothing/gloves/white/redcoat + item_color = "redcoat" //Exists for washing machines. Is not different from white gloves in any way. diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index d363775fa57c..283944f44af0 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -1,125 +1,125 @@ -/obj/item/clothing/gloves/yellow - desc = "These gloves will protect the wearer from electric shock." - name = "insulated gloves" - icon_state = "yellow" - item_state = "ygloves" - siemens_coefficient = 0 - permeability_coefficient = 0.05 - item_color="yellow" - -/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 = "ygloves" - siemens_coefficient = 1 //Set to a default of 1, gets overridden in New() - permeability_coefficient = 0.05 - - item_color="yellow" - -/obj/item/clothing/gloves/fyellow/atom_init() - . = ..() - 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 = "bgloves" - item_color="brown" - - cold_protection = ARMS - min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = ARMS - max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/gloves/black/strip // gloves for stripping items - siemens_coefficient = 0.2 - - -/obj/item/clothing/gloves/black/hos - name = "head of security's gloves" - item_color = "hosred" //Exists for washing machines. - -/obj/item/clothing/gloves/black/ce - name = "chief engineer's gloves" - item_color = "chief" //Exists for washing machines. - - -/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 = "orangegloves" - item_color="orange" - -/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 = "redgloves" - item_color = "red" - -/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 = "rainbowgloves" - item_color = "rainbow" - -/obj/item/clothing/gloves/rainbow/clown - item_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 = "bluegloves" - item_color="blue" - -/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 = "purplegloves" - item_color="purple" - -/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 = "greengloves" - item_color="green" - -/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 = "graygloves" - item_color="grey" - -/obj/item/clothing/gloves/grey/rd - item_color = "director" //Exists for washing machines. Is not different from gray gloves in any way. - -/obj/item/clothing/gloves/grey/hop - item_color = "hop" //Exists for washing machines. Is not different from gray gloves in any way. - - -/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 = "lightbrowngloves" - item_color="light brown" - -/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" - item_color="brown" - -/obj/item/clothing/gloves/brown/cargo - item_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 = "ygloves" + siemens_coefficient = 0 + permeability_coefficient = 0.05 + item_color="yellow" + +/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 = "ygloves" + siemens_coefficient = 1 //Set to a default of 1, gets overridden in New() + permeability_coefficient = 0.05 + + item_color="yellow" + +/obj/item/clothing/gloves/fyellow/atom_init() + . = ..() + 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 = "bgloves" + item_color="brown" + + cold_protection = ARMS + min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = ARMS + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/gloves/black/strip // gloves for stripping items + siemens_coefficient = 0.2 + + +/obj/item/clothing/gloves/black/hos + name = "head of security's gloves" + item_color = "hosred" //Exists for washing machines. + +/obj/item/clothing/gloves/black/ce + name = "chief engineer's gloves" + item_color = "chief" //Exists for washing machines. + + +/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 = "orangegloves" + item_color="orange" + +/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 = "redgloves" + item_color = "red" + +/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 = "rainbowgloves" + item_color = "rainbow" + +/obj/item/clothing/gloves/rainbow/clown + item_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 = "bluegloves" + item_color="blue" + +/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 = "purplegloves" + item_color="purple" + +/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 = "greengloves" + item_color="green" + +/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 = "graygloves" + item_color="grey" + +/obj/item/clothing/gloves/grey/rd + item_color = "director" //Exists for washing machines. Is not different from gray gloves in any way. + +/obj/item/clothing/gloves/grey/hop + item_color = "hop" //Exists for washing machines. Is not different from gray gloves in any way. + + +/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 = "lightbrowngloves" + item_color="light brown" + +/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" + item_color="brown" + +/obj/item/clothing/gloves/brown/cargo + item_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 8642728a4dca..4cc923bb24fa 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -1,135 +1,135 @@ -/obj/item/clothing/gloves/captain - desc = "Regal blue gloves, with a nice gold trim. Swanky." - name = "captain's gloves" - icon_state = "captain" - item_state = "egloves" - item_color = "captain" - cold_protection = ARMS - min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = ARMS - max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/gloves/cyborg - desc = "beep... boop... borp..." - name = "cyborg gloves" - icon_state = "black" - item_state = "r_hands" - siemens_coefficient = 1.0 - -/obj/item/clothing/gloves/swat - desc = "These tactical gloves are somewhat fire and impact-resistant." - name = "\improper SWAT Gloves" - icon_state = "black" - item_state = "swat_gl" - siemens_coefficient = 0.6 - permeability_coefficient = 0.05 - - cold_protection = ARMS - min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = ARMS - max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE - -/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 = "swat_gl" - siemens_coefficient = 0 - permeability_coefficient = 0.05 - cold_protection = ARMS - min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = ARMS - max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/gloves/latex - name = "latex gloves" - desc = "Sterile latex gloves." - icon_state = "latex" - item_state = "lgloves" - siemens_coefficient = 0.30 - permeability_coefficient = 0.01 - item_color="white" - germ_level = 0 - -/obj/item/clothing/gloves/latex/nitrile - name = "nitrile gloves" - desc = "Sterile nitrile gloves" - icon_state = "nitrile" - item_state = "ngloves" - -/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 = "ggloves" - permeability_coefficient = 0.9 - siemens_coefficient = 0.9 - -/obj/item/clothing/gloves/security //Sec gloves - desc = "Heavily padded heavy-duty red security gloves." - name = "security gloves" - icon_state = "security_red" - item_state = "security_red" - siemens_coefficient = 0.5 - permeability_coefficient = 0.04 - cold_protection = ARMS - min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = ARMS - max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/gloves/fingerless - desc = "A pair of gloves. They don't seem to have fingers." - name = "black fingerless gloves" - icon_state = "fingerless_black" - item_state = "fingerless_black" - item_color="black" - clipped = TRUE - species_restricted = list("exclude","stunglove") - -/obj/item/clothing/gloves/fingerless/red - name = "red fingerless gloves" - icon_state = "fingerless_red" - item_state = "fingerless_red" - item_color="red" - -/obj/item/clothing/gloves/fingerless/orange - name = "orange fingerless gloves" - icon_state = "fingerless_orange" - item_state = "fingerless_orange" - item_color="orange" - -/obj/item/clothing/gloves/fingerless/green - name = "green fingerless gloves" - icon_state = "fingerless_green" - item_state = "fingerless_green" - item_color="green" - -/obj/item/clothing/gloves/fingerless/blue - name = "blue fingerless gloves" - icon_state = "fingerless_blue" - item_state = "fingerless_blue" - item_color="blue" - -/obj/item/clothing/gloves/fingerless/purple - name = "purple fingerless gloves" - icon_state = "fingerless_purple" - item_state = "fingerless_purple" - item_color="purple" - -/obj/item/clothing/gloves/fingerless/yellow - name = "yellow fingerless gloves" - icon_state = "fingerless_yellow" - item_state = "fingerless_yellow" - item_color="yellow" - -/obj/item/clothing/gloves/fingerless/rainbow - name = "rainbow fingerless gloves" - icon_state = "fingerless_rainbow" - item_state = "fingerless_rainbow" - item_color="rainbow" - -/obj/item/clothing/gloves/security/marinad - desc = "These were made to hold a full automatic gun." - name = "marine gloves" - icon_state = "marinad" - item_state = "bgloves" +/obj/item/clothing/gloves/captain + desc = "Regal blue gloves, with a nice gold trim. Swanky." + name = "captain's gloves" + icon_state = "captain" + item_state = "egloves" + item_color = "captain" + cold_protection = ARMS + min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = ARMS + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/gloves/cyborg + desc = "beep... boop... borp..." + name = "cyborg gloves" + icon_state = "black" + item_state = "r_hands" + siemens_coefficient = 1.0 + +/obj/item/clothing/gloves/swat + desc = "These tactical gloves are somewhat fire and impact-resistant." + name = "\improper SWAT Gloves" + icon_state = "black" + item_state = "swat_gl" + siemens_coefficient = 0.6 + permeability_coefficient = 0.05 + + cold_protection = ARMS + min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = ARMS + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + +/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 = "swat_gl" + siemens_coefficient = 0 + permeability_coefficient = 0.05 + cold_protection = ARMS + min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = ARMS + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/gloves/latex + name = "latex gloves" + desc = "Sterile latex gloves." + icon_state = "latex" + item_state = "lgloves" + siemens_coefficient = 0.30 + permeability_coefficient = 0.01 + item_color="white" + germ_level = 0 + +/obj/item/clothing/gloves/latex/nitrile + name = "nitrile gloves" + desc = "Sterile nitrile gloves" + icon_state = "nitrile" + item_state = "ngloves" + +/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 = "ggloves" + permeability_coefficient = 0.9 + siemens_coefficient = 0.9 + +/obj/item/clothing/gloves/security //Sec gloves + desc = "Heavily padded heavy-duty red security gloves." + name = "security gloves" + icon_state = "security_red" + item_state = "security_red" + siemens_coefficient = 0.5 + permeability_coefficient = 0.04 + cold_protection = ARMS + min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = ARMS + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/gloves/fingerless + desc = "A pair of gloves. They don't seem to have fingers." + name = "black fingerless gloves" + icon_state = "fingerless_black" + item_state = "fingerless_black" + item_color="black" + clipped = TRUE + species_restricted = list("exclude","stunglove") + +/obj/item/clothing/gloves/fingerless/red + name = "red fingerless gloves" + icon_state = "fingerless_red" + item_state = "fingerless_red" + item_color="red" + +/obj/item/clothing/gloves/fingerless/orange + name = "orange fingerless gloves" + icon_state = "fingerless_orange" + item_state = "fingerless_orange" + item_color="orange" + +/obj/item/clothing/gloves/fingerless/green + name = "green fingerless gloves" + icon_state = "fingerless_green" + item_state = "fingerless_green" + item_color="green" + +/obj/item/clothing/gloves/fingerless/blue + name = "blue fingerless gloves" + icon_state = "fingerless_blue" + item_state = "fingerless_blue" + item_color="blue" + +/obj/item/clothing/gloves/fingerless/purple + name = "purple fingerless gloves" + icon_state = "fingerless_purple" + item_state = "fingerless_purple" + item_color="purple" + +/obj/item/clothing/gloves/fingerless/yellow + name = "yellow fingerless gloves" + icon_state = "fingerless_yellow" + item_state = "fingerless_yellow" + item_color="yellow" + +/obj/item/clothing/gloves/fingerless/rainbow + name = "rainbow fingerless gloves" + icon_state = "fingerless_rainbow" + item_state = "fingerless_rainbow" + item_color="rainbow" + +/obj/item/clothing/gloves/security/marinad + desc = "These were made to hold a full automatic gun." + name = "marine gloves" + icon_state = "marinad" + item_state = "bgloves" diff --git a/code/modules/clothing/gloves/stungloves.dm b/code/modules/clothing/gloves/stungloves.dm index 47bb62e5b13e..c77570ef3771 100644 --- a/code/modules/clothing/gloves/stungloves.dm +++ b/code/modules/clothing/gloves/stungloves.dm @@ -1,93 +1,93 @@ -/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 - - //add wires - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = W - if (clipped) - to_chat(user, "The [src] are too badly mangled for wiring.") - return - - if(wired) - to_chat(user, "The [src] are already wired.") - return - - if(!C.use(2)) - to_chat(user, "There is not enough wire to cover the [src].") - return - - wired = TRUE - siemens_coefficient = 3.0 - to_chat(user, "You wrap some wires around the [src].") - update_icon() - return - - //add cell - else if(istype(W, /obj/item/weapon/stock_parts/cell)) - if(!wired) - to_chat(user, "The [src] need to be wired first.") - else if(!cell) - user.drop_item() - W.loc = src - cell = W - to_chat(user, "You attach the [cell] to the [src].") - update_icon() - else - to_chat(user, "A [cell] is already attached to the [src].") - return - - else if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel)) - - //stunglove stuff - if(cell) - cell.updateicon() - to_chat(user, "You cut the [cell] away from the [src].") - cell.loc = get_turf(src.loc) - cell = null - update_icon() - return - if(wired) //wires disappear into the void because fuck that shit - wired = FALSE - siemens_coefficient = initial(siemens_coefficient) - to_chat(user, "You cut the wires away from the [src].") - update_icon() - return - - //clipping fingertips - if(!clipped) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) - user.visible_message("\red [user] cuts the fingertips off of the [src].","\red You cut the fingertips off of the [src].") - - clipped = TRUE - protect_fingers = FALSE - name = "mangled [name]" - desc = "[desc]
                    They have had the fingertips cut off of them." - if("exclude" in species_restricted) - species_restricted -= UNATHI - species_restricted -= TAJARAN - else - to_chat(user, "The [src] have already been clipped!") - return - ..() - -/obj/item/clothing/gloves/update_icon() - ..() - overlays.Cut() - if(wired) - overlays += image(icon = icon, icon_state = "gloves_wire") - if(cell) - overlays += image(icon = icon, icon_state = "gloves_cell") - if(wired && cell) - var/obj/item/weapon/stock_parts/cell/C = cell - if(!C.charge) - item_state = "stungloves_charge" - else - item_state = "stungloves" - else - item_state = initial(item_state) - if(ishuman(src.loc)) // Update item_state if src in gloves slot - 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 + + //add wires + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = W + if (clipped) + to_chat(user, "The [src] are too badly mangled for wiring.") + return + + if(wired) + to_chat(user, "The [src] are already wired.") + return + + if(!C.use(2)) + to_chat(user, "There is not enough wire to cover the [src].") + return + + wired = TRUE + siemens_coefficient = 3.0 + to_chat(user, "You wrap some wires around the [src].") + update_icon() + return + + //add cell + else if(istype(W, /obj/item/weapon/stock_parts/cell)) + if(!wired) + to_chat(user, "The [src] need to be wired first.") + else if(!cell) + user.drop_item() + W.loc = src + cell = W + to_chat(user, "You attach the [cell] to the [src].") + update_icon() + else + to_chat(user, "A [cell] is already attached to the [src].") + return + + else if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel)) + + //stunglove stuff + if(cell) + cell.updateicon() + to_chat(user, "You cut the [cell] away from the [src].") + cell.loc = get_turf(src.loc) + cell = null + update_icon() + return + if(wired) //wires disappear into the void because fuck that shit + wired = FALSE + siemens_coefficient = initial(siemens_coefficient) + to_chat(user, "You cut the wires away from the [src].") + update_icon() + return + + //clipping fingertips + if(!clipped) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + user.visible_message("\red [user] cuts the fingertips off of the [src].","\red You cut the fingertips off of the [src].") + + clipped = TRUE + protect_fingers = FALSE + name = "mangled [name]" + desc = "[desc]
                    They have had the fingertips cut off of them." + if("exclude" in species_restricted) + species_restricted -= UNATHI + species_restricted -= TAJARAN + else + to_chat(user, "The [src] have already been clipped!") + return + ..() + +/obj/item/clothing/gloves/update_icon() + ..() + overlays.Cut() + if(wired) + overlays += image(icon = icon, icon_state = "gloves_wire") + if(cell) + overlays += image(icon = icon, icon_state = "gloves_cell") + if(wired && cell) + var/obj/item/weapon/stock_parts/cell/C = cell + if(!C.charge) + item_state = "stungloves_charge" + else + item_state = "stungloves" + else + item_state = initial(item_state) + if(ishuman(src.loc)) // Update item_state if src in gloves slot + 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 03fd2cf98f0b..f21b78d2b28e 100644 --- a/code/modules/clothing/head/collectable.dm +++ b/code/modules/clothing/head/collectable.dm @@ -1,131 +1,131 @@ - -//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 hat" - desc = "an ultra rare hat. It commands a certain respect." - icon_state = "petehat" - -/obj/item/clothing/head/collectable/slime - name = "collectable slime cap!" - desc = "It just latches right in place!" - icon_state = "slime" - body_parts_covered = 0 - -/obj/item/clothing/head/collectable/xenom - name = "collectable xenomorph helmet!" - desc = "Hiss hiss hiss!" - icon_state = "xenom" - body_parts_covered = HEAD|FACE|EYES - -/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 = "chefhat" - -/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" - body_parts_covered = 0 - -/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" - body_parts_covered = 0 - -/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" - body_parts_covered = 0 - -/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" - body_parts_covered = 0 - -/obj/item/clothing/head/collectable/beret - name = "collectable beret" - desc = "A Collectable red Beret. It smells faintly of Garlic." - icon_state = "beret" - body_parts_covered = 0 - -/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" - body_parts_covered = HEAD|FACE|EYES - -/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" - body_parts_covered = 0 - -/obj/item/clothing/head/collectable/kitty - name = "collectable kitty ears" - desc = "The fur feels.....a bit too realistic." - icon_state = "kitty" - item_state = "kitty" - body_parts_covered = 0 - -/obj/item/clothing/head/collectable/rabbitears - name = "collectable rabbit ears" - desc = "Not as lucky as the feet!" - icon_state = "bunny" - item_state = "bunny" - body_parts_covered = 0 - -/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" - body_parts_covered = 0 - -/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" - body_parts_covered = 0 - -/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" + +//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 hat" + desc = "an ultra rare hat. It commands a certain respect." + icon_state = "petehat" + +/obj/item/clothing/head/collectable/slime + name = "collectable slime cap!" + desc = "It just latches right in place!" + icon_state = "slime" + body_parts_covered = 0 + +/obj/item/clothing/head/collectable/xenom + name = "collectable xenomorph helmet!" + desc = "Hiss hiss hiss!" + icon_state = "xenom" + body_parts_covered = HEAD|FACE|EYES + +/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 = "chefhat" + +/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" + body_parts_covered = 0 + +/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" + body_parts_covered = 0 + +/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" + body_parts_covered = 0 + +/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" + body_parts_covered = 0 + +/obj/item/clothing/head/collectable/beret + name = "collectable beret" + desc = "A Collectable red Beret. It smells faintly of Garlic." + icon_state = "beret" + body_parts_covered = 0 + +/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" + body_parts_covered = HEAD|FACE|EYES + +/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" + body_parts_covered = 0 + +/obj/item/clothing/head/collectable/kitty + name = "collectable kitty ears" + desc = "The fur feels.....a bit too realistic." + icon_state = "kitty" + item_state = "kitty" + body_parts_covered = 0 + +/obj/item/clothing/head/collectable/rabbitears + name = "collectable rabbit ears" + desc = "Not as lucky as the feet!" + icon_state = "bunny" + item_state = "bunny" + body_parts_covered = 0 + +/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" + body_parts_covered = 0 + +/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" + body_parts_covered = 0 + +/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" diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 3ce6877f3abd..11c3ba78db0b 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -1,169 +1,169 @@ -/obj/item/clothing/head/helmet - name = "helmet" - desc = "Standard Security gear. Protects the head from impacts." - icon_state = "helmet" - flags = HEADCOVERSEYES | THICKMATERIAL - item_state = "helmet" - armor = list(melee = 50, bullet = 60, laser = 50,energy = 20, bomb = 35, bio = 0, rad = 0) - flags_inv = HIDEEARS|HIDEEYES - 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.3 - w_class = 3 - -/obj/item/clothing/head/helmet/warden - name = "warden's hat" - desc = "It's a special helmet issued to the Warden of a security force. Protects the head from impacts." - icon_state = "helmet_warden" - -/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 = HEADCOVERSEYES - armor = list(melee = 80, bullet = 60, laser = 50,energy = 10, bomb = 25, bio = 10, rad = 0) - flags_inv = HIDEEARS - body_parts_covered = 0 - siemens_coefficient = 0.8 - -/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 - body_parts_covered = 1 - -/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 = HEADCOVERSEYES | THICKMATERIAL | HEADCOVERSMOUTH - armor = list(melee = 82, bullet = 15, laser = 5,energy = 5, bomb = 5, bio = 2, rad = 0) - flags_inv = HIDEEARS - siemens_coefficient = 0.3 - action_button_name = "Adjust helmet visor" - var/up = 0 - -/obj/item/clothing/head/helmet/riot/attack_self() - toggle() - -/obj/item/clothing/head/helmet/riot/verb/toggle() - set category = "Object" - set name = "Adjust helmet visor" - set src in usr - - if(usr.canmove && !usr.stat && !usr.restrained()) - if(src.up) - src.up = !src.up - src.flags |= (HEADCOVERSEYES | HEADCOVERSMOUTH) - icon_state = initial(icon_state) - to_chat(usr, "You pull the visor down on") - else - src.up = !src.up - src.flags &= ~(HEADCOVERSEYES | HEADCOVERSMOUTH) - icon_state = "[initial(icon_state)]up" - to_chat(usr, "You push the visor up on") - usr.update_inv_head() //so our mob-overlays update - -/obj/item/clothing/head/helmet/bulletproof - name = "bulletproof helmet" - desc = "A bulletproof security helmet that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." - icon_state = "bulletproof" - -/obj/item/clothing/head/helmet/laserproof - name = "ablative helmet" - desc = "A ablative security helmet that excels in protecting the wearer against energy and laser projectiles." - icon_state = "laserproof" - armor = list(melee = 10, bullet = 10, laser = 45,energy = 55, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0 - - var/hit_reflect_chance = 40 - -/obj/item/clothing/head/helmet/laserproof/IsReflect(def_zone) - if(prob(hit_reflect_chance)) - return TRUE - -/obj/item/clothing/head/helmet/swat - name = "\improper SWAT helmet" - desc = "They're often used by highly trained Swat Members." - icon_state = "swat" - flags = HEADCOVERSEYES | THICKMATERIAL - item_state = "swat" - armor = list(melee = 80, bullet = 75, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) - flags_inv = HIDEEARS|HIDEEYES - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0.3 - -/obj/item/clothing/head/helmet/thunderdome - name = "\improper thunderdome helmet" - desc = "'Let the battle commence!'" - icon_state = "thunderdome" - flags = HEADCOVERSEYES - 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 = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR - item_state = "gladiator" - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES - siemens_coefficient = 1 - -/obj/item/clothing/head/helmet/tactical - name = "tactical helmet" - desc = "An armored helmet capable of being fitted with a multitude of attachments." - icon_state = "swathelm" - item_state = "helmet" - flags = HEADCOVERSEYES - armor = list(melee = 62, bullet = 60, laser = 50,energy = 35, bomb = 10, bio = 2, rad = 0) - flags_inv = HIDEEARS - siemens_coefficient = 0.7 - -/obj/item/clothing/head/helmet/tactical/marinad - name = "marine helmet" - desc = "Spectrum alloy helmet. Lightweight and ready for action." - icon_state = "marinad" - item_state = "marinad_helmet" - - -/obj/item/clothing/head/helmet/helmet_of_justice - name = "helmet of justice" - desc = "Prepare for Justice!" - icon_state = "shitcuritron_0" - item_state = "helmet" - var/on = 0 - action_button_name = "Toggle Helmet" - -/obj/item/clothing/head/helmet/helmet_of_justice/attack_self(mob/user) - on = !on - icon_state = "shitcuritron_[on]" - user.update_inv_head() - -/obj/item/clothing/head/helmet/warden/blue - 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 = "oldwardenhelm" - item_state = "helmet" - -/obj/item/clothing/head/helmet/roman - name = "roman helmet" - desc = "An ancient helmet made of bronze and leather." - armor = list(melee = 25, bullet = 0, laser = 25, 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." - icon_state = "roman_c" - item_state = "roman_c" +/obj/item/clothing/head/helmet + name = "helmet" + desc = "Standard Security gear. Protects the head from impacts." + icon_state = "helmet" + flags = HEADCOVERSEYES | THICKMATERIAL + item_state = "helmet" + armor = list(melee = 50, bullet = 60, laser = 50,energy = 20, bomb = 35, bio = 0, rad = 0) + flags_inv = HIDEEARS|HIDEEYES + 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.3 + w_class = 3 + +/obj/item/clothing/head/helmet/warden + name = "warden's hat" + desc = "It's a special helmet issued to the Warden of a security force. Protects the head from impacts." + icon_state = "helmet_warden" + +/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 = HEADCOVERSEYES + armor = list(melee = 80, bullet = 60, laser = 50,energy = 10, bomb = 25, bio = 10, rad = 0) + flags_inv = HIDEEARS + body_parts_covered = 0 + siemens_coefficient = 0.8 + +/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 + body_parts_covered = 1 + +/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 = HEADCOVERSEYES | THICKMATERIAL | HEADCOVERSMOUTH + armor = list(melee = 82, bullet = 15, laser = 5,energy = 5, bomb = 5, bio = 2, rad = 0) + flags_inv = HIDEEARS + siemens_coefficient = 0.3 + action_button_name = "Adjust helmet visor" + var/up = 0 + +/obj/item/clothing/head/helmet/riot/attack_self() + toggle() + +/obj/item/clothing/head/helmet/riot/verb/toggle() + set category = "Object" + set name = "Adjust helmet visor" + set src in usr + + if(usr.canmove && !usr.stat && !usr.restrained()) + if(src.up) + src.up = !src.up + src.flags |= (HEADCOVERSEYES | HEADCOVERSMOUTH) + icon_state = initial(icon_state) + to_chat(usr, "You pull the visor down on") + else + src.up = !src.up + src.flags &= ~(HEADCOVERSEYES | HEADCOVERSMOUTH) + icon_state = "[initial(icon_state)]up" + to_chat(usr, "You push the visor up on") + usr.update_inv_head() //so our mob-overlays update + +/obj/item/clothing/head/helmet/bulletproof + name = "bulletproof helmet" + desc = "A bulletproof security helmet that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." + icon_state = "bulletproof" + +/obj/item/clothing/head/helmet/laserproof + name = "ablative helmet" + desc = "A ablative security helmet that excels in protecting the wearer against energy and laser projectiles." + icon_state = "laserproof" + armor = list(melee = 10, bullet = 10, laser = 45,energy = 55, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0 + + var/hit_reflect_chance = 40 + +/obj/item/clothing/head/helmet/laserproof/IsReflect(def_zone) + if(prob(hit_reflect_chance)) + return TRUE + +/obj/item/clothing/head/helmet/swat + name = "\improper SWAT helmet" + desc = "They're often used by highly trained Swat Members." + icon_state = "swat" + flags = HEADCOVERSEYES | THICKMATERIAL + item_state = "swat" + armor = list(melee = 80, bullet = 75, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) + flags_inv = HIDEEARS|HIDEEYES + cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.3 + +/obj/item/clothing/head/helmet/thunderdome + name = "\improper thunderdome helmet" + desc = "'Let the battle commence!'" + icon_state = "thunderdome" + flags = HEADCOVERSEYES + 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 = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR + item_state = "gladiator" + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES + siemens_coefficient = 1 + +/obj/item/clothing/head/helmet/tactical + name = "tactical helmet" + desc = "An armored helmet capable of being fitted with a multitude of attachments." + icon_state = "swathelm" + item_state = "helmet" + flags = HEADCOVERSEYES + armor = list(melee = 62, bullet = 60, laser = 50,energy = 35, bomb = 10, bio = 2, rad = 0) + flags_inv = HIDEEARS + siemens_coefficient = 0.7 + +/obj/item/clothing/head/helmet/tactical/marinad + name = "marine helmet" + desc = "Spectrum alloy helmet. Lightweight and ready for action." + icon_state = "marinad" + item_state = "marinad_helmet" + + +/obj/item/clothing/head/helmet/helmet_of_justice + name = "helmet of justice" + desc = "Prepare for Justice!" + icon_state = "shitcuritron_0" + item_state = "helmet" + var/on = 0 + action_button_name = "Toggle Helmet" + +/obj/item/clothing/head/helmet/helmet_of_justice/attack_self(mob/user) + on = !on + icon_state = "shitcuritron_[on]" + user.update_inv_head() + +/obj/item/clothing/head/helmet/warden/blue + 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 = "oldwardenhelm" + item_state = "helmet" + +/obj/item/clothing/head/helmet/roman + name = "roman helmet" + desc = "An ancient helmet made of bronze and leather." + armor = list(melee = 25, bullet = 0, laser = 25, 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." + icon_state = "roman_c" + item_state = "roman_c" diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index a6560100b0b7..077b5eb19e00 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -1,96 +1,96 @@ - -//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 = "chefhat" - desc = "The commander in chef's head wear." - 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." - 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_inv = 0 - body_parts_covered = 0 - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0.9 - body_parts_covered = 0 - -//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 = HEADCOVERSEYES|BLOCKHAIR - siemens_coefficient = 0.9 - body_parts_covered = HEAD|EYES - -//Chaplain -/obj/item/clothing/head/nun_hood - name = "nun hood" - desc = "Maximum piety in this star system." - icon_state = "nun_hood" - flags = HEADCOVERSEYES|BLOCKHAIR - siemens_coefficient = 0.9 - -//Mime -/obj/item/clothing/head/beret - name = "beret" - desc = "A beret, an artists favorite headwear." - icon_state = "beret" - siemens_coefficient = 0.9 - body_parts_covered = 0 - -//Security -/obj/item/clothing/head/beret/sec - name = "officer's 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" - -/obj/item/clothing/head/beret/sec/warden - name = "warden's beret" - desc = "A beret with the copper security insignia emblazoned on it. For wardens that are more inclined towards style than safety." - icon_state = "beret_warden" - -/obj/item/clothing/head/beret/sec/hos - name = "head of security's beret" - desc = "A beret with the gold security insignia emblazoned on it. Shows who has the longest baton on the station." - icon_state = "beret_hos" - -//Engineering -/obj/item/clothing/head/beret/eng - name = "engineering beret" - desc = "A beret with the engineering insignia emblazoned on it. For engineers that are more inclined towards style than safety." - icon_state = "e_beret_badge" - -//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 = BLOCKHEADHAIR - -/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 = "chefhat" + desc = "The commander in chef's head wear." + 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." + 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_inv = 0 + body_parts_covered = 0 + cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.9 + body_parts_covered = 0 + +//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 = HEADCOVERSEYES|BLOCKHAIR + siemens_coefficient = 0.9 + body_parts_covered = HEAD|EYES + +//Chaplain +/obj/item/clothing/head/nun_hood + name = "nun hood" + desc = "Maximum piety in this star system." + icon_state = "nun_hood" + flags = HEADCOVERSEYES|BLOCKHAIR + siemens_coefficient = 0.9 + +//Mime +/obj/item/clothing/head/beret + name = "beret" + desc = "A beret, an artists favorite headwear." + icon_state = "beret" + siemens_coefficient = 0.9 + body_parts_covered = 0 + +//Security +/obj/item/clothing/head/beret/sec + name = "officer's 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" + +/obj/item/clothing/head/beret/sec/warden + name = "warden's beret" + desc = "A beret with the copper security insignia emblazoned on it. For wardens that are more inclined towards style than safety." + icon_state = "beret_warden" + +/obj/item/clothing/head/beret/sec/hos + name = "head of security's beret" + desc = "A beret with the gold security insignia emblazoned on it. Shows who has the longest baton on the station." + icon_state = "beret_hos" + +//Engineering +/obj/item/clothing/head/beret/eng + name = "engineering beret" + desc = "A beret with the engineering insignia emblazoned on it. For engineers that are more inclined towards style than safety." + icon_state = "e_beret_badge" + +//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 = BLOCKHEADHAIR + +/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 77b2e460552b..673a5b672808 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -1,391 +1,391 @@ -/obj/item/clothing/head/centhat - name = "\improper CentComm. hat" - icon_state = "centcom" - desc = "It's good to be emperor." - item_state = "centhat" - siemens_coefficient = 0.9 - body_parts_covered = 0 - -/obj/item/clothing/head/hairflower - name = "hair flower pin" - icon_state = "hairflower" - desc = "Smells nice." - item_state = "hairflower" - body_parts_covered = 0 - -/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" - siemens_coefficient = 0.9 - body_parts_covered = 0 - -/obj/item/clothing/head/redcoat - name = "redcoat's hat" - icon_state = "redcoat" - desc = "'I guess it's a redhead.'" - body_parts_covered = 0 - -/obj/item/clothing/head/mailman - name = "mailman's hat" - icon_state = "mailman" - desc = "'Right-on-time' mail service head wear." - body_parts_covered = 0 - -/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" - permeability_coefficient = 0.01 - siemens_coefficient = 0.9 - body_parts_covered = 0 - -/obj/item/clothing/head/hasturhood - name = "hastur's hood" - desc = "It's unspeakably stylish." - icon_state = "hasturhood" - flags = HEADCOVERSEYES|BLOCKHAIR - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/head/nursehat - name = "nurse's hat" - desc = "It allows quick identification of trained medical personnel." - icon_state = "nursehat" - siemens_coefficient = 0.9 - body_parts_covered = 0 - -/obj/item/clothing/head/syndicatefake - name = "red space-helmet replica" - icon_state = "syndicate-helm" - item_state = "syndicate-helm" - 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 = BLOCKHAIR - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - siemens_coefficient = 2.0 - body_parts_covered = HEAD|FACE|EYES - -/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 = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR - item_state="cueball" - flags_inv = 0 - body_parts_covered = HEAD|FACE|EYES - -/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 = HEADCOVERSEYES | HEADCOVERSMOUTH - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/head/justice - name = "justice hat" - desc = "Fight for what's righteous!" - icon_state = "justicered" - item_state = "justicered" - flags = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR - flags_inv = HIDEEARS|HIDEEYES|HIDEFACE - body_parts_covered = HEAD|FACE|EYES - -/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" - body_parts_covered = 0 - -/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" - body_parts_covered = 0 - -/obj/item/clothing/head/hgpiratecap - name = "pirate hat" - desc = "Yarr." - icon_state = "hgpiratecap" - item_state = "hgpiratecap" - body_parts_covered = 0 - -/obj/item/clothing/head/bandana - name = "pirate bandana" - desc = "Yarr." - icon_state = "bandana" - item_state = "bandana" - -/obj/item/clothing/head/bowler - name = "bowler-hat" - desc = "Gentleman, elite aboard!" - icon_state = "bowler" - item_state = "bowler" - body_parts_covered = 0 - -//stylish bs12 hats - -/obj/item/clothing/head/feathertrilby - name = "\improper feather trilby" - icon_state = "feather_trilby" - item_state = "feather_trilby" - desc = "A sharp, stylish hat with a feather." - -/obj/item/clothing/head/fez - name = "\improper fez" - icon_state = "fez" - item_state = "fez" - desc = "You should wear a fez. Fezzes are cool." - -//end bs12 hats - -/obj/item/clothing/head/witchwig - name = "witch costume wig" - desc = "Eeeee~heheheheheheh!" - icon_state = "witch" - item_state = "witch" - flags = BLOCKHAIR - siemens_coefficient = 2.0 - -/obj/item/clothing/head/chicken - name = "chicken suit head" - desc = "Bkaw!" - icon_state = "chickenhead" - item_state = "chickensuit" - flags = BLOCKHAIR - siemens_coefficient = 2.0 - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/head/bearpelt - name = "bear pelt hat" - desc = "Fuzzy." - icon_state = "bearpelt" - item_state = "bearpelt" - flags = BLOCKHAIR - siemens_coefficient = 2.0 - -/obj/item/clothing/head/headscarf - name = "zhan headscarf" - icon_state = "zhan_scarf" - item_state = "zhan_scarf" - desc = "White headscarf" - body_parts_covered = 0 - species_restricted = list(UNATHI , TAJARAN , HUMAN , DIONA , IPC) - -/obj/item/clothing/head/skrell_headwear - name = "skrell yellow headwear" - icon_state = "skrell_yellow" - item_state = "skrell_yellow" - desc = "Just two pieces of yellow cloth" - body_parts_covered = 0 - species_restricted = list(SKRELL) - -/obj/item/clothing/head/skrell_headwear/red - name = "skrell red headwear" - icon_state = "skrell_red" - item_state = "skrell_red" - desc = "Just two pieces of red cloth" - body_parts_covered = 0 - species_restricted = list(SKRELL) - -/obj/item/clothing/head/skrell_headwear/blue - name = "skrell blue headwear" - icon_state = "skrell_blue" - item_state = "skrell_blue" - desc = "Just two pieces of blue cloth" - body_parts_covered = 0 - species_restricted = list(SKRELL) - -/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 = BLOCKHAIR - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - siemens_coefficient = 2.0 - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/head/fedora - name = "fedora" - icon_state = "fedora" - item_state = "fedora" - desc = "A really cool hat if you're a mobster. A really lame hat if you're not." - action_button_name = "Tip Fedora" - -/obj/item/clothing/head/fedora/attack_self(mob/user) - fedoraproc(user) - -/obj/item/clothing/head/fedora/proc/fedoraproc(mob/user) - if(user.canmove && !user.stat && !user.restrained()) - for(var/mob/living/carbon/M in range(7,src)) - M.show_message("[user] tips their fedora.") - -/obj/item/clothing/head/fedora/verb/fedoratip() - set category = "Object" - set name = "Tip Fedora" - set src in usr - - fedoraproc(usr) - -/obj/item/clothing/head/fedora/black - name = "fedora" - desc = "Someone wearing this definitely makes them cool." - icon_state = "hat_black" - -/obj/item/clothing/head/fedora/white - name = "white fedora" - desc = "Someone wearing this definitely makes them cool." - icon_state = "hat_white" - -/obj/item/clothing/head/fedora/brown - name = "brown fedora" - desc = "Someone wearing this definitely makes them cool." - icon_state = "hat_brown" - - -/obj/item/clothing/head/batman_helmet - name = "Batman helmet" - desc = "It's not who you are underneath, it's what you do that defines you." - icon_state = "batman_helmet" - item_state = "batman_helmet" - flags = HEADCOVERSEYES | HEADCOVERSMOUTH | BLOCKHAIR - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/head/beret/rosa - name = "white beret" - icon_state = "rosas_hat" - item_state = "helmet" - -/obj/item/clothing/head/sombrero - name = "sombrero" - icon_state = "sombrero" - item_state = "helmet" - desc = "You feel mexican just wearing this." - -/obj/item/clothing/head/sombrero/green - name = "green sombrero" - icon_state = "greensombrero" - item_state = "greensombrero" - desc = "As elegant as a dancing cactus." - -/obj/item/clothing/head/sombrero/shamebrero - name = "shamebrero" - icon_state = "shamebrero" - item_state = "shamebrero" - desc = "You never asked for this." - -/obj/item/clothing/head/western - name = "western hat" - icon_state = "western_hat" - item_state = "western_hat" - -/obj/item/clothing/head/western/cowboy - name = "cowboy hat" - icon_state = "cowboy_hat" - item_state = "cowboy_hat" - desc = "Howdy, partner!" - -/obj/item/clothing/head/indiana - name = "leather hat" - icon_state = "indiana_hat" - item_state = "indiana_hat" - desc = "Be aware of rolling boulders." - -/obj/item/clothing/head/necromancer_hood - name = "necromancer's hood" - desc = "It's hood that covers the head." - icon_state = "necromancer" - item_state = "necromancer" - flags = HEADCOVERSEYES|BLOCKHAIR - siemens_coefficient = 0.9 - -/obj/item/clothing/head/chaplain_hood/brown - name = "brown hood" - icon_state = "brown_hood" - -/obj/item/clothing/head/chaplain_hood/green - name = "green hood" - icon_state = "green_hood" - -/obj/item/clothing/head/beret/red - name = "red beret" - desc = "Bonjour, but in red. Smells like baguette, pardon my French." - icon_state = "beret_red" - -/obj/item/clothing/head/beret/blue - name = "blue beret" - desc = "Bonjour, but in blue. Smells like baguette, pardon my French." - icon_state = "beret_blue" - -/obj/item/clothing/head/beret/black - name = "black beret" - desc = "Bonjour, but in black. Smells like baguette, pardon my French." - icon_state = "beret_black" - -/obj/item/clothing/head/beret/purple - name = "purple beret" - desc = "Bonjour, but in purple. Smells like baguette, pardon my French." - icon_state = "beret_purple" - -/obj/item/clothing/head/beret/centcomofficer - name = "officers beret" - desc = "A black beret adorned with the shield silver kite shield with an engraved sword of the NanoTrasen security forces, announcing to the world that the wearer is a defender of NanoTrasen." - icon_state = "centcomofficerberet" - -/obj/item/clothing/head/beret/centcomcaptain - name = "captains beret" - desc = "A white beret adorned with the shield cobalt kite shield with an engraved sword of the NanoTrasen security forces, worn only by those captaining a vessel of the NanoTrasen Navy." - icon_state = "centcomcaptain" - -/obj/item/clothing/head/angel_nimb - name = "nimb" - desc = "Just a Nimb" - icon_state = "nimb" - -/obj/item/clothing/head/hooded/carp_hood - name = "carp hood" - desc = "A hood attached to a carp costume." - icon_state = "carp_casual" - body_parts_covered = HEAD - cold_protection = HEAD - flags_inv = BLOCKHAIR|HIDEEARS - -/obj/item/clothing/head/hooded/ian_hood - name = "corgi hood" - desc = "A hood that looks just like a corgi's head, it won't guarantee dog biscuits." - icon_state = "ian" - body_parts_covered = HEAD +/obj/item/clothing/head/centhat + name = "\improper CentComm. hat" + icon_state = "centcom" + desc = "It's good to be emperor." + item_state = "centhat" + siemens_coefficient = 0.9 + body_parts_covered = 0 + +/obj/item/clothing/head/hairflower + name = "hair flower pin" + icon_state = "hairflower" + desc = "Smells nice." + item_state = "hairflower" + body_parts_covered = 0 + +/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" + siemens_coefficient = 0.9 + body_parts_covered = 0 + +/obj/item/clothing/head/redcoat + name = "redcoat's hat" + icon_state = "redcoat" + desc = "'I guess it's a redhead.'" + body_parts_covered = 0 + +/obj/item/clothing/head/mailman + name = "mailman's hat" + icon_state = "mailman" + desc = "'Right-on-time' mail service head wear." + body_parts_covered = 0 + +/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" + permeability_coefficient = 0.01 + siemens_coefficient = 0.9 + body_parts_covered = 0 + +/obj/item/clothing/head/hasturhood + name = "hastur's hood" + desc = "It's unspeakably stylish." + icon_state = "hasturhood" + flags = HEADCOVERSEYES|BLOCKHAIR + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/head/nursehat + name = "nurse's hat" + desc = "It allows quick identification of trained medical personnel." + icon_state = "nursehat" + siemens_coefficient = 0.9 + body_parts_covered = 0 + +/obj/item/clothing/head/syndicatefake + name = "red space-helmet replica" + icon_state = "syndicate-helm" + item_state = "syndicate-helm" + 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 = BLOCKHAIR + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + siemens_coefficient = 2.0 + body_parts_covered = HEAD|FACE|EYES + +/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 = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR + item_state="cueball" + flags_inv = 0 + body_parts_covered = HEAD|FACE|EYES + +/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 = HEADCOVERSEYES | HEADCOVERSMOUTH + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/head/justice + name = "justice hat" + desc = "Fight for what's righteous!" + icon_state = "justicered" + item_state = "justicered" + flags = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR + flags_inv = HIDEEARS|HIDEEYES|HIDEFACE + body_parts_covered = HEAD|FACE|EYES + +/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" + body_parts_covered = 0 + +/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" + body_parts_covered = 0 + +/obj/item/clothing/head/hgpiratecap + name = "pirate hat" + desc = "Yarr." + icon_state = "hgpiratecap" + item_state = "hgpiratecap" + body_parts_covered = 0 + +/obj/item/clothing/head/bandana + name = "pirate bandana" + desc = "Yarr." + icon_state = "bandana" + item_state = "bandana" + +/obj/item/clothing/head/bowler + name = "bowler-hat" + desc = "Gentleman, elite aboard!" + icon_state = "bowler" + item_state = "bowler" + body_parts_covered = 0 + +//stylish bs12 hats + +/obj/item/clothing/head/feathertrilby + name = "\improper feather trilby" + icon_state = "feather_trilby" + item_state = "feather_trilby" + desc = "A sharp, stylish hat with a feather." + +/obj/item/clothing/head/fez + name = "\improper fez" + icon_state = "fez" + item_state = "fez" + desc = "You should wear a fez. Fezzes are cool." + +//end bs12 hats + +/obj/item/clothing/head/witchwig + name = "witch costume wig" + desc = "Eeeee~heheheheheheh!" + icon_state = "witch" + item_state = "witch" + flags = BLOCKHAIR + siemens_coefficient = 2.0 + +/obj/item/clothing/head/chicken + name = "chicken suit head" + desc = "Bkaw!" + icon_state = "chickenhead" + item_state = "chickensuit" + flags = BLOCKHAIR + siemens_coefficient = 2.0 + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/head/bearpelt + name = "bear pelt hat" + desc = "Fuzzy." + icon_state = "bearpelt" + item_state = "bearpelt" + flags = BLOCKHAIR + siemens_coefficient = 2.0 + +/obj/item/clothing/head/headscarf + name = "zhan headscarf" + icon_state = "zhan_scarf" + item_state = "zhan_scarf" + desc = "White headscarf" + body_parts_covered = 0 + species_restricted = list(UNATHI , TAJARAN , HUMAN , DIONA , IPC) + +/obj/item/clothing/head/skrell_headwear + name = "skrell yellow headwear" + icon_state = "skrell_yellow" + item_state = "skrell_yellow" + desc = "Just two pieces of yellow cloth" + body_parts_covered = 0 + species_restricted = list(SKRELL) + +/obj/item/clothing/head/skrell_headwear/red + name = "skrell red headwear" + icon_state = "skrell_red" + item_state = "skrell_red" + desc = "Just two pieces of red cloth" + body_parts_covered = 0 + species_restricted = list(SKRELL) + +/obj/item/clothing/head/skrell_headwear/blue + name = "skrell blue headwear" + icon_state = "skrell_blue" + item_state = "skrell_blue" + desc = "Just two pieces of blue cloth" + body_parts_covered = 0 + species_restricted = list(SKRELL) + +/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 = BLOCKHAIR + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + siemens_coefficient = 2.0 + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/head/fedora + name = "fedora" + icon_state = "fedora" + item_state = "fedora" + desc = "A really cool hat if you're a mobster. A really lame hat if you're not." + action_button_name = "Tip Fedora" + +/obj/item/clothing/head/fedora/attack_self(mob/user) + fedoraproc(user) + +/obj/item/clothing/head/fedora/proc/fedoraproc(mob/user) + if(user.canmove && !user.stat && !user.restrained()) + for(var/mob/living/carbon/M in range(7,src)) + M.show_message("[user] tips their fedora.") + +/obj/item/clothing/head/fedora/verb/fedoratip() + set category = "Object" + set name = "Tip Fedora" + set src in usr + + fedoraproc(usr) + +/obj/item/clothing/head/fedora/black + name = "fedora" + desc = "Someone wearing this definitely makes them cool." + icon_state = "hat_black" + +/obj/item/clothing/head/fedora/white + name = "white fedora" + desc = "Someone wearing this definitely makes them cool." + icon_state = "hat_white" + +/obj/item/clothing/head/fedora/brown + name = "brown fedora" + desc = "Someone wearing this definitely makes them cool." + icon_state = "hat_brown" + + +/obj/item/clothing/head/batman_helmet + name = "Batman helmet" + desc = "It's not who you are underneath, it's what you do that defines you." + icon_state = "batman_helmet" + item_state = "batman_helmet" + flags = HEADCOVERSEYES | HEADCOVERSMOUTH | BLOCKHAIR + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/head/beret/rosa + name = "white beret" + icon_state = "rosas_hat" + item_state = "helmet" + +/obj/item/clothing/head/sombrero + name = "sombrero" + icon_state = "sombrero" + item_state = "helmet" + desc = "You feel mexican just wearing this." + +/obj/item/clothing/head/sombrero/green + name = "green sombrero" + icon_state = "greensombrero" + item_state = "greensombrero" + desc = "As elegant as a dancing cactus." + +/obj/item/clothing/head/sombrero/shamebrero + name = "shamebrero" + icon_state = "shamebrero" + item_state = "shamebrero" + desc = "You never asked for this." + +/obj/item/clothing/head/western + name = "western hat" + icon_state = "western_hat" + item_state = "western_hat" + +/obj/item/clothing/head/western/cowboy + name = "cowboy hat" + icon_state = "cowboy_hat" + item_state = "cowboy_hat" + desc = "Howdy, partner!" + +/obj/item/clothing/head/indiana + name = "leather hat" + icon_state = "indiana_hat" + item_state = "indiana_hat" + desc = "Be aware of rolling boulders." + +/obj/item/clothing/head/necromancer_hood + name = "necromancer's hood" + desc = "It's hood that covers the head." + icon_state = "necromancer" + item_state = "necromancer" + flags = HEADCOVERSEYES|BLOCKHAIR + siemens_coefficient = 0.9 + +/obj/item/clothing/head/chaplain_hood/brown + name = "brown hood" + icon_state = "brown_hood" + +/obj/item/clothing/head/chaplain_hood/green + name = "green hood" + icon_state = "green_hood" + +/obj/item/clothing/head/beret/red + name = "red beret" + desc = "Bonjour, but in red. Smells like baguette, pardon my French." + icon_state = "beret_red" + +/obj/item/clothing/head/beret/blue + name = "blue beret" + desc = "Bonjour, but in blue. Smells like baguette, pardon my French." + icon_state = "beret_blue" + +/obj/item/clothing/head/beret/black + name = "black beret" + desc = "Bonjour, but in black. Smells like baguette, pardon my French." + icon_state = "beret_black" + +/obj/item/clothing/head/beret/purple + name = "purple beret" + desc = "Bonjour, but in purple. Smells like baguette, pardon my French." + icon_state = "beret_purple" + +/obj/item/clothing/head/beret/centcomofficer + name = "officers beret" + desc = "A black beret adorned with the shield silver kite shield with an engraved sword of the NanoTrasen security forces, announcing to the world that the wearer is a defender of NanoTrasen." + icon_state = "centcomofficerberet" + +/obj/item/clothing/head/beret/centcomcaptain + name = "captains beret" + desc = "A white beret adorned with the shield cobalt kite shield with an engraved sword of the NanoTrasen security forces, worn only by those captaining a vessel of the NanoTrasen Navy." + icon_state = "centcomcaptain" + +/obj/item/clothing/head/angel_nimb + name = "nimb" + desc = "Just a Nimb" + icon_state = "nimb" + +/obj/item/clothing/head/hooded/carp_hood + name = "carp hood" + desc = "A hood attached to a carp costume." + icon_state = "carp_casual" + body_parts_covered = HEAD + cold_protection = HEAD + flags_inv = BLOCKHAIR|HIDEEARS + +/obj/item/clothing/head/hooded/ian_hood + name = "corgi hood" + desc = "A hood that looks just like a corgi's head, it won't guarantee dog biscuits." + icon_state = "ian" + body_parts_covered = HEAD flags_inv = BLOCKHAIR|HIDEEARS \ 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 0342517f3c0a..cff577de1ccd 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -1,167 +1,167 @@ -/* - * Contents: - * Welding mask - * Cakehat - * Ushanka - * Pumpkin head - * Kitty ears - * - */ - -/* - * 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 = (HEADCOVERSEYES | HEADCOVERSMOUTH) - item_state = "welding" - m_amt = 3000 - g_amt = 1000 - var/up = 0 - 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|FACE|EYES - action_button_name = "Flip Welding Mask" - siemens_coefficient = 0.9 - w_class = 3 - -/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.canmove && !usr.stat && !usr.restrained()) - if(src.up) - src.up = !src.up - src.flags |= (HEADCOVERSEYES | HEADCOVERSMOUTH) - flags_inv |= (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) - icon_state = initial(icon_state) - to_chat(usr, "You flip the [src] down to protect your eyes.") - else - src.up = !src.up - src.flags &= ~(HEADCOVERSEYES | HEADCOVERSMOUTH) - flags_inv &= ~(HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) - icon_state = "[initial(icon_state)]up" - to_chat(usr, "You push the [src] up out of your face.") - usr.update_inv_head() //so our mob-overlays update - - -/* - * Cakehat - */ -/obj/item/clothing/head/cakehat - name = "cake-hat" - desc = "It's tasty looking!" - icon_state = "cake0" - flags = HEADCOVERSEYES - 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. - body_parts_covered = EYES - -/obj/item/clothing/head/cakehat/process() - if(!onfire) - STOP_PROCESSING(SSobj, src) - return - - var/turf/location = src.loc - if(iscarbon(location)) - var/mob/living/carbon/M = location - if(M.l_hand == src || M.r_hand == src || M.head == src || M.mouth == src) - location = M.loc - - if (istype(location, /turf)) - location.hotspot_expose(700, 1) - -/obj/item/clothing/head/cakehat/attack_self(mob/user) - if(status > 1) return - src.onfire = !( src.onfire ) - if (src.onfire) - src.force = 3 - src.damtype = "fire" - src.icon_state = "cake1" - START_PROCESSING(SSobj, src) - else - src.force = null - src.damtype = "brute" - src.icon_state = "cake0" - 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) - 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" - item_color = "pumpkin" - flags = HEADCOVERSEYES | HEADCOVERSMOUTH | BLOCKHAIR - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE - body_parts_covered = HEAD|EYES - var/brightness_on = 2 //luminosity when on - var/on = 0 - w_class = 3 - - 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]_[item_color]" - item_state = "hardhat[on]_[item_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" - body_parts_covered = 0 - var/icon/mob - var/icon/mob2 - siemens_coefficient = 1.5 - - update_icon(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) +/* + * Contents: + * Welding mask + * Cakehat + * Ushanka + * Pumpkin head + * Kitty ears + * + */ + +/* + * 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 = (HEADCOVERSEYES | HEADCOVERSMOUTH) + item_state = "welding" + m_amt = 3000 + g_amt = 1000 + var/up = 0 + 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|FACE|EYES + action_button_name = "Flip Welding Mask" + siemens_coefficient = 0.9 + w_class = 3 + +/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.canmove && !usr.stat && !usr.restrained()) + if(src.up) + src.up = !src.up + src.flags |= (HEADCOVERSEYES | HEADCOVERSMOUTH) + flags_inv |= (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) + icon_state = initial(icon_state) + to_chat(usr, "You flip the [src] down to protect your eyes.") + else + src.up = !src.up + src.flags &= ~(HEADCOVERSEYES | HEADCOVERSMOUTH) + flags_inv &= ~(HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) + icon_state = "[initial(icon_state)]up" + to_chat(usr, "You push the [src] up out of your face.") + usr.update_inv_head() //so our mob-overlays update + + +/* + * Cakehat + */ +/obj/item/clothing/head/cakehat + name = "cake-hat" + desc = "It's tasty looking!" + icon_state = "cake0" + flags = HEADCOVERSEYES + 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. + body_parts_covered = EYES + +/obj/item/clothing/head/cakehat/process() + if(!onfire) + STOP_PROCESSING(SSobj, src) + return + + var/turf/location = src.loc + if(iscarbon(location)) + var/mob/living/carbon/M = location + if(M.l_hand == src || M.r_hand == src || M.head == src || M.mouth == src) + location = M.loc + + if (istype(location, /turf)) + location.hotspot_expose(700, 1) + +/obj/item/clothing/head/cakehat/attack_self(mob/user) + if(status > 1) return + src.onfire = !( src.onfire ) + if (src.onfire) + src.force = 3 + src.damtype = "fire" + src.icon_state = "cake1" + START_PROCESSING(SSobj, src) + else + src.force = null + src.damtype = "brute" + src.icon_state = "cake0" + 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) + 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" + item_color = "pumpkin" + flags = HEADCOVERSEYES | HEADCOVERSMOUTH | BLOCKHAIR + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + body_parts_covered = HEAD|EYES + var/brightness_on = 2 //luminosity when on + var/on = 0 + w_class = 3 + + 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]_[item_color]" + item_state = "hardhat[on]_[item_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" + body_parts_covered = 0 + var/icon/mob + var/icon/mob2 + siemens_coefficient = 1.5 + + update_icon(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) diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index ed78dbe14de9..29897e94850b 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -1,107 +1,107 @@ -/obj/item/clothing/head/soft - name = "cargo cap" - desc = "It's a baseball hat in a tasteless yellow color." - icon_state = "cargosoft" - flags = HEADCOVERSEYES - item_state = "helmet" - item_color = "cargo" - var/flipped = 0 - siemens_coefficient = 0.9 - body_parts_covered = 0 - -/obj/item/clothing/head/soft/dropped() - src.icon_state = "[item_color]soft" - src.flipped=0 - ..() - -/obj/item/clothing/head/soft/verb/flip() - set category = "Object" - set name = "Flip cap" - set src in usr - if(usr.canmove && !usr.stat && !usr.restrained()) - src.flipped = !src.flipped - if(src.flipped) - icon_state = "[item_color]soft_flipped" - to_chat(usr, "You flip the hat backwards.") - else - icon_state = "[item_color]soft" - to_chat(usr, "You flip the hat back in normal position.") - usr.update_inv_head() //so our mob-overlays update - -/obj/item/clothing/head/soft/red - name = "red cap" - desc = "It's a baseball hat in a tasteless red color." - icon_state = "redsoft" - item_color = "red" - -/obj/item/clothing/head/soft/blue - name = "blue cap" - desc = "It's a baseball hat in a tasteless blue color." - icon_state = "bluesoft" - item_color = "blue" - -/obj/item/clothing/head/soft/green - name = "green cap" - desc = "It's a baseball hat in a tasteless green color." - icon_state = "greensoft" - item_color = "green" - -/obj/item/clothing/head/soft/yellow - name = "yellow cap" - desc = "It's a baseball hat in a tasteless yellow color." - icon_state = "yellowsoft" - item_color = "yellow" - -/obj/item/clothing/head/soft/grey - name = "grey cap" - desc = "It's a baseball hat in a tasteful grey color." - icon_state = "greysoft" - item_color = "grey" - -/obj/item/clothing/head/soft/orange - name = "orange cap" - desc = "It's a baseball hat in a tasteless orange color." - icon_state = "orangesoft" - item_color = "orange" - -/obj/item/clothing/head/soft/mime - name = "white cap" - desc = "It's a baseball hat in a tasteless white color." - icon_state = "mimesoft" - item_color = "mime" - -/obj/item/clothing/head/soft/purple - name = "purple cap" - desc = "It's a baseball hat in a tasteless purple color." - icon_state = "purplesoft" - item_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" - item_color = "rainbow" - -/obj/item/clothing/head/soft/sec - name = "security cap" - desc = "It's baseball hat in tasteful red color." - icon_state = "secsoft" - item_color = "sec" - -/obj/item/clothing/head/soft/sec/corp - name = "corporate security cap" - desc = "It's baseball hat in corporate colors." - icon_state = "corpsoft" - item_color = "corp" - -/obj/item/clothing/head/soft/trash - name = "trash cap" - desc = "It's baseball hat." - icon_state = "trashsoft" - item_color = "trash" - -/obj/item/clothing/head/soft/janitor - name = "janitor cap" - desc = "It's janitor hat." - icon_state = "janitorsoft" +/obj/item/clothing/head/soft + name = "cargo cap" + desc = "It's a baseball hat in a tasteless yellow color." + icon_state = "cargosoft" + flags = HEADCOVERSEYES + item_state = "helmet" + item_color = "cargo" + var/flipped = 0 + siemens_coefficient = 0.9 + body_parts_covered = 0 + +/obj/item/clothing/head/soft/dropped() + src.icon_state = "[item_color]soft" + src.flipped=0 + ..() + +/obj/item/clothing/head/soft/verb/flip() + set category = "Object" + set name = "Flip cap" + set src in usr + if(usr.canmove && !usr.stat && !usr.restrained()) + src.flipped = !src.flipped + if(src.flipped) + icon_state = "[item_color]soft_flipped" + to_chat(usr, "You flip the hat backwards.") + else + icon_state = "[item_color]soft" + to_chat(usr, "You flip the hat back in normal position.") + usr.update_inv_head() //so our mob-overlays update + +/obj/item/clothing/head/soft/red + name = "red cap" + desc = "It's a baseball hat in a tasteless red color." + icon_state = "redsoft" + item_color = "red" + +/obj/item/clothing/head/soft/blue + name = "blue cap" + desc = "It's a baseball hat in a tasteless blue color." + icon_state = "bluesoft" + item_color = "blue" + +/obj/item/clothing/head/soft/green + name = "green cap" + desc = "It's a baseball hat in a tasteless green color." + icon_state = "greensoft" + item_color = "green" + +/obj/item/clothing/head/soft/yellow + name = "yellow cap" + desc = "It's a baseball hat in a tasteless yellow color." + icon_state = "yellowsoft" + item_color = "yellow" + +/obj/item/clothing/head/soft/grey + name = "grey cap" + desc = "It's a baseball hat in a tasteful grey color." + icon_state = "greysoft" + item_color = "grey" + +/obj/item/clothing/head/soft/orange + name = "orange cap" + desc = "It's a baseball hat in a tasteless orange color." + icon_state = "orangesoft" + item_color = "orange" + +/obj/item/clothing/head/soft/mime + name = "white cap" + desc = "It's a baseball hat in a tasteless white color." + icon_state = "mimesoft" + item_color = "mime" + +/obj/item/clothing/head/soft/purple + name = "purple cap" + desc = "It's a baseball hat in a tasteless purple color." + icon_state = "purplesoft" + item_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" + item_color = "rainbow" + +/obj/item/clothing/head/soft/sec + name = "security cap" + desc = "It's baseball hat in tasteful red color." + icon_state = "secsoft" + item_color = "sec" + +/obj/item/clothing/head/soft/sec/corp + name = "corporate security cap" + desc = "It's baseball hat in corporate colors." + icon_state = "corpsoft" + item_color = "corp" + +/obj/item/clothing/head/soft/trash + name = "trash cap" + desc = "It's baseball hat." + icon_state = "trashsoft" + item_color = "trash" + +/obj/item/clothing/head/soft/janitor + name = "janitor cap" + desc = "It's janitor hat." + icon_state = "janitorsoft" item_color = "janitor" \ No newline at end of file diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm index 38cab31358d7..03bbbe2992a0 100644 --- a/code/modules/clothing/masks/boxing.dm +++ b/code/modules/clothing/masks/boxing.dm @@ -1,41 +1,41 @@ -/obj/item/clothing/mask/balaclava - name = "balaclava" - desc = "LOADSAMONEY" - icon_state = "balaclava" - item_state = "balaclava" - flags = BLOCKHAIR - flags_inv = HIDEFACE - body_parts_covered = FACE - w_class = 2 - -/obj/item/clothing/mask/balaclava/tactical - name = "green balaclava" - desc = "Designed to both hide identities and keep your face comfy and warm." - icon_state = "swatclava" - item_state = "balaclava" - flags = BLOCKHAIR - flags_inv = HIDEFACE - w_class = 2 - -/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 = BLOCKHAIR - flags_inv = HIDEFACE - body_parts_covered = HEAD|FACE - w_class = 2 - siemens_coefficient = 3.0 - -/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" - -/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 = BLOCKHAIR + flags_inv = HIDEFACE + body_parts_covered = FACE + w_class = 2 + +/obj/item/clothing/mask/balaclava/tactical + name = "green balaclava" + desc = "Designed to both hide identities and keep your face comfy and warm." + icon_state = "swatclava" + item_state = "balaclava" + flags = BLOCKHAIR + flags_inv = HIDEFACE + w_class = 2 + +/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 = BLOCKHAIR + flags_inv = HIDEFACE + body_parts_covered = HEAD|FACE + w_class = 2 + siemens_coefficient = 3.0 + +/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" + +/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" diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm index dad3e7cebc52..3fe568386d69 100644 --- a/code/modules/clothing/masks/breath.dm +++ b/code/modules/clothing/masks/breath.dm @@ -1,53 +1,53 @@ -/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 = MASKCOVERSMOUTH | MASKINTERNALS - body_parts_covered = 0 - w_class = 2 - gas_transfer_coefficient = 0.10 - permeability_coefficient = 0.50 - action_button_name = "Adjust mask" - var/hanging = 0 - -/obj/item/clothing/mask/breath/attack_self() - - if(usr.canmove && !usr.stat && !usr.restrained()) - if(!src.hanging) - src.hanging = !src.hanging - gas_transfer_coefficient = 1 //gas is now escaping to the turf and vice versa - flags &= ~(MASKCOVERSMOUTH | MASKINTERNALS) - icon_state = "breathdown" - to_chat(usr, "Your mask is now hanging on your neck.") - - else - src.hanging = !src.hanging - gas_transfer_coefficient = 0.10 - flags |= MASKCOVERSMOUTH | MASKINTERNALS - icon_state = "breath" - to_chat(usr, "You pull the mask up to cover your face.") - usr.update_inv_wear_mask() - -/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 - -/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 , VOX_ARMALIS) - sprite_sheets = list( - VOX_ARMALIS = 'icons/mob/species/armalis/mask.dmi' - ) - -/obj/item/clothing/mask/breath/vox/attack_self() - - to_chat(usr, "You can't really adjust this mask - it's moulded to your beak!") - return +/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 = MASKCOVERSMOUTH | MASKINTERNALS + body_parts_covered = 0 + w_class = 2 + gas_transfer_coefficient = 0.10 + permeability_coefficient = 0.50 + action_button_name = "Adjust mask" + var/hanging = 0 + +/obj/item/clothing/mask/breath/attack_self() + + if(usr.canmove && !usr.stat && !usr.restrained()) + if(!src.hanging) + src.hanging = !src.hanging + gas_transfer_coefficient = 1 //gas is now escaping to the turf and vice versa + flags &= ~(MASKCOVERSMOUTH | MASKINTERNALS) + icon_state = "breathdown" + to_chat(usr, "Your mask is now hanging on your neck.") + + else + src.hanging = !src.hanging + gas_transfer_coefficient = 0.10 + flags |= MASKCOVERSMOUTH | MASKINTERNALS + icon_state = "breath" + to_chat(usr, "You pull the mask up to cover your face.") + usr.update_inv_wear_mask() + +/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 + +/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 , VOX_ARMALIS) + sprite_sheets = list( + VOX_ARMALIS = 'icons/mob/species/armalis/mask.dmi' + ) + +/obj/item/clothing/mask/breath/vox/attack_self() + + to_chat(usr, "You can't really adjust this mask - it's moulded to your beak!") + return diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index efb876195ffe..83a4fdc9ca5c 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -1,282 +1,282 @@ -/obj/item/clothing/mask/gas - name = "gas mask" - desc = "A face-covering mask that can be connected to an air supply. Filters harmful gases from the air." - icon = 'icons/obj/clothing/masks.dmi' - icon_state = "gas_mask_tc" - flags = MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS - flags_inv = HIDEEARS|HIDEEYES|HIDEFACE - body_parts_covered = FACE|EYES - w_class = 3.0 - item_state = "gas_mask_tc" - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.01 - siemens_coefficient = 0.9 - var/gas_filter_strength = 1 //For gas mask filters - -// **** Welding gas mask **** - -/obj/item/clothing/mask/gas/welding - name = "welding mask" - desc = "A gas mask with built-in welding goggles and a face shield. Looks like a skull - clearly designed by a nerd." - icon_state = "weldingmask" - item_state = "weldingmask" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) - origin_tech = "materials=2;engineering=2" - action_button_name = "Toggle Welding Mask" - siemens_coefficient = 0.9 - body_parts_covered = FACE|EYES - w_class = 3 - var/up = 0 - -/obj/item/clothing/mask/gas/welding/attack_self() - toggle() - -/obj/item/clothing/mask/gas/welding/verb/toggle() - set category = "Object" - set name = "Adjust welding mask" - set src in usr - - if(usr.canmove && !usr.stat && !usr.restrained()) - if(src.up) - src.up = !src.up - src.flags |= (HEADCOVERSEYES | HEADCOVERSMOUTH) - flags_inv |= (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) - body_parts_covered |= EYES - icon_state = initial(icon_state) - to_chat(usr, "You adjust \the [src] down to protect your eyes.") - else - src.up = !src.up - src.flags &= ~(HEADCOVERSEYES | HEADCOVERSMOUTH) - flags_inv &= ~(HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) - body_parts_covered &= ~EYES - icon_state = "[initial(icon_state)]up" - to_chat(usr, "You push \the [src] up out of your face.") - - usr.update_inv_wear_mask() - -// ******************************************************************** - -// **** Security gas mask (TG-stuff) **** -/obj/item/clothing/mask/gas/sechailer - name = "security gas mask" - desc = "A standard issue Security gas mask with integrated 'Compli-o-nator 3000' device, plays over a dozen pre-recorded compliance phrases designed to get scumbags to stand still whilst you taze them. Do not tamper with the device." - action_button_name = "Toggle Mask" - icon_state = "secmask" - var/cooldown = 0 - var/aggressiveness = 2 - flags = MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS | BLOCKHAIR - -/obj/item/clothing/mask/gas/sechailer/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/screwdriver)) - switch(aggressiveness) - if(1) - to_chat(user, "\blue You set the restrictor to the middle position.") - aggressiveness = 2 - if(2) - to_chat(user, "\blue You set the restrictor to the last position.") - aggressiveness = 3 - if(3) - to_chat(user, "\blue You set the restrictor to the first position.") - aggressiveness = 1 - if(4) - to_chat(user, "\red You adjust the restrictor but nothing happens, probably because its broken.") - else if(istype(W, /obj/item/weapon/wirecutters)) - if(aggressiveness != 4) - to_chat(user, "\red You broke it!") - aggressiveness = 4 - else - ..() - -/obj/item/clothing/mask/gas/sechailer/attack_self() - halt() - -/obj/item/clothing/mask/gas/sechailer/verb/halt() - set category = "Object" - set name = "HALT" - set src in usr - if(!istype(usr, /mob/living)) return - if(usr.stat) return - - var/phrase = 0 //selects which phrase to use - var/phrase_text = null - var/phrase_sound = null - - - if(cooldown < world.time - 35) // A cooldown, to stop people being jerks - switch(aggressiveness) // checks if the user has unlocked the restricted phrases - if(1) - phrase = rand(1,5) // set the upper limit as the phrase above the first 'bad cop' phrase, the mask will only play 'nice' phrases - if(2) - phrase = rand(1,11) // default setting, set upper limit to last 'bad cop' phrase. Mask will play good cop and bad cop phrases - if(3) - phrase = rand(1,18) // user has unlocked all phrases, set upper limit to last phrase. The mask will play all phrases - if(4) - phrase = rand(12,18) // user has broke the restrictor, it will now only play shitcurity phrases - - switch(phrase) //sets the properties of the chosen phrase - if(1) // good cop - phrase_text = "HALT! HALT! HALT! HALT!" - phrase_sound = "halt" - if(2) - phrase_text = "Stop in the name of the Law." - phrase_sound = "bobby" - if(3) - phrase_text = "Compliance is in your best interest." - phrase_sound = "compliance" - if(4) - phrase_text = "Prepare for justice!" - phrase_sound = "justice" - if(5) - phrase_text = "Running will only increase your sentence." - phrase_sound = "running" - if(6) // bad cop - phrase_text = "Don't move, Creep!" - phrase_sound = "dontmove" - if(7) - phrase_text = "Down on the floor, Creep!" - phrase_sound = "floor" - if(8) - phrase_text = "Dead or alive you're coming with me." - phrase_sound = "robocop" - if(9) - phrase_text = "God made today for the crooks we could not catch yesterday." - phrase_sound = "god" - if(10) - phrase_text = "Freeze, Scum Bag!" - phrase_sound = "freeze" - if(11) - phrase_text = "Stop right there, criminal scum!" - phrase_sound = "imperial" - if(12) // LA-PD - phrase_text = "Stop or I'll bash you." - phrase_sound = "bash" - if(13) - phrase_text = "Go ahead, make my day." - phrase_sound = "harry" - if(14) - phrase_text = "Stop breaking the law, ass hole." - phrase_sound = "asshole" - if(15) - phrase_text = "You have the right to shut the fuck up." - phrase_sound = "stfu" - if(16) - phrase_text = "Shut up crime!" - phrase_sound = "shutup" - if(17) - phrase_text = "Face the wrath of the golden bolt." - phrase_sound = "super" - if(18) - phrase_text = "I am, the LAW!" - phrase_sound = "dredd" - - usr.visible_message("[usr]'s Compli-o-Nator: [phrase_text]") - playsound(src.loc, "sound/voice/complionator/[phrase_sound].ogg", 100, 0, 4) - cooldown = world.time - -//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 phoron 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) - body_parts_covered = HEAD|FACE - -/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 - body_parts_covered = FACE|EYES - -/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 = "mask_syndi" - item_state = "mask_syndi" - siemens_coefficient = 0.7 - -/obj/item/clothing/mask/gas/voice - name = "gas mask" - icon_state = "gas_mask_orange" - //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 = 0//This didn't do anything before. It now checks if the mask has special functions/N - origin_tech = "syndicate=4" - -/obj/item/clothing/mask/gas/voice/space_ninja - name = "ninja mask" - desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement." - icon_state = "s-ninja" - item_state = "s-ninja_mask" - vchange = 1 - siemens_coefficient = 0.2 - -/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" - flags = MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS - -/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" - flags = MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS - -/obj/item/clothing/mask/gas/mime - name = "mime mask" - desc = "The traditional mime's mask. It has an eerie facial posture." - icon_state = "mime" - flags = MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS - -/obj/item/clothing/mask/gas/fawkes //--getup1 - name = "strange mask" - desc = "Remember, remember, the fifth of November" - icon_state = "fawkes" - -/obj/item/clothing/mask/gas/monkeymask - name = "monkey mask" - desc = "A mask used when acting as a monkey." - icon_state = "monkeymask" - item_state = "monkeymask" - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/mask/gas/sexymime - name = "sexy mime mask" - desc = "A traditional female mime's mask." - icon_state = "sexymime" - flags = MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS - -/obj/item/clothing/mask/gas/death_commando - name = "death commando mask" - icon_state = "death_commando_mask" - item_state = "death_commando_mask" - siemens_coefficient = 0.2 - -/obj/item/clothing/mask/gas/cyborg - name = "cyborg visor" - desc = "Beep boop." - icon_state = "death" - -/obj/item/clothing/mask/gas/owl_mask - name = "owl mask" - desc = "Twoooo!" - icon_state = "owl" - -/obj/item/clothing/mask/gas/coloured - icon_state = "gas_mask_orange" - -/obj/item/clothing/mask/gas/coloured/examine(mob/user) - ..() - if(src in user) - to_chat(user, "The small label on the back side tells: \"Designed by W&J Company\".") - -/obj/item/clothing/mask/gas/coloured/atom_init() - . = ..() - var/color = pick("orange", "blue") - icon_state = "gas_mask_[color]" +/obj/item/clothing/mask/gas + name = "gas mask" + desc = "A face-covering mask that can be connected to an air supply. Filters harmful gases from the air." + icon = 'icons/obj/clothing/masks.dmi' + icon_state = "gas_mask_tc" + flags = MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS + flags_inv = HIDEEARS|HIDEEYES|HIDEFACE + body_parts_covered = FACE|EYES + w_class = 3.0 + item_state = "gas_mask_tc" + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + siemens_coefficient = 0.9 + var/gas_filter_strength = 1 //For gas mask filters + +// **** Welding gas mask **** + +/obj/item/clothing/mask/gas/welding + name = "welding mask" + desc = "A gas mask with built-in welding goggles and a face shield. Looks like a skull - clearly designed by a nerd." + icon_state = "weldingmask" + item_state = "weldingmask" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) + origin_tech = "materials=2;engineering=2" + action_button_name = "Toggle Welding Mask" + siemens_coefficient = 0.9 + body_parts_covered = FACE|EYES + w_class = 3 + var/up = 0 + +/obj/item/clothing/mask/gas/welding/attack_self() + toggle() + +/obj/item/clothing/mask/gas/welding/verb/toggle() + set category = "Object" + set name = "Adjust welding mask" + set src in usr + + if(usr.canmove && !usr.stat && !usr.restrained()) + if(src.up) + src.up = !src.up + src.flags |= (HEADCOVERSEYES | HEADCOVERSMOUTH) + flags_inv |= (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) + body_parts_covered |= EYES + icon_state = initial(icon_state) + to_chat(usr, "You adjust \the [src] down to protect your eyes.") + else + src.up = !src.up + src.flags &= ~(HEADCOVERSEYES | HEADCOVERSMOUTH) + flags_inv &= ~(HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) + body_parts_covered &= ~EYES + icon_state = "[initial(icon_state)]up" + to_chat(usr, "You push \the [src] up out of your face.") + + usr.update_inv_wear_mask() + +// ******************************************************************** + +// **** Security gas mask (TG-stuff) **** +/obj/item/clothing/mask/gas/sechailer + name = "security gas mask" + desc = "A standard issue Security gas mask with integrated 'Compli-o-nator 3000' device, plays over a dozen pre-recorded compliance phrases designed to get scumbags to stand still whilst you taze them. Do not tamper with the device." + action_button_name = "Toggle Mask" + icon_state = "secmask" + var/cooldown = 0 + var/aggressiveness = 2 + flags = MASKCOVERSMOUTH | MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS | BLOCKHAIR + +/obj/item/clothing/mask/gas/sechailer/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/screwdriver)) + switch(aggressiveness) + if(1) + to_chat(user, "\blue You set the restrictor to the middle position.") + aggressiveness = 2 + if(2) + to_chat(user, "\blue You set the restrictor to the last position.") + aggressiveness = 3 + if(3) + to_chat(user, "\blue You set the restrictor to the first position.") + aggressiveness = 1 + if(4) + to_chat(user, "\red You adjust the restrictor but nothing happens, probably because its broken.") + else if(istype(W, /obj/item/weapon/wirecutters)) + if(aggressiveness != 4) + to_chat(user, "\red You broke it!") + aggressiveness = 4 + else + ..() + +/obj/item/clothing/mask/gas/sechailer/attack_self() + halt() + +/obj/item/clothing/mask/gas/sechailer/verb/halt() + set category = "Object" + set name = "HALT" + set src in usr + if(!istype(usr, /mob/living)) return + if(usr.stat) return + + var/phrase = 0 //selects which phrase to use + var/phrase_text = null + var/phrase_sound = null + + + if(cooldown < world.time - 35) // A cooldown, to stop people being jerks + switch(aggressiveness) // checks if the user has unlocked the restricted phrases + if(1) + phrase = rand(1,5) // set the upper limit as the phrase above the first 'bad cop' phrase, the mask will only play 'nice' phrases + if(2) + phrase = rand(1,11) // default setting, set upper limit to last 'bad cop' phrase. Mask will play good cop and bad cop phrases + if(3) + phrase = rand(1,18) // user has unlocked all phrases, set upper limit to last phrase. The mask will play all phrases + if(4) + phrase = rand(12,18) // user has broke the restrictor, it will now only play shitcurity phrases + + switch(phrase) //sets the properties of the chosen phrase + if(1) // good cop + phrase_text = "HALT! HALT! HALT! HALT!" + phrase_sound = "halt" + if(2) + phrase_text = "Stop in the name of the Law." + phrase_sound = "bobby" + if(3) + phrase_text = "Compliance is in your best interest." + phrase_sound = "compliance" + if(4) + phrase_text = "Prepare for justice!" + phrase_sound = "justice" + if(5) + phrase_text = "Running will only increase your sentence." + phrase_sound = "running" + if(6) // bad cop + phrase_text = "Don't move, Creep!" + phrase_sound = "dontmove" + if(7) + phrase_text = "Down on the floor, Creep!" + phrase_sound = "floor" + if(8) + phrase_text = "Dead or alive you're coming with me." + phrase_sound = "robocop" + if(9) + phrase_text = "God made today for the crooks we could not catch yesterday." + phrase_sound = "god" + if(10) + phrase_text = "Freeze, Scum Bag!" + phrase_sound = "freeze" + if(11) + phrase_text = "Stop right there, criminal scum!" + phrase_sound = "imperial" + if(12) // LA-PD + phrase_text = "Stop or I'll bash you." + phrase_sound = "bash" + if(13) + phrase_text = "Go ahead, make my day." + phrase_sound = "harry" + if(14) + phrase_text = "Stop breaking the law, ass hole." + phrase_sound = "asshole" + if(15) + phrase_text = "You have the right to shut the fuck up." + phrase_sound = "stfu" + if(16) + phrase_text = "Shut up crime!" + phrase_sound = "shutup" + if(17) + phrase_text = "Face the wrath of the golden bolt." + phrase_sound = "super" + if(18) + phrase_text = "I am, the LAW!" + phrase_sound = "dredd" + + usr.visible_message("[usr]'s Compli-o-Nator: [phrase_text]") + playsound(src.loc, "sound/voice/complionator/[phrase_sound].ogg", 100, 0, 4) + cooldown = world.time + +//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 phoron 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) + body_parts_covered = HEAD|FACE + +/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 + body_parts_covered = FACE|EYES + +/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 = "mask_syndi" + item_state = "mask_syndi" + siemens_coefficient = 0.7 + +/obj/item/clothing/mask/gas/voice + name = "gas mask" + icon_state = "gas_mask_orange" + //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 = 0//This didn't do anything before. It now checks if the mask has special functions/N + origin_tech = "syndicate=4" + +/obj/item/clothing/mask/gas/voice/space_ninja + name = "ninja mask" + desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement." + icon_state = "s-ninja" + item_state = "s-ninja_mask" + vchange = 1 + siemens_coefficient = 0.2 + +/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" + flags = MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS + +/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" + flags = MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS + +/obj/item/clothing/mask/gas/mime + name = "mime mask" + desc = "The traditional mime's mask. It has an eerie facial posture." + icon_state = "mime" + flags = MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS + +/obj/item/clothing/mask/gas/fawkes //--getup1 + name = "strange mask" + desc = "Remember, remember, the fifth of November" + icon_state = "fawkes" + +/obj/item/clothing/mask/gas/monkeymask + name = "monkey mask" + desc = "A mask used when acting as a monkey." + icon_state = "monkeymask" + item_state = "monkeymask" + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/mask/gas/sexymime + name = "sexy mime mask" + desc = "A traditional female mime's mask." + icon_state = "sexymime" + flags = MASKCOVERSEYES | BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS + +/obj/item/clothing/mask/gas/death_commando + name = "death commando mask" + icon_state = "death_commando_mask" + item_state = "death_commando_mask" + siemens_coefficient = 0.2 + +/obj/item/clothing/mask/gas/cyborg + name = "cyborg visor" + desc = "Beep boop." + icon_state = "death" + +/obj/item/clothing/mask/gas/owl_mask + name = "owl mask" + desc = "Twoooo!" + icon_state = "owl" + +/obj/item/clothing/mask/gas/coloured + icon_state = "gas_mask_orange" + +/obj/item/clothing/mask/gas/coloured/examine(mob/user) + ..() + if(src in user) + to_chat(user, "The small label on the back side tells: \"Designed by W&J Company\".") + +/obj/item/clothing/mask/gas/coloured/atom_init() + . = ..() + var/color = pick("orange", "blue") + icon_state = "gas_mask_[color]" diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 802f7d581cd0..adb5f959a894 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -1,277 +1,277 @@ -/obj/item/clothing/mask/muzzle - name = "muzzle" - desc = "To stop that awful noise." - icon_state = "muzzle" - item_state = "muzzle" - flags = MASKCOVERSMOUTH - body_parts_covered = 0 - w_class = 2 - gas_transfer_coefficient = 0.90 - -//Monkeys can not take the muzzle off of themself! Call PETA! -/obj/item/clothing/mask/muzzle/attack_paw(mob/user) - 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 = 2 - flags = MASKCOVERSMOUTH - body_parts_covered = 0 - 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) - -/obj/item/clothing/mask/fakemoustache - name = "fake moustache" - desc = "Warning: moustache is fake." - icon_state = "fake-moustache" - flags_inv = HIDEFACE - body_parts_covered = 0 - -/obj/item/clothing/mask/fake_face - name = "fake face" - desc = "Warning: this face not a fake." - icon_state = "fake_face" - flags_inv = HIDEFACE - body_parts_covered = 0 - -/obj/item/clothing/mask/snorkel - name = "snorkel" - desc = "For the Swimming Savant." - icon_state = "snorkel" - flags_inv = HIDEFACE - body_parts_covered = 0 - -//scarves (fit in in mask slot) - -/obj/item/clothing/mask/scarf - name = "scarf" - desc = "A simple neck scarf." - icon_state = "bluescarf" - item_state = "bluescarf" - flags = MASKCOVERSMOUTH - w_class = 2 - gas_transfer_coefficient = 0.90 - action_button_name = "Adjust scarf" - var/hanging = 0 - -/obj/item/clothing/mask/scarf/blue - name = "blue neck scarf" - desc = "A blue neck scarf." - icon_state = "bluescarf" - item_state = "bluescarf" - -/obj/item/clothing/mask/scarf/red - name = "red scarf" - desc = "A red neck scarf." - icon_state = "redscarf" - item_state = "redscarf" - -/obj/item/clothing/mask/scarf/green - name = "green scarf" - desc = "A green neck scarf." - icon_state = "greenscarf" - item_state = "greenscarf" - -/obj/item/clothing/mask/scarf/yellow - name = "yellow scarf" - desc = "A yellow neck scarf." - icon_state = "yellowscarf" - item_state = "yellowscarf" - -/obj/item/clothing/mask/scarf/violet - name = "violet scarf" - desc = "A violet neck scarf." - icon_state = "violetscarf" - item_state = "violetscarf" - -/obj/item/clothing/mask/scarf/attack_self(mob/user) - - if(user.incapacitated()) - return - - - if(!hanging) - hanging = !hanging - gas_transfer_coefficient = 1 //gas is now escaping to the turf and vice versa - flags &= ~MASKCOVERSMOUTH - icon_state = "[initial(icon_state)]down" - to_chat(user, "Your scarf is now hanging on your neck.") - else - hanging = !hanging - gas_transfer_coefficient = 0.90 - flags |= MASKCOVERSMOUTH - icon_state = "[initial(icon_state)]" - to_chat(user, "You pull the scarf up to cover your face.") - user.update_inv_wear_mask() - - - - -/obj/item/clothing/mask/scarf/ninja - name = "ninja scarf" - desc = "A stealthy, dark scarf." - icon_state = "ninja_scarf" - item_state = "ninja_scarf" - flags = MASKCOVERSMOUTH - w_class = 2 - gas_transfer_coefficient = 0.90 - siemens_coefficient = 0 - -/obj/item/clothing/mask/pig - name = "pig mask" - desc = "A rubber pig mask." - icon_state = "pig" - item_state = "pig" - flags = BLOCKHAIR - flags_inv = HIDEFACE - w_class = 2 - siemens_coefficient = 0.9 - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/mask/pig/speechModification(message) - if(!canremove) - message = pick("Oink!", "Squeeeeeeee!", "Oink Oink!") - return message - -/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 = BLOCKHAIR - flags_inv = HIDEFACE - body_parts_covered = HEAD|FACE|EYES - w_class = 2 - siemens_coefficient = 0.9 - -/obj/item/clothing/mask/horsehead/speechModification(message) - if(!canremove) - message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!") - return message - -/obj/item/clothing/mask/cowmask - name = "cowface" - desc = "It looks like a mask, but closer inspection reveals it's melded onto this persons face!" - icon_state = "cowmask" - item_state = "cowmask" - flags = BLOCKHAIR - flags_inv = HIDEFACE - body_parts_covered = HEAD|FACE|EYES - w_class = 2 - -/obj/item/clothing/mask/cowmask/speechModification(message) - if(!canremove) - message = pick("Moooooooo!", "Moo!", "Moooo!") - return message - -/obj/item/clothing/mask/bandana - name = "botany bandana" - desc = "A fine bandana with nanotech lining and a hydroponics pattern." - w_class = 1 - flags = MASKCOVERSMOUTH - action_button_name = "Adjust Bandana" - icon_state = "bandbotany" - body_parts_covered = 0 - -/obj/item/clothing/mask/chicken - name = "chicken suit head" - desc = "Bkaw!" - icon_state = "chickenmask" - flags = BLOCKHAIR - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/mask/chicken/speechModification(message) - if(!canremove) - message = pick("BKAW!", "BUK BUK!", "Ba-Gawk!") - return message - -/obj/item/clothing/mask/bandana/verb/adjustmask() - set category = "Object" - set name = "Adjust bandana" - set src in usr - if(usr.canmove && !usr.stat && !usr.restrained()) - flags ^= MASKCOVERSMOUTH - if(flags & MASKCOVERSMOUTH) - src.icon_state = initial(icon_state) - to_chat(usr, "Your bandana is now covering your face.") - else - src.icon_state += "_up" - to_chat(usr, "You tie the bandana around your head.") - usr.update_inv_wear_mask() - -/obj/item/clothing/mask/bandana/attack_self(mob/user) - adjustmask(user) - -/obj/item/clothing/mask/bandana/red - name = "red bandana" - desc = "A fine red bandana with nanotech lining." - icon_state = "bandred" - -/obj/item/clothing/mask/bandana/blue - name = "blue bandana" - desc = "A fine blue bandana with nanotech lining." - icon_state = "bandblue" - -/obj/item/clothing/mask/bandana/green - name = "green bandana" - desc = "A fine green bandana with nanotech lining." - icon_state = "bandgreen" - -/obj/item/clothing/mask/bandana/gold - name = "gold bandana" - desc = "A fine gold bandana with nanotech lining." - icon_state = "bandgold" - -/obj/item/clothing/mask/bandana/black - name = "black bandana" - desc = "A fine black bandana with nanotech lining." - icon_state = "bandblack" - -/obj/item/clothing/mask/bandana/skull - name = "skull bandana" - desc = "A fine black bandana with nanotech lining and a skull emblem." - icon_state = "bandskull" - -/obj/item/clothing/mask/tie/collar - name = "silver collar" - desc = "A common collar with silver covering" - icon_state = "collar" - body_parts_covered = 0 - -/obj/item/clothing/mask/tie/collar2 - name = "gold collar" - desc = "A common collar with gold covering" - icon_state = "collar2" - body_parts_covered = 0 - -/obj/item/clothing/mask/ecig - name = "electronic cigarette" - desc = "An electronic cigarette. Most of the relief of a real cigarette with none of the side effects. Often used by smokers who are trying to quit the habit." - icon_state = "ecig" - item_state = "ecig" - throw_speed = 0.5 - w_class = 1 - body_parts_covered = null - var/last_time_used = 0 - -/obj/item/clothing/mask/ecig/attack_self(mob/user) - if(world.time > last_time_used + 20) - if(icon_state == "ecig") - icon_state = "ecig_on" - item_state = "ecig_on" - to_chat(user, "You turn the [src] on") - else - icon_state = "ecig" - item_state = "ecig" - to_chat(user, "You turn the [src] off") - last_time_used = world.time - return +/obj/item/clothing/mask/muzzle + name = "muzzle" + desc = "To stop that awful noise." + icon_state = "muzzle" + item_state = "muzzle" + flags = MASKCOVERSMOUTH + body_parts_covered = 0 + w_class = 2 + gas_transfer_coefficient = 0.90 + +//Monkeys can not take the muzzle off of themself! Call PETA! +/obj/item/clothing/mask/muzzle/attack_paw(mob/user) + 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 = 2 + flags = MASKCOVERSMOUTH + body_parts_covered = 0 + 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) + +/obj/item/clothing/mask/fakemoustache + name = "fake moustache" + desc = "Warning: moustache is fake." + icon_state = "fake-moustache" + flags_inv = HIDEFACE + body_parts_covered = 0 + +/obj/item/clothing/mask/fake_face + name = "fake face" + desc = "Warning: this face not a fake." + icon_state = "fake_face" + flags_inv = HIDEFACE + body_parts_covered = 0 + +/obj/item/clothing/mask/snorkel + name = "snorkel" + desc = "For the Swimming Savant." + icon_state = "snorkel" + flags_inv = HIDEFACE + body_parts_covered = 0 + +//scarves (fit in in mask slot) + +/obj/item/clothing/mask/scarf + name = "scarf" + desc = "A simple neck scarf." + icon_state = "bluescarf" + item_state = "bluescarf" + flags = MASKCOVERSMOUTH + w_class = 2 + gas_transfer_coefficient = 0.90 + action_button_name = "Adjust scarf" + var/hanging = 0 + +/obj/item/clothing/mask/scarf/blue + name = "blue neck scarf" + desc = "A blue neck scarf." + icon_state = "bluescarf" + item_state = "bluescarf" + +/obj/item/clothing/mask/scarf/red + name = "red scarf" + desc = "A red neck scarf." + icon_state = "redscarf" + item_state = "redscarf" + +/obj/item/clothing/mask/scarf/green + name = "green scarf" + desc = "A green neck scarf." + icon_state = "greenscarf" + item_state = "greenscarf" + +/obj/item/clothing/mask/scarf/yellow + name = "yellow scarf" + desc = "A yellow neck scarf." + icon_state = "yellowscarf" + item_state = "yellowscarf" + +/obj/item/clothing/mask/scarf/violet + name = "violet scarf" + desc = "A violet neck scarf." + icon_state = "violetscarf" + item_state = "violetscarf" + +/obj/item/clothing/mask/scarf/attack_self(mob/user) + + if(user.incapacitated()) + return + + + if(!hanging) + hanging = !hanging + gas_transfer_coefficient = 1 //gas is now escaping to the turf and vice versa + flags &= ~MASKCOVERSMOUTH + icon_state = "[initial(icon_state)]down" + to_chat(user, "Your scarf is now hanging on your neck.") + else + hanging = !hanging + gas_transfer_coefficient = 0.90 + flags |= MASKCOVERSMOUTH + icon_state = "[initial(icon_state)]" + to_chat(user, "You pull the scarf up to cover your face.") + user.update_inv_wear_mask() + + + + +/obj/item/clothing/mask/scarf/ninja + name = "ninja scarf" + desc = "A stealthy, dark scarf." + icon_state = "ninja_scarf" + item_state = "ninja_scarf" + flags = MASKCOVERSMOUTH + w_class = 2 + gas_transfer_coefficient = 0.90 + siemens_coefficient = 0 + +/obj/item/clothing/mask/pig + name = "pig mask" + desc = "A rubber pig mask." + icon_state = "pig" + item_state = "pig" + flags = BLOCKHAIR + flags_inv = HIDEFACE + w_class = 2 + siemens_coefficient = 0.9 + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/mask/pig/speechModification(message) + if(!canremove) + message = pick("Oink!", "Squeeeeeeee!", "Oink Oink!") + return message + +/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 = BLOCKHAIR + flags_inv = HIDEFACE + body_parts_covered = HEAD|FACE|EYES + w_class = 2 + siemens_coefficient = 0.9 + +/obj/item/clothing/mask/horsehead/speechModification(message) + if(!canremove) + message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!") + return message + +/obj/item/clothing/mask/cowmask + name = "cowface" + desc = "It looks like a mask, but closer inspection reveals it's melded onto this persons face!" + icon_state = "cowmask" + item_state = "cowmask" + flags = BLOCKHAIR + flags_inv = HIDEFACE + body_parts_covered = HEAD|FACE|EYES + w_class = 2 + +/obj/item/clothing/mask/cowmask/speechModification(message) + if(!canremove) + message = pick("Moooooooo!", "Moo!", "Moooo!") + return message + +/obj/item/clothing/mask/bandana + name = "botany bandana" + desc = "A fine bandana with nanotech lining and a hydroponics pattern." + w_class = 1 + flags = MASKCOVERSMOUTH + action_button_name = "Adjust Bandana" + icon_state = "bandbotany" + body_parts_covered = 0 + +/obj/item/clothing/mask/chicken + name = "chicken suit head" + desc = "Bkaw!" + icon_state = "chickenmask" + flags = BLOCKHAIR + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/mask/chicken/speechModification(message) + if(!canremove) + message = pick("BKAW!", "BUK BUK!", "Ba-Gawk!") + return message + +/obj/item/clothing/mask/bandana/verb/adjustmask() + set category = "Object" + set name = "Adjust bandana" + set src in usr + if(usr.canmove && !usr.stat && !usr.restrained()) + flags ^= MASKCOVERSMOUTH + if(flags & MASKCOVERSMOUTH) + src.icon_state = initial(icon_state) + to_chat(usr, "Your bandana is now covering your face.") + else + src.icon_state += "_up" + to_chat(usr, "You tie the bandana around your head.") + usr.update_inv_wear_mask() + +/obj/item/clothing/mask/bandana/attack_self(mob/user) + adjustmask(user) + +/obj/item/clothing/mask/bandana/red + name = "red bandana" + desc = "A fine red bandana with nanotech lining." + icon_state = "bandred" + +/obj/item/clothing/mask/bandana/blue + name = "blue bandana" + desc = "A fine blue bandana with nanotech lining." + icon_state = "bandblue" + +/obj/item/clothing/mask/bandana/green + name = "green bandana" + desc = "A fine green bandana with nanotech lining." + icon_state = "bandgreen" + +/obj/item/clothing/mask/bandana/gold + name = "gold bandana" + desc = "A fine gold bandana with nanotech lining." + icon_state = "bandgold" + +/obj/item/clothing/mask/bandana/black + name = "black bandana" + desc = "A fine black bandana with nanotech lining." + icon_state = "bandblack" + +/obj/item/clothing/mask/bandana/skull + name = "skull bandana" + desc = "A fine black bandana with nanotech lining and a skull emblem." + icon_state = "bandskull" + +/obj/item/clothing/mask/tie/collar + name = "silver collar" + desc = "A common collar with silver covering" + icon_state = "collar" + body_parts_covered = 0 + +/obj/item/clothing/mask/tie/collar2 + name = "gold collar" + desc = "A common collar with gold covering" + icon_state = "collar2" + body_parts_covered = 0 + +/obj/item/clothing/mask/ecig + name = "electronic cigarette" + desc = "An electronic cigarette. Most of the relief of a real cigarette with none of the side effects. Often used by smokers who are trying to quit the habit." + icon_state = "ecig" + item_state = "ecig" + throw_speed = 0.5 + w_class = 1 + body_parts_covered = null + var/last_time_used = 0 + +/obj/item/clothing/mask/ecig/attack_self(mob/user) + if(world.time > last_time_used + 20) + if(icon_state == "ecig") + icon_state = "ecig_on" + item_state = "ecig_on" + to_chat(user, "You turn the [src] on") + else + icon_state = "ecig" + item_state = "ecig" + to_chat(user, "You turn the [src] off") + last_time_used = world.time + return diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index af78430ca4c9..949d61cb6c67 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -1,157 +1,157 @@ -/obj/item/clothing/shoes/black - name = "black shoes" - icon_state = "black" - item_color = "black" - item_state = "bl_shoes" - desc = "A pair of black shoes." - clipped_status = CLIPPABLE - - cold_protection = LEGS - min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = LEGS - max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/shoes/black/redcoat - item_color = "redcoat" //Exists for washing machines. Is not different from black shoes in any way. - - -/obj/item/clothing/shoes/brown - name = "brown shoes" - desc = "A pair of brown shoes." - icon_state = "brown" - item_color = "brown" - item_state = "b_shoes" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/brown/captain - item_color = "captain" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/hop - item_color = "hop" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/ce - item_color = "chief" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/rd - item_color = "director" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/cmo - item_color = "medical" //Exists for washing machines. Is not different from brown shoes in any way. - -/obj/item/clothing/shoes/brown/cmo - item_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" - item_color = "blue" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/green - name = "green shoes" - icon_state = "green" - item_color = "green" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/yellow - name = "yellow shoes" - icon_state = "yellow" - item_color = "yellow" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/purple - name = "purple shoes" - icon_state = "purple" - item_color = "purple" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/red - name = "red shoes" - desc = "Stylish red shoes." - icon_state = "red" - item_color = "red" - item_state = "r_shoes" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/white - name = "white shoes" - icon_state = "white" - permeability_coefficient = 0.01 - item_color = "white" - item_state = "w_shoes" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/leather - name = "leather shoes" - desc = "A sturdy pair of leather shoes." - icon_state = "leather" - item_color = "leather" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/rainbow - name = "rainbow shoes" - desc = "Very gay shoes." - icon_state = "rain_bow" - item_color = "rainbow" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/orange - name = "orange shoes" - icon_state = "orange" - item_color = "orange" - item_state = "o_shoes" - var/obj/item/weapon/handcuffs/chained = null - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/orange/proc/attach_cuffs(obj/item/weapon/handcuffs/cuffs, mob/user) - if (src.chained) - return - user.drop_item(cuffs) - cuffs.loc = src - chained = cuffs - slowdown = 15 - name = "shackles" - icon_state = "orange1" - item_state = "o_shoes1" - -/obj/item/clothing/shoes/orange/proc/remove_cuffs() - if (!src.chained) - return - chained.loc = get_turf(src) - slowdown = initial(slowdown) - name = initial(name) - icon_state = "orange" - item_state = "o_shoes" - chained = null - -/obj/item/clothing/shoes/orange/attack_self(mob/user) - ..() - remove_cuffs() - -/obj/item/clothing/shoes/orange/attackby(H, mob/user) - ..() - if (istype(H, /obj/item/weapon/handcuffs)) - attach_cuffs(H, user) - -/obj/item/clothing/shoes/orange/attack_hand(mob/user) - var/confirmed = 1 - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(chained && src == H.shoes) - if(user.is_busy()) return - confirmed = 0 - H.visible_message("[H] attempts to remove the [src]!", - "You attempt to remove the [src]. (This will take around 2 minutes and you need to stand still)") - if(do_after(user,1200,target = usr)) - confirmed = 1 - if(confirmed) - return ..() - -/obj/item/clothing/shoes/orange/candals/atom_init() - . = ..() - chained = new /obj/item/weapon/handcuffs(src) - slowdown = 15 - name = "shackles" - icon_state = "orange1" - item_state = "o_shoes1" +/obj/item/clothing/shoes/black + name = "black shoes" + icon_state = "black" + item_color = "black" + item_state = "bl_shoes" + desc = "A pair of black shoes." + clipped_status = CLIPPABLE + + cold_protection = LEGS + min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = LEGS + max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/shoes/black/redcoat + item_color = "redcoat" //Exists for washing machines. Is not different from black shoes in any way. + + +/obj/item/clothing/shoes/brown + name = "brown shoes" + desc = "A pair of brown shoes." + icon_state = "brown" + item_color = "brown" + item_state = "b_shoes" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/brown/captain + item_color = "captain" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/hop + item_color = "hop" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/ce + item_color = "chief" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/rd + item_color = "director" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/cmo + item_color = "medical" //Exists for washing machines. Is not different from brown shoes in any way. + +/obj/item/clothing/shoes/brown/cmo + item_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" + item_color = "blue" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/green + name = "green shoes" + icon_state = "green" + item_color = "green" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/yellow + name = "yellow shoes" + icon_state = "yellow" + item_color = "yellow" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/purple + name = "purple shoes" + icon_state = "purple" + item_color = "purple" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/red + name = "red shoes" + desc = "Stylish red shoes." + icon_state = "red" + item_color = "red" + item_state = "r_shoes" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/white + name = "white shoes" + icon_state = "white" + permeability_coefficient = 0.01 + item_color = "white" + item_state = "w_shoes" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/leather + name = "leather shoes" + desc = "A sturdy pair of leather shoes." + icon_state = "leather" + item_color = "leather" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/rainbow + name = "rainbow shoes" + desc = "Very gay shoes." + icon_state = "rain_bow" + item_color = "rainbow" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/orange + name = "orange shoes" + icon_state = "orange" + item_color = "orange" + item_state = "o_shoes" + var/obj/item/weapon/handcuffs/chained = null + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/orange/proc/attach_cuffs(obj/item/weapon/handcuffs/cuffs, mob/user) + if (src.chained) + return + user.drop_item(cuffs) + cuffs.loc = src + chained = cuffs + slowdown = 15 + name = "shackles" + icon_state = "orange1" + item_state = "o_shoes1" + +/obj/item/clothing/shoes/orange/proc/remove_cuffs() + if (!src.chained) + return + chained.loc = get_turf(src) + slowdown = initial(slowdown) + name = initial(name) + icon_state = "orange" + item_state = "o_shoes" + chained = null + +/obj/item/clothing/shoes/orange/attack_self(mob/user) + ..() + remove_cuffs() + +/obj/item/clothing/shoes/orange/attackby(H, mob/user) + ..() + if (istype(H, /obj/item/weapon/handcuffs)) + attach_cuffs(H, user) + +/obj/item/clothing/shoes/orange/attack_hand(mob/user) + var/confirmed = 1 + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(chained && src == H.shoes) + if(user.is_busy()) return + confirmed = 0 + H.visible_message("[H] attempts to remove the [src]!", + "You attempt to remove the [src]. (This will take around 2 minutes and you need to stand still)") + if(do_after(user,1200,target = usr)) + confirmed = 1 + if(confirmed) + return ..() + +/obj/item/clothing/shoes/orange/candals/atom_init() + . = ..() + chained = new /obj/item/weapon/handcuffs(src) + slowdown = 15 + name = "shackles" + icon_state = "orange1" + item_state = "o_shoes1" diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index a870541825a4..36c2f9887214 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -1,38 +1,38 @@ -/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" - item_state = "magboots" - species_restricted = null - var/magpulse = 0 - var/magboot_state = "magboots" - var/slowdown_off = 2 - action_button_name = "Toggle Magboots" - origin_tech = "materials=3;magnets=4;engineering=4" -// flags = NOSLIP //disabled by default - -/obj/item/clothing/shoes/magboots/attack_self(mob/user) - if(magpulse) - flags &= ~NOSLIP - slowdown = SHOES_SLOWDOWN - magpulse = 0 - icon_state = "[magboot_state]0" - to_chat(user, "You disable the mag-pulse traction system.") - else - flags |= NOSLIP - slowdown = slowdown_off - magpulse = 1 - icon_state = "[magboot_state]1" - to_chat(user, "You enable the mag-pulse traction system.") - user.update_inv_shoes() //so our mob-overlays update - user.update_gravity(user.mob_has_gravity()) - -/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].") - -/obj/item/clothing/shoes/magboots/negates_gravity() - return flags & NOSLIP +/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" + item_state = "magboots" + species_restricted = null + var/magpulse = 0 + var/magboot_state = "magboots" + var/slowdown_off = 2 + action_button_name = "Toggle Magboots" + origin_tech = "materials=3;magnets=4;engineering=4" +// flags = NOSLIP //disabled by default + +/obj/item/clothing/shoes/magboots/attack_self(mob/user) + if(magpulse) + flags &= ~NOSLIP + slowdown = SHOES_SLOWDOWN + magpulse = 0 + icon_state = "[magboot_state]0" + to_chat(user, "You disable the mag-pulse traction system.") + else + flags |= NOSLIP + slowdown = slowdown_off + magpulse = 1 + icon_state = "[magboot_state]1" + to_chat(user, "You enable the mag-pulse traction system.") + user.update_inv_shoes() //so our mob-overlays update + user.update_gravity(user.mob_has_gravity()) + +/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].") + +/obj/item/clothing/shoes/magboots/negates_gravity() + return flags & NOSLIP diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index e7e792f5f6be..568b65d7d0e3 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -1,202 +1,202 @@ -/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_restricted = null - -/obj/item/clothing/shoes/mime - name = "mime shoes" - icon_state = "mime" - item_color = "mime" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/swat - name = "\improper SWAT shoes" - desc = "When you want to turn up the heat." - icon_state = "swat" - item_state = "wjboots" - flags = NOSLIP - siemens_coefficient = 0.6 - clipped_status = CLIPPABLE - -/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" - item_state = "wjboots" - flags = NOSLIP - siemens_coefficient = 0.6 - clipped_status = CLIPPABLE - - cold_protection = LEGS - min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = LEGS - max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/shoes/combat/cut // Basically combat shoes but for xenos. - name = "mangled combat boots" - desc = "When you REALLY want to turn up the heat
                    They have the toe caps cut off of them." - icon_state = "swat_cut" - clipped_status = CLIPPED - species_restricted = list("exclude", DIONA, VOX) - -/obj/item/clothing/shoes/space_ninja - name = "ninja shoes" - desc = "A pair of running shoes. Excellent for running and even better for smashing skulls." - icon_state = "s-ninja" - permeability_coefficient = 0.01 - flags = NOSLIP - siemens_coefficient = 0.2 - - cold_protection = LEGS - min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = LEGS - max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE - species_restricted = null - -/obj/item/clothing/shoes/tourist - name = "flip-flops" - desc = "These cheap sandals don't look very comfortable." - icon_state = "tourist" - permeability_coefficient = 1 - species_restricted = null - w_class = 2 - -/obj/item/clothing/shoes/sandal - desc = "A pair of rather plain, wooden sandals." - name = "sandals" - icon_state = "wizard" - species_restricted = null - body_parts_covered = 0 - -/obj/item/clothing/shoes/sandal/marisa - desc = "A pair of magic, black shoes." - name = "magic shoes" - icon_state = "black" - body_parts_covered = LEGS - -/obj/item/clothing/shoes/galoshes - desc = "Rubber boots." - name = "galoshes" - icon_state = "galoshes" - permeability_coefficient = 0.05 - flags = NOSLIP - slowdown = SHOES_SLOWDOWN+1 - species_restricted = null - -/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 - item_color = "clown" -// var/footstep = 1 //used for squeeks whilst walking - species_restricted = null - -/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 = "wjboots" - item_state = "wjboots" - item_color = "hosred" - siemens_coefficient = 0.7 - clipped_status = CLIPPABLE - -/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" - item_color = "cult" - siemens_coefficient = 0.7 - - cold_protection = LEGS - min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = LEGS - max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE - species_restricted = null - -/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" - species_restricted = null - w_class = 2 - -/obj/item/clothing/shoes/slippers_worn - name = "worn bunny slippers" - desc = "Fluffy..." - icon_state = "slippers_worn" - item_state = "slippers_worn" - w_class = 2 - -/obj/item/clothing/shoes/laceup - name = "laceup shoes" - desc = "The height of fashion, and they're pre-polished!" - icon_state = "laceups" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/swimmingfins - desc = "Help you swim good." - name = "swimming fins" - icon_state = "flippers" - flags = NOSLIP - slowdown = SHOES_SLOWDOWN+1 - species_restricted = null - -/obj/item/clothing/shoes/centcom - name = "dress shoes" - desc = "They appear impeccably polished." - icon_state = "laceups" - clipped_status = CLIPPABLE - -/obj/item/clothing/shoes/rosas_shoes - name = "white shoes" - icon_state = "rosas_shoes" - item_color = "rosas_shoes" - permeability_coefficient = 0.01 - -/obj/item/clothing/shoes/western - name = "western boots" - icon_state = "western_boots" - item_color = "western_boots" - -/obj/item/clothing/shoes/magboots/syndie - desc = "Light-weighted magnetic boots that have a custom syndicate paintjob for use in combat." - name = "gorlex magboots" - icon_state = "syndiemag0" - magboot_state = "syndiemag" - slowdown_off = 1 - -/obj/item/clothing/shoes/workboots - name = "work boots" - icon_state = "workboots" - item_color = "workboots" - item_state = "b_shoes" // need sprites for this - clipped_status = CLIPPABLE - -/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/heels - name = "Heels" - icon_state = "high_shoes" - -/obj/item/clothing/shoes/heels/alternate - icon_state = "high_shoes2" +/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_restricted = null + +/obj/item/clothing/shoes/mime + name = "mime shoes" + icon_state = "mime" + item_color = "mime" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/swat + name = "\improper SWAT shoes" + desc = "When you want to turn up the heat." + icon_state = "swat" + item_state = "wjboots" + flags = NOSLIP + siemens_coefficient = 0.6 + clipped_status = CLIPPABLE + +/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" + item_state = "wjboots" + flags = NOSLIP + siemens_coefficient = 0.6 + clipped_status = CLIPPABLE + + cold_protection = LEGS + min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = LEGS + max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/shoes/combat/cut // Basically combat shoes but for xenos. + name = "mangled combat boots" + desc = "When you REALLY want to turn up the heat
                    They have the toe caps cut off of them." + icon_state = "swat_cut" + clipped_status = CLIPPED + species_restricted = list("exclude", DIONA, VOX) + +/obj/item/clothing/shoes/space_ninja + name = "ninja shoes" + desc = "A pair of running shoes. Excellent for running and even better for smashing skulls." + icon_state = "s-ninja" + permeability_coefficient = 0.01 + flags = NOSLIP + siemens_coefficient = 0.2 + + cold_protection = LEGS + min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = LEGS + max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE + species_restricted = null + +/obj/item/clothing/shoes/tourist + name = "flip-flops" + desc = "These cheap sandals don't look very comfortable." + icon_state = "tourist" + permeability_coefficient = 1 + species_restricted = null + w_class = 2 + +/obj/item/clothing/shoes/sandal + desc = "A pair of rather plain, wooden sandals." + name = "sandals" + icon_state = "wizard" + species_restricted = null + body_parts_covered = 0 + +/obj/item/clothing/shoes/sandal/marisa + desc = "A pair of magic, black shoes." + name = "magic shoes" + icon_state = "black" + body_parts_covered = LEGS + +/obj/item/clothing/shoes/galoshes + desc = "Rubber boots." + name = "galoshes" + icon_state = "galoshes" + permeability_coefficient = 0.05 + flags = NOSLIP + slowdown = SHOES_SLOWDOWN+1 + species_restricted = null + +/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 + item_color = "clown" +// var/footstep = 1 //used for squeeks whilst walking + species_restricted = null + +/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 = "wjboots" + item_state = "wjboots" + item_color = "hosred" + siemens_coefficient = 0.7 + clipped_status = CLIPPABLE + +/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" + item_color = "cult" + siemens_coefficient = 0.7 + + cold_protection = LEGS + min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = LEGS + max_heat_protection_temperature = SHOE_MAX_HEAT_PROTECTION_TEMPERATURE + species_restricted = null + +/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" + species_restricted = null + w_class = 2 + +/obj/item/clothing/shoes/slippers_worn + name = "worn bunny slippers" + desc = "Fluffy..." + icon_state = "slippers_worn" + item_state = "slippers_worn" + w_class = 2 + +/obj/item/clothing/shoes/laceup + name = "laceup shoes" + desc = "The height of fashion, and they're pre-polished!" + icon_state = "laceups" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/swimmingfins + desc = "Help you swim good." + name = "swimming fins" + icon_state = "flippers" + flags = NOSLIP + slowdown = SHOES_SLOWDOWN+1 + species_restricted = null + +/obj/item/clothing/shoes/centcom + name = "dress shoes" + desc = "They appear impeccably polished." + icon_state = "laceups" + clipped_status = CLIPPABLE + +/obj/item/clothing/shoes/rosas_shoes + name = "white shoes" + icon_state = "rosas_shoes" + item_color = "rosas_shoes" + permeability_coefficient = 0.01 + +/obj/item/clothing/shoes/western + name = "western boots" + icon_state = "western_boots" + item_color = "western_boots" + +/obj/item/clothing/shoes/magboots/syndie + desc = "Light-weighted magnetic boots that have a custom syndicate paintjob for use in combat." + name = "gorlex magboots" + icon_state = "syndiemag0" + magboot_state = "syndiemag" + slowdown_off = 1 + +/obj/item/clothing/shoes/workboots + name = "work boots" + icon_state = "workboots" + item_color = "workboots" + item_state = "b_shoes" // need sprites for this + clipped_status = CLIPPABLE + +/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/heels + name = "Heels" + icon_state = "high_shoes" + +/obj/item/clothing/shoes/heels/alternate + icon_state = "high_shoes2" diff --git a/code/modules/clothing/spacesuits/captain.dm b/code/modules/clothing/spacesuits/captain.dm index f19fac4ceb7b..488d3591f362 100644 --- a/code/modules/clothing/spacesuits/captain.dm +++ b/code/modules/clothing/spacesuits/captain.dm @@ -1,31 +1,31 @@ -//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 = HEADCOVERSEYES | BLOCKHAIR - flags_pressure = STOPS_LOWPRESSUREDMAGE - flags_inv = HIDEFACE - permeability_coefficient = 0.01 - armor = list(melee = 65, bullet = 45, laser = 45,energy = 25, bomb = 50, bio = 100, rad = 50) - siemens_coefficient = 0.4 - -//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" - w_class = 4 - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.02 - flags_pressure = STOPS_LOWPRESSUREDMAGE - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|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_box/magazine, /obj/item/ammo_casing, /obj/item/weapon/melee/baton, /obj/item/weapon/handcuffs, /obj/item/weapon/tank/jetpack) - slowdown = 1.5 - armor = list(melee = 65, bullet = 45, laser = 45, energy = 25, bomb = 50, bio = 100, rad = 50) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS - min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0.4 +//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 = HEADCOVERSEYES | BLOCKHAIR + flags_pressure = STOPS_LOWPRESSUREDMAGE + flags_inv = HIDEFACE + permeability_coefficient = 0.01 + armor = list(melee = 65, bullet = 45, laser = 45,energy = 25, bomb = 50, bio = 100, rad = 50) + siemens_coefficient = 0.4 + +//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" + w_class = 4 + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.02 + flags_pressure = STOPS_LOWPRESSUREDMAGE + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|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_box/magazine, /obj/item/ammo_casing, /obj/item/weapon/melee/baton, /obj/item/weapon/handcuffs, /obj/item/weapon/tank/jetpack) + slowdown = 1.5 + armor = list(melee = 65, bullet = 45, laser = 45, energy = 25, bomb = 50, bio = 100, rad = 50) + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.4 diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index c53659764d54..f01f120e4fea 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -1,102 +1,102 @@ -//Deathsquad suit -/obj/item/clothing/head/helmet/space/deathsquad - name = "deathsquad helmet" - desc = "That's not red paint. That's real blood." - icon_state = "deathsquad" - item_state = "deathsquad" - armor = list(melee = 80, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 30, rad = 30) - -/obj/item/clothing/head/helmet/space/deathsquad/beret - name = "special operations officer's beret" - desc = "An armored beret commonly used by special operations officers." - icon_state = "beret_badge" - armor = list(melee = 80, bullet = 70, laser = 60,energy = 10, bomb = 25, bio = 10, rad = 0) - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0.9 - -//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 = HEADCOVERSEYES | BLOCKHAIR - body_parts_covered = HEAD - -/obj/item/clothing/suit/space/santa - name = "Santa's suit" - desc = "Festive!" - icon_state = "santa" - item_state = "santa" - slowdown = 0 - flags = ONESIZEFITSALL - allowed = list(/obj/item) //for stuffing exta special presents - -/obj/item/clothing/head/helmet/syndiassault - name = "assault helmet" - icon_state = "assaulthelmet_b" - item_state = "assaulthelmet_b" - armor = list(melee = 50, bullet = 60, laser = 45, energy = 70, bomb = 50, bio = 0, rad = 50) - siemens_coefficient = 0.2 - -/obj/item/clothing/head/helmet/syndiassault/alternate - icon_state = "assaulthelmet" - item_state = "assaulthelmet" - -//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 = 35, laser = 60,energy = 60, bomb = 30, bio = 30, rad = 30) - flags = HEADCOVERSEYES | BLOCKHAIR - -/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_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank) - slowdown = 0 - armor = list(melee = 60, bullet = 35, laser = 60,energy = 60, bomb = 30, bio = 30, rad = 30) - breach_threshold = 25 - -//Buget suit - -/obj/item/clothing/suit/space/cheap - name = "budget spacesuit" - desc = "It was an attempt to force the assistants to work in space.The label on the side reads: Not for atheists" - resilience = 0.6 - -/obj/item/clothing/head/helmet/space/cheap - name = "budget spacesuit helmet" - desc = "It was an attempt to force the assistants to work in space. At least 60% of them survived in the spacesuit." - -//Mime's Hardsuit -/obj/item/clothing/head/helmet/space/mime - name = "mime hardsuit helmet" - desc = "A hardsuit helmet specifically designed for the mime." - icon_state = "mim" - item_state = "mim" - -obj/item/clothing/suit/space/mime - name = "mime hardsuit" - desc = "A hardsuit specifically designed for the mime." - icon_state = "mime" - item_state = "mime" - allowed = list(/obj/item/weapon/tank) - -/obj/item/clothing/head/helmet/space/clown - name = "clown hardsuit helmet" - desc = "A hardsuit helmet specifically designed for the clown. SPESSHONK!" - icon_state = "kluwne" - item_state = "kluwne" - -obj/item/clothing/suit/space/clown - name = "clown hardsuit" - desc = "A hardsuit specifically designed for the clown. SPESSHONK!" - icon_state = "clowan" - item_state = "clowan" - allowed = list(/obj/item/weapon/tank) +//Deathsquad suit +/obj/item/clothing/head/helmet/space/deathsquad + name = "deathsquad helmet" + desc = "That's not red paint. That's real blood." + icon_state = "deathsquad" + item_state = "deathsquad" + armor = list(melee = 80, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 30, rad = 30) + +/obj/item/clothing/head/helmet/space/deathsquad/beret + name = "special operations officer's beret" + desc = "An armored beret commonly used by special operations officers." + icon_state = "beret_badge" + armor = list(melee = 80, bullet = 70, laser = 60,energy = 10, bomb = 25, bio = 10, rad = 0) + cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0.9 + +//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 = HEADCOVERSEYES | BLOCKHAIR + body_parts_covered = HEAD + +/obj/item/clothing/suit/space/santa + name = "Santa's suit" + desc = "Festive!" + icon_state = "santa" + item_state = "santa" + slowdown = 0 + flags = ONESIZEFITSALL + allowed = list(/obj/item) //for stuffing exta special presents + +/obj/item/clothing/head/helmet/syndiassault + name = "assault helmet" + icon_state = "assaulthelmet_b" + item_state = "assaulthelmet_b" + armor = list(melee = 50, bullet = 60, laser = 45, energy = 70, bomb = 50, bio = 0, rad = 50) + siemens_coefficient = 0.2 + +/obj/item/clothing/head/helmet/syndiassault/alternate + icon_state = "assaulthelmet" + item_state = "assaulthelmet" + +//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 = 35, laser = 60,energy = 60, bomb = 30, bio = 30, rad = 30) + flags = HEADCOVERSEYES | BLOCKHAIR + +/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_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank) + slowdown = 0 + armor = list(melee = 60, bullet = 35, laser = 60,energy = 60, bomb = 30, bio = 30, rad = 30) + breach_threshold = 25 + +//Buget suit + +/obj/item/clothing/suit/space/cheap + name = "budget spacesuit" + desc = "It was an attempt to force the assistants to work in space.The label on the side reads: Not for atheists" + resilience = 0.6 + +/obj/item/clothing/head/helmet/space/cheap + name = "budget spacesuit helmet" + desc = "It was an attempt to force the assistants to work in space. At least 60% of them survived in the spacesuit." + +//Mime's Hardsuit +/obj/item/clothing/head/helmet/space/mime + name = "mime hardsuit helmet" + desc = "A hardsuit helmet specifically designed for the mime." + icon_state = "mim" + item_state = "mim" + +obj/item/clothing/suit/space/mime + name = "mime hardsuit" + desc = "A hardsuit specifically designed for the mime." + icon_state = "mime" + item_state = "mime" + allowed = list(/obj/item/weapon/tank) + +/obj/item/clothing/head/helmet/space/clown + name = "clown hardsuit helmet" + desc = "A hardsuit helmet specifically designed for the clown. SPESSHONK!" + icon_state = "kluwne" + item_state = "kluwne" + +obj/item/clothing/suit/space/clown + name = "clown hardsuit" + desc = "A hardsuit specifically designed for the clown. SPESSHONK!" + icon_state = "clowan" + item_state = "clowan" + allowed = list(/obj/item/weapon/tank) diff --git a/code/modules/clothing/spacesuits/ninja.dm b/code/modules/clothing/spacesuits/ninja.dm index b0bc8e5e2a71..0b5a6bf2d232 100644 --- a/code/modules/clothing/spacesuits/ninja.dm +++ b/code/modules/clothing/spacesuits/ninja.dm @@ -1,68 +1,68 @@ -/obj/item/clothing/head/helmet/space/space_ninja - desc = "What may appear to be a simple black garment is in fact a highly sophisticated nano-weave helmet. Standard issue ninja gear." - name = "ninja hood" - icon_state = "s-ninja" - item_state = "s-ninja_mask" - allowed = list(/obj/item/weapon/stock_parts/cell) - armor = list(melee = 60, bullet = 50, laser = 60,energy = 45, bomb = 50, bio = 100, rad = 50) - species_restricted = null - body_parts_covered = HEAD|FACE - blockTracking = 1 - -/obj/item/clothing/suit/space/space_ninja - name = "ninja suit" - desc = "A unique, vaccum-proof suit of nano-enhanced armor designed specifically for Spider Clan assassins." - icon_state = "s-ninja" - item_state = "s-ninja_suit" - allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/stock_parts/cell) - slowdown = 0 - armor = list(melee = 60, bullet = 50, laser = 60,energy = 45, bomb = 30, bio = 100, rad = 50) - species_restricted = null //Workaround for spawning alien ninja without internals. - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - supporting_limbs = list() - - // Hardsuit breaching data - breach_threshold = 30 //A suit breach is a major issue for ninjas. This should maybe help. - can_breach = 1 - - //Important parts of the suit. - var/mob/living/carbon/affecting = null//The wearer. - var/obj/item/weapon/stock_parts/cell/cell//Starts out with a high-capacity cell using New(). - var/datum/effect/effect/system/spark_spread/spark_system//To create sparks. - var/reagent_list[] = list("tricordrazine","tramadol","dexalinp","spaceacillin","anti_toxin","nutriment","radium","hyronalin")//The reagents ids which are added to the suit at New(). - var/stored_research[]//For stealing station research. - var/obj/item/weapon/disk/tech_disk/t_disk//To copy design onto disk. - - //Other articles of ninja gear worn together, used to easily reference them after initializing. - var/obj/item/clothing/head/helmet/space/space_ninja/n_hood - var/obj/item/clothing/shoes/space_ninja/n_shoes - var/obj/item/clothing/gloves/space_ninja/n_gloves - - //Main function variables. - var/s_initialized = 0//Suit starts off. - var/s_coold = 0//If the suit is on cooldown. Can be used to attach different cooldowns to abilities. Ticks down every second based on suit ntick(). - var/s_cost = 5.0//Base energy cost each ntick. - var/s_acost = 25.0//Additional cost for additional powers active. - var/k_cost = 200.0//Kamikaze energy cost each ntick. - var/k_damage = 1.0//Brute damage potentially done by Kamikaze each ntick. - var/s_delay = 40.0//How fast the suit does certain things, lower is faster. Can be overridden in specific procs. Also determines adverse probability. - var/a_transfer = 20.0//How much reagent is transferred when injecting. - var/r_maxamount = 80.0//How much reagent in total there is. - - //Support function variables. - var/spideros = 0//Mode of SpiderOS. This can change so I won't bother listing the modes here (0 is hub). Check ninja_equipment.dm for how it all works. - var/s_active = 0//Stealth off. - var/s_busy = 0//Is the suit busy with a process? Like AI hacking. Used for safety functions. - var/kamikaze = 0//Kamikaze on or off. - var/k_unlock = 0//To unlock Kamikaze. - - //Ability function variables. - var/s_bombs = 10.0//Number of starting ninja smoke bombs. - var/a_boost = 3.0//Number of adrenaline boosters. - - //Onboard AI related variables. - var/mob/living/silicon/ai/AI//If there is an AI inside the suit. - var/obj/item/device/paicard/pai//A slot for a pAI device - var/obj/effect/overlay/hologram//Is the AI hologram on or off? Visible only to the wearer of the suit. This works by attaching an image to a blank overlay. - var/flush = 0//If an AI purge is in progress. - var/s_control = 1//If user in control of the suit. +/obj/item/clothing/head/helmet/space/space_ninja + desc = "What may appear to be a simple black garment is in fact a highly sophisticated nano-weave helmet. Standard issue ninja gear." + name = "ninja hood" + icon_state = "s-ninja" + item_state = "s-ninja_mask" + allowed = list(/obj/item/weapon/stock_parts/cell) + armor = list(melee = 60, bullet = 50, laser = 60,energy = 45, bomb = 50, bio = 100, rad = 50) + species_restricted = null + body_parts_covered = HEAD|FACE + blockTracking = 1 + +/obj/item/clothing/suit/space/space_ninja + name = "ninja suit" + desc = "A unique, vaccum-proof suit of nano-enhanced armor designed specifically for Spider Clan assassins." + icon_state = "s-ninja" + item_state = "s-ninja_suit" + allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/stock_parts/cell) + slowdown = 0 + armor = list(melee = 60, bullet = 50, laser = 60,energy = 45, bomb = 30, bio = 100, rad = 50) + species_restricted = null //Workaround for spawning alien ninja without internals. + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + supporting_limbs = list() + + // Hardsuit breaching data + breach_threshold = 30 //A suit breach is a major issue for ninjas. This should maybe help. + can_breach = 1 + + //Important parts of the suit. + var/mob/living/carbon/affecting = null//The wearer. + var/obj/item/weapon/stock_parts/cell/cell//Starts out with a high-capacity cell using New(). + var/datum/effect/effect/system/spark_spread/spark_system//To create sparks. + var/reagent_list[] = list("tricordrazine","tramadol","dexalinp","spaceacillin","anti_toxin","nutriment","radium","hyronalin")//The reagents ids which are added to the suit at New(). + var/stored_research[]//For stealing station research. + var/obj/item/weapon/disk/tech_disk/t_disk//To copy design onto disk. + + //Other articles of ninja gear worn together, used to easily reference them after initializing. + var/obj/item/clothing/head/helmet/space/space_ninja/n_hood + var/obj/item/clothing/shoes/space_ninja/n_shoes + var/obj/item/clothing/gloves/space_ninja/n_gloves + + //Main function variables. + var/s_initialized = 0//Suit starts off. + var/s_coold = 0//If the suit is on cooldown. Can be used to attach different cooldowns to abilities. Ticks down every second based on suit ntick(). + var/s_cost = 5.0//Base energy cost each ntick. + var/s_acost = 25.0//Additional cost for additional powers active. + var/k_cost = 200.0//Kamikaze energy cost each ntick. + var/k_damage = 1.0//Brute damage potentially done by Kamikaze each ntick. + var/s_delay = 40.0//How fast the suit does certain things, lower is faster. Can be overridden in specific procs. Also determines adverse probability. + var/a_transfer = 20.0//How much reagent is transferred when injecting. + var/r_maxamount = 80.0//How much reagent in total there is. + + //Support function variables. + var/spideros = 0//Mode of SpiderOS. This can change so I won't bother listing the modes here (0 is hub). Check ninja_equipment.dm for how it all works. + var/s_active = 0//Stealth off. + var/s_busy = 0//Is the suit busy with a process? Like AI hacking. Used for safety functions. + var/kamikaze = 0//Kamikaze on or off. + var/k_unlock = 0//To unlock Kamikaze. + + //Ability function variables. + var/s_bombs = 10.0//Number of starting ninja smoke bombs. + var/a_boost = 3.0//Number of adrenaline boosters. + + //Onboard AI related variables. + var/mob/living/silicon/ai/AI//If there is an AI inside the suit. + var/obj/item/device/paicard/pai//A slot for a pAI device + var/obj/effect/overlay/hologram//Is the AI hologram on or off? Visible only to the wearer of the suit. This works by attaching an image to a blank overlay. + var/flush = 0//If an AI purge is in progress. + var/s_control = 1//If user in control of the suit. diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index c3b74c06baba..a094b1116ccb 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -1,550 +1,550 @@ -//Regular rig suits -/obj/item/clothing/head/helmet/space/rig - name = "hardsuit helmet" - desc = "A special helmet designed for work in a hazardous, low-pressure environment." - icon_state = "rig0-engineering" - item_state = "eng_helm" - armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 20) - - action_button_name = "Toggle Helmet Light" - allowed = list(/obj/item/device/flashlight) - var/brightness_on = 4 //luminosity when on - var/on = 0 - item_color = "engineering" //Determines used sprites: rig[on]-[color] and rig[on]-[color]2 (lying down sprite) - heat_protection = HEAD - max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE - - //Species-specific stuff. - species_restricted = list("exclude", UNATHI, TAJARAN, SKRELL, DIONA, VOX) - sprite_sheets_refit = list( - UNATHI = 'icons/mob/species/unathi/helmet.dmi', - TAJARAN = 'icons/mob/species/tajaran/helmet.dmi', - SKRELL = 'icons/mob/species/skrell/helmet.dmi', - ) - sprite_sheets_obj = list( - UNATHI = 'icons/obj/clothing/species/unathi/hats.dmi', - TAJARAN = 'icons/obj/clothing/species/tajaran/hats.dmi', - SKRELL = 'icons/obj/clothing/species/skrell/hats.dmi', - ) - -/obj/item/clothing/head/helmet/space/rig/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 = "rig[on]-[item_color]" -// item_state = "rig[on]-[color]" - usr.update_inv_head() - - if(on) set_light(brightness_on) - else set_light(0) - - if(istype(user,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - H.update_inv_head() - -/obj/item/clothing/suit/space/rig - name = "hardsuit" - desc = "A special space suit for environments that might pose hazards beyond just the vacuum of space. Provides more protection than a standard space suit." - icon_state = "rig-engineering" - item_state = "eng_hardsuit" - slowdown = 1 - armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 20) - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner, /obj/item/weapon/rcd) - heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE - - species_restricted = list("exclude" , UNATHI , TAJARAN , DIONA , VOX) - sprite_sheets_refit = list( - UNATHI = 'icons/mob/species/unathi/suit.dmi', - TAJARAN = 'icons/mob/species/tajaran/suit.dmi', - SKRELL = 'icons/mob/species/skrell/suit.dmi', - ) - sprite_sheets_obj = list( - UNATHI = 'icons/obj/clothing/species/unathi/suits.dmi', - TAJARAN = 'icons/obj/clothing/species/tajaran/suits.dmi', - SKRELL = 'icons/obj/clothing/species/skrell/suits.dmi', - ) - var/magpulse = 0 - - //Breach thresholds, should ideally be inherited by most (if not all) hardsuits. - breach_threshold = 18 - can_breach = 1 - - //Component/device holders. - var/obj/item/weapon/stock_parts/gloves = null // Basic capacitor allows insulation, upgrades allow shock gloves etc. - - var/attached_boots = 1 // Can't wear boots if some are attached - var/obj/item/clothing/shoes/magboots/boots = null // Deployable boots, if any. - var/attached_helmet = 1 // Can't wear a helmet if one is deployable. - var/obj/item/clothing/head/helmet/helmet = null // Deployable helmet, if any. - - var/list/max_mounted_devices = 0 // Maximum devices. Easy. - var/list/can_mount = null // Types of device that can be hardpoint mounted. - var/list/mounted_devices = null // Holder for the above device. - var/obj/item/active_device = null // Currently deployed device, if any. - -/obj/item/clothing/suit/space/rig/equipped(mob/M) - ..() - - var/mob/living/carbon/human/H = M - - if(!istype(H)) return - - if(H.wear_suit != src) - return - -/obj/item/clothing/suit/space/rig/dropped() - ..() - - var/mob/living/carbon/human/H - - if(helmet) - H = helmet.loc - if(istype(H)) - if(helmet && H.head == helmet) - helmet.canremove = 1 - H.drop_from_inventory(helmet) - helmet.loc = src - - if(boots) - H = boots.loc - if(istype(H)) - if(boots && H.shoes == boots) - boots.canremove = 1 - H.drop_from_inventory(boots) - boots.loc = src - -/obj/item/clothing/suit/space/rig/verb/toggle_helmet() - - set name = "Toggle Helmet" - set category = "Object" - set src in usr - - if(!istype(src.loc,/mob/living)) return - - if(!helmet) - to_chat(usr, "There is no helmet installed.") - return - - var/mob/living/carbon/human/H = usr - - if(!istype(H)) return - if(H.stat) return - if(H.wear_suit != src) return - - if(H.head == helmet) - helmet.canremove = 1 - H.drop_from_inventory(helmet) - helmet.loc = src - to_chat(H, "\blue You retract your hardsuit helmet.") - - else if(H.equip_to_slot_if_possible(helmet, slot_head)) - helmet.canremove = 0 - to_chat(H, "You deploy your hardsuit helmet, sealing you off from the world.") - return - -/obj/item/clothing/suit/space/rig/verb/toggle_magboots() - - set name = "Toggle Space Suit Magboots" - set category = "Object" - set src in usr - - if(!istype(src.loc,/mob/living)) return - - if(!boots) - to_chat(usr, "\The [src] does not have any boots installed.") - return - - var/mob/living/carbon/human/H = usr - - if(!istype(H)) return - if(H.stat) return - if(H.wear_suit != src) return - - if(magpulse) - flags &= ~NOSLIP - src.slowdown = initial(slowdown) - magpulse = 0 - to_chat(H, "You disable \the [src] the mag-pulse traction system.") - else - flags |= NOSLIP - src.slowdown += boots.slowdown_off - magpulse = 1 - to_chat(H, "You enable the mag-pulse traction system.") - -/obj/item/clothing/suit/space/rig/attackby(obj/item/W, mob/user) - - if(!isliving(user)) return - - if(user.a_intent == "help") - - if(isliving(loc) && !istype(W, /obj/item/weapon/patcher)) - to_chat(user, "How do you propose to modify a hardsuit while it is being worn?") - return - - var/target_zone = user.zone_sel.selecting - - if(target_zone == BP_HEAD) - - //Installing a component into or modifying the contents of the helmet. - if(!attached_helmet) - to_chat(user, "\The [src] does not have a helmet mount.") - return - - if(istype(W,/obj/item/weapon/screwdriver)) - if(!helmet) - to_chat(user, "\The [src] does not have a helmet installed.") - else - to_chat(user, "You detatch \the [helmet] from \the [src]'s helmet mount.") - helmet.loc = get_turf(src) - src.helmet = null - return - else if(istype(W,/obj/item/clothing/head/helmet/space)) - if(helmet) - to_chat(user, "\The [src] already has a helmet installed.") - else - to_chat(user, "You attach \the [W] to \the [src]'s helmet mount.") - user.drop_item() - W.loc = src - src.helmet = W - return - else - return ..() - - else if(target_zone == BP_L_LEG || target_zone == BP_R_LEG) - - //Installing a component into or modifying the contents of the feet. - if(!attached_boots) - to_chat(user, "\The [src] does not have boot mounts.") - return - - if(istype(W,/obj/item/weapon/screwdriver)) - if(!boots) - to_chat(user, "\The [src] does not have any boots installed.") - else - to_chat(user, "You detatch \the [boots] from \the [src]'s boot mounts.") - boots.loc = get_turf(src) - boots = null - return - else if(istype(W,/obj/item/clothing/shoes/magboots)) - if(boots) - to_chat(user, "\The [src] already has magboots installed.") - else - to_chat(user, "You attach \the [W] to \the [src]'s boot mounts.") - user.drop_item() - W.loc = src - boots = W - else - return ..() - - else //wat - return ..() - - ..() - -/obj/item/clothing/suit/space/rig/examine(mob/user) - ..() - to_chat(user, "Its mag-pulse traction system appears to be [magpulse ? "enabled" : "disabled"].") - -//Engineering rig -/obj/item/clothing/head/helmet/space/rig/engineering - 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 = 10,energy = 5, bomb = 35, bio = 100, rad = 80) - siemens_coefficient = 0 - -/obj/item/clothing/suit/space/rig/engineering - name = "engineering hardsuit" - desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding. Heavy insulation layer adds additional weight" - icon_state = "rig-engineering" - item_state = "eng_hardsuit" - slowdown = 3 - armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 80) - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd) - siemens_coefficient = 0 - -//Chief Engineer's rig -/obj/item/clothing/head/helmet/space/rig/engineering/chief - 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-chief" - item_state = "ce_helm" - item_color = "chief" - max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/suit/space/rig/engineering/chief - icon_state = "rig-chief" - name = "advanced hardsuit" - desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish." - item_state = "ce_hardsuit" - slowdown = 1 - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE - -//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" - item_color = "mining" - armor = list(melee = 60, bullet = 5, laser = 10,energy = 5, bomb = 55, bio = 100, rad = 20) - -/obj/item/clothing/suit/space/rig/mining - icon_state = "rig-mining" - name = "mining hardsuit" - desc = "A special suit that protects against hazardous, low pressure environments. Has reinforced plating." - item_state = "mining_hardsuit" - armor = list(melee = 90, bullet = 5, laser = 10,energy = 5, bomb = 55, bio = 100, rad = 20) - breach_threshold = 26 - - -//Syndicate rig -/obj/item/clothing/head/helmet/space/rig/syndi - name = "blood-red hybrid helmet" - desc = "An advanced helmet designed for work in special operations. Property of Gorlex Marauders." - icon_state = "rig0-syndie" - item_state = "syndie_helm" - armor = list(melee = 60, bullet = 55, laser = 30,energy = 30, bomb = 50, bio = 100, rad = 60) - var/obj/machinery/camera/camera - var/combat_mode = FALSE - species_restricted = list("exclude" , SKRELL , DIONA, VOX) - var/image/lamp = null - var/equipped_on_head = FALSE - flags = BLOCKHAIR | THICKMATERIAL | PHORONGUARD - light_color = "#00f397" - -/obj/item/clothing/head/helmet/space/rig/syndi/equipped(mob/user, slot) - . = ..() - if(slot == slot_head) - equipped_on_head = TRUE - update_icon(user) - -/obj/item/clothing/head/helmet/space/rig/syndi/dropped(mob/user) - . = ..() - if(equipped_on_head) - equipped_on_head = FALSE - update_icon(user) - -/obj/item/clothing/head/helmet/space/rig/syndi/proc/checklight() - if(on) - set_light(l_range = brightness_on, l_color = light_color) - else if(combat_mode) - set_light(l_range = 1.23) // Minimal possible light_range that'll make helm lights visible in full dark from distance. Most likely going to break if somebody will touch lightning formulae. - else - set_light(0) - -/obj/item/clothing/head/helmet/space/rig/syndi/update_icon(mob/user) - user.overlays -= lamp - if(equipped_on_head && camera && (on || combat_mode)) - lamp = image(icon = 'icons/mob/nuclear_helm_overlays.dmi', icon_state = "terror[combat_mode ? "_combat" : ""]_glow", layer = ABOVE_LIGHTING_LAYER) - lamp.plane = LIGHTING_PLANE + 1 - lamp.alpha = on ? 255 : 127 - user.overlays += lamp - icon_state = "rig[on]-syndie[combat_mode ? "-combat" : ""]" - user.update_inv_head() - -/obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user) - if(camera) - on = !on - else - camera = new /obj/machinery/camera(src) - camera.replace_networks(list("NUKE")) - cameranet.removeCamera(camera) - camera.c_tag = user.name - to_chat(user, "User scanned as [camera.c_tag]. Camera activated.") - checklight() - update_icon(user) - -/obj/item/clothing/head/helmet/space/rig/syndi/verb/toggle() - set category = "Object" - set name = "Adjust helmet" - set src in usr - - if(usr.canmove && !usr.stat && !usr.restrained()) - combat_mode = !combat_mode - if(combat_mode) - armor = list(melee = 60, bullet = 65, laser = 55,energy = 45, bomb = 50, bio = 100, rad = 60) - canremove = FALSE - flags |= (HEADCOVERSEYES | HEADCOVERSMOUTH) - usr.visible_message("[usr] moves faceplate of their helmet into combat position, covering their visor and extending cameras.") - else - armor = list(melee = 60, bullet = 55, laser = 30,energy = 30, bomb = 50, bio = 100, rad = 60) - canremove = TRUE - flags &= ~(HEADCOVERSEYES | HEADCOVERSMOUTH) - usr.visible_message("[usr] pulls up faceplate from helmet's visor, retracting cameras") - checklight() - update_icon(usr) - -/obj/item/clothing/head/helmet/space/rig/syndi/examine(mob/user) - ..() - if(src in view(1, user)) - to_chat(user, "This helmet has a built-in camera. It's [camera ? "" : "in"]active.") - -/obj/item/clothing/head/helmet/space/rig/syndi/attackby(obj/item/W, mob/living/carbon/human/user) - if(!istype(user) || user.species.flags[IS_SYNTHETIC]) - return - if(!istype(W, /obj/item/weapon/reagent_containers/pill)) - return - if(!combat_mode && equipped_on_head) - user.SetNextMove(CLICK_CD_RAPID) - var/obj/item/weapon/reagent_containers/pill/P = W - P.reagents.trans_to_ingest(user, W.reagents.total_volume) - to_chat(user, "[src] consumes [W] and injected reagents to you!") - qdel(W) - - -/obj/item/clothing/suit/space/rig/syndi - name = "blood-red hybrid suit" - desc = "An advanced suit that protects against injuries during special operations. Property of Gorlex Marauders." - icon_state = "rig-syndie" - item_state = "syndie_hardsuit" - slowdown = 1.4 - armor = list(melee = 60, bullet = 65, laser = 55, energy = 45, bomb = 50, bio = 100, rad = 60) - allowed = list(/obj/item/device/flashlight, - /obj/item/weapon/tank, - /obj/item/device/suit_cooling_unit, - /obj/item/weapon/gun, - /obj/item/ammo_box/magazine, - /obj/item/ammo_casing, - /obj/item/weapon/melee/baton, - /obj/item/weapon/melee/energy/sword, - /obj/item/weapon/handcuffs) - species_restricted = list("exclude" , UNATHI , TAJARAN , DIONA, VOX) - action_button_name = "Toggle space suit mode" - var/combat_mode = FALSE - -/obj/item/clothing/suit/space/rig/syndi/update_icon(mob/user) - ..() - icon_state = "rig-syndie[combat_mode ? "-combat" : ""]" - user.update_inv_wear_suit() - -/obj/item/clothing/suit/space/rig/syndi/ui_action_click() - toggle_mode() - -/obj/item/clothing/suit/space/rig/syndi/verb/toggle_mode() - set category = "Object" - set name = "Adjust space suit" - set src in usr - - if(usr.canmove && !usr.stat && !usr.restrained()) - combat_mode = !combat_mode - if(combat_mode) - canremove = FALSE - can_breach = FALSE - flags_pressure &= ~STOPS_PRESSUREDMAGE - playsound(usr, "sound/effects/air_release.ogg", 50) - usr.visible_message("[usr]'s suit depressurizes, exposing armor plates.") - else - canremove = TRUE - can_breach = TRUE - flags_pressure |= STOPS_PRESSUREDMAGE - playsound(usr, "sound/effects/inflate.ogg", 30) - usr.visible_message("[usr]'s suit inflates and pressurizes.") - update_icon(usr) - - -//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" - item_color = "wiz" - unacidable = 1 //No longer shall our kind be foiled by lone chemists with spray bottles! - armor = list(melee = 40, bullet = 33, laser = 33,energy = 33, bomb = 33, bio = 100, rad = 66) - -/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 - unacidable = 1 - armor = list(melee = 40, bullet = 33, laser = 33,energy = 33, bomb = 33, bio = 100, rad = 66) - -//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" - item_color = "medical" - armor = list(melee = 30, bullet = 5, laser = 10,energy = 5, bomb = 25, bio = 100, rad = 50) - -/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" - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical) - armor = list(melee = 30, bullet = 5, laser = 10,energy = 5, bomb = 25, bio = 100, rad = 50) - -//CMO Rig -/obj/item/clothing/head/helmet/space/rig/medical/cmo - name = "advanced medical hardsuit helmet" - desc = "A special helmet designed for work in a hazardous, low pressure environment. Has minor radiation shielding." - icon_state = "rig0-cmo" - item_state = "medical_helm" - item_color = "cmo" - -/obj/item/clothing/suit/space/rig/medical/cmo - icon_state = "rig-cmo" - name = "advanced medical hardsuit" - desc = "A special suit that protects against hazardous, low pressure environments. Has minor radiation shielding." - item_state = "medical_hardsuit" - slowdown = 0.5 - -//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" - item_color = "sec" - armor = list(melee = 60, bullet = 60, laser = 60, energy = 30, bomb = 65, bio = 100, rad = 10) - -/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" - armor = list(melee = 60, bullet = 60, laser = 60, energy = 30, bomb = 65, bio = 100, rad = 10) - allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/melee/baton) - breach_threshold = 20 - slowdown = 1.4 - -//HoS Rig -/obj/item/clothing/head/helmet/space/rig/security/hos - name = "advanced 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-hos" - item_state = "sec_helm" - item_color = "hos" - -/obj/item/clothing/suit/space/rig/security/hos - icon_state = "rig-hos" - name = "advanced security hardsuit" - desc = "A special suit that protects against hazardous, low pressure environments. Has an additional layer of armor." - item_state = "sec_hardsuit" - slowdown = 0.7 - -//Atmospherics Rig (BS12) -/obj/item/clothing/head/helmet/space/rig/atmos - desc = "A special helmet designed for work in a hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding." - name = "atmospherics hardsuit helmet" - icon_state = "rig0-atmos" - item_state = "atmos_helm" - item_color = "atmos" - armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 50) - max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE - -/obj/item/clothing/suit/space/rig/atmos - desc = "A special suit that protects against hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding." - icon_state = "rig-atmos" - name = "atmos hardsuit" - item_state = "atmos_hardsuit" - armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 50) - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE +//Regular rig suits +/obj/item/clothing/head/helmet/space/rig + name = "hardsuit helmet" + desc = "A special helmet designed for work in a hazardous, low-pressure environment." + icon_state = "rig0-engineering" + item_state = "eng_helm" + armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 20) + + action_button_name = "Toggle Helmet Light" + allowed = list(/obj/item/device/flashlight) + var/brightness_on = 4 //luminosity when on + var/on = 0 + item_color = "engineering" //Determines used sprites: rig[on]-[color] and rig[on]-[color]2 (lying down sprite) + heat_protection = HEAD + max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE + + //Species-specific stuff. + species_restricted = list("exclude", UNATHI, TAJARAN, SKRELL, DIONA, VOX) + sprite_sheets_refit = list( + UNATHI = 'icons/mob/species/unathi/helmet.dmi', + TAJARAN = 'icons/mob/species/tajaran/helmet.dmi', + SKRELL = 'icons/mob/species/skrell/helmet.dmi', + ) + sprite_sheets_obj = list( + UNATHI = 'icons/obj/clothing/species/unathi/hats.dmi', + TAJARAN = 'icons/obj/clothing/species/tajaran/hats.dmi', + SKRELL = 'icons/obj/clothing/species/skrell/hats.dmi', + ) + +/obj/item/clothing/head/helmet/space/rig/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 = "rig[on]-[item_color]" +// item_state = "rig[on]-[color]" + usr.update_inv_head() + + if(on) set_light(brightness_on) + else set_light(0) + + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.update_inv_head() + +/obj/item/clothing/suit/space/rig + name = "hardsuit" + desc = "A special space suit for environments that might pose hazards beyond just the vacuum of space. Provides more protection than a standard space suit." + icon_state = "rig-engineering" + item_state = "eng_hardsuit" + slowdown = 1 + armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 20) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner, /obj/item/weapon/rcd) + heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE + + species_restricted = list("exclude" , UNATHI , TAJARAN , DIONA , VOX) + sprite_sheets_refit = list( + UNATHI = 'icons/mob/species/unathi/suit.dmi', + TAJARAN = 'icons/mob/species/tajaran/suit.dmi', + SKRELL = 'icons/mob/species/skrell/suit.dmi', + ) + sprite_sheets_obj = list( + UNATHI = 'icons/obj/clothing/species/unathi/suits.dmi', + TAJARAN = 'icons/obj/clothing/species/tajaran/suits.dmi', + SKRELL = 'icons/obj/clothing/species/skrell/suits.dmi', + ) + var/magpulse = 0 + + //Breach thresholds, should ideally be inherited by most (if not all) hardsuits. + breach_threshold = 18 + can_breach = 1 + + //Component/device holders. + var/obj/item/weapon/stock_parts/gloves = null // Basic capacitor allows insulation, upgrades allow shock gloves etc. + + var/attached_boots = 1 // Can't wear boots if some are attached + var/obj/item/clothing/shoes/magboots/boots = null // Deployable boots, if any. + var/attached_helmet = 1 // Can't wear a helmet if one is deployable. + var/obj/item/clothing/head/helmet/helmet = null // Deployable helmet, if any. + + var/list/max_mounted_devices = 0 // Maximum devices. Easy. + var/list/can_mount = null // Types of device that can be hardpoint mounted. + var/list/mounted_devices = null // Holder for the above device. + var/obj/item/active_device = null // Currently deployed device, if any. + +/obj/item/clothing/suit/space/rig/equipped(mob/M) + ..() + + var/mob/living/carbon/human/H = M + + if(!istype(H)) return + + if(H.wear_suit != src) + return + +/obj/item/clothing/suit/space/rig/dropped() + ..() + + var/mob/living/carbon/human/H + + if(helmet) + H = helmet.loc + if(istype(H)) + if(helmet && H.head == helmet) + helmet.canremove = 1 + H.drop_from_inventory(helmet) + helmet.loc = src + + if(boots) + H = boots.loc + if(istype(H)) + if(boots && H.shoes == boots) + boots.canremove = 1 + H.drop_from_inventory(boots) + boots.loc = src + +/obj/item/clothing/suit/space/rig/verb/toggle_helmet() + + set name = "Toggle Helmet" + set category = "Object" + set src in usr + + if(!istype(src.loc,/mob/living)) return + + if(!helmet) + to_chat(usr, "There is no helmet installed.") + return + + var/mob/living/carbon/human/H = usr + + if(!istype(H)) return + if(H.stat) return + if(H.wear_suit != src) return + + if(H.head == helmet) + helmet.canremove = 1 + H.drop_from_inventory(helmet) + helmet.loc = src + to_chat(H, "\blue You retract your hardsuit helmet.") + + else if(H.equip_to_slot_if_possible(helmet, slot_head)) + helmet.canremove = 0 + to_chat(H, "You deploy your hardsuit helmet, sealing you off from the world.") + return + +/obj/item/clothing/suit/space/rig/verb/toggle_magboots() + + set name = "Toggle Space Suit Magboots" + set category = "Object" + set src in usr + + if(!istype(src.loc,/mob/living)) return + + if(!boots) + to_chat(usr, "\The [src] does not have any boots installed.") + return + + var/mob/living/carbon/human/H = usr + + if(!istype(H)) return + if(H.stat) return + if(H.wear_suit != src) return + + if(magpulse) + flags &= ~NOSLIP + src.slowdown = initial(slowdown) + magpulse = 0 + to_chat(H, "You disable \the [src] the mag-pulse traction system.") + else + flags |= NOSLIP + src.slowdown += boots.slowdown_off + magpulse = 1 + to_chat(H, "You enable the mag-pulse traction system.") + +/obj/item/clothing/suit/space/rig/attackby(obj/item/W, mob/user) + + if(!isliving(user)) return + + if(user.a_intent == "help") + + if(isliving(loc) && !istype(W, /obj/item/weapon/patcher)) + to_chat(user, "How do you propose to modify a hardsuit while it is being worn?") + return + + var/target_zone = user.zone_sel.selecting + + if(target_zone == BP_HEAD) + + //Installing a component into or modifying the contents of the helmet. + if(!attached_helmet) + to_chat(user, "\The [src] does not have a helmet mount.") + return + + if(istype(W,/obj/item/weapon/screwdriver)) + if(!helmet) + to_chat(user, "\The [src] does not have a helmet installed.") + else + to_chat(user, "You detatch \the [helmet] from \the [src]'s helmet mount.") + helmet.loc = get_turf(src) + src.helmet = null + return + else if(istype(W,/obj/item/clothing/head/helmet/space)) + if(helmet) + to_chat(user, "\The [src] already has a helmet installed.") + else + to_chat(user, "You attach \the [W] to \the [src]'s helmet mount.") + user.drop_item() + W.loc = src + src.helmet = W + return + else + return ..() + + else if(target_zone == BP_L_LEG || target_zone == BP_R_LEG) + + //Installing a component into or modifying the contents of the feet. + if(!attached_boots) + to_chat(user, "\The [src] does not have boot mounts.") + return + + if(istype(W,/obj/item/weapon/screwdriver)) + if(!boots) + to_chat(user, "\The [src] does not have any boots installed.") + else + to_chat(user, "You detatch \the [boots] from \the [src]'s boot mounts.") + boots.loc = get_turf(src) + boots = null + return + else if(istype(W,/obj/item/clothing/shoes/magboots)) + if(boots) + to_chat(user, "\The [src] already has magboots installed.") + else + to_chat(user, "You attach \the [W] to \the [src]'s boot mounts.") + user.drop_item() + W.loc = src + boots = W + else + return ..() + + else //wat + return ..() + + ..() + +/obj/item/clothing/suit/space/rig/examine(mob/user) + ..() + to_chat(user, "Its mag-pulse traction system appears to be [magpulse ? "enabled" : "disabled"].") + +//Engineering rig +/obj/item/clothing/head/helmet/space/rig/engineering + 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 = 10,energy = 5, bomb = 35, bio = 100, rad = 80) + siemens_coefficient = 0 + +/obj/item/clothing/suit/space/rig/engineering + name = "engineering hardsuit" + desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding. Heavy insulation layer adds additional weight" + icon_state = "rig-engineering" + item_state = "eng_hardsuit" + slowdown = 3 + armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 80) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/bag/ore,/obj/item/device/t_scanner,/obj/item/weapon/pickaxe, /obj/item/weapon/rcd) + siemens_coefficient = 0 + +//Chief Engineer's rig +/obj/item/clothing/head/helmet/space/rig/engineering/chief + 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-chief" + item_state = "ce_helm" + item_color = "chief" + max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/suit/space/rig/engineering/chief + icon_state = "rig-chief" + name = "advanced hardsuit" + desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish." + item_state = "ce_hardsuit" + slowdown = 1 + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE + +//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" + item_color = "mining" + armor = list(melee = 60, bullet = 5, laser = 10,energy = 5, bomb = 55, bio = 100, rad = 20) + +/obj/item/clothing/suit/space/rig/mining + icon_state = "rig-mining" + name = "mining hardsuit" + desc = "A special suit that protects against hazardous, low pressure environments. Has reinforced plating." + item_state = "mining_hardsuit" + armor = list(melee = 90, bullet = 5, laser = 10,energy = 5, bomb = 55, bio = 100, rad = 20) + breach_threshold = 26 + + +//Syndicate rig +/obj/item/clothing/head/helmet/space/rig/syndi + name = "blood-red hybrid helmet" + desc = "An advanced helmet designed for work in special operations. Property of Gorlex Marauders." + icon_state = "rig0-syndie" + item_state = "syndie_helm" + armor = list(melee = 60, bullet = 55, laser = 30,energy = 30, bomb = 50, bio = 100, rad = 60) + var/obj/machinery/camera/camera + var/combat_mode = FALSE + species_restricted = list("exclude" , SKRELL , DIONA, VOX) + var/image/lamp = null + var/equipped_on_head = FALSE + flags = BLOCKHAIR | THICKMATERIAL | PHORONGUARD + light_color = "#00f397" + +/obj/item/clothing/head/helmet/space/rig/syndi/equipped(mob/user, slot) + . = ..() + if(slot == slot_head) + equipped_on_head = TRUE + update_icon(user) + +/obj/item/clothing/head/helmet/space/rig/syndi/dropped(mob/user) + . = ..() + if(equipped_on_head) + equipped_on_head = FALSE + update_icon(user) + +/obj/item/clothing/head/helmet/space/rig/syndi/proc/checklight() + if(on) + set_light(l_range = brightness_on, l_color = light_color) + else if(combat_mode) + set_light(l_range = 1.23) // Minimal possible light_range that'll make helm lights visible in full dark from distance. Most likely going to break if somebody will touch lightning formulae. + else + set_light(0) + +/obj/item/clothing/head/helmet/space/rig/syndi/update_icon(mob/user) + user.overlays -= lamp + if(equipped_on_head && camera && (on || combat_mode)) + lamp = image(icon = 'icons/mob/nuclear_helm_overlays.dmi', icon_state = "terror[combat_mode ? "_combat" : ""]_glow", layer = ABOVE_LIGHTING_LAYER) + lamp.plane = LIGHTING_PLANE + 1 + lamp.alpha = on ? 255 : 127 + user.overlays += lamp + icon_state = "rig[on]-syndie[combat_mode ? "-combat" : ""]" + user.update_inv_head() + +/obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user) + if(camera) + on = !on + else + camera = new /obj/machinery/camera(src) + camera.replace_networks(list("NUKE")) + cameranet.removeCamera(camera) + camera.c_tag = user.name + to_chat(user, "User scanned as [camera.c_tag]. Camera activated.") + checklight() + update_icon(user) + +/obj/item/clothing/head/helmet/space/rig/syndi/verb/toggle() + set category = "Object" + set name = "Adjust helmet" + set src in usr + + if(usr.canmove && !usr.stat && !usr.restrained()) + combat_mode = !combat_mode + if(combat_mode) + armor = list(melee = 60, bullet = 65, laser = 55,energy = 45, bomb = 50, bio = 100, rad = 60) + canremove = FALSE + flags |= (HEADCOVERSEYES | HEADCOVERSMOUTH) + usr.visible_message("[usr] moves faceplate of their helmet into combat position, covering their visor and extending cameras.") + else + armor = list(melee = 60, bullet = 55, laser = 30,energy = 30, bomb = 50, bio = 100, rad = 60) + canremove = TRUE + flags &= ~(HEADCOVERSEYES | HEADCOVERSMOUTH) + usr.visible_message("[usr] pulls up faceplate from helmet's visor, retracting cameras") + checklight() + update_icon(usr) + +/obj/item/clothing/head/helmet/space/rig/syndi/examine(mob/user) + ..() + if(src in view(1, user)) + to_chat(user, "This helmet has a built-in camera. It's [camera ? "" : "in"]active.") + +/obj/item/clothing/head/helmet/space/rig/syndi/attackby(obj/item/W, mob/living/carbon/human/user) + if(!istype(user) || user.species.flags[IS_SYNTHETIC]) + return + if(!istype(W, /obj/item/weapon/reagent_containers/pill)) + return + if(!combat_mode && equipped_on_head) + user.SetNextMove(CLICK_CD_RAPID) + var/obj/item/weapon/reagent_containers/pill/P = W + P.reagents.trans_to_ingest(user, W.reagents.total_volume) + to_chat(user, "[src] consumes [W] and injected reagents to you!") + qdel(W) + + +/obj/item/clothing/suit/space/rig/syndi + name = "blood-red hybrid suit" + desc = "An advanced suit that protects against injuries during special operations. Property of Gorlex Marauders." + icon_state = "rig-syndie" + item_state = "syndie_hardsuit" + slowdown = 1.4 + armor = list(melee = 60, bullet = 65, laser = 55, energy = 45, bomb = 50, bio = 100, rad = 60) + allowed = list(/obj/item/device/flashlight, + /obj/item/weapon/tank, + /obj/item/device/suit_cooling_unit, + /obj/item/weapon/gun, + /obj/item/ammo_box/magazine, + /obj/item/ammo_casing, + /obj/item/weapon/melee/baton, + /obj/item/weapon/melee/energy/sword, + /obj/item/weapon/handcuffs) + species_restricted = list("exclude" , UNATHI , TAJARAN , DIONA, VOX) + action_button_name = "Toggle space suit mode" + var/combat_mode = FALSE + +/obj/item/clothing/suit/space/rig/syndi/update_icon(mob/user) + ..() + icon_state = "rig-syndie[combat_mode ? "-combat" : ""]" + user.update_inv_wear_suit() + +/obj/item/clothing/suit/space/rig/syndi/ui_action_click() + toggle_mode() + +/obj/item/clothing/suit/space/rig/syndi/verb/toggle_mode() + set category = "Object" + set name = "Adjust space suit" + set src in usr + + if(usr.canmove && !usr.stat && !usr.restrained()) + combat_mode = !combat_mode + if(combat_mode) + canremove = FALSE + can_breach = FALSE + flags_pressure &= ~STOPS_PRESSUREDMAGE + playsound(usr, "sound/effects/air_release.ogg", 50) + usr.visible_message("[usr]'s suit depressurizes, exposing armor plates.") + else + canremove = TRUE + can_breach = TRUE + flags_pressure |= STOPS_PRESSUREDMAGE + playsound(usr, "sound/effects/inflate.ogg", 30) + usr.visible_message("[usr]'s suit inflates and pressurizes.") + update_icon(usr) + + +//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" + item_color = "wiz" + unacidable = 1 //No longer shall our kind be foiled by lone chemists with spray bottles! + armor = list(melee = 40, bullet = 33, laser = 33,energy = 33, bomb = 33, bio = 100, rad = 66) + +/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 + unacidable = 1 + armor = list(melee = 40, bullet = 33, laser = 33,energy = 33, bomb = 33, bio = 100, rad = 66) + +//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" + item_color = "medical" + armor = list(melee = 30, bullet = 5, laser = 10,energy = 5, bomb = 25, bio = 100, rad = 50) + +/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" + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage/firstaid,/obj/item/device/healthanalyzer,/obj/item/stack/medical) + armor = list(melee = 30, bullet = 5, laser = 10,energy = 5, bomb = 25, bio = 100, rad = 50) + +//CMO Rig +/obj/item/clothing/head/helmet/space/rig/medical/cmo + name = "advanced medical hardsuit helmet" + desc = "A special helmet designed for work in a hazardous, low pressure environment. Has minor radiation shielding." + icon_state = "rig0-cmo" + item_state = "medical_helm" + item_color = "cmo" + +/obj/item/clothing/suit/space/rig/medical/cmo + icon_state = "rig-cmo" + name = "advanced medical hardsuit" + desc = "A special suit that protects against hazardous, low pressure environments. Has minor radiation shielding." + item_state = "medical_hardsuit" + slowdown = 0.5 + +//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" + item_color = "sec" + armor = list(melee = 60, bullet = 60, laser = 60, energy = 30, bomb = 65, bio = 100, rad = 10) + +/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" + armor = list(melee = 60, bullet = 60, laser = 60, energy = 30, bomb = 65, bio = 100, rad = 10) + allowed = list(/obj/item/weapon/gun,/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/melee/baton) + breach_threshold = 20 + slowdown = 1.4 + +//HoS Rig +/obj/item/clothing/head/helmet/space/rig/security/hos + name = "advanced 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-hos" + item_state = "sec_helm" + item_color = "hos" + +/obj/item/clothing/suit/space/rig/security/hos + icon_state = "rig-hos" + name = "advanced security hardsuit" + desc = "A special suit that protects against hazardous, low pressure environments. Has an additional layer of armor." + item_state = "sec_hardsuit" + slowdown = 0.7 + +//Atmospherics Rig (BS12) +/obj/item/clothing/head/helmet/space/rig/atmos + desc = "A special helmet designed for work in a hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding." + name = "atmospherics hardsuit helmet" + icon_state = "rig0-atmos" + item_state = "atmos_helm" + item_color = "atmos" + armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 50) + max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE + +/obj/item/clothing/suit/space/rig/atmos + desc = "A special suit that protects against hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding." + icon_state = "rig-atmos" + name = "atmos hardsuit" + item_state = "atmos_hardsuit" + armor = list(melee = 40, bullet = 5, laser = 10,energy = 5, bomb = 35, bio = 100, rad = 50) + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm index f5ed3dc851f3..19d26066949a 100644 --- a/code/modules/clothing/spacesuits/syndi.dm +++ b/code/modules/clothing/spacesuits/syndi.dm @@ -1,141 +1,141 @@ -//Regular syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate - name = "red space helmet" - icon_state = "syndicate-helm" - item_state = "syndicate-helm" - desc = "Has a tag: Totally not property of an enemy corporation, honest." - armor = list(melee = 60, bullet = 35, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - action_button_name = "Toggle Helmet Light" - var/brightness = 3 //light_range when on - var/lit = FALSE - species_restricted = list("exclude" , DIONA , VOX) - var/image/lamp = null - -/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 of a hostile corporation, honest!" - w_class = 3 - allowed = list(/obj/item/weapon/gun, - /obj/item/ammo_box/magazine, - /obj/item/ammo_casing, - /obj/item/weapon/melee/baton, - /obj/item/weapon/melee/energy/sword, - /obj/item/weapon/handcuffs, - /obj/item/weapon/tank/emergency_oxygen) - slowdown = 1 - armor = list(melee = 60, bullet = 35, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - species_restricted = list("exclude" , DIONA , VOX) - -/obj/item/clothing/head/helmet/space/syndicate/update_icon(mob/user) - . = ..() - icon_state = "[initial(icon_state)][lit ? "-lit" : ""]" - user.update_inv_head() - -/obj/item/clothing/head/helmet/space/syndicate/attack_self(mob/user) - . = ..() - lit = !lit - set_light(lit ? brightness : 0) - update_icon(user) - - -//Civilian syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/civilian - name = "civilian space helmet" - desc = "Space helmet made by unknown manufacturer." - icon_state = "syndicate-helm-civ" - item_state = "syndicate-helm-jailbreaker" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) - species_restricted = list("exclude" , UNATHI , TAJARAN , SKRELL , DIONA , VOX) - -/obj/item/clothing/suit/space/syndicate/civilian - name = "civilian space suit" - desc = "Space suit made by unknown manufacturer." - icon_state = "syndicate-civ" - item_state = "s_suit" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) - - -//Striker syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/striker - name = "striker space helmet" - desc = "That's obviously some kind of military space helmet." - icon_state = "syndicate-helm-striker" - item_state = "syndicate-helm-striker" - armor = list(melee = 60, bullet = 45, laser = 40,energy = 45, bomb = 50, bio = 100, rad = 30) - brightness = 4 - -/obj/item/clothing/suit/space/syndicate/striker - name = "striker space suit" - desc = "That's obviously some kind of military space suit." - icon_state = "syndicate-striker" - item_state = "syndicate-striker" - armor = list(melee = 60, bullet = 45, laser = 40,energy = 45, bomb = 50, bio = 100, rad = 30) - breach_threshold = 12 - - -//Jailbreaker syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/jailbreaker - name = "jailbreaker space helmet" - desc = "The look of this space helmet gives you an urge to buckle up and dismantle the floor in a crowded room." - icon_state = "syndicate-helm-jailbreaker" - item_state = "syndicate-helm-jailbreaker" - -/obj/item/clothing/suit/space/syndicate/jailbreaker - name = "jailbreaker space suit" - desc = "The look of this space suit gives you an urge to buckle up and dismantle the floor in a crowded room." - icon_state = "syndicate-jailbreaker" - item_state = "syndicate-jailbreaker" - - -//Infiltrator syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/infiltrator - name = "infiltrator space helmet" - desc = "Space helmet made by unknown manufacturer. It's made from some strange composite material." - icon_state = "syndicate-helm-infiltrator" - item_state = "syndicate-helm-elite" - action_button_name = null - -/obj/item/clothing/suit/space/syndicate/infiltrator - name = "infiltrator space suit" - desc = "Space suit made by unknown manufacturer. It's made from some strange composite material." - icon_state = "syndicate-infiltrator" - item_state = "syndicate-elite" - -/obj/item/clothing/head/helmet/space/syndicate/infiltrator/attack_self(mob/user) - return - - -//Striketeam syndicate space suit -/obj/item/clothing/head/helmet/space/syndicate/elite - name = "elite striker space helmet" - desc = "It looks like the person wearing this should be death incarnate wannabe." - icon_state = "syndicate-helm-elite" - item_state = "syndicate-helm-elite" - armor = list(melee = 75, bullet = 65, laser = 65, energy = 65, bomb = 70, bio = 100, rad = 20) - action_button_name = null - -/obj/item/clothing/head/helmet/space/syndicate/elite/attack_self(mob/user) - return - -/obj/item/clothing/suit/space/syndicate/elite - name = "elite striker space suit" - desc = "It looks like the person wearing this should be death incarnate wannabe." - icon_state = "syndicate-elite" - item_state = "syndicate-elite" - armor = list(melee = 75, bullet = 65, laser = 65, energy = 65, bomb = 70, bio = 100, rad = 20) - breach_threshold = 32 - - -/obj/item/clothing/head/helmet/space/syndicate/elite/commander - name = "striker commander space helmet" - desc = "Person wearing this was the death incarnate. You still feel edgy vibes coming from the inside." - icon_state = "syndicate-helm-commander" - item_state = "syndicate-helm-commander" - -/obj/item/clothing/suit/space/syndicate/elite/commander - name = "striker commander space suit" - desc = "Person wearing this was the death incarnate. You still feel edgy vibes coming from the inside." - icon_state = "syndicate-commander" - item_state = "syndicate-commander" +//Regular syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate + name = "red space helmet" + icon_state = "syndicate-helm" + item_state = "syndicate-helm" + desc = "Has a tag: Totally not property of an enemy corporation, honest." + armor = list(melee = 60, bullet = 35, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) + action_button_name = "Toggle Helmet Light" + var/brightness = 3 //light_range when on + var/lit = FALSE + species_restricted = list("exclude" , DIONA , VOX) + var/image/lamp = null + +/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 of a hostile corporation, honest!" + w_class = 3 + allowed = list(/obj/item/weapon/gun, + /obj/item/ammo_box/magazine, + /obj/item/ammo_casing, + /obj/item/weapon/melee/baton, + /obj/item/weapon/melee/energy/sword, + /obj/item/weapon/handcuffs, + /obj/item/weapon/tank/emergency_oxygen) + slowdown = 1 + armor = list(melee = 60, bullet = 35, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) + species_restricted = list("exclude" , DIONA , VOX) + +/obj/item/clothing/head/helmet/space/syndicate/update_icon(mob/user) + . = ..() + icon_state = "[initial(icon_state)][lit ? "-lit" : ""]" + user.update_inv_head() + +/obj/item/clothing/head/helmet/space/syndicate/attack_self(mob/user) + . = ..() + lit = !lit + set_light(lit ? brightness : 0) + update_icon(user) + + +//Civilian syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/civilian + name = "civilian space helmet" + desc = "Space helmet made by unknown manufacturer." + icon_state = "syndicate-helm-civ" + item_state = "syndicate-helm-jailbreaker" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) + species_restricted = list("exclude" , UNATHI , TAJARAN , SKRELL , DIONA , VOX) + +/obj/item/clothing/suit/space/syndicate/civilian + name = "civilian space suit" + desc = "Space suit made by unknown manufacturer." + icon_state = "syndicate-civ" + item_state = "s_suit" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) + + +//Striker syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/striker + name = "striker space helmet" + desc = "That's obviously some kind of military space helmet." + icon_state = "syndicate-helm-striker" + item_state = "syndicate-helm-striker" + armor = list(melee = 60, bullet = 45, laser = 40,energy = 45, bomb = 50, bio = 100, rad = 30) + brightness = 4 + +/obj/item/clothing/suit/space/syndicate/striker + name = "striker space suit" + desc = "That's obviously some kind of military space suit." + icon_state = "syndicate-striker" + item_state = "syndicate-striker" + armor = list(melee = 60, bullet = 45, laser = 40,energy = 45, bomb = 50, bio = 100, rad = 30) + breach_threshold = 12 + + +//Jailbreaker syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/jailbreaker + name = "jailbreaker space helmet" + desc = "The look of this space helmet gives you an urge to buckle up and dismantle the floor in a crowded room." + icon_state = "syndicate-helm-jailbreaker" + item_state = "syndicate-helm-jailbreaker" + +/obj/item/clothing/suit/space/syndicate/jailbreaker + name = "jailbreaker space suit" + desc = "The look of this space suit gives you an urge to buckle up and dismantle the floor in a crowded room." + icon_state = "syndicate-jailbreaker" + item_state = "syndicate-jailbreaker" + + +//Infiltrator syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/infiltrator + name = "infiltrator space helmet" + desc = "Space helmet made by unknown manufacturer. It's made from some strange composite material." + icon_state = "syndicate-helm-infiltrator" + item_state = "syndicate-helm-elite" + action_button_name = null + +/obj/item/clothing/suit/space/syndicate/infiltrator + name = "infiltrator space suit" + desc = "Space suit made by unknown manufacturer. It's made from some strange composite material." + icon_state = "syndicate-infiltrator" + item_state = "syndicate-elite" + +/obj/item/clothing/head/helmet/space/syndicate/infiltrator/attack_self(mob/user) + return + + +//Striketeam syndicate space suit +/obj/item/clothing/head/helmet/space/syndicate/elite + name = "elite striker space helmet" + desc = "It looks like the person wearing this should be death incarnate wannabe." + icon_state = "syndicate-helm-elite" + item_state = "syndicate-helm-elite" + armor = list(melee = 75, bullet = 65, laser = 65, energy = 65, bomb = 70, bio = 100, rad = 20) + action_button_name = null + +/obj/item/clothing/head/helmet/space/syndicate/elite/attack_self(mob/user) + return + +/obj/item/clothing/suit/space/syndicate/elite + name = "elite striker space suit" + desc = "It looks like the person wearing this should be death incarnate wannabe." + icon_state = "syndicate-elite" + item_state = "syndicate-elite" + armor = list(melee = 75, bullet = 65, laser = 65, energy = 65, bomb = 70, bio = 100, rad = 20) + breach_threshold = 32 + + +/obj/item/clothing/head/helmet/space/syndicate/elite/commander + name = "striker commander space helmet" + desc = "Person wearing this was the death incarnate. You still feel edgy vibes coming from the inside." + icon_state = "syndicate-helm-commander" + item_state = "syndicate-helm-commander" + +/obj/item/clothing/suit/space/syndicate/elite/commander + name = "striker commander space suit" + desc = "Person wearing this was the death incarnate. You still feel edgy vibes coming from the inside." + icon_state = "syndicate-commander" + item_state = "syndicate-commander" diff --git a/code/modules/clothing/spacesuits/void.dm b/code/modules/clothing/spacesuits/void.dm index 120eb4f3af84..da9982af2afd 100644 --- a/code/modules/clothing/spacesuits/void.dm +++ b/code/modules/clothing/spacesuits/void.dm @@ -1,14 +1,14 @@ - -//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." - icon_state = "void" - item_state = "void" - -/obj/item/clothing/suit/space/nasavoid - name = "NASA voidsuit" - icon_state = "void" - item_state = "void" - 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." + icon_state = "void" + item_state = "void" + +/obj/item/clothing/suit/space/nasavoid + name = "NASA voidsuit" + icon_state = "void" + item_state = "void" + 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/armor.dm b/code/modules/clothing/suits/armor.dm index 77835a504de8..29875c725153 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -1,310 +1,310 @@ -/obj/item/clothing/suit/armor - allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) - body_parts_covered = UPPER_TORSO|LOWER_TORSO - flags = THICKMATERIAL - cold_protection = UPPER_TORSO|LOWER_TORSO - min_cold_protection_temperature = ARMOR_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = UPPER_TORSO|LOWER_TORSO - max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0.4 - - -/obj/item/clothing/suit/armor/vest - name = "armor" - desc = "An armored vest that protects against some damage." - icon_state = "armor" - item_state = "armor" - blood_overlay_type = "armor" - flags = THICKMATERIAL - armor = list(melee = 50, bullet = 45, laser = 40, energy = 25, bomb = 35, bio = 0, rad = 0) - -/obj/item/clothing/suit/armor/vest/security - name = "security armor" - desc = "An armored vest that protects against some damage. This one has NanoTrasen corporate badge." - icon_state = "armorsec" - item_state = "armor" - -/obj/item/clothing/suit/storage/flak - name = "security armor" - desc = "An armored vest that protects against some damage. This one has four pockets for storage." - icon_state = "armorsec" - item_state = "armor" - blood_overlay_type = "armor" - allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) - body_parts_covered = UPPER_TORSO|LOWER_TORSO - flags = THICKMATERIAL - cold_protection = UPPER_TORSO|LOWER_TORSO - min_cold_protection_temperature = ARMOR_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = UPPER_TORSO|LOWER_TORSO - max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0.4 - armor = list(melee = 50, bullet = 45, laser = 40, energy = 25, bomb = 35, bio = 0, rad = 0) - -/obj/item/clothing/suit/storage/flak/atom_init() - . = ..() - pockets = new/obj/item/weapon/storage/internal(src) - pockets.set_slots(slots = 4, slot_size = ITEM_SIZE_SMALL) - -/obj/item/clothing/suit/storage/flak/marinad - name = "marine armor" - desc = "This thing will protect you from any angry flora or fauna." - icon_state = "marinad" - item_state = "marinad_armor" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - slowdown = 1 - armor = list(melee = 60, bullet = 65, laser = 55, energy = 60, bomb = 40, bio = 0, rad = 0) -/obj/item/clothing/suit/armor/vest/warden - name = "Warden's jacket" - desc = "An armoured jacket with gold rank pips and livery." - icon_state = "warden_jacket" - item_state = "armor" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/suit/storage/flak/warden - name = "Warden's jacket" - desc = "An armoured jacket with gold rank pips and livery." - icon_state = "warden_jacket" - item_state = "armor" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/suit/armor/vest/leather - name = "security overcoat" - desc = "Lightly armored leather overcoat meant as casual wear for high-ranking officers. Bears the crest of Nanotrasen Security." - icon_state = "leather_overcoat-sec" - item_state = "hostrench" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -/obj/item/clothing/suit/armor/hos - name = "armored coat" - desc = "A greatcoat enhanced 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 = 80, bullet = 60, laser = 55, energy = 35, bomb = 50, bio = 0, rad = 0) - flags_inv = HIDEJUMPSUIT - siemens_coefficient = 0.6 - -/obj/item/clothing/suit/armor/riot - name = "riot suit" - desc = "A suit of armor with heavy padding to protect against melee attacks. Looks like it might impair movement." - icon_state = "riot" - item_state = "swat_suit" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - slowdown = 1 - armor = list(melee = 70, bullet = 10, laser = 5, energy = 10, bomb = 0, bio = 0, rad = 0) - flags_inv = HIDEJUMPSUIT - -/obj/item/clothing/suit/armor/bulletproof - name = "bulletproof Vest" - desc = "A vest that excels in protecting the wearer against high-velocity solid projectiles." - icon_state = "bulletproof" - item_state = "armor" - blood_overlay_type = "armor" - armor = list(melee = 10, bullet = 80, laser = 25, energy = 20, bomb = 35, bio = 0, rad = 0) - -/obj/item/clothing/suit/storage/flak/bulletproof - name = "bulletproof Vest" - desc = "A vest that excels in protecting the wearer against high-velocity solid projectiles." - icon_state = "bulletproof" - item_state = "armor" - blood_overlay_type = "armor" - armor = list(melee = 10, bullet = 80, laser = 25, energy = 20, bomb = 35, bio = 0, rad = 0) - -/obj/item/clothing/suit/storage/flak/bulletproof/atom_init() - . = ..() - pockets = new/obj/item/weapon/storage/internal(src) - pockets.set_slots(slots = 5, slot_size = ITEM_SIZE_SMALL) - -/obj/item/clothing/suit/armor/laserproof - name = "ablative armor vest" - desc = "A vest that excels in protecting the wearer against energy projectiles." - icon_state = "armor_reflec" - item_state = "armor_reflec" - blood_overlay_type = "armor" - armor = list(melee = 10, bullet = 10, laser = 65, energy = 75, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0 - var/hit_reflect_chance = 40 - -/obj/item/clothing/suit/armor/laserproof/IsReflect(def_zone) - if(!(def_zone in list(BP_CHEST , BP_GROIN))) //If not shot where ablative is covering you, you don't get the reflection bonus! - return 0 - if (prob(hit_reflect_chance)) - return 1 - -/obj/item/clothing/suit/armor/swat - name = "swat suit" - desc = "A heavily armored suit that protects against moderate damage. Used in special operations." - icon_state = "deathsquad" - item_state = "swat_suit" - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.01 - flags = THICKMATERIAL - allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen) - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - slowdown = 1 - armor = list(melee = 80, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 0, rad = 0) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS - min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE - flags_pressure = STOPS_LOWPRESSUREDMAGE - -/obj/item/clothing/suit/armor/swat/officer - name = "officer jacket" - desc = "An armored jacket used in special operations." - icon_state = "detective" - item_state = "det_suit" - blood_overlay_type = "coat" - flags_inv = 0 - body_parts_covered = UPPER_TORSO|ARMS - - -/obj/item/clothing/suit/armor/det_suit - name = "armor" - desc = "An armored vest with a detective's badge on it." - icon_state = "detective-armor" - item_state = "armor" - blood_overlay_type = "armor" - flags = ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO - armor = list(melee = 50, bullet = 55, laser = 25, energy = 20, bomb = 35, bio = 0, rad = 0) - - -//Reactive armor -//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!) -/obj/item/clothing/suit/armor/reactive - name = "reactive teleport armor" - desc = "Someone seperated our Research Director from his own head!" - var/active = 0.0 - icon_state = "reactiveoff" - item_state = "reactiveoff" - blood_overlay_type = "armor" - slowdown = 1 - armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) - -/obj/item/clothing/suit/armor/reactive/Get_shield_chance() - if(active) - return 35 - return 0 - -/obj/item/clothing/suit/armor/reactive/attack_self(mob/user) - src.active = !( src.active ) - if (src.active) - to_chat(user, "\blue The reactive armor is now active.") - src.icon_state = "reactive" - src.item_state = "reactive" - else - to_chat(user, "\blue The reactive armor is now inactive.") - src.icon_state = "reactiveoff" - src.item_state = "reactiveoff" - src.add_fingerprint(user) - return - -/obj/item/clothing/suit/armor/reactive/emp_act(severity) - active = 0 - src.icon_state = "reactiveoff" - src.item_state = "reactiveoff" - ..() - - -//All of the armor below is mostly unused - - -/obj/item/clothing/suit/armor/centcomm - name = "Cent. Com. armor" - desc = "A suit that protects against some damage." - icon_state = "centcom" - item_state = "centcom" - w_class = 4//bulky item - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS - min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE - siemens_coefficient = 0 - -/obj/item/clothing/suit/armor/heavy - name = "heavy armor" - desc = "A heavily armored suit that protects against moderate damage." - icon_state = "heavy" - item_state = "swat_suit" - w_class = 4//bulky item - gas_transfer_coefficient = 0.90 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - slowdown = 3 - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - siemens_coefficient = 0 - -/obj/item/clothing/suit/armor/tdome - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - -/obj/item/clothing/suit/armor/tdome/red - name = "thunderdome suit (red)" - desc = "Reddish armor." - icon_state = "tdred" - item_state = "tdred" - siemens_coefficient = 1 - -/obj/item/clothing/suit/armor/tdome/green - name = "thunderdome suit (green)" - desc = "Pukish armor." - icon_state = "tdgreen" - item_state = "tdgreen" - siemens_coefficient = 1 - -/obj/item/clothing/suit/armor/tactical - name = "tactical armor" - desc = "A suit of armor most often used by Special Weapons and Tactics squads. Includes padded vest with pockets along with shoulder and kneeguards." - icon_state = "swatarmor" - item_state = "armor" - var/obj/item/weapon/gun/holstered = null - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - slowdown = 1 - armor = list(melee = 60, bullet = 65, laser = 50, energy = 60, bomb = 40, bio = 0, rad = 0) - -/obj/item/clothing/suit/armor/tactical/verb/holster() - set name = "Holster" - set category = "Object" - set src in usr - if(!istype(usr, /mob/living)) return - if(usr.stat) return - - if(!holstered) - if(!istype(usr.get_active_hand(), /obj/item/weapon/gun)) - to_chat(usr, "\blue You need your gun equiped to holster it.") - return - var/obj/item/weapon/gun/W = usr.get_active_hand() - if (!W.isHandgun()) - to_chat(usr, "\red This gun won't fit in \the belt!") - return - holstered = usr.get_active_hand() - usr.drop_item() - holstered.loc = src - usr.visible_message("\blue \The [usr] holsters \the [holstered].", "You holster \the [holstered].") - else - if(istype(usr.get_active_hand(),/obj) && istype(usr.get_inactive_hand(),/obj)) - to_chat(usr, "\red You need an empty hand to draw the gun!") - else - if(usr.a_intent == "hurt") - usr.visible_message("\red \The [usr] draws \the [holstered], ready to shoot!", \ - "\red You draw \the [holstered], ready to shoot!") - else - usr.visible_message("\blue \The [usr] draws \the [holstered], pointing it at the ground.", \ - "\blue You draw \the [holstered], pointing it at the ground.") - usr.put_in_hands(holstered) - holstered = null - -/obj/item/clothing/suit/armor/syndiassault - name = "assault armor" - icon_state = "assaultarmor" - item_state = "assaultarmor" - flags = THICKMATERIAL - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - slowdown = 0.5 - armor = list(melee = 50, bullet = 60, laser = 40, energy = 70, bomb = 50, bio = 0, rad = 50) - siemens_coefficient = 0.2 - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS - min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE +/obj/item/clothing/suit/armor + allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) + body_parts_covered = UPPER_TORSO|LOWER_TORSO + flags = THICKMATERIAL + cold_protection = UPPER_TORSO|LOWER_TORSO + min_cold_protection_temperature = ARMOR_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = UPPER_TORSO|LOWER_TORSO + max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE + siemens_coefficient = 0.4 + + +/obj/item/clothing/suit/armor/vest + name = "armor" + desc = "An armored vest that protects against some damage." + icon_state = "armor" + item_state = "armor" + blood_overlay_type = "armor" + flags = THICKMATERIAL + armor = list(melee = 50, bullet = 45, laser = 40, energy = 25, bomb = 35, bio = 0, rad = 0) + +/obj/item/clothing/suit/armor/vest/security + name = "security armor" + desc = "An armored vest that protects against some damage. This one has NanoTrasen corporate badge." + icon_state = "armorsec" + item_state = "armor" + +/obj/item/clothing/suit/storage/flak + name = "security armor" + desc = "An armored vest that protects against some damage. This one has four pockets for storage." + icon_state = "armorsec" + item_state = "armor" + blood_overlay_type = "armor" + allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) + body_parts_covered = UPPER_TORSO|LOWER_TORSO + flags = THICKMATERIAL + cold_protection = UPPER_TORSO|LOWER_TORSO + min_cold_protection_temperature = ARMOR_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = UPPER_TORSO|LOWER_TORSO + max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE + siemens_coefficient = 0.4 + armor = list(melee = 50, bullet = 45, laser = 40, energy = 25, bomb = 35, bio = 0, rad = 0) + +/obj/item/clothing/suit/storage/flak/atom_init() + . = ..() + pockets = new/obj/item/weapon/storage/internal(src) + pockets.set_slots(slots = 4, slot_size = ITEM_SIZE_SMALL) + +/obj/item/clothing/suit/storage/flak/marinad + name = "marine armor" + desc = "This thing will protect you from any angry flora or fauna." + icon_state = "marinad" + item_state = "marinad_armor" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + slowdown = 1 + armor = list(melee = 60, bullet = 65, laser = 55, energy = 60, bomb = 40, bio = 0, rad = 0) +/obj/item/clothing/suit/armor/vest/warden + name = "Warden's jacket" + desc = "An armoured jacket with gold rank pips and livery." + icon_state = "warden_jacket" + item_state = "armor" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/suit/storage/flak/warden + name = "Warden's jacket" + desc = "An armoured jacket with gold rank pips and livery." + icon_state = "warden_jacket" + item_state = "armor" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/suit/armor/vest/leather + name = "security overcoat" + desc = "Lightly armored leather overcoat meant as casual wear for high-ranking officers. Bears the crest of Nanotrasen Security." + icon_state = "leather_overcoat-sec" + item_state = "hostrench" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +/obj/item/clothing/suit/armor/hos + name = "armored coat" + desc = "A greatcoat enhanced 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 = 80, bullet = 60, laser = 55, energy = 35, bomb = 50, bio = 0, rad = 0) + flags_inv = HIDEJUMPSUIT + siemens_coefficient = 0.6 + +/obj/item/clothing/suit/armor/riot + name = "riot suit" + desc = "A suit of armor with heavy padding to protect against melee attacks. Looks like it might impair movement." + icon_state = "riot" + item_state = "swat_suit" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + slowdown = 1 + armor = list(melee = 70, bullet = 10, laser = 5, energy = 10, bomb = 0, bio = 0, rad = 0) + flags_inv = HIDEJUMPSUIT + +/obj/item/clothing/suit/armor/bulletproof + name = "bulletproof Vest" + desc = "A vest that excels in protecting the wearer against high-velocity solid projectiles." + icon_state = "bulletproof" + item_state = "armor" + blood_overlay_type = "armor" + armor = list(melee = 10, bullet = 80, laser = 25, energy = 20, bomb = 35, bio = 0, rad = 0) + +/obj/item/clothing/suit/storage/flak/bulletproof + name = "bulletproof Vest" + desc = "A vest that excels in protecting the wearer against high-velocity solid projectiles." + icon_state = "bulletproof" + item_state = "armor" + blood_overlay_type = "armor" + armor = list(melee = 10, bullet = 80, laser = 25, energy = 20, bomb = 35, bio = 0, rad = 0) + +/obj/item/clothing/suit/storage/flak/bulletproof/atom_init() + . = ..() + pockets = new/obj/item/weapon/storage/internal(src) + pockets.set_slots(slots = 5, slot_size = ITEM_SIZE_SMALL) + +/obj/item/clothing/suit/armor/laserproof + name = "ablative armor vest" + desc = "A vest that excels in protecting the wearer against energy projectiles." + icon_state = "armor_reflec" + item_state = "armor_reflec" + blood_overlay_type = "armor" + armor = list(melee = 10, bullet = 10, laser = 65, energy = 75, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0 + var/hit_reflect_chance = 40 + +/obj/item/clothing/suit/armor/laserproof/IsReflect(def_zone) + if(!(def_zone in list(BP_CHEST , BP_GROIN))) //If not shot where ablative is covering you, you don't get the reflection bonus! + return 0 + if (prob(hit_reflect_chance)) + return 1 + +/obj/item/clothing/suit/armor/swat + name = "swat suit" + desc = "A heavily armored suit that protects against moderate damage. Used in special operations." + icon_state = "deathsquad" + item_state = "swat_suit" + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + flags = THICKMATERIAL + allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen) + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + slowdown = 1 + armor = list(melee = 80, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 0, rad = 0) + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + flags_pressure = STOPS_LOWPRESSUREDMAGE + +/obj/item/clothing/suit/armor/swat/officer + name = "officer jacket" + desc = "An armored jacket used in special operations." + icon_state = "detective" + item_state = "det_suit" + blood_overlay_type = "coat" + flags_inv = 0 + body_parts_covered = UPPER_TORSO|ARMS + + +/obj/item/clothing/suit/armor/det_suit + name = "armor" + desc = "An armored vest with a detective's badge on it." + icon_state = "detective-armor" + item_state = "armor" + blood_overlay_type = "armor" + flags = ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO + armor = list(melee = 50, bullet = 55, laser = 25, energy = 20, bomb = 35, bio = 0, rad = 0) + + +//Reactive armor +//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!) +/obj/item/clothing/suit/armor/reactive + name = "reactive teleport armor" + desc = "Someone seperated our Research Director from his own head!" + var/active = 0.0 + icon_state = "reactiveoff" + item_state = "reactiveoff" + blood_overlay_type = "armor" + slowdown = 1 + armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) + +/obj/item/clothing/suit/armor/reactive/Get_shield_chance() + if(active) + return 35 + return 0 + +/obj/item/clothing/suit/armor/reactive/attack_self(mob/user) + src.active = !( src.active ) + if (src.active) + to_chat(user, "\blue The reactive armor is now active.") + src.icon_state = "reactive" + src.item_state = "reactive" + else + to_chat(user, "\blue The reactive armor is now inactive.") + src.icon_state = "reactiveoff" + src.item_state = "reactiveoff" + src.add_fingerprint(user) + return + +/obj/item/clothing/suit/armor/reactive/emp_act(severity) + active = 0 + src.icon_state = "reactiveoff" + src.item_state = "reactiveoff" + ..() + + +//All of the armor below is mostly unused + + +/obj/item/clothing/suit/armor/centcomm + name = "Cent. Com. armor" + desc = "A suit that protects against some damage." + icon_state = "centcom" + item_state = "centcom" + w_class = 4//bulky item + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen) + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + siemens_coefficient = 0 + +/obj/item/clothing/suit/armor/heavy + name = "heavy armor" + desc = "A heavily armored suit that protects against moderate damage." + icon_state = "heavy" + item_state = "swat_suit" + w_class = 4//bulky item + gas_transfer_coefficient = 0.90 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + slowdown = 3 + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + siemens_coefficient = 0 + +/obj/item/clothing/suit/armor/tdome + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + +/obj/item/clothing/suit/armor/tdome/red + name = "thunderdome suit (red)" + desc = "Reddish armor." + icon_state = "tdred" + item_state = "tdred" + siemens_coefficient = 1 + +/obj/item/clothing/suit/armor/tdome/green + name = "thunderdome suit (green)" + desc = "Pukish armor." + icon_state = "tdgreen" + item_state = "tdgreen" + siemens_coefficient = 1 + +/obj/item/clothing/suit/armor/tactical + name = "tactical armor" + desc = "A suit of armor most often used by Special Weapons and Tactics squads. Includes padded vest with pockets along with shoulder and kneeguards." + icon_state = "swatarmor" + item_state = "armor" + var/obj/item/weapon/gun/holstered = null + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + slowdown = 1 + armor = list(melee = 60, bullet = 65, laser = 50, energy = 60, bomb = 40, bio = 0, rad = 0) + +/obj/item/clothing/suit/armor/tactical/verb/holster() + set name = "Holster" + set category = "Object" + set src in usr + if(!istype(usr, /mob/living)) return + if(usr.stat) return + + if(!holstered) + if(!istype(usr.get_active_hand(), /obj/item/weapon/gun)) + to_chat(usr, "\blue You need your gun equiped to holster it.") + return + var/obj/item/weapon/gun/W = usr.get_active_hand() + if (!W.isHandgun()) + to_chat(usr, "\red This gun won't fit in \the belt!") + return + holstered = usr.get_active_hand() + usr.drop_item() + holstered.loc = src + usr.visible_message("\blue \The [usr] holsters \the [holstered].", "You holster \the [holstered].") + else + if(istype(usr.get_active_hand(),/obj) && istype(usr.get_inactive_hand(),/obj)) + to_chat(usr, "\red You need an empty hand to draw the gun!") + else + if(usr.a_intent == "hurt") + usr.visible_message("\red \The [usr] draws \the [holstered], ready to shoot!", \ + "\red You draw \the [holstered], ready to shoot!") + else + usr.visible_message("\blue \The [usr] draws \the [holstered], pointing it at the ground.", \ + "\blue You draw \the [holstered], pointing it at the ground.") + usr.put_in_hands(holstered) + holstered = null + +/obj/item/clothing/suit/armor/syndiassault + name = "assault armor" + icon_state = "assaultarmor" + item_state = "assaultarmor" + flags = THICKMATERIAL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + slowdown = 0.5 + armor = list(melee = 50, bullet = 60, laser = 40, energy = 70, bomb = 50, bio = 0, rad = 50) + siemens_coefficient = 0.2 + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index 06cab26ce7a5..11d6a5c67875 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -1,86 +1,86 @@ -//Biosuit complete with shoes (in the item sprite) -/obj/item/clothing/head/bio_hood - name = "bio hood" - icon_state = "bio" - desc = "A hood that protects the head and face from biological comtaminants." - permeability_coefficient = 0.01 - flags = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR|THICKMATERIAL|PHORONGUARD - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES - body_parts_covered = HEAD|FACE|EYES - siemens_coefficient = 0.4 - -/obj/item/clothing/suit/bio_suit - name = "bio suit" - desc = "A suit that protects against biological contamination." - icon_state = "bio" - item_state = "bio_suit" - w_class = 4//bulky item - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.01 - flags = THICKMATERIAL | PHORONGUARD - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - slowdown = 1.0 - allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/pen,/obj/item/device/flashlight/pen) - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL - siemens_coefficient = 0.4 - - -//Standard biosuit, orange stripe -/obj/item/clothing/head/bio_hood/general - icon_state = "bio_general" - body_parts_covered = HEAD|FACE|EYES - -/obj/item/clothing/suit/bio_suit/general - icon_state = "bio_general" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -//Virology biosuit, green stripe -/obj/item/clothing/head/bio_hood/virology - icon_state = "bio_virology" - -/obj/item/clothing/suit/bio_suit/virology - icon_state = "bio_virology" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -//Security biosuit, grey with red stripe across the chest -/obj/item/clothing/head/bio_hood/security - icon_state = "bio_security" - -/obj/item/clothing/suit/bio_suit/security - icon_state = "bio_security" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -//Janitor's biosuit, grey with purple arms -/obj/item/clothing/head/bio_hood/janitor - icon_state = "bio_janitor" - -/obj/item/clothing/suit/bio_suit/janitor - icon_state = "bio_janitor" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - - -//Scientist's biosuit, white with a pink-ish hue -/obj/item/clothing/head/bio_hood/scientist - icon_state = "bio_scientist" - -/obj/item/clothing/suit/bio_suit/scientist - icon_state = "bio_scientist" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -//CMO's biosuit, blue stripe -/obj/item/clothing/suit/bio_suit/cmo - icon_state = "bio_cmo" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -/obj/item/clothing/head/bio_hood/cmo - icon_state = "bio_cmo" - - -//Plague Dr mask can be found in clothing/masks/gasmask.dm -/obj/item/clothing/suit/bio_suit/plaguedoctorsuit - name = "Plague doctor suit" - desc = "It protected doctors from the Black Death, back then. You bet your arse it's gonna help you against viruses." - icon_state = "plaguedoctor" - item_state = "bio_suit" +//Biosuit complete with shoes (in the item sprite) +/obj/item/clothing/head/bio_hood + name = "bio hood" + icon_state = "bio" + desc = "A hood that protects the head and face from biological comtaminants." + permeability_coefficient = 0.01 + flags = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR|THICKMATERIAL|PHORONGUARD + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES + body_parts_covered = HEAD|FACE|EYES + siemens_coefficient = 0.4 + +/obj/item/clothing/suit/bio_suit + name = "bio suit" + desc = "A suit that protects against biological contamination." + icon_state = "bio" + item_state = "bio_suit" + w_class = 4//bulky item + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + flags = THICKMATERIAL | PHORONGUARD + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + slowdown = 1.0 + allowed = list(/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/pen,/obj/item/device/flashlight/pen) + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL + siemens_coefficient = 0.4 + + +//Standard biosuit, orange stripe +/obj/item/clothing/head/bio_hood/general + icon_state = "bio_general" + body_parts_covered = HEAD|FACE|EYES + +/obj/item/clothing/suit/bio_suit/general + icon_state = "bio_general" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +//Virology biosuit, green stripe +/obj/item/clothing/head/bio_hood/virology + icon_state = "bio_virology" + +/obj/item/clothing/suit/bio_suit/virology + icon_state = "bio_virology" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +//Security biosuit, grey with red stripe across the chest +/obj/item/clothing/head/bio_hood/security + icon_state = "bio_security" + +/obj/item/clothing/suit/bio_suit/security + icon_state = "bio_security" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +//Janitor's biosuit, grey with purple arms +/obj/item/clothing/head/bio_hood/janitor + icon_state = "bio_janitor" + +/obj/item/clothing/suit/bio_suit/janitor + icon_state = "bio_janitor" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + + +//Scientist's biosuit, white with a pink-ish hue +/obj/item/clothing/head/bio_hood/scientist + icon_state = "bio_scientist" + +/obj/item/clothing/suit/bio_suit/scientist + icon_state = "bio_scientist" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +//CMO's biosuit, blue stripe +/obj/item/clothing/suit/bio_suit/cmo + icon_state = "bio_cmo" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +/obj/item/clothing/head/bio_hood/cmo + icon_state = "bio_cmo" + + +//Plague Dr mask can be found in clothing/masks/gasmask.dm +/obj/item/clothing/suit/bio_suit/plaguedoctorsuit + name = "Plague doctor suit" + desc = "It protected doctors from the Black Death, back then. You bet your arse it's gonna help you against viruses." + icon_state = "plaguedoctor" + item_state = "bio_suit" diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index e23de8f78b12..6fd1f5663071 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -1,234 +1,234 @@ -/* - * Job related - */ - -//Botonist -/obj/item/clothing/suit/apron - name = "apron" - desc = "A basic blue apron." - icon_state = "apron" - item_state = "overalls" - blood_overlay_type = "armor" - body_parts_covered = 0 - allowed = list (/obj/item/weapon/reagent_containers/spray/plantbgone,/obj/item/device/plant_analyzer,/obj/item/seeds,/obj/item/nutrient,/obj/item/weapon/minihoe) - -//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|ARMS - flags_inv = HIDEJUMPSUIT - -/obj/item/clothing/suit/captunic/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 - flags_inv = HIDEJUMPSUIT - -//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|ARMS - sprite_sheets = list(VOX = 'icons/mob/species/vox/suit.dmi') - -//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 - flags_inv = HIDESHOES|HIDEJUMPSUIT - -//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/kitchenknife,/obj/item/weapon/butch) - -//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 = 0 - -//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" - 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_box/magazine,/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) - body_parts_covered = UPPER_TORSO|ARMS - armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) - -/obj/item/clothing/suit/storage/det_suit/black - icon_state = "detective2" - -//Forensics -/obj/item/clothing/suit/storage/forensics - name = "jacket" - desc = "A forensics technician jacket." - item_state = "det_suit" - 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_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) - body_parts_covered = UPPER_TORSO|ARMS - 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/clothing/mask/gas, /obj/item/taperoll/engineering) - body_parts_covered = UPPER_TORSO - -//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 - -/obj/item/clothing/suit/storage/internalaffairs/verb/toggle() - set name = "Toggle Coat Buttons" - set category = "Object" - set src in usr - - if(!usr.canmove || usr.stat || 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) - body_parts_covered = UPPER_TORSO|ARMS - -/obj/item/clothing/suit/storage/fr_jacket/verb/toggle() - set name = "Toggle Jacket Buttons" - set category = "Object" - set src in usr - - if(!usr.canmove || usr.stat || 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 - body_parts_covered = 0 - -//Recycler -/obj/item/clothing/suit/recyclervest - name = "recycler vest" - desc = "This is Recycler vest." - icon = 'icons/obj/clothing/suits.dmi' - icon_state = "recycler_vest_open" - item_state = "recycler_vest" - blood_overlay_type = "coat" //it's the less thing that I can put here - body_parts_covered = 0 - action_button_name = "Toggle vest buttons" - -/obj/item/clothing/suit/recyclervest/ui_action_click() - toggle() - -/obj/item/clothing/suit/recyclervest/proc/toggle() - switch(icon_state) - if("recycler_vest_open") - src.icon_state = "recycler_vest" - to_chat(usr, "You button up the vest.") - if("recycler_vest") - src.icon_state = "recycler_vest_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 - -/obj/item/clothing/suit/surgicalapron - name = "surgical apron" - desc = "A sterile blue apron for performing surgery." - icon_state = "surgical" - item_state = "surgical" - blood_overlay_type = "armor" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - 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/scalpel,/obj/item/weapon/retractor,/obj/item/weapon/hemostat, +/* + * Job related + */ + +//Botonist +/obj/item/clothing/suit/apron + name = "apron" + desc = "A basic blue apron." + icon_state = "apron" + item_state = "overalls" + blood_overlay_type = "armor" + body_parts_covered = 0 + allowed = list (/obj/item/weapon/reagent_containers/spray/plantbgone,/obj/item/device/plant_analyzer,/obj/item/seeds,/obj/item/nutrient,/obj/item/weapon/minihoe) + +//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|ARMS + flags_inv = HIDEJUMPSUIT + +/obj/item/clothing/suit/captunic/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 + flags_inv = HIDEJUMPSUIT + +//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|ARMS + sprite_sheets = list(VOX = 'icons/mob/species/vox/suit.dmi') + +//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 + flags_inv = HIDESHOES|HIDEJUMPSUIT + +//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/kitchenknife,/obj/item/weapon/butch) + +//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 = 0 + +//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" + 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_box/magazine,/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) + body_parts_covered = UPPER_TORSO|ARMS + armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) + +/obj/item/clothing/suit/storage/det_suit/black + icon_state = "detective2" + +//Forensics +/obj/item/clothing/suit/storage/forensics + name = "jacket" + desc = "A forensics technician jacket." + item_state = "det_suit" + 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_box/magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) + body_parts_covered = UPPER_TORSO|ARMS + 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/clothing/mask/gas, /obj/item/taperoll/engineering) + body_parts_covered = UPPER_TORSO + +//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 + +/obj/item/clothing/suit/storage/internalaffairs/verb/toggle() + set name = "Toggle Coat Buttons" + set category = "Object" + set src in usr + + if(!usr.canmove || usr.stat || 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) + body_parts_covered = UPPER_TORSO|ARMS + +/obj/item/clothing/suit/storage/fr_jacket/verb/toggle() + set name = "Toggle Jacket Buttons" + set category = "Object" + set src in usr + + if(!usr.canmove || usr.stat || 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 + body_parts_covered = 0 + +//Recycler +/obj/item/clothing/suit/recyclervest + name = "recycler vest" + desc = "This is Recycler vest." + icon = 'icons/obj/clothing/suits.dmi' + icon_state = "recycler_vest_open" + item_state = "recycler_vest" + blood_overlay_type = "coat" //it's the less thing that I can put here + body_parts_covered = 0 + action_button_name = "Toggle vest buttons" + +/obj/item/clothing/suit/recyclervest/ui_action_click() + toggle() + +/obj/item/clothing/suit/recyclervest/proc/toggle() + switch(icon_state) + if("recycler_vest_open") + src.icon_state = "recycler_vest" + to_chat(usr, "You button up the vest.") + if("recycler_vest") + src.icon_state = "recycler_vest_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 + +/obj/item/clothing/suit/surgicalapron + name = "surgical apron" + desc = "A sterile blue apron for performing surgery." + icon_state = "surgical" + item_state = "surgical" + blood_overlay_type = "armor" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + 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/scalpel,/obj/item/weapon/retractor,/obj/item/weapon/hemostat, /obj/item/weapon/cautery,/obj/item/weapon/bonegel,/obj/item/weapon/FixOVein) \ No newline at end of file diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm index b44a27a30787..8207256c265b 100644 --- a/code/modules/clothing/suits/labcoat.dm +++ b/code/modules/clothing/suits/labcoat.dm @@ -1,103 +1,103 @@ -/obj/item/clothing/suit/storage/labcoat - name = "labcoat" - desc = "A suit that protects against minor chemical spills." - icon_state = "labcoat" - item_state = "labcoat" - blood_overlay_type = "coat" - var/can_button_up = 1 - var/is_button_up = 1 - flags = ONESIZEFITSALL - body_parts_covered = UPPER_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,/obj/item/weapon/reagent_containers/glass/bottle,/obj/item/weapon/reagent_containers/glass/beaker,/obj/item/weapon/reagent_containers/pill,/obj/item/weapon/storage/pill_bottle,/obj/item/weapon/paper) - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0) - -/obj/item/clothing/suit/storage/labcoat/verb/toggle() - set name = "Toggle Labcoat Buttons" - set category = "Object" - set src in usr - - if(!usr.canmove || usr.stat || usr.restrained()) - return 0 - if(!can_button_up) - to_chat(usr, "You attempt to button-up the velcro on your [src], before promptly realising how silly you are.") - return 0 - - if(!src.is_button_up) - src.icon_state = initial(icon_state) - to_chat(usr, "You button up your labcoat.") - src.is_button_up = 1 - else - src.icon_state += "_open" - to_chat(usr, "You unbutton your labcoat.") - src.is_button_up = 0 - usr.update_inv_wear_suit() //so our overlays update - -/obj/item/clothing/suit/storage/labcoat/red - name = "red labcoat" - desc = "A suit that protects against minor chemical spills. This one is red." - icon_state = "red_labcoat" - item_state = "red_labcoat" - -/obj/item/clothing/suit/storage/labcoat/blue - name = "blue labcoat" - desc = "A suit that protects against minor chemical spills. This one is blue." - icon_state = "blue_labcoat" - item_state = "blue_labcoat" - -/obj/item/clothing/suit/storage/labcoat/purple - name = "purple labcoat" - desc = "A suit that protects against minor chemical spills. This one is purple." - icon_state = "purple_labcoat" - item_state = "purple_labcoat" - -/obj/item/clothing/suit/storage/labcoat/orange - name = "orange labcoat" - desc = "A suit that protects against minor chemical spills. This one is orange." - icon_state = "orange_labcoat" - item_state = "orange_labcoat" - -/obj/item/clothing/suit/storage/labcoat/green - name = "green labcoat" - desc = "A suit that protects against minor chemical spills. This one is green." - icon_state = "green_labcoat" - item_state = "green_labcoat" - -/obj/item/clothing/suit/storage/labcoat/cmo - name = "chief medical officer's labcoat" - desc = "Bluer than the standard model." - icon_state = "labcoat_cmo" - item_state = "labcoat_cmo" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 70, rad = 10) - -/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." - icon_state = "labgreen" - item_state = "labgreen" - -/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." - icon_state = "labcoat_gen" - -/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." - icon_state = "labcoat_chem" - -/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." - icon_state = "labcoat_vir" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 0) - -/obj/item/clothing/suit/storage/labcoat/science - name = "scientist labcoat" - desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder." - icon_state = "labcoat_tox" - -/obj/item/clothing/suit/storage/labcoat/rd - name = "research director's labcoat" - desc = "It smells like weird science." - icon_state = "labcoat_rd" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 20, bio = 50, rad = 50) +/obj/item/clothing/suit/storage/labcoat + name = "labcoat" + desc = "A suit that protects against minor chemical spills." + icon_state = "labcoat" + item_state = "labcoat" + blood_overlay_type = "coat" + var/can_button_up = 1 + var/is_button_up = 1 + flags = ONESIZEFITSALL + body_parts_covered = UPPER_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,/obj/item/weapon/reagent_containers/glass/bottle,/obj/item/weapon/reagent_containers/glass/beaker,/obj/item/weapon/reagent_containers/pill,/obj/item/weapon/storage/pill_bottle,/obj/item/weapon/paper) + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0) + +/obj/item/clothing/suit/storage/labcoat/verb/toggle() + set name = "Toggle Labcoat Buttons" + set category = "Object" + set src in usr + + if(!usr.canmove || usr.stat || usr.restrained()) + return 0 + if(!can_button_up) + to_chat(usr, "You attempt to button-up the velcro on your [src], before promptly realising how silly you are.") + return 0 + + if(!src.is_button_up) + src.icon_state = initial(icon_state) + to_chat(usr, "You button up your labcoat.") + src.is_button_up = 1 + else + src.icon_state += "_open" + to_chat(usr, "You unbutton your labcoat.") + src.is_button_up = 0 + usr.update_inv_wear_suit() //so our overlays update + +/obj/item/clothing/suit/storage/labcoat/red + name = "red labcoat" + desc = "A suit that protects against minor chemical spills. This one is red." + icon_state = "red_labcoat" + item_state = "red_labcoat" + +/obj/item/clothing/suit/storage/labcoat/blue + name = "blue labcoat" + desc = "A suit that protects against minor chemical spills. This one is blue." + icon_state = "blue_labcoat" + item_state = "blue_labcoat" + +/obj/item/clothing/suit/storage/labcoat/purple + name = "purple labcoat" + desc = "A suit that protects against minor chemical spills. This one is purple." + icon_state = "purple_labcoat" + item_state = "purple_labcoat" + +/obj/item/clothing/suit/storage/labcoat/orange + name = "orange labcoat" + desc = "A suit that protects against minor chemical spills. This one is orange." + icon_state = "orange_labcoat" + item_state = "orange_labcoat" + +/obj/item/clothing/suit/storage/labcoat/green + name = "green labcoat" + desc = "A suit that protects against minor chemical spills. This one is green." + icon_state = "green_labcoat" + item_state = "green_labcoat" + +/obj/item/clothing/suit/storage/labcoat/cmo + name = "chief medical officer's labcoat" + desc = "Bluer than the standard model." + icon_state = "labcoat_cmo" + item_state = "labcoat_cmo" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 70, rad = 10) + +/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." + icon_state = "labgreen" + item_state = "labgreen" + +/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." + icon_state = "labcoat_gen" + +/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." + icon_state = "labcoat_chem" + +/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." + icon_state = "labcoat_vir" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 0) + +/obj/item/clothing/suit/storage/labcoat/science + name = "scientist labcoat" + desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder." + icon_state = "labcoat_tox" + +/obj/item/clothing/suit/storage/labcoat/rd + name = "research director's labcoat" + desc = "It smells like weird science." + icon_state = "labcoat_rd" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 20, bio = 50, rad = 50) diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index e82f6a4cc2d9..c46c2bc5165c 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -1,620 +1,620 @@ -/* - * 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" - body_parts_covered = UPPER_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 = "Reputed to go faster." - icon_state = "redtag" - item_state = "redtag" - blood_overlay_type = "armor" - body_parts_covered = UPPER_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" - body_parts_covered = UPPER_TORSO|ARMS - - -/obj/item/clothing/suit/hgpirate - name = "pirate captain coat" - desc = "Yarr." - icon_state = "hgpirate" - item_state = "hgpirate" - flags_inv = HIDEJUMPSUIT - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - - -/obj/item/clothing/suit/cyborg_suit - name = "cyborg suit" - desc = "Suit for a cyborg costume." - icon_state = "death" - item_state = "death" - flags = CONDUCT - 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" - - -/obj/item/clothing/suit/johnny_coat - name = "johnny~~ coat" - desc = "Johnny~~" - icon_state = "johnny" - item_state = "johnny" - - -/obj/item/clothing/suit/justice - name = "justice suit" - desc = "This pretty much looks ridiculous." - icon_state = "justice" - item_state = "justice" - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - - -/obj/item/clothing/suit/judgerobe - name = "judge's robe" - desc = "This robe commands authority." - icon_state = "judge" - item_state = "judge" - 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 - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/toy) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - -/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 = HEAD|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 - 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 - 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 - -/* - * 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" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL - -/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" - body_parts_covered = UPPER_TORSO|ARMS - -/obj/item/clothing/suit/nerdshirt - name = "gamer shirt" - desc = "A baggy shirt with a vintage game character on it. Why would someone wear this?" - icon_state = "nerdshirt" - item_state = "nerdshirt" - -/obj/item/clothing/suit/blueshirt - name = "blue shirt" - desc = "A blue shirt with some strange symbols. Look out for aliens!" - icon_state = "blueshirt" - item_state = "blueshirt" - -/obj/item/clothing/suit/chemshirt - name = "chemistry shirt" - desc = "A nice orange shirt made from a special fabric that hides any reagent stains. Has a drawn beaker with some glowy acid inside. Wanna cook?" - icon_state = "chemshirt" - item_state = "chemshirt" - -/obj/item/clothing/suit/roundshirt - name = "science shirt" - desc = "A purple, sciency t-shirt with a picture of a burning star. Save the Earth! Oh wait, already too late for that" - icon_state = "roundshirt" - item_state = "roundshirt" - -/obj/item/clothing/suit/catshirt - name = "cat shirt" - desc = "Very comfy, grey t-shirt with a picture of a cute kitty. And the best part: any cat or tajaran hair blends into the design very well!" - icon_state = "catshirt" - item_state = "catshirt" - -/obj/item/clothing/suit/jacket - name = "bomber jacket" - desc = "Aviators not included." - icon_state = "bomberjacket" - item_state = "johnny" - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/toy,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter) - -/obj/item/clothing/suit/jacket/leather - name = "leather jacket" - desc = "Pompadour not included." - icon_state = "leatherjacket" - item_state = "hostrench" - -/obj/item/clothing/suit/jacket/leather/overcoat - name = "leather overcoat" - desc = "That's a damn fine coat." - icon_state = "leather_overcoat" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - -/obj/item/clothing/suit/jacket/puffer - name = "puffer jacket" - desc = "A thick jacket with a rubbery, water-resistant shell." - icon_state = "pufferjacket" - item_state = "hostrench" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - cold_protection = UPPER_TORSO|LOWER_TORSO - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 35, rad = 0) - -/obj/item/clothing/suit/jacket/puffer/vest - name = "puffer vest" - desc = "A thick vest with a rubbery, water-resistant shell." - icon_state = "puffervest" - item_state = "armor" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - cold_protection = UPPER_TORSO|LOWER_TORSO - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 30, rad = 0) - -//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 flowing, black coat." - icon_state = "leathercoat" - item_state = "leathercoat" - -/obj/item/clothing/suit/serifcoat - name = "serif coat" - desc = "A old coat" - icon_state = "serif_coat" - item_state = "det_suit" - -//stripper -/obj/item/clothing/under/stripper - body_parts_covered = 0 - -/obj/item/clothing/under/stripper/stripper_pink - name = "pink swimsuit" - desc = "A rather skimpy pink swimsuit." - icon_state = "stripper_p" - item_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" - item_color = "stripper_g" - siemens_coefficient = 1 - -/obj/item/clothing/suit/stripper_pink - name = "pink skimpy dress" - desc = "A rather skimpy pink dress." - icon_state = "stripper_p" - item_state = "stripper_p" - siemens_coefficient = 1 - -/obj/item/clothing/suit/stripper_green - name = "green skimpy dress" - desc = "A rather skimpy green dress." - icon_state = "stripper_g" - 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" - item_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 - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - siemens_coefficient = 2.0 -//swimsuit -/obj/item/clothing/under/swimsuit/ - siemens_coefficient = 1 - body_parts_covered = 0 - -/obj/item/clothing/under/swimsuit/black - name = "black swimsuit" - desc = "An oldfashioned black swimsuit." - icon_state = "swim_black" - item_color = "swim_black" - siemens_coefficient = 1 - -/obj/item/clothing/under/swimsuit/blue - name = "blue swimsuit" - desc = "An oldfashioned blue swimsuit." - icon_state = "swim_blue" - item_color = "swim_blue" - siemens_coefficient = 1 - -/obj/item/clothing/under/swimsuit/purple - name = "purple swimsuit" - desc = "An oldfashioned purple swimsuit." - icon_state = "swim_purp" - item_color = "swim_purp" - siemens_coefficient = 1 - -/obj/item/clothing/under/swimsuit/green - name = "green swimsuit" - desc = "An oldfashioned green swimsuit." - icon_state = "swim_green" - item_color = "swim_green" - siemens_coefficient = 1 - -/obj/item/clothing/under/swimsuit/red - name = "red swimsuit" - desc = "An oldfashioned red swimsuit." - icon_state = "swim_red" - item_color = "swim_red" - siemens_coefficient = 1 - -/obj/item/clothing/suit/batman - name = "Batman costume" - desc = "My parents are dead" - icon_state = "batman" - item_state = "batman" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_inv = HIDESHOES|HIDEJUMPSUIT - -/obj/item/clothing/suit/superman - name = "Superman costume" - desc = "Is it a bird? Is it a plane?" - icon_state = "superman" - item_state = "superman" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_inv = HIDESHOES|HIDEJUMPSUIT - - -/obj/item/clothing/suit/storage/miljacket_army - name = "field jacket olive" - desc = "Initially designed for the US military under the MIL-DTL-43455K standard, it is now also worn as a civilian item of clothing. Classic olive." - icon_state = "miljacket_army" - item_state = "miljacket_army" - var/can_button_up = 1 - var/is_button_up = 1 - cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/suit/storage/miljacket_army/verb/toggle() - set name = "Toggle Jacket Buttons" - set category = "Object" - set src in usr - - if(!usr.canmove || usr.stat || usr.restrained()) - return 0 - if(!can_button_up) - to_chat(usr, "You attempt to button-up the velcro on your [src], before promptly realising how silly you are.") - return 0 - - if(!src.is_button_up) - src.icon_state = initial(icon_state) - to_chat(usr, "You button up your jacket.") - src.is_button_up = 1 - else - src.icon_state += "_open" - to_chat(usr, "You unbutton your jacket.") - src.is_button_up = 0 - usr.update_inv_wear_suit() //so our overlays update - -/obj/item/clothing/suit/storage/miljacket_army/miljacket_ranger - name = "field jacket desert" - desc = "Initially designed for the US military under the MIL-DTL-43455K standard, it is now also worn as a civilian item of clothing. Marine cold desert." - icon_state = "miljacket_ranger" - item_state = "miljacket_ranger" - -/obj/item/clothing/suit/storage/miljacket_army/miljacket_navy - name = "field jacket navy" - desc = "Initially designed for the US military under the MIL-DTL-43455K standard, it is now also worn as a civilian item of clothing. Like a navy seal," - icon_state = "miljacket_navy" - item_state = "miljacket_navy" - -/obj/item/clothing/suit/poncho - name = "poncho" - desc = "Your classic, non-racist poncho." - icon_state = "classicponcho" - item_state = "classicponcho" - -/obj/item/clothing/suit/poncho/green - name = "green poncho" - desc = "Your classic, non-racist poncho. This one is green." - icon_state = "greenponcho" - item_state = "greenponcho" - -/obj/item/clothing/suit/poncho/rainbow - name = "green poncho" - desc = "Your classic, non-racist poncho. This one is rainbow." - icon_state = "rainbowponcho" - item_state = "rainbowponcho" - -/obj/item/clothing/suit/poncho/red - name = "red poncho" - desc = "Your classic, non-racist poncho. This one is red." - icon_state = "redponcho" - item_state = "redponcho" - -/obj/item/clothing/suit/poncho/ponchoshame - name = "poncho of shame" - desc = "Forced to live on your shameful acting as a fake mexican, you and your poncho have grown inseperable. Literally." - icon_state = "ponchoshame" - item_state = "ponchoshame" - -//Mafia -/obj/item/clothing/suit/browntrenchcoat - name = "brown trench coat" - desc = "It makes you stand out. Just the opposite of why it's typically worn. Nice try trying to blend in while wearing it." - icon_state = "trenchcoat_brown" - item_state = "trenchcoat_brown" - -/obj/item/clothing/suit/blacktrenchcoat - name = "black trench coat" - desc = "That shade of black just makes you look a bit more evil. Good for those mafia types." - icon_state = "trenchcoat_black" - item_state = "trenchcoat_black" - -/obj/item/clothing/suit/storage/det_suit/max_payne - desc = "An 20th-century multi-purpose trenchcoat. Someone who wears this means serious business." - icon_state = "maxcoat" - -/obj/item/clothing/suit/necromancer_hoodie - name = "necromancer hoodie" - desc = "This suit says to you 'hush'!" - icon_state = "necromancer" - item_state = "necromancer" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -/obj/item/clothing/suit/chaplain_hoodie/brown - name = "brown robe" - icon_state = "brown_robe" - item_state = "brown_robe" - -/obj/item/clothing/suit/chaplain_hoodie/green - name = "green robe" - icon_state = "green_robe" - item_state = "green_robe" - -/obj/item/clothing/suit/chaplain_hoodie/black - name = "black robe" - icon_state = "black_robe" - -/obj/item/clothing/suit/armor/vest/cuirass - name = "cuirass" - desc = "A metal armor, which cover torso." - icon_state = "cuirass" - item_state = "cuirass" - blood_overlay_type = "armor" - flags = THICKMATERIAL - armor = list(melee = 50, bullet = 30, laser = 10, energy = 10, bomb = 25, bio = 0, rad = 0) - -/obj/item/clothing/suit/goodman_jacket - name = "brown jacket" - desc = "A good jacket for good men." - icon_state = "gmjacket" - -/obj/item/clothing/suit/goodman_jacket/verb/toggle() - set name = "Toggle Jacket Buttons" - set category = "Object" - set src in usr - - if(!usr.canmove || usr.stat || usr.restrained()) - return 0 - - if(src.icon_state == "gmjacket_open") - src.icon_state = "gmjacket" - src.item_state = "gmjacket" - to_chat(usr, "You button up the suit jacket.") - else if(src.icon_state == "gmjacket") - src.icon_state = "gmjacket_open" - src.item_state = "gmjacket_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() - -/obj/item/clothing/suit/hooded/carp_costume - name = "carp costume" - desc = "A costume made from 'synthetic' carp scales, it smells." - icon_state = "carp_casual" - item_state = "labcoat" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS //Space carp like space, so you should too - allowed = list(/obj/item/weapon/tank/emergency_oxygen) - hoodtype = /obj/item/clothing/head/hooded/carp_hood - -/obj/item/clothing/suit/hooded/ian_costume //It's Ian, rub his bell- oh god what happened to his inside parts? - name = "corgi costume" - desc = "A costume that looks like someone made a human-like corgi, it won't guarantee belly rubs." - icon_state = "ian" - item_state = "labcoat" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - allowed = list() - hoodtype = /obj/item/clothing/head/hooded/ian_hood - -/obj/item/clothing/suit/hooded/angel_suit - name = "Angel Suit" - desc = "Angel costume, which Emits aura of light." - icon_state = "angela_suit" - hoodtype = /obj/item/clothing/head/angel_nimb - -/obj/item/clothing/suit/student_jacket - name = "Student Jacket" - desc = "A Student's jacket from the eighties." - icon_state = "student_jacket" - action_button_name = "To Fasten" - var/fastened = TRUE - -/obj/item/clothing/suit/student_jacket/ui_action_click() - if(fastened) - icon_state = "student_jacket_open" - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - if(H.wear_suit == src) - H.update_inv_wear_suit() - else - icon_state = "student_jacket" - if(ishuman(loc)) - var/mob/living/carbon/human/H = loc - if(H.wear_suit == src) - H.update_inv_wear_suit() - fastened = !fastened - -/obj/item/clothing/suit/atlas_jacket - name = "atlas jacket" - desc = "Stylish white satin jacket with a scorpion embroidered on the back." - icon_state = "atlas_jacket" - -/obj/item/clothing/suit/shawl - name = "shawl" - desc = "A pink Shawl for Hindi Womans." - icon_state = "shawl" - -/obj/item/clothing/suit/sukeban_coat - name = "sukeban coat" - desc = "Just a Street Japanese coat" - icon_state = "sukeban_coat" - -/obj/item/clothing/suit/plaid - name = "plaid" - desc = "Home warm plaid" - icon_state = "plaid" - -/obj/item/clothing/suit/tuxedo - name = "tuxedo" - desc = "A semi-formal evening suit distinguished primarily by satin or grosgrain facings on the jacket's lapels" - icon_state = "tuxedo" - -/obj/item/clothing/suit/syndieshirt - name = "red shirt" - desc = "Brand new, incredibly comfortable t-shirt with a logo of Syndicate." - icon_state = "syndieshirt" - item_state = "syndieshirt" - body_parts_covered = UPPER_TORSO|ARMS +/* + * 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" + body_parts_covered = UPPER_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 = "Reputed to go faster." + icon_state = "redtag" + item_state = "redtag" + blood_overlay_type = "armor" + body_parts_covered = UPPER_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" + body_parts_covered = UPPER_TORSO|ARMS + + +/obj/item/clothing/suit/hgpirate + name = "pirate captain coat" + desc = "Yarr." + icon_state = "hgpirate" + item_state = "hgpirate" + flags_inv = HIDEJUMPSUIT + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + + +/obj/item/clothing/suit/cyborg_suit + name = "cyborg suit" + desc = "Suit for a cyborg costume." + icon_state = "death" + item_state = "death" + flags = CONDUCT + 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" + + +/obj/item/clothing/suit/johnny_coat + name = "johnny~~ coat" + desc = "Johnny~~" + icon_state = "johnny" + item_state = "johnny" + + +/obj/item/clothing/suit/justice + name = "justice suit" + desc = "This pretty much looks ridiculous." + icon_state = "justice" + item_state = "justice" + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + + +/obj/item/clothing/suit/judgerobe + name = "judge's robe" + desc = "This robe commands authority." + icon_state = "judge" + item_state = "judge" + 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 + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/toy) + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + +/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 = HEAD|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 + 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 + 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 + +/* + * 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" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL + +/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" + body_parts_covered = UPPER_TORSO|ARMS + +/obj/item/clothing/suit/nerdshirt + name = "gamer shirt" + desc = "A baggy shirt with a vintage game character on it. Why would someone wear this?" + icon_state = "nerdshirt" + item_state = "nerdshirt" + +/obj/item/clothing/suit/blueshirt + name = "blue shirt" + desc = "A blue shirt with some strange symbols. Look out for aliens!" + icon_state = "blueshirt" + item_state = "blueshirt" + +/obj/item/clothing/suit/chemshirt + name = "chemistry shirt" + desc = "A nice orange shirt made from a special fabric that hides any reagent stains. Has a drawn beaker with some glowy acid inside. Wanna cook?" + icon_state = "chemshirt" + item_state = "chemshirt" + +/obj/item/clothing/suit/roundshirt + name = "science shirt" + desc = "A purple, sciency t-shirt with a picture of a burning star. Save the Earth! Oh wait, already too late for that" + icon_state = "roundshirt" + item_state = "roundshirt" + +/obj/item/clothing/suit/catshirt + name = "cat shirt" + desc = "Very comfy, grey t-shirt with a picture of a cute kitty. And the best part: any cat or tajaran hair blends into the design very well!" + icon_state = "catshirt" + item_state = "catshirt" + +/obj/item/clothing/suit/jacket + name = "bomber jacket" + desc = "Aviators not included." + icon_state = "bomberjacket" + item_state = "johnny" + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/toy,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter) + +/obj/item/clothing/suit/jacket/leather + name = "leather jacket" + desc = "Pompadour not included." + icon_state = "leatherjacket" + item_state = "hostrench" + +/obj/item/clothing/suit/jacket/leather/overcoat + name = "leather overcoat" + desc = "That's a damn fine coat." + icon_state = "leather_overcoat" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + +/obj/item/clothing/suit/jacket/puffer + name = "puffer jacket" + desc = "A thick jacket with a rubbery, water-resistant shell." + icon_state = "pufferjacket" + item_state = "hostrench" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + cold_protection = UPPER_TORSO|LOWER_TORSO + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 35, rad = 0) + +/obj/item/clothing/suit/jacket/puffer/vest + name = "puffer vest" + desc = "A thick vest with a rubbery, water-resistant shell." + icon_state = "puffervest" + item_state = "armor" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + cold_protection = UPPER_TORSO|LOWER_TORSO + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 30, rad = 0) + +//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 flowing, black coat." + icon_state = "leathercoat" + item_state = "leathercoat" + +/obj/item/clothing/suit/serifcoat + name = "serif coat" + desc = "A old coat" + icon_state = "serif_coat" + item_state = "det_suit" + +//stripper +/obj/item/clothing/under/stripper + body_parts_covered = 0 + +/obj/item/clothing/under/stripper/stripper_pink + name = "pink swimsuit" + desc = "A rather skimpy pink swimsuit." + icon_state = "stripper_p" + item_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" + item_color = "stripper_g" + siemens_coefficient = 1 + +/obj/item/clothing/suit/stripper_pink + name = "pink skimpy dress" + desc = "A rather skimpy pink dress." + icon_state = "stripper_p" + item_state = "stripper_p" + siemens_coefficient = 1 + +/obj/item/clothing/suit/stripper_green + name = "green skimpy dress" + desc = "A rather skimpy green dress." + icon_state = "stripper_g" + 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" + item_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 + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT + siemens_coefficient = 2.0 +//swimsuit +/obj/item/clothing/under/swimsuit/ + siemens_coefficient = 1 + body_parts_covered = 0 + +/obj/item/clothing/under/swimsuit/black + name = "black swimsuit" + desc = "An oldfashioned black swimsuit." + icon_state = "swim_black" + item_color = "swim_black" + siemens_coefficient = 1 + +/obj/item/clothing/under/swimsuit/blue + name = "blue swimsuit" + desc = "An oldfashioned blue swimsuit." + icon_state = "swim_blue" + item_color = "swim_blue" + siemens_coefficient = 1 + +/obj/item/clothing/under/swimsuit/purple + name = "purple swimsuit" + desc = "An oldfashioned purple swimsuit." + icon_state = "swim_purp" + item_color = "swim_purp" + siemens_coefficient = 1 + +/obj/item/clothing/under/swimsuit/green + name = "green swimsuit" + desc = "An oldfashioned green swimsuit." + icon_state = "swim_green" + item_color = "swim_green" + siemens_coefficient = 1 + +/obj/item/clothing/under/swimsuit/red + name = "red swimsuit" + desc = "An oldfashioned red swimsuit." + icon_state = "swim_red" + item_color = "swim_red" + siemens_coefficient = 1 + +/obj/item/clothing/suit/batman + name = "Batman costume" + desc = "My parents are dead" + icon_state = "batman" + item_state = "batman" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + flags_inv = HIDESHOES|HIDEJUMPSUIT + +/obj/item/clothing/suit/superman + name = "Superman costume" + desc = "Is it a bird? Is it a plane?" + icon_state = "superman" + item_state = "superman" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + flags_inv = HIDESHOES|HIDEJUMPSUIT + + +/obj/item/clothing/suit/storage/miljacket_army + name = "field jacket olive" + desc = "Initially designed for the US military under the MIL-DTL-43455K standard, it is now also worn as a civilian item of clothing. Classic olive." + icon_state = "miljacket_army" + item_state = "miljacket_army" + var/can_button_up = 1 + var/is_button_up = 1 + cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/suit/storage/miljacket_army/verb/toggle() + set name = "Toggle Jacket Buttons" + set category = "Object" + set src in usr + + if(!usr.canmove || usr.stat || usr.restrained()) + return 0 + if(!can_button_up) + to_chat(usr, "You attempt to button-up the velcro on your [src], before promptly realising how silly you are.") + return 0 + + if(!src.is_button_up) + src.icon_state = initial(icon_state) + to_chat(usr, "You button up your jacket.") + src.is_button_up = 1 + else + src.icon_state += "_open" + to_chat(usr, "You unbutton your jacket.") + src.is_button_up = 0 + usr.update_inv_wear_suit() //so our overlays update + +/obj/item/clothing/suit/storage/miljacket_army/miljacket_ranger + name = "field jacket desert" + desc = "Initially designed for the US military under the MIL-DTL-43455K standard, it is now also worn as a civilian item of clothing. Marine cold desert." + icon_state = "miljacket_ranger" + item_state = "miljacket_ranger" + +/obj/item/clothing/suit/storage/miljacket_army/miljacket_navy + name = "field jacket navy" + desc = "Initially designed for the US military under the MIL-DTL-43455K standard, it is now also worn as a civilian item of clothing. Like a navy seal," + icon_state = "miljacket_navy" + item_state = "miljacket_navy" + +/obj/item/clothing/suit/poncho + name = "poncho" + desc = "Your classic, non-racist poncho." + icon_state = "classicponcho" + item_state = "classicponcho" + +/obj/item/clothing/suit/poncho/green + name = "green poncho" + desc = "Your classic, non-racist poncho. This one is green." + icon_state = "greenponcho" + item_state = "greenponcho" + +/obj/item/clothing/suit/poncho/rainbow + name = "green poncho" + desc = "Your classic, non-racist poncho. This one is rainbow." + icon_state = "rainbowponcho" + item_state = "rainbowponcho" + +/obj/item/clothing/suit/poncho/red + name = "red poncho" + desc = "Your classic, non-racist poncho. This one is red." + icon_state = "redponcho" + item_state = "redponcho" + +/obj/item/clothing/suit/poncho/ponchoshame + name = "poncho of shame" + desc = "Forced to live on your shameful acting as a fake mexican, you and your poncho have grown inseperable. Literally." + icon_state = "ponchoshame" + item_state = "ponchoshame" + +//Mafia +/obj/item/clothing/suit/browntrenchcoat + name = "brown trench coat" + desc = "It makes you stand out. Just the opposite of why it's typically worn. Nice try trying to blend in while wearing it." + icon_state = "trenchcoat_brown" + item_state = "trenchcoat_brown" + +/obj/item/clothing/suit/blacktrenchcoat + name = "black trench coat" + desc = "That shade of black just makes you look a bit more evil. Good for those mafia types." + icon_state = "trenchcoat_black" + item_state = "trenchcoat_black" + +/obj/item/clothing/suit/storage/det_suit/max_payne + desc = "An 20th-century multi-purpose trenchcoat. Someone who wears this means serious business." + icon_state = "maxcoat" + +/obj/item/clothing/suit/necromancer_hoodie + name = "necromancer hoodie" + desc = "This suit says to you 'hush'!" + icon_state = "necromancer" + item_state = "necromancer" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +/obj/item/clothing/suit/chaplain_hoodie/brown + name = "brown robe" + icon_state = "brown_robe" + item_state = "brown_robe" + +/obj/item/clothing/suit/chaplain_hoodie/green + name = "green robe" + icon_state = "green_robe" + item_state = "green_robe" + +/obj/item/clothing/suit/chaplain_hoodie/black + name = "black robe" + icon_state = "black_robe" + +/obj/item/clothing/suit/armor/vest/cuirass + name = "cuirass" + desc = "A metal armor, which cover torso." + icon_state = "cuirass" + item_state = "cuirass" + blood_overlay_type = "armor" + flags = THICKMATERIAL + armor = list(melee = 50, bullet = 30, laser = 10, energy = 10, bomb = 25, bio = 0, rad = 0) + +/obj/item/clothing/suit/goodman_jacket + name = "brown jacket" + desc = "A good jacket for good men." + icon_state = "gmjacket" + +/obj/item/clothing/suit/goodman_jacket/verb/toggle() + set name = "Toggle Jacket Buttons" + set category = "Object" + set src in usr + + if(!usr.canmove || usr.stat || usr.restrained()) + return 0 + + if(src.icon_state == "gmjacket_open") + src.icon_state = "gmjacket" + src.item_state = "gmjacket" + to_chat(usr, "You button up the suit jacket.") + else if(src.icon_state == "gmjacket") + src.icon_state = "gmjacket_open" + src.item_state = "gmjacket_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() + +/obj/item/clothing/suit/hooded/carp_costume + name = "carp costume" + desc = "A costume made from 'synthetic' carp scales, it smells." + icon_state = "carp_casual" + item_state = "labcoat" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS //Space carp like space, so you should too + allowed = list(/obj/item/weapon/tank/emergency_oxygen) + hoodtype = /obj/item/clothing/head/hooded/carp_hood + +/obj/item/clothing/suit/hooded/ian_costume //It's Ian, rub his bell- oh god what happened to his inside parts? + name = "corgi costume" + desc = "A costume that looks like someone made a human-like corgi, it won't guarantee belly rubs." + icon_state = "ian" + item_state = "labcoat" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + allowed = list() + hoodtype = /obj/item/clothing/head/hooded/ian_hood + +/obj/item/clothing/suit/hooded/angel_suit + name = "Angel Suit" + desc = "Angel costume, which Emits aura of light." + icon_state = "angela_suit" + hoodtype = /obj/item/clothing/head/angel_nimb + +/obj/item/clothing/suit/student_jacket + name = "Student Jacket" + desc = "A Student's jacket from the eighties." + icon_state = "student_jacket" + action_button_name = "To Fasten" + var/fastened = TRUE + +/obj/item/clothing/suit/student_jacket/ui_action_click() + if(fastened) + icon_state = "student_jacket_open" + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + if(H.wear_suit == src) + H.update_inv_wear_suit() + else + icon_state = "student_jacket" + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + if(H.wear_suit == src) + H.update_inv_wear_suit() + fastened = !fastened + +/obj/item/clothing/suit/atlas_jacket + name = "atlas jacket" + desc = "Stylish white satin jacket with a scorpion embroidered on the back." + icon_state = "atlas_jacket" + +/obj/item/clothing/suit/shawl + name = "shawl" + desc = "A pink Shawl for Hindi Womans." + icon_state = "shawl" + +/obj/item/clothing/suit/sukeban_coat + name = "sukeban coat" + desc = "Just a Street Japanese coat" + icon_state = "sukeban_coat" + +/obj/item/clothing/suit/plaid + name = "plaid" + desc = "Home warm plaid" + icon_state = "plaid" + +/obj/item/clothing/suit/tuxedo + name = "tuxedo" + desc = "A semi-formal evening suit distinguished primarily by satin or grosgrain facings on the jacket's lapels" + icon_state = "tuxedo" + +/obj/item/clothing/suit/syndieshirt + name = "red shirt" + desc = "Brand new, incredibly comfortable t-shirt with a logo of Syndicate." + icon_state = "syndieshirt" + item_state = "syndieshirt" + body_parts_covered = UPPER_TORSO|ARMS diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 5abaa1d8d98d..ac4bf342a077 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -1,108 +1,108 @@ -/* - * 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" - w_class = 4//bulky item - gas_transfer_coefficient = 0.90 - permeability_coefficient = 0.50 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/extinguisher) - slowdown = 1.0 - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL - flags_pressure = STOPS_HIGHPRESSUREDMAGE - heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS - - -/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 = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0) - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES - body_parts_covered = HEAD|FACE|EYES - siemens_coefficient = 0.2 - - -/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 - slowdown = 2 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0) - flags_inv = HIDEJUMPSUIT|HIDETAIL - heat_protection = UPPER_TORSO|LOWER_TORSO - max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE - siemens_coefficient = 0.2 - - -/obj/item/clothing/head/bomb_hood/security - icon_state = "bombsuitsec" - item_state = "bombsuitsec" - body_parts_covered = HEAD - -/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) - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -/* - * 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 = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR - body_parts_covered = HEAD|FACE|EYES - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) - - -/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|ARMS - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/clothing/head/radiation,/obj/item/clothing/mask/gas) - slowdown = 1.5 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) - flags_inv = HIDEJUMPSUIT|HIDETAIL +/* + * 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" + w_class = 4//bulky item + gas_transfer_coefficient = 0.90 + permeability_coefficient = 0.50 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/weapon/extinguisher) + slowdown = 1.0 + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL + flags_pressure = STOPS_HIGHPRESSUREDMAGE + heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS + + +/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 = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0) + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES + body_parts_covered = HEAD|FACE|EYES + siemens_coefficient = 0.2 + + +/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 + slowdown = 2 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0) + flags_inv = HIDEJUMPSUIT|HIDETAIL + heat_protection = UPPER_TORSO|LOWER_TORSO + max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE + siemens_coefficient = 0.2 + + +/obj/item/clothing/head/bomb_hood/security + icon_state = "bombsuitsec" + item_state = "bombsuitsec" + body_parts_covered = HEAD + +/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) + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +/* + * 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 = HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR + body_parts_covered = HEAD|FACE|EYES + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) + + +/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|ARMS + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/clothing/head/radiation,/obj/item/clothing/mask/gas) + slowdown = 1.5 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) + flags_inv = HIDEJUMPSUIT|HIDETAIL diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index aa2da70e484c..91964e2df831 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -1,136 +1,136 @@ -/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.4 - body_parts_covered = 0 - -/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" - -/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" - body_parts_covered = HEAD|FACE - -/obj/item/clothing/head/wizard/marisa - name = "witch hat" - desc = "Strange-looking hat-wear, makes you want to cast fireballs." - icon_state = "marisa" - -/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" - body_parts_covered = HEAD|FACE|EYES - -/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" - -/obj/item/clothing/head/wizard/cap - name = "gentlemans cap" - desc = "A checkered gray flat cap woven together with the rarest of threads." - icon_state = "gentcap" - -/obj/item/clothing/head/wizard/redhood - name = "wizard hood" - desc = "A strange red gem-lined hoodie" - icon_state = "wiz_red_hood" - -/obj/item/clothing/head/wizard/bluehood - name = "wizard hood" - desc = "A strange blue gem-lined hoodie." - icon_state = "wiz_blue_hood" - -/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 - armor = list(melee = 30, bullet = 10, laser = 10,energy = 20, bomb = 20, bio = 20, rad = 20) - allowed = list(/obj/item/weapon/teleportation_scroll) - flags_inv = HIDEJUMPSUIT - siemens_coefficient = 0.4 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -/obj/item/clothing/suit/wizrobe/wiz_blue - name = "blue jacket" - desc = "A stylish gem-lined jacket straight from deep space." - icon_state = "mage_jacket_blue" - item_state = "mage_jacket_blue" - -/obj/item/clothing/suit/wizrobe/wiz_red - name = "red jacket" - desc = "A stylish gem-lined jacket straight from deep space." - icon_state = "mage_jacket_red" - item_state = "mage_jacket_red" - -/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" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - -/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" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS - -/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/gentlecoat - name = "gentlemans coat" - desc = "A heavy threaded twead gray jacket. For a different sort of Gentleman." - icon_state = "gentlecoat" - item_state = "gentlecoat" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/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" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - -/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) - -/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) +/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.4 + body_parts_covered = 0 + +/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" + +/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" + body_parts_covered = HEAD|FACE + +/obj/item/clothing/head/wizard/marisa + name = "witch hat" + desc = "Strange-looking hat-wear, makes you want to cast fireballs." + icon_state = "marisa" + +/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" + body_parts_covered = HEAD|FACE|EYES + +/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" + +/obj/item/clothing/head/wizard/cap + name = "gentlemans cap" + desc = "A checkered gray flat cap woven together with the rarest of threads." + icon_state = "gentcap" + +/obj/item/clothing/head/wizard/redhood + name = "wizard hood" + desc = "A strange red gem-lined hoodie" + icon_state = "wiz_red_hood" + +/obj/item/clothing/head/wizard/bluehood + name = "wizard hood" + desc = "A strange blue gem-lined hoodie." + icon_state = "wiz_blue_hood" + +/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 + armor = list(melee = 30, bullet = 10, laser = 10,energy = 20, bomb = 20, bio = 20, rad = 20) + allowed = list(/obj/item/weapon/teleportation_scroll) + flags_inv = HIDEJUMPSUIT + siemens_coefficient = 0.4 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +/obj/item/clothing/suit/wizrobe/wiz_blue + name = "blue jacket" + desc = "A stylish gem-lined jacket straight from deep space." + icon_state = "mage_jacket_blue" + item_state = "mage_jacket_blue" + +/obj/item/clothing/suit/wizrobe/wiz_red + name = "red jacket" + desc = "A stylish gem-lined jacket straight from deep space." + icon_state = "mage_jacket_red" + item_state = "mage_jacket_red" + +/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" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + +/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" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS + +/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/gentlecoat + name = "gentlemans coat" + desc = "A heavy threaded twead gray jacket. For a different sort of Gentleman." + icon_state = "gentlecoat" + item_state = "gentlecoat" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/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" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + +/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) + +/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) diff --git a/code/modules/clothing/under/chameleon.dm b/code/modules/clothing/under/chameleon.dm index 1417bf09de1f..e09cb1b628aa 100644 --- a/code/modules/clothing/under/chameleon.dm +++ b/code/modules/clothing/under/chameleon.dm @@ -1,512 +1,512 @@ -//***************** -//**Cham Jumpsuit** -//***************** - -/obj/item/clothing/under/chameleon -//starts off as black - name = "black jumpsuit" - icon_state = "black" - item_state = "bl_suit" - item_color = "black" - desc = "It's a plain jumpsuit. It seems to have a small dial on the wrist." - origin_tech = "syndicate=3" - var/list/clothing_choices = list() - -/obj/item/clothing/under/chameleon/atom_init() - . = ..() - var/blocked = list(/obj/item/clothing/under/chameleon, /obj/item/clothing/under/golem, /obj/item/clothing/under/gimmick)//Prevent infinite loops and bad jumpsuits. - for(var/U in typesof(/obj/item/clothing/under)-blocked) - var/obj/item/clothing/under/V = new U - clothing_choices[V.name] = U - -/obj/item/clothing/under/chameleon/emp_act(severity) - name = "psychedelic" - desc = "Groovy!" - icon_state = "psyche" - item_color = "psyche" - update_icon() - usr.update_inv_w_uniform() - -/obj/item/clothing/under/chameleon/verb/change() - set name = "Change Jumpsuit Appearance" - set category = "Object" - set src in usr - - var/picked = input("Select jumpsuit to change it to", "Chameleon Jumpsuit")as null|anything in clothing_choices - if(!picked || !clothing_choices[picked]) - return - var/newtype = clothing_choices[picked] - var/obj/item/clothing/A = new newtype - - desc = null - permeability_coefficient = 0.90 - - - if(A.icon_custom) // - icon = A.icon_custom - icon_custom = A.icon_custom - else - icon = A.icon - icon_custom = null - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - item_color = A.item_color - body_parts_covered = A.body_parts_covered - if(usr) - usr.update_inv_w_uniform() //so our overlays update. - -//***************** -//**Chameleon Hat** -//***************** - -/obj/item/clothing/head/chameleon - name = "grey cap" - icon_state = "greysoft" - item_state = "greysoft" - item_color = "grey" - desc = "It looks like a plain hat, but upon closer inspection, there's an advanced holographic array installed inside. It seems to have a small dial inside." - origin_tech = "syndicate=3" - body_parts_covered = 0 - var/list/clothing_choices = list() - -/obj/item/clothing/head/chameleon/atom_init() - . = ..() - var/blocked = list(/obj/item/clothing/head/chameleon, - /obj/item/clothing/head/helmet/space/golem, /obj/item/clothing/head/justice,)//Prevent infinite loops and bad hats. - for(var/U in typesof(/obj/item/clothing/head)-blocked) - var/obj/item/clothing/head/V = new U - clothing_choices[V.name] = U - -/obj/item/clothing/head/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. - name = "grey cap" - desc = "It's a baseball hat in a tasteful grey colour." - icon_state = "greysoft" - item_color = "grey" - update_icon() - usr.update_inv_head() - -/obj/item/clothing/head/chameleon/verb/change() - set name = "Change Hat/Helmet Appearance" - set category = "Object" - set src in usr - - var/picked = input("Select headwear to change it to", "Chameleon Hat")as null|anything in clothing_choices - if(!picked || !clothing_choices[picked]) - return - var/newtype = clothing_choices[picked] - var/obj/item/clothing/A = new newtype - - desc = null - permeability_coefficient = 0.90 - - if(A.icon_custom) - icon = A.icon_custom - icon_custom = A.icon_custom - else - icon = A.icon - icon_custom = null - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - item_color = A.item_color - flags_inv = A.flags_inv - body_parts_covered = A.body_parts_covered - if(usr) - usr.update_inv_head() //so our overlays update. - -//****************** -//**Chameleon Suit** -//****************** - -/obj/item/clothing/suit/chameleon - name = "armor" - icon_state = "armor" - item_state = "armor" - desc = "It appears to be a vest of standard armor, except this is embedded with a hidden holographic cloaker, allowing it to change it's appearance, but offering no protection.. It seems to have a small dial inside." - origin_tech = "syndicate=3" - var/list/clothing_choices = list() - -/obj/item/clothing/suit/chameleon/atom_init() - . = ..() - var/blocked = list(/obj/item/clothing/suit/chameleon, /obj/item/clothing/suit/space/space_ninja, - /obj/item/clothing/suit/space/golem, /obj/item/clothing/suit/cyborg_suit, /obj/item/clothing/suit/justice, - /obj/item/clothing/suit/greatcoat)//Prevent infinite loops and bad suits. - for(var/U in typesof(/obj/item/clothing/suit)-blocked) - var/obj/item/clothing/suit/V = new U - clothing_choices[V.name] = U - -/obj/item/clothing/suit/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. - name = "armor" - desc = "An armored vest that protects against some damage." - icon_state = "armor" - item_color = "armor" - update_icon() - usr.update_inv_wear_suit() - -/obj/item/clothing/suit/chameleon/verb/change() - set name = "Change Exosuit Appearance" - set category = "Object" - set src in usr - - var/picked = input("Select exosuit to change it to", "Chameleon Exosuit")as null|anything in clothing_choices - if(!picked || !clothing_choices[picked]) - return - var/newtype = clothing_choices[picked] - var/obj/item/clothing/A = new newtype - - desc = null - permeability_coefficient = 0.90 - - if(A.icon_custom) - icon = A.icon_custom - icon_custom = A.icon_custom - else - icon = A.icon - icon_custom = null - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - item_color = A.item_color - flags_inv = A.flags_inv - body_parts_covered = A.body_parts_covered - if(usr) - usr.update_inv_wear_suit() //so our overlays update. - -//******************* -//**Chameleon Shoes** -//******************* -/obj/item/clothing/shoes/chameleon - name = "black shoes" - icon_state = "black" - item_state = "black" - item_color = "black" - desc = "They're comfy black shoes, with clever cloaking technology built in. It seems to have a small dial on the back of each shoe." - origin_tech = "syndicate=3" - var/list/clothing_choices = list() - -/obj/item/clothing/shoes/chameleon/atom_init() - . = ..() - var/blocked = list(/obj/item/clothing/shoes/chameleon, - /obj/item/clothing/shoes/golem, /obj/item/clothing/shoes/syndigaloshes, /obj/item/clothing/shoes/cyborg)//prevent infinite loops and bad shoes. - for(var/U in typesof(/obj/item/clothing/shoes)-blocked) - var/obj/item/clothing/shoes/V = new U - clothing_choices[V.name] = U - -/obj/item/clothing/shoes/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. - name = "black shoes" - desc = "A pair of black shoes." - icon_state = "black" - item_state = "black" - item_color = "black" - update_icon() - usr.update_inv_shoes() - -/obj/item/clothing/shoes/chameleon/verb/change() - set name = "Change Footwear Appearance" - set category = "Object" - set src in usr - - var/picked = input("Select shoes to change it to", "Chameleon Shoes")as null|anything in clothing_choices - if(!picked || !clothing_choices[picked]) - return - var/newtype = clothing_choices[picked] - var/obj/item/clothing/A = new newtype - - desc = null - permeability_coefficient = 0.90 - - if(A.icon_custom) - icon = A.icon_custom - icon_custom = A.icon_custom - else - icon = A.icon - icon_custom = null - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - item_color = A.item_color - if(usr) - usr.update_inv_shoes() //so our overlays update. - -//********************** -//**Chameleon Backpack** -//********************** -/obj/item/weapon/storage/backpack/chameleon - name = "backpack" - icon_state = "backpack" - item_state = "backpack" - desc = "A backpack outfitted with cloaking tech. It seems to have a small dial inside, kept away from the storage." - origin_tech = "syndicate=3" - var/list/clothing_choices = list() - -/obj/item/weapon/storage/backpack/chameleon/atom_init() - . = ..() - var/blocked = list(/obj/item/weapon/storage/backpack/chameleon, /obj/item/weapon/storage/backpack/satchel/withwallet) - for(var/U in typesof(/obj/item/weapon/storage/backpack)-blocked)//Prevent infinite loops and bad backpacks. - var/obj/item/weapon/storage/backpack/V = new U - clothing_choices[V.name] = U - -/obj/item/weapon/storage/backpack/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. - name = "backpack" - desc = "You wear this on your back and put items into it." - icon_state = "backpack" - item_state = "backpack" - update_icon() - usr.update_inv_back() - -/obj/item/weapon/storage/backpack/chameleon/verb/change() - set name = "Change Backpack Appearance" - set category = "Object" - set src in usr - - var/picked = input("Select backpack to change it to", "Chameleon Backpack")as null|anything in clothing_choices - if(!picked || !clothing_choices[picked]) - return - var/newtype = clothing_choices[picked] - var/obj/item/weapon/storage/backpack/A = new newtype - - desc = null - permeability_coefficient = 0.90 - - if(A.icon_custom) - icon = A.icon_custom - icon_custom = A.icon_custom - else - icon = A.icon - icon_custom = null - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - item_color = A.item_color - if(usr) - usr.update_inv_back() //so our overlays update. - -//******************** -//**Chameleon Gloves** -//******************** - -/obj/item/clothing/gloves/chameleon - name = "black gloves" - icon_state = "black" - item_state = "bgloves" - item_color = "brown" - desc = "It looks like a pair of gloves, but it seems to have a small dial inside." - origin_tech = "syndicate=3" - var/list/clothing_choices = list() - -/obj/item/clothing/gloves/chameleon/atom_init() - . = ..() - var/blocked = list(/obj/item/clothing/gloves/chameleon)//Prevent infinite loops and bad hats. - for(var/U in typesof(/obj/item/clothing/gloves)-blocked) - var/obj/item/clothing/gloves/V = new U - clothing_choices[V.name] = U - -/obj/item/clothing/gloves/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. - name = "black gloves" - desc = "It looks like a pair of gloves, but it seems to have a small dial inside." - icon_state = "black" - item_color = "brown" - update_icon() - usr.update_inv_gloves() - -/obj/item/clothing/gloves/chameleon/verb/change() - set name = "Change Gloves Appearance" - set category = "Object" - set src in usr - - var/picked = input("Select gloves to change it to", "Chameleon Gloves")as null|anything in clothing_choices - if(!picked || !clothing_choices[picked]) - return - var/newtype = clothing_choices[picked] - var/obj/item/clothing/A = new newtype - - desc = null - permeability_coefficient = 0.90 - - if(A.icon_custom) - icon = A.icon_custom - icon_custom = A.icon_custom - else - icon = A.icon - icon_custom = null - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - item_color = A.item_color - flags_inv = A.flags_inv - if(usr) - usr.update_inv_gloves() //so our overlays update. - -//****************** -//**Chameleon Mask** -//****************** - -/obj/item/clothing/mask/chameleon - name = "gas mask" - icon_state = "gas_mask_tc" - item_state = "gas_mask_tc" - desc = "It looks like a plain gask mask, but on closer inspection, it seems to have a small dial inside." - origin_tech = "syndicate=3" - var/list/clothing_choices = list() - -/obj/item/clothing/mask/chameleon/atom_init() - . = ..() - var/blocked = list(/obj/item/clothing/mask/chameleon)//Prevent infinite loops and bad hats. - for(var/U in typesof(/obj/item/clothing/mask)-blocked) - var/obj/item/clothing/mask/V = new U - if(V) - clothing_choices[V.name] = U - -/obj/item/clothing/mask/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. - name = "gas mask" - desc = "It's a gas mask." - item_state = "gas_mask_tc" - icon_state = "gas_mask_tc" - update_icon() - usr.update_inv_wear_mask() - -/obj/item/clothing/mask/chameleon/verb/change() - set name = "Change Mask Appearance" - set category = "Object" - set src in usr - - var/picked = input("Select mask to change it to", "Chameleon Mask")as null|anything in clothing_choices - if(!picked || !clothing_choices[picked]) - return - var/newtype = clothing_choices[picked] - var/obj/item/clothing/A = new newtype - - desc = null - permeability_coefficient = 0.90 - - if(A.icon_custom) - icon = A.icon_custom - icon_custom = A.icon_custom - else - icon = A.icon - icon_custom = null - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - flags_inv = A.flags_inv - body_parts_covered = A.body_parts_covered - if(usr) - usr.update_inv_wear_mask() //so our overlays update. - -//********************* -//**Chameleon Glasses** -//********************* - -/obj/item/clothing/glasses/chameleon - name = "optical meson scanner" - icon_state = "meson" - item_state = "glasses" - desc = "It looks like a plain set of mesons, but on closer inspection, it seems to have a small dial inside." - origin_tech = "syndicate=3" - var/list/clothing_choices = list() - -/obj/item/clothing/glasses/chameleon/atom_init() - . = ..() - var/blocked = list(/obj/item/clothing/glasses/chameleon)//Prevent infinite loops and bad hats. - for(var/U in typesof(/obj/item/clothing/glasses)-blocked) - var/obj/item/clothing/glasses/V = new U - clothing_choices[V.name] = U - -/obj/item/clothing/glasses/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. - name = "optical meson scanner" - desc = "It's a set of mesons." - icon_state = "meson" - update_icon() - usr.update_inv_glasses() - -/obj/item/clothing/glasses/chameleon/verb/change() - set name = "Change Glasses Appearance" - set category = "Object" - set src in usr - - var/picked = input("Select glasses to change it to", "Chameleon Glasses")as null|anything in clothing_choices - if(!picked || !clothing_choices[picked]) - return - var/newtype = clothing_choices[picked] - var/obj/item/clothing/A = new newtype - - desc = null - permeability_coefficient = 0.90 - - if(A.icon_custom) - icon = A.icon_custom - icon_custom = A.icon_custom - else - icon = A.icon - icon_custom = null - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - flags_inv = A.flags_inv - if(usr) - usr.update_inv_glasses() //so our overlays update. - -//***************** -//**Chameleon Gun** -//***************** -/obj/item/weapon/gun/projectile/chameleon - name = "desert eagle" - desc = "A fake Desert Eagle with a dial on the side to change the gun's disguise." - icon_state = "deagle" - w_class = 3.0 - origin_tech = "combat=2;materials=2;syndicate=3" - mag_type = /obj/item/ammo_box/magazine/chameleon - var/list/gun_choices = list() - -/obj/item/weapon/gun/projectile/chameleon/atom_init() - . = ..() - var/blocked = list(/obj/item/weapon/gun/projectile/chameleon) - for(var/U in typesof(/obj/item/weapon/gun/)-blocked) - var/obj/item/weapon/gun/V = new U - gun_choices[V.name] = U - -/obj/item/weapon/gun/projectile/chameleon/emp_act(severity) - name = "desert eagle" - desc = "It's a desert eagle." - icon_state = "deagle" - update_icon() - usr.update_inv_r_hand() - usr.update_inv_l_hand() - -/obj/item/weapon/gun/projectile/chameleon/verb/change() - set name = "Change Gun Appearance" - set category = "Object" - set src in usr - - var/picked = input("Select gun to change it to", "Chameleon Gun")as null|anything in gun_choices - if(!picked || !gun_choices[picked]) - return - var/newtype = gun_choices[picked] - var/obj/item/weapon/gun/A = new newtype - - desc = null - permeability_coefficient = 0.90 - - if(A.icon_custom) - icon = A.icon_custom - icon_custom = A.icon_custom - else - icon = A.icon - icon_custom = null - desc = A.desc - name = A.name - icon_state = A.icon_state - item_state = A.item_state - flags_inv = A.flags_inv - if(usr) - usr.update_inv_r_hand() - usr.update_inv_l_hand() //so our overlays update. +//***************** +//**Cham Jumpsuit** +//***************** + +/obj/item/clothing/under/chameleon +//starts off as black + name = "black jumpsuit" + icon_state = "black" + item_state = "bl_suit" + item_color = "black" + desc = "It's a plain jumpsuit. It seems to have a small dial on the wrist." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + +/obj/item/clothing/under/chameleon/atom_init() + . = ..() + var/blocked = list(/obj/item/clothing/under/chameleon, /obj/item/clothing/under/golem, /obj/item/clothing/under/gimmick)//Prevent infinite loops and bad jumpsuits. + for(var/U in typesof(/obj/item/clothing/under)-blocked) + var/obj/item/clothing/under/V = new U + clothing_choices[V.name] = U + +/obj/item/clothing/under/chameleon/emp_act(severity) + name = "psychedelic" + desc = "Groovy!" + icon_state = "psyche" + item_color = "psyche" + update_icon() + usr.update_inv_w_uniform() + +/obj/item/clothing/under/chameleon/verb/change() + set name = "Change Jumpsuit Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select jumpsuit to change it to", "Chameleon Jumpsuit")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + + if(A.icon_custom) // + icon = A.icon_custom + icon_custom = A.icon_custom + else + icon = A.icon + icon_custom = null + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + body_parts_covered = A.body_parts_covered + if(usr) + usr.update_inv_w_uniform() //so our overlays update. + +//***************** +//**Chameleon Hat** +//***************** + +/obj/item/clothing/head/chameleon + name = "grey cap" + icon_state = "greysoft" + item_state = "greysoft" + item_color = "grey" + desc = "It looks like a plain hat, but upon closer inspection, there's an advanced holographic array installed inside. It seems to have a small dial inside." + origin_tech = "syndicate=3" + body_parts_covered = 0 + var/list/clothing_choices = list() + +/obj/item/clothing/head/chameleon/atom_init() + . = ..() + var/blocked = list(/obj/item/clothing/head/chameleon, + /obj/item/clothing/head/helmet/space/golem, /obj/item/clothing/head/justice,)//Prevent infinite loops and bad hats. + for(var/U in typesof(/obj/item/clothing/head)-blocked) + var/obj/item/clothing/head/V = new U + clothing_choices[V.name] = U + +/obj/item/clothing/head/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "grey cap" + desc = "It's a baseball hat in a tasteful grey colour." + icon_state = "greysoft" + item_color = "grey" + update_icon() + usr.update_inv_head() + +/obj/item/clothing/head/chameleon/verb/change() + set name = "Change Hat/Helmet Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select headwear to change it to", "Chameleon Hat")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + if(A.icon_custom) + icon = A.icon_custom + icon_custom = A.icon_custom + else + icon = A.icon + icon_custom = null + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + flags_inv = A.flags_inv + body_parts_covered = A.body_parts_covered + if(usr) + usr.update_inv_head() //so our overlays update. + +//****************** +//**Chameleon Suit** +//****************** + +/obj/item/clothing/suit/chameleon + name = "armor" + icon_state = "armor" + item_state = "armor" + desc = "It appears to be a vest of standard armor, except this is embedded with a hidden holographic cloaker, allowing it to change it's appearance, but offering no protection.. It seems to have a small dial inside." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + +/obj/item/clothing/suit/chameleon/atom_init() + . = ..() + var/blocked = list(/obj/item/clothing/suit/chameleon, /obj/item/clothing/suit/space/space_ninja, + /obj/item/clothing/suit/space/golem, /obj/item/clothing/suit/cyborg_suit, /obj/item/clothing/suit/justice, + /obj/item/clothing/suit/greatcoat)//Prevent infinite loops and bad suits. + for(var/U in typesof(/obj/item/clothing/suit)-blocked) + var/obj/item/clothing/suit/V = new U + clothing_choices[V.name] = U + +/obj/item/clothing/suit/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "armor" + desc = "An armored vest that protects against some damage." + icon_state = "armor" + item_color = "armor" + update_icon() + usr.update_inv_wear_suit() + +/obj/item/clothing/suit/chameleon/verb/change() + set name = "Change Exosuit Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select exosuit to change it to", "Chameleon Exosuit")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + if(A.icon_custom) + icon = A.icon_custom + icon_custom = A.icon_custom + else + icon = A.icon + icon_custom = null + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + flags_inv = A.flags_inv + body_parts_covered = A.body_parts_covered + if(usr) + usr.update_inv_wear_suit() //so our overlays update. + +//******************* +//**Chameleon Shoes** +//******************* +/obj/item/clothing/shoes/chameleon + name = "black shoes" + icon_state = "black" + item_state = "black" + item_color = "black" + desc = "They're comfy black shoes, with clever cloaking technology built in. It seems to have a small dial on the back of each shoe." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + +/obj/item/clothing/shoes/chameleon/atom_init() + . = ..() + var/blocked = list(/obj/item/clothing/shoes/chameleon, + /obj/item/clothing/shoes/golem, /obj/item/clothing/shoes/syndigaloshes, /obj/item/clothing/shoes/cyborg)//prevent infinite loops and bad shoes. + for(var/U in typesof(/obj/item/clothing/shoes)-blocked) + var/obj/item/clothing/shoes/V = new U + clothing_choices[V.name] = U + +/obj/item/clothing/shoes/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "black shoes" + desc = "A pair of black shoes." + icon_state = "black" + item_state = "black" + item_color = "black" + update_icon() + usr.update_inv_shoes() + +/obj/item/clothing/shoes/chameleon/verb/change() + set name = "Change Footwear Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select shoes to change it to", "Chameleon Shoes")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + if(A.icon_custom) + icon = A.icon_custom + icon_custom = A.icon_custom + else + icon = A.icon + icon_custom = null + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + if(usr) + usr.update_inv_shoes() //so our overlays update. + +//********************** +//**Chameleon Backpack** +//********************** +/obj/item/weapon/storage/backpack/chameleon + name = "backpack" + icon_state = "backpack" + item_state = "backpack" + desc = "A backpack outfitted with cloaking tech. It seems to have a small dial inside, kept away from the storage." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + +/obj/item/weapon/storage/backpack/chameleon/atom_init() + . = ..() + var/blocked = list(/obj/item/weapon/storage/backpack/chameleon, /obj/item/weapon/storage/backpack/satchel/withwallet) + for(var/U in typesof(/obj/item/weapon/storage/backpack)-blocked)//Prevent infinite loops and bad backpacks. + var/obj/item/weapon/storage/backpack/V = new U + clothing_choices[V.name] = U + +/obj/item/weapon/storage/backpack/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "backpack" + desc = "You wear this on your back and put items into it." + icon_state = "backpack" + item_state = "backpack" + update_icon() + usr.update_inv_back() + +/obj/item/weapon/storage/backpack/chameleon/verb/change() + set name = "Change Backpack Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select backpack to change it to", "Chameleon Backpack")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/weapon/storage/backpack/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + if(A.icon_custom) + icon = A.icon_custom + icon_custom = A.icon_custom + else + icon = A.icon + icon_custom = null + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + if(usr) + usr.update_inv_back() //so our overlays update. + +//******************** +//**Chameleon Gloves** +//******************** + +/obj/item/clothing/gloves/chameleon + name = "black gloves" + icon_state = "black" + item_state = "bgloves" + item_color = "brown" + desc = "It looks like a pair of gloves, but it seems to have a small dial inside." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + +/obj/item/clothing/gloves/chameleon/atom_init() + . = ..() + var/blocked = list(/obj/item/clothing/gloves/chameleon)//Prevent infinite loops and bad hats. + for(var/U in typesof(/obj/item/clothing/gloves)-blocked) + var/obj/item/clothing/gloves/V = new U + clothing_choices[V.name] = U + +/obj/item/clothing/gloves/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "black gloves" + desc = "It looks like a pair of gloves, but it seems to have a small dial inside." + icon_state = "black" + item_color = "brown" + update_icon() + usr.update_inv_gloves() + +/obj/item/clothing/gloves/chameleon/verb/change() + set name = "Change Gloves Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select gloves to change it to", "Chameleon Gloves")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + if(A.icon_custom) + icon = A.icon_custom + icon_custom = A.icon_custom + else + icon = A.icon + icon_custom = null + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + item_color = A.item_color + flags_inv = A.flags_inv + if(usr) + usr.update_inv_gloves() //so our overlays update. + +//****************** +//**Chameleon Mask** +//****************** + +/obj/item/clothing/mask/chameleon + name = "gas mask" + icon_state = "gas_mask_tc" + item_state = "gas_mask_tc" + desc = "It looks like a plain gask mask, but on closer inspection, it seems to have a small dial inside." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + +/obj/item/clothing/mask/chameleon/atom_init() + . = ..() + var/blocked = list(/obj/item/clothing/mask/chameleon)//Prevent infinite loops and bad hats. + for(var/U in typesof(/obj/item/clothing/mask)-blocked) + var/obj/item/clothing/mask/V = new U + if(V) + clothing_choices[V.name] = U + +/obj/item/clothing/mask/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "gas mask" + desc = "It's a gas mask." + item_state = "gas_mask_tc" + icon_state = "gas_mask_tc" + update_icon() + usr.update_inv_wear_mask() + +/obj/item/clothing/mask/chameleon/verb/change() + set name = "Change Mask Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select mask to change it to", "Chameleon Mask")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + if(A.icon_custom) + icon = A.icon_custom + icon_custom = A.icon_custom + else + icon = A.icon + icon_custom = null + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + flags_inv = A.flags_inv + body_parts_covered = A.body_parts_covered + if(usr) + usr.update_inv_wear_mask() //so our overlays update. + +//********************* +//**Chameleon Glasses** +//********************* + +/obj/item/clothing/glasses/chameleon + name = "optical meson scanner" + icon_state = "meson" + item_state = "glasses" + desc = "It looks like a plain set of mesons, but on closer inspection, it seems to have a small dial inside." + origin_tech = "syndicate=3" + var/list/clothing_choices = list() + +/obj/item/clothing/glasses/chameleon/atom_init() + . = ..() + var/blocked = list(/obj/item/clothing/glasses/chameleon)//Prevent infinite loops and bad hats. + for(var/U in typesof(/obj/item/clothing/glasses)-blocked) + var/obj/item/clothing/glasses/V = new U + clothing_choices[V.name] = U + +/obj/item/clothing/glasses/chameleon/emp_act(severity) //Because we don't have psych for all slots right now but still want a downside to EMP. In this case your cover's blown. + name = "optical meson scanner" + desc = "It's a set of mesons." + icon_state = "meson" + update_icon() + usr.update_inv_glasses() + +/obj/item/clothing/glasses/chameleon/verb/change() + set name = "Change Glasses Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select glasses to change it to", "Chameleon Glasses")as null|anything in clothing_choices + if(!picked || !clothing_choices[picked]) + return + var/newtype = clothing_choices[picked] + var/obj/item/clothing/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + if(A.icon_custom) + icon = A.icon_custom + icon_custom = A.icon_custom + else + icon = A.icon + icon_custom = null + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + flags_inv = A.flags_inv + if(usr) + usr.update_inv_glasses() //so our overlays update. + +//***************** +//**Chameleon Gun** +//***************** +/obj/item/weapon/gun/projectile/chameleon + name = "desert eagle" + desc = "A fake Desert Eagle with a dial on the side to change the gun's disguise." + icon_state = "deagle" + w_class = 3.0 + origin_tech = "combat=2;materials=2;syndicate=3" + mag_type = /obj/item/ammo_box/magazine/chameleon + var/list/gun_choices = list() + +/obj/item/weapon/gun/projectile/chameleon/atom_init() + . = ..() + var/blocked = list(/obj/item/weapon/gun/projectile/chameleon) + for(var/U in typesof(/obj/item/weapon/gun/)-blocked) + var/obj/item/weapon/gun/V = new U + gun_choices[V.name] = U + +/obj/item/weapon/gun/projectile/chameleon/emp_act(severity) + name = "desert eagle" + desc = "It's a desert eagle." + icon_state = "deagle" + update_icon() + usr.update_inv_r_hand() + usr.update_inv_l_hand() + +/obj/item/weapon/gun/projectile/chameleon/verb/change() + set name = "Change Gun Appearance" + set category = "Object" + set src in usr + + var/picked = input("Select gun to change it to", "Chameleon Gun")as null|anything in gun_choices + if(!picked || !gun_choices[picked]) + return + var/newtype = gun_choices[picked] + var/obj/item/weapon/gun/A = new newtype + + desc = null + permeability_coefficient = 0.90 + + if(A.icon_custom) + icon = A.icon_custom + icon_custom = A.icon_custom + else + icon = A.icon + icon_custom = null + desc = A.desc + name = A.name + icon_state = A.icon_state + item_state = A.item_state + flags_inv = A.flags_inv + if(usr) + usr.update_inv_r_hand() + usr.update_inv_l_hand() //so our overlays update. diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm index 7abfda65c577..ccca3083461d 100644 --- a/code/modules/clothing/under/color.dm +++ b/code/modules/clothing/under/color.dm @@ -1,156 +1,156 @@ -/obj/item/clothing/under/color/black - name = "black jumpsuit" - icon_state = "black" - item_state = "bl_suit" - item_color = "black" - flags = 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" - item_color = "blackf" - -/obj/item/clothing/under/color/blue - name = "blue jumpsuit" - icon_state = "blue" - item_state = "b_suit" - item_color = "blue" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/color/green - name = "green jumpsuit" - icon_state = "green" - item_state = "g_suit" - item_color = "green" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/color/grey - name = "grey jumpsuit" - icon_state = "grey" - item_state = "gy_suit" - item_color = "grey" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/color/orange - name = "orange jumpsuit" - desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position." - icon_state = "orange" - item_state = "o_suit" - item_color = "orange" - has_sensor = 2 - sensor_mode = 3 - flags = ONESIZEFITSALL - -/obj/item/clothing/under/color/pink - name = "pink jumpsuit" - icon_state = "pink" - item_state = "p_suit" - item_color = "pink" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/color/red - name = "red jumpsuit" - icon_state = "red" - item_state = "r_suit" - item_color = "red" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/color/white - name = "white jumpsuit" - icon_state = "white" - item_state = "w_suit" - item_color = "white" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/color/yellow - name = "yellow jumpsuit" - icon_state = "yellow" - item_state = "y_suit" - item_color = "yellow" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/psyche - name = "psychedelic" - desc = "Groovy!" - icon_state = "psyche" - item_color = "psyche" - -/obj/item/clothing/under/lightblue - name = "lightblue" - desc = "lightblue" - icon_state = "lightblue" - item_color = "lightblue" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/aqua - name = "aqua" - desc = "aqua" - icon_state = "aqua" - item_color = "aqua" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/purple - name = "purple" - desc = "purple" - icon_state = "purple" - item_state = "p_suit" - item_color = "purple" - -/obj/item/clothing/under/lightpurple - name = "lightpurple" - desc = "lightpurple" - icon_state = "lightpurple" - item_color = "lightpurple" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/lightgreen - name = "lightgreen" - desc = "lightgreen" - icon_state = "lightgreen" - item_color = "lightgreen" - -/obj/item/clothing/under/lightblue - name = "lightblue" - desc = "lightblue" - icon_state = "lightblue" - item_color = "lightblue" - -/obj/item/clothing/under/lightbrown - name = "lightbrown" - desc = "lightbrown" - icon_state = "lightbrown" - item_color = "lightbrown" - -/obj/item/clothing/under/brown - name = "brown" - desc = "brown" - icon_state = "brown" - item_color = "brown" - -/obj/item/clothing/under/yellowgreen - name = "yellowgreen" - desc = "yellowgreen" - icon_state = "yellowgreen" - item_color = "yellowgreen" - -/obj/item/clothing/under/darkblue - name = "darkblue" - desc = "darkblue" - icon_state = "darkblue" - item_color = "darkblue" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/lightred - name = "lightred" - desc = "lightred" - icon_state = "lightred" - item_color = "lightred" - -/obj/item/clothing/under/darkred - name = "darkred" - desc = "darkred" - icon_state = "darkred" - item_color = "darkred" - flags = ONESIZEFITSALL +/obj/item/clothing/under/color/black + name = "black jumpsuit" + icon_state = "black" + item_state = "bl_suit" + item_color = "black" + flags = 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" + item_color = "blackf" + +/obj/item/clothing/under/color/blue + name = "blue jumpsuit" + icon_state = "blue" + item_state = "b_suit" + item_color = "blue" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/color/green + name = "green jumpsuit" + icon_state = "green" + item_state = "g_suit" + item_color = "green" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/color/grey + name = "grey jumpsuit" + icon_state = "grey" + item_state = "gy_suit" + item_color = "grey" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/color/orange + name = "orange jumpsuit" + desc = "It's standardised Nanotrasen prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position." + icon_state = "orange" + item_state = "o_suit" + item_color = "orange" + has_sensor = 2 + sensor_mode = 3 + flags = ONESIZEFITSALL + +/obj/item/clothing/under/color/pink + name = "pink jumpsuit" + icon_state = "pink" + item_state = "p_suit" + item_color = "pink" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/color/red + name = "red jumpsuit" + icon_state = "red" + item_state = "r_suit" + item_color = "red" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/color/white + name = "white jumpsuit" + icon_state = "white" + item_state = "w_suit" + item_color = "white" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/color/yellow + name = "yellow jumpsuit" + icon_state = "yellow" + item_state = "y_suit" + item_color = "yellow" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/psyche + name = "psychedelic" + desc = "Groovy!" + icon_state = "psyche" + item_color = "psyche" + +/obj/item/clothing/under/lightblue + name = "lightblue" + desc = "lightblue" + icon_state = "lightblue" + item_color = "lightblue" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/aqua + name = "aqua" + desc = "aqua" + icon_state = "aqua" + item_color = "aqua" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/purple + name = "purple" + desc = "purple" + icon_state = "purple" + item_state = "p_suit" + item_color = "purple" + +/obj/item/clothing/under/lightpurple + name = "lightpurple" + desc = "lightpurple" + icon_state = "lightpurple" + item_color = "lightpurple" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/lightgreen + name = "lightgreen" + desc = "lightgreen" + icon_state = "lightgreen" + item_color = "lightgreen" + +/obj/item/clothing/under/lightblue + name = "lightblue" + desc = "lightblue" + icon_state = "lightblue" + item_color = "lightblue" + +/obj/item/clothing/under/lightbrown + name = "lightbrown" + desc = "lightbrown" + icon_state = "lightbrown" + item_color = "lightbrown" + +/obj/item/clothing/under/brown + name = "brown" + desc = "brown" + icon_state = "brown" + item_color = "brown" + +/obj/item/clothing/under/yellowgreen + name = "yellowgreen" + desc = "yellowgreen" + icon_state = "yellowgreen" + item_color = "yellowgreen" + +/obj/item/clothing/under/darkblue + name = "darkblue" + desc = "darkblue" + icon_state = "darkblue" + item_color = "darkblue" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/lightred + name = "lightred" + desc = "lightred" + icon_state = "lightred" + item_color = "lightred" + +/obj/item/clothing/under/darkred + name = "darkred" + desc = "darkred" + icon_state = "darkred" + item_color = "darkred" + flags = ONESIZEFITSALL diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index 18a5763e1f7f..f99f50730548 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -1,210 +1,210 @@ -//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" - item_color = "ba_suit" - flags = ONESIZEFITSALL - - -/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" - item_color = "captain" - flags = ONESIZEFITSALL - - -/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" - item_color = "qm" - flags = ONESIZEFITSALL - - -/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" - item_color = "cargo" - flags = ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/under/rank/recycler - name = "recycler's jumpsuit" - desc = "Stinks." - icon_state = "recycler" - item_state = "lb_suit" - item_color = "recycler" - flags = ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/under/rank/recyclercasual - name = "recycler's casual jumpsuit" - desc = "Stinks." - icon_state = "recyclercasual" - item_state = "lb_suit" - item_color = "recyclercasual" - flags = ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/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" - item_color = "chapblack" - flags = ONESIZEFITSALL - - -/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" - item_color = "chef" - flags = ONESIZEFITSALL - - -/obj/item/clothing/under/rank/clown - name = "clown suit" - desc = "'HONK!'" - icon_state = "clown" - item_state = "clown" - item_color = "clown" - flags = 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" - item_color = "hop" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/head_of_personnel_whimsy - desc = "A blue jacket and red tie, with matching red cuffs! Snazzy. Wearing this makes you feel more important than your job title does." - name = "head of personnel's suit" - icon_state = "hopwhimsy" - item_state = "hopwhimsy" - item_color = "hopwhimsy" - flags = ONESIZEFITSALL - - -/obj/item/clothing/under/rank/hydroponics - desc = "It's a jumpsuit designed to protect against minor plant-related hazards." - name = "botanist's jumpsuit" - icon_state = "hydroponics" - item_state = "g_suit" - item_color = "hydroponics" - permeability_coefficient = 0.50 - flags = 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" - item_color = "internalaffairs" - flags = ONESIZEFITSALL - - -/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" - item_color = "janitor" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - - -/obj/item/clothing/under/lawyer - desc = "Slick threads." - name = "lawyer suit" - - -/obj/item/clothing/under/lawyer/black - icon_state = "lawyer_black" - item_state = "lawyer_black" - item_color = "lawyer_black" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/lawyer/female - icon_state = "black_suit_fem" - item_state = "black_suit_fem" - item_color = "black_suit_fem" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/lawyer/red - icon_state = "lawyer_red" - item_state = "lawyer_red" - item_color = "lawyer_red" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/lawyer/blue - icon_state = "lawyer_blue" - item_state = "lawyer_blue" - item_color = "lawyer_blue" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/lawyer/bluesuit - name = "blue suit" - desc = "A classy suit and tie." - icon_state = "bluesuit" - item_state = "bluesuit" - item_color = "bluesuit" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/lawyer/purpsuit - name = "purple suit" - icon_state = "lawyer_purp" - item_state = "lawyer_purp" - item_color = "lawyer_purp" - flags = ONESIZEFITSALL - -/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" - item_color = "oldman" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/librarian - name = "sensible suit" - desc = "It's very... sensible." - icon_state = "red_suit" - item_state = "red_suit" - item_color = "red_suit" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/mime - name = "mime's outfit" - desc = "It's not very colourful." - icon_state = "mimesuit" - item_state = "mimesuit" - item_color = "mimesuit" - flags = 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" - item_color = "miner" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/barber - desc = "A suit, that oozes fabulous." - name = "barber's uniform" - icon_state = "barber" - item_state = "barber" - item_color = "barber" - flags = ONESIZEFITSALL +//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" + item_color = "ba_suit" + flags = ONESIZEFITSALL + + +/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" + item_color = "captain" + flags = ONESIZEFITSALL + + +/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" + item_color = "qm" + flags = ONESIZEFITSALL + + +/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" + item_color = "cargo" + flags = ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/under/rank/recycler + name = "recycler's jumpsuit" + desc = "Stinks." + icon_state = "recycler" + item_state = "lb_suit" + item_color = "recycler" + flags = ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/under/rank/recyclercasual + name = "recycler's casual jumpsuit" + desc = "Stinks." + icon_state = "recyclercasual" + item_state = "lb_suit" + item_color = "recyclercasual" + flags = ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/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" + item_color = "chapblack" + flags = ONESIZEFITSALL + + +/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" + item_color = "chef" + flags = ONESIZEFITSALL + + +/obj/item/clothing/under/rank/clown + name = "clown suit" + desc = "'HONK!'" + icon_state = "clown" + item_state = "clown" + item_color = "clown" + flags = 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" + item_color = "hop" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/head_of_personnel_whimsy + desc = "A blue jacket and red tie, with matching red cuffs! Snazzy. Wearing this makes you feel more important than your job title does." + name = "head of personnel's suit" + icon_state = "hopwhimsy" + item_state = "hopwhimsy" + item_color = "hopwhimsy" + flags = ONESIZEFITSALL + + +/obj/item/clothing/under/rank/hydroponics + desc = "It's a jumpsuit designed to protect against minor plant-related hazards." + name = "botanist's jumpsuit" + icon_state = "hydroponics" + item_state = "g_suit" + item_color = "hydroponics" + permeability_coefficient = 0.50 + flags = 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" + item_color = "internalaffairs" + flags = ONESIZEFITSALL + + +/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" + item_color = "janitor" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + + +/obj/item/clothing/under/lawyer + desc = "Slick threads." + name = "lawyer suit" + + +/obj/item/clothing/under/lawyer/black + icon_state = "lawyer_black" + item_state = "lawyer_black" + item_color = "lawyer_black" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/lawyer/female + icon_state = "black_suit_fem" + item_state = "black_suit_fem" + item_color = "black_suit_fem" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/lawyer/red + icon_state = "lawyer_red" + item_state = "lawyer_red" + item_color = "lawyer_red" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/lawyer/blue + icon_state = "lawyer_blue" + item_state = "lawyer_blue" + item_color = "lawyer_blue" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/lawyer/bluesuit + name = "blue suit" + desc = "A classy suit and tie." + icon_state = "bluesuit" + item_state = "bluesuit" + item_color = "bluesuit" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/lawyer/purpsuit + name = "purple suit" + icon_state = "lawyer_purp" + item_state = "lawyer_purp" + item_color = "lawyer_purp" + flags = ONESIZEFITSALL + +/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" + item_color = "oldman" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/librarian + name = "sensible suit" + desc = "It's very... sensible." + icon_state = "red_suit" + item_state = "red_suit" + item_color = "red_suit" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/mime + name = "mime's outfit" + desc = "It's not very colourful." + icon_state = "mimesuit" + item_state = "mimesuit" + item_color = "mimesuit" + flags = 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" + item_color = "miner" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/barber + desc = "A suit, that oozes fabulous." + name = "barber's uniform" + icon_state = "barber" + item_state = "barber" + item_color = "barber" + flags = ONESIZEFITSALL diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index 6fc60ffb94fb..9cea1bb9ce28 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -1,34 +1,34 @@ -//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" - item_color = "chief" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) - flags = ONESIZEFITSALL - -/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" - item_color = "atmos" - flags = ONESIZEFITSALL - -/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" - item_color = "engine" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/roboticist - desc = "It's a slimming black with reinforced seams; great for industrial work." - name = "roboticist's jumpsuit" - icon_state = "robotics" - item_state = "robotics" - item_color = "robotics" - flags = ONESIZEFITSALL +//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" + item_color = "chief" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) + flags = ONESIZEFITSALL + +/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" + item_color = "atmos" + flags = ONESIZEFITSALL + +/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" + item_color = "engine" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 10) + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/roboticist + desc = "It's a slimming black with reinforced seams; great for industrial work." + name = "roboticist's jumpsuit" + icon_state = "robotics" + item_state = "robotics" + item_color = "robotics" + flags = ONESIZEFITSALL diff --git a/code/modules/clothing/under/jobs/medsci.dm b/code/modules/clothing/under/jobs/medsci.dm index a682c8c89461..7f6e966136b6 100644 --- a/code/modules/clothing/under/jobs/medsci.dm +++ b/code/modules/clothing/under/jobs/medsci.dm @@ -1,228 +1,228 @@ -/* - * 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" - item_color = "director" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/research_director/rdalt - desc = "A dress suit and slacks stained with hard work and dedication to science. Perhaps other things as well, but mostly hard work and dedication." - name = "head researcher uniform" - icon_state = "rdalt" - item_state = "g_suit" - item_color = "rdalt" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/research_director/dress_rd - name = "research director dress uniform" - desc = "Feminine fashion for the style concious RD. Its fabric provides minor protection from biological contaminants." - icon_state = "dress_rd" - item_color = "dress_rd" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/under/rank/scientist - desc = "It's made of a special fiber that provides minor protection against biohazards. It has markings that denote the wearer as a scientist." - name = "scientist's jumpsuit" - icon_state = "science" - item_state = "w_suit" - item_color = "sciencewhite" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) - flags = ONESIZEFITSALL - - -/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" - item_color = "chemistrywhite" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/chemist/skirt - name = "chemist's jumpskirt" - icon_state = "skirt_chemistry" - item_color = "skirt_chemistry" - -/* - * 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" - item_color = "cmo" - flags = ONESIZEFITSALL - 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/chief_medical_officer/skirt - name = "chief medical officer's jumpskirt" - icon_state = "skirt_cmo" - item_color = "skirt_cmo" - -/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" - item_color = "geneticswhite" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/geneticist/skirt - name = "geneticist's jumpskirt" - icon_state = "skirt_genetics" - item_color = "skirt_genetics" - -/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" - item_color = "virologywhite" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/virologist/skirt - name = "virologist's jumpskirt" - icon_state = "skirt_virology" - item_color = "skirt_virology" - -/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" - item_color = "nursesuit" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/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" - item_color = "nurse" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/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" - item_color = "orderly" - 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/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" - item_color = "medical" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/medical/skirt - name = "medical doctor's jumpskirt" - icon_state = "skirt_medical" - item_color = "skirt_medical" - -/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" - item_color = "scrubsblue" - flags = ONESIZEFITSALL - -/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" - item_color = "scrubsgreen" - flags = ONESIZEFITSALL - -/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" - item_color = "scrubspurple" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/psych - desc = "A basic white jumpsuit. It has turqouise markings that denote the wearer as a psychiatrist." - name = "psychiatrist's jumpsuit" - icon_state = "psych" - item_state = "w_suit" - item_color = "psych" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/psych/turtleneck - desc = "A turqouise turtleneck and a pair of dark blue slacks, belonging to a psychologist." - name = "psychologist's turtleneck" - icon_state = "psychturtle" - item_state = "b_suit" - item_color = "psychturtle" - - -/* - * 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" - item_color = "genetics_new" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - -/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" - item_color = "chemist_new" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL - -/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" - item_color = "scientist_new" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) - flags = ONESIZEFITSALL - -/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" - item_color = "virologist_new" - permeability_coefficient = 0.50 - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) - flags = ONESIZEFITSALL +/* + * 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" + item_color = "director" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/research_director/rdalt + desc = "A dress suit and slacks stained with hard work and dedication to science. Perhaps other things as well, but mostly hard work and dedication." + name = "head researcher uniform" + icon_state = "rdalt" + item_state = "g_suit" + item_color = "rdalt" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/research_director/dress_rd + name = "research director dress uniform" + desc = "Feminine fashion for the style concious RD. Its fabric provides minor protection from biological contaminants." + icon_state = "dress_rd" + item_color = "dress_rd" + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/under/rank/scientist + desc = "It's made of a special fiber that provides minor protection against biohazards. It has markings that denote the wearer as a scientist." + name = "scientist's jumpsuit" + icon_state = "science" + item_state = "w_suit" + item_color = "sciencewhite" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) + flags = ONESIZEFITSALL + + +/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" + item_color = "chemistrywhite" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/chemist/skirt + name = "chemist's jumpskirt" + icon_state = "skirt_chemistry" + item_color = "skirt_chemistry" + +/* + * 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" + item_color = "cmo" + flags = ONESIZEFITSALL + 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/chief_medical_officer/skirt + name = "chief medical officer's jumpskirt" + icon_state = "skirt_cmo" + item_color = "skirt_cmo" + +/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" + item_color = "geneticswhite" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/geneticist/skirt + name = "geneticist's jumpskirt" + icon_state = "skirt_genetics" + item_color = "skirt_genetics" + +/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" + item_color = "virologywhite" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/virologist/skirt + name = "virologist's jumpskirt" + icon_state = "skirt_virology" + item_color = "skirt_virology" + +/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" + item_color = "nursesuit" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/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" + item_color = "nurse" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/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" + item_color = "orderly" + 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/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" + item_color = "medical" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/medical/skirt + name = "medical doctor's jumpskirt" + icon_state = "skirt_medical" + item_color = "skirt_medical" + +/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" + item_color = "scrubsblue" + flags = ONESIZEFITSALL + +/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" + item_color = "scrubsgreen" + flags = ONESIZEFITSALL + +/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" + item_color = "scrubspurple" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/psych + desc = "A basic white jumpsuit. It has turqouise markings that denote the wearer as a psychiatrist." + name = "psychiatrist's jumpsuit" + icon_state = "psych" + item_state = "w_suit" + item_color = "psych" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/psych/turtleneck + desc = "A turqouise turtleneck and a pair of dark blue slacks, belonging to a psychologist." + name = "psychologist's turtleneck" + icon_state = "psychturtle" + item_state = "b_suit" + item_color = "psychturtle" + + +/* + * 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" + item_color = "genetics_new" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + +/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" + item_color = "chemist_new" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL + +/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" + item_color = "scientist_new" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0) + flags = ONESIZEFITSALL + +/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" + item_color = "virologist_new" + permeability_coefficient = 0.50 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0) + flags = ONESIZEFITSALL diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm index 251b7790d244..8821e166864b 100644 --- a/code/modules/clothing/under/jobs/security.dm +++ b/code/modules/clothing/under/jobs/security.dm @@ -1,168 +1,168 @@ -/* - * 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" - item_color = "warden" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = ONESIZEFITSALL - siemens_coefficient = 0.9 - -/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" - item_color = "secred" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = ONESIZEFITSALL - siemens_coefficient = 0.9 - -/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" - item_color = "dispatch" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS - 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" - item_color = "redshirt2" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = ONESIZEFITSALL - siemens_coefficient = 0.9 - -/obj/item/clothing/under/rank/security/corp - icon_state = "sec_corporate" - item_state = "sec_corporate" - item_color = "sec_corporate" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/warden/corp - icon_state = "warden_corporate" - item_state = "warden_corporate" - item_color = "warden_corporate" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/tactical - name = "tactical jumpsuit" - desc = "It's made of a slightly sturdier material than standard jumpsuits, to allow for robust protection." - icon_state = "swatunder" - item_state = "swatunder" - item_color = "swatunder" - armor = list(melee = 10, bullet = 5, laser = 5,energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0.9 - -/obj/item/clothing/under/tactical/marinad - name = "marine jumpsuit" - desc = "Boots and Utes" - icon_state = "marinad" - item_state = "johnny" - item_color = "marinad" - armor = list(melee = 10, bullet = 5, laser = 5,energy = 0, bomb = 0, bio = 0, rad = 0) - 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" - item_color = "detective" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = ONESIZEFITSALL - siemens_coefficient = 0.9 - -/obj/item/clothing/under/det/black - icon_state = "detective2" - item_color = "detective2" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/det/slob - icon_state = "polsuit" - item_color = "polsuit" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/det/slob/verb/rollup() - set name = "Roll suit sleeves" - set category = "Object" - set src in usr - item_color = item_color == "polsuit" ? "polsuit_rolled" : "polsuit" - if (ishuman(loc)) - var/mob/living/carbon/human/H = loc - H.update_inv_w_uniform() - -/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 - body_parts_covered = 0 - -/obj/item/clothing/head/det_hat/black - icon_state = "detective2" - - -/* - * 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" - item_color = "hosred" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = ONESIZEFITSALL - siemens_coefficient = 0.8 - -/obj/item/clothing/under/rank/head_of_security/turtleneck - name = "head of security's turtleneck" - icon_state = "hos_turtleneck" - item_color = "hos_turtleneck" - item_state = "hos_turtleneck" - flags = 0 - -/obj/item/clothing/under/rank/head_of_security/corp - icon_state = "hos_corporate" - item_state = "hos_corporate" - item_color = "hos_corporate" - flags = ONESIZEFITSALL - -//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 = "jensen" - item_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 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS +/* + * 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" + item_color = "warden" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = ONESIZEFITSALL + siemens_coefficient = 0.9 + +/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" + item_color = "secred" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = ONESIZEFITSALL + siemens_coefficient = 0.9 + +/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" + item_color = "dispatch" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS + 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" + item_color = "redshirt2" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = ONESIZEFITSALL + siemens_coefficient = 0.9 + +/obj/item/clothing/under/rank/security/corp + icon_state = "sec_corporate" + item_state = "sec_corporate" + item_color = "sec_corporate" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/warden/corp + icon_state = "warden_corporate" + item_state = "warden_corporate" + item_color = "warden_corporate" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/tactical + name = "tactical jumpsuit" + desc = "It's made of a slightly sturdier material than standard jumpsuits, to allow for robust protection." + icon_state = "swatunder" + item_state = "swatunder" + item_color = "swatunder" + armor = list(melee = 10, bullet = 5, laser = 5,energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0.9 + +/obj/item/clothing/under/tactical/marinad + name = "marine jumpsuit" + desc = "Boots and Utes" + icon_state = "marinad" + item_state = "johnny" + item_color = "marinad" + armor = list(melee = 10, bullet = 5, laser = 5,energy = 0, bomb = 0, bio = 0, rad = 0) + 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" + item_color = "detective" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = ONESIZEFITSALL + siemens_coefficient = 0.9 + +/obj/item/clothing/under/det/black + icon_state = "detective2" + item_color = "detective2" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/det/slob + icon_state = "polsuit" + item_color = "polsuit" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/det/slob/verb/rollup() + set name = "Roll suit sleeves" + set category = "Object" + set src in usr + item_color = item_color == "polsuit" ? "polsuit_rolled" : "polsuit" + if (ishuman(loc)) + var/mob/living/carbon/human/H = loc + H.update_inv_w_uniform() + +/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 + body_parts_covered = 0 + +/obj/item/clothing/head/det_hat/black + icon_state = "detective2" + + +/* + * 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" + item_color = "hosred" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = ONESIZEFITSALL + siemens_coefficient = 0.8 + +/obj/item/clothing/under/rank/head_of_security/turtleneck + name = "head of security's turtleneck" + icon_state = "hos_turtleneck" + item_color = "hos_turtleneck" + item_state = "hos_turtleneck" + flags = 0 + +/obj/item/clothing/under/rank/head_of_security/corp + icon_state = "hos_corporate" + item_state = "hos_corporate" + item_color = "hos_corporate" + flags = ONESIZEFITSALL + +//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 = "jensen" + item_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 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index da50243f8c3d..71ec76311b23 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -1,751 +1,751 @@ -/obj/item/clothing/under/pj/red - name = "red pj's" - desc = "Sleepwear." - icon_state = "red_pyjamas" - item_color = "red_pyjamas" - item_state = "w_suit" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/pj/blue - name = "blue pj's" - desc = "Sleepwear." - icon_state = "blue_pyjamas" - item_color = "blue_pyjamas" - item_state = "w_suit" - flags = ONESIZEFITSALL - -/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" - item_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" - item_color = "scratch" - -/obj/item/clothing/under/sl_suit - desc = "It's a very amish looking suit." - name = "amish suit" - icon_state = "sl_suit" - item_color = "sl_suit" - -/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" - item_color = "waiter" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/tourist - name = "hawaiian shirt" - desc = "How gauche." - icon_state = "tourist" - item_state = "tourist" - item_color = "tourist" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/mailman - name = "mailman's jumpsuit" - desc = "'Special delivery!'" - icon_state = "mailman" - item_state = "b_suit" - item_color = "mailman" - -/obj/item/clothing/under/sexyclown - name = "sexy-clown suit" - desc = "It makes you look HONKable!" - icon_state = "sexyclown" - item_state = "sexyclown" - item_color = "sexyclown" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/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" - item_color = "vice" - flags = ONESIZEFITSALL - -/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" - item_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" - item_color = "centcom" - -/obj/item/clothing/under/ert - name = "ERT tactical uniform" - desc = "A short-sleeved black uniform, paired with grey digital-camo cargo pants. It looks very tactical." - icon_state = "ert_uniform" - item_state = "bl_suit" - item_color = "ert_uniform" - -/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" - item_color = "black" - w_class = 4//bulky item - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.02 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - 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" - item_color = "syndicate" - desc = "it's a cybernetically enhanced jumpsuit used for administrative duties." - gas_transfer_coefficient = 0.01 - permeability_coefficient = 0.01 - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - armor = list(melee = 100, bullet = 100, laser = 100,energy = 100, bomb = 100, bio = 100, rad = 100) - cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS - 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" - item_color = "owl" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/johnny - name = "johnny~~ jumpsuit" - desc = "Johnny~~" - icon_state = "johnny" - item_color = "johnny" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rainbow - name = "rainbow" - desc = "rainbow" - icon_state = "rainbow" - item_state = "rainbow" - item_color = "rainbow" - flags = ONESIZEFITSALL - -/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" - item_color = "psysuit" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - -/obj/item/clothing/under/gentlesuit - name = "gentlemans suit" - desc = "A silk black shirt with a white tie and a matching gray vest and slacks. Feels proper." - icon_state = "gentlesuit" - item_state = "gentlesuit" - item_color = "gentlesuit" - -/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" - item_color = "green_suit" - flags = ONESIZEFITSALL - -/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" - item_color = "teal_suit" - flags = ONESIZEFITSALL - -/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" - item_color = "black_suit" - -/obj/item/clothing/under/suit_jacket/reinforced //armored jackets for special agents - name = "black suit" - desc = "A black suit and red tie. Very formal. This one looks a bit stronger than others." - icon_state = "black_suit" - item_state = "bl_suit" - item_color = "black_suit" - body_parts_covered = UPPER_TORSO|ARMS - armor = list(melee = 18, bullet = 12, laser = 5, energy = 5, bomb = 0, bio = 0, rad = 0) - -/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" - item_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" - item_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" - item_color = "red_suit" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/suit_jacket/charcoal - name = "charcoal suit" - desc = "A charcoal suit and red tie. Very professional." - icon_state = "charcoal_suit" - item_state = "charcoal_suit" - item_color = "charcoal_suit" - -/obj/item/clothing/under/suit_jacket/navy - name = "navy suit" - desc = "A navy suit and red tie, intended for the station's finest." - icon_state = "navy_suit" - item_state = "navy_suit" - item_color = "navy_suit" - -/obj/item/clothing/under/suit_jacket/burgundy - name = "burgundy suit" - desc = "A burgundy suit and black tie. Somewhat formal." - icon_state = "burgundy_suit" - item_state = "burgundy_suit" - item_color = "burgundy_suit" - -/obj/item/clothing/under/suit_jacket/checkered - name = "checkered suit" - desc = "That's a very nice suit you have there. Shame if something were to happen to it, eh?" - icon_state = "checkered_suit" - item_state = "checkered_suit" - item_color = "checkered_suit" - -/obj/item/clothing/under/suit_jacket/tan - name = "tan suit" - desc = "A tan suit with a yellow tie. Smart, but casual." - icon_state = "tan_suit" - item_state = "tan_suit" - item_color = "tan_suit" - -/obj/item/clothing/under/suit_jacket/white - name = "white suit" - desc = "A white suit and jacket with a blue shirt. You wanna play rough? OKAY!." - icon_state = "white_suit" - item_state = "white_suit" - item_color = "white_suit" - -/obj/item/clothing/under/suit_jacket/rouge - name = "rogue jacket" - desc = "A suit and jacket with a jeans. For the bad guy!" - icon_state = "rogue_jacket" - item_state = "rogue_jacket" - item_color = "rogue_jacket" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/blackskirt - name = "black skirt" - desc = "A black skirt, very fancy!" - icon_state = "blackskirt" - item_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" - item_color = "schoolgirl" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/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" - item_color = "overalls" - -/obj/item/clothing/under/pirate - name = "pirate outfit" - desc = "Yarr." - icon_state = "pirate" - item_state = "pirate" - item_color = "pirate" - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS - -/obj/item/clothing/under/soviet - name = "soviet uniform" - desc = "For the Motherland!" - icon_state = "soviet" - item_state = "soviet" - item_color = "soviet" - -/obj/item/clothing/under/redcoat - name = "redcoat uniform" - desc = "Looks old." - icon_state = "redcoat" - item_state = "redcoat" - item_color = "redcoat" - -/obj/item/clothing/under/kilt - name = "kilt" - desc = "Includes shoes and plaid." - icon_state = "kilt" - item_state = "kilt" - item_color = "kilt" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/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" - item_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" - item_color = "gladiator" - body_parts_covered = LOWER_TORSO - -//dress -/obj/item/clothing/under/dress/ - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/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" - item_color = "dress_fire" - -/obj/item/clothing/under/dress/dress_green - name = "green dress" - desc = "A simple, tight fitting green dress." - icon_state = "dress_green" - item_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" - item_color = "dress_orange" - -/obj/item/clothing/under/dress/dress_pink - name = "pink dress" - desc = "A simple, tight fitting pink dress." - icon_state = "dress_pink" - item_color = "dress_pink" - -/obj/item/clothing/under/dress/dress_yellow - name = "yellow dress" - desc = "A flirty, little yellow dress." - icon_state = "dress_yellow" - item_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" - item_color = "dress_saloon" - -/obj/item/clothing/under/dress/dress_summer - name = "summer dress" - desc = "Ruffle your way through the season in this sweet, sunshine green dress." - icon_state = "dress_summer" - item_color = "dress_summer" - -/obj/item/clothing/under/dress/dress_vintage - name = "vintage dress" - desc = "Take a swan dive into vintage love, dames!" - icon_state = "dress_vintage" - item_color = "dress_vintage" - -/obj/item/clothing/under/dress/dress_evening - name = "elegant evening dress" - desc = "A stylish gown perfect for a wedding-guest dress, ball gown or your next formal celebration." - icon_state = "dress_evening" - item_color = "dress_evening" - -/obj/item/clothing/under/dress/dress_party - name = "party dress" - desc = "The party doesnt start til you walk in, so make an entrance no one can ignore." - icon_state = "dress_party" - item_color = "dress_party" - - -/obj/item/clothing/under/dress/dress_cap - name = "captain dress uniform" - desc = "Feminine fashion for the style concious captain." - icon_state = "dress_cap" - item_color = "dress_cap" - flags = ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/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" - item_color = "dress_hop" - flags = ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/under/dress/dress_hr - name = "human resources director uniform" - desc = "Superior class for the nosy H.R. Director." - icon_state = "huresource" - item_color = "huresource" - flags = ONESIZEFITSALL - body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - -/obj/item/clothing/under/dress/plaid_blue - name = "blue plaid skirt" - desc = "A preppy blue skirt with a white blouse." - icon_state = "plaid_blue" - item_color = "plaid_blue" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/dress/plaid_red - name = "red plaid skirt" - desc = "A preppy red skirt with a white blouse." - icon_state = "plaid_red" - item_color = "plaid_red" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/dress/plaid_purple - name = "blue purple skirt" - desc = "A preppy purple skirt with a white blouse." - icon_state = "plaid_purple" - item_color = "plaid_purple" - flags = ONESIZEFITSALL - -//wedding stuff -/obj/item/clothing/under/wedding/ - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS - -/obj/item/clothing/under/wedding/bride_orange - name = "orange wedding dress" - desc = "A big and puffy orange dress." - icon_state = "bride_orange" - item_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" - item_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" - item_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" - item_color = "bride_red" - flags_inv = HIDESHOES - -/obj/item/clothing/under/wedding/bride_white - name = "silky wedding dress" - desc = "A white wedding gown made from the finest silk." - icon_state = "bride_white" - item_color = "bride_white" - flags_inv = HIDESHOES - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/obj/item/clothing/under/sundress - name = "sundress" - desc = "Makes you want to frolic in a field of daisies." - icon_state = "sundress" - item_state = "sundress" - item_color = "sundress" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/obj/item/clothing/under/rank/mecha_operator - desc = "It's a slimming black with reinforced seams." - name = "pilot's jumpsuit" - icon_state = "robotics2" - item_state = "robotics" - item_color = "robotics2" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/cadet - desc = "" - name = "security cadet's uniform" - icon_state = "officertanclothes" - item_state = "r_suit" - item_color = "officertanclothes" - flags = ONESIZEFITSALL - -/obj/item/clothing/under/rank/forensic_technician - desc = "It has a Forensics rank stripe on it." - name = "forensics jumpsuit" - icon_state = "forensicsred" - item_state = "r_suit" - item_color = "forensicsred" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - flags = ONESIZEFITSALL - siemens_coefficient = 0.9 - -/obj/item/clothing/under/rank/cargo_fem - name = "quartermaster's dress" - desc = "It's a jumpsuit worn by the quartermaster. It's specially designed to prevent back injuries caused by pushing paper." - icon_state = "qm_f" - item_state = "lb_suit" - item_color = "qm_f" - -/obj/item/clothing/under/rank/head_of_security_fem - 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 dress" - icon_state = "hos_f" - item_state = "r_suit" - item_color = "hos_f" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0.8 - -/obj/item/clothing/under/rank/warden_fem - 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 dress" - icon_state = "warden_f" - item_state = "r_suit" - item_color = "warden_f" - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0.9 - -/obj/item/clothing/under/rank/roboticist_fem - desc = "It's a slimming black with reinforced seams; great for industrial work." - name = "roboticist's female jumpsuit" - icon_state = "roboticist_f" - item_state = "robo" - item_color = "roboticist_f" - -/obj/item/clothing/under/rank/hydroponics_fem - desc = "It's a jumpsuit designed to protect against minor plant-related hazards." - name = "botanist's female jumpsuit" - icon_state = "hydroponics_f" - item_state = "g_suit" - item_color = "hydroponics_f" - permeability_coefficient = 0.50 - -/obj/item/clothing/under/rank/bartender_fem - desc = "It looks like it could use some more flair." - name = "bartender's female uniform" - icon_state = "bar_f" - item_state = "ba_suit" - item_color = "bar_f" - -/obj/item/clothing/under/kimono - name = "kimono" - icon_state = "kimono" - item_state = "kimono" - item_color = "kimono" - body_parts_covered = UPPER_TORSO|LOWER_TORSO - -/obj/item/clothing/under/blacktango - name = "black tango dress" - desc = "Filled with latin fire." - icon_state = "tango" - item_state = "wcoat" - item_color = "tango" - -/obj/item/clothing/under/rank/centcom_officer_old - desc = "It's a jumpsuit worn by Centcom Officers." - name = "\improper Centcom officer's jumpsuit" - icon_state = "officer_old" - item_state = "g_suit" - item_color = "officer_old" - -/obj/item/clothing/under/rank/centcom_commander_old - desc = "It's a jumpsuit worn by Centcom's highest-tier Commanders." - name = "\improper Centcom officer's jumpsuit" - icon_state = "centcom_old" - item_state = "dg_suit" - item_color = "centcom_old" - -//Mafia -/obj/item/clothing/under/mafia - name = "mafia outfit" - desc = "The business of the mafia is business." - icon_state = "mafia" - item_state = "mafia" - item_color = "mafia" - -/obj/item/clothing/under/mafia/vest - name = "mafia vest" - desc = "Extreme problems often require extreme solutions." - icon_state = "mafia_vest" - item_state = "mafia_vest" - item_color = "mafia_vest" - -/obj/item/clothing/under/mafia/white - name = "white mafia outfit" - desc = "The best defense against the treacherous is treachery." - icon_state = "mafia_white" - item_state = "mafia_white" - item_color = "mafia_white" - -/obj/item/clothing/under/mafia/sue - name = "mafia vest" - desc = "The business is born into." - icon_state = "sue_vest" - item_state = "sue_vest" - item_color = "sue_vest" - -/obj/item/clothing/under/mafia/tan - name = "leather mafia outfit" - desc = "The big drum sounds good only from a distance." - icon_state = "mafia_tan" - item_state = "mafia_tan" - item_color = "mafia_tan" - -/obj/item/clothing/under/mafia/flappers - name = "flappers" - desc = "Nothing like the roaring 20s, flapping the night away on the dance floor." - icon_state = "flapper" - item_state = "flapper" - item_color = "flapper" - -/obj/item/clothing/under/det/max_payne - icon_state = "max" - item_color = "max" - -/obj/item/clothing/under/rank/capcamsole - desc = "It's a blue feminine camisole with some gold markings denoting the rank of \"Captain\" and gold aquila on it." - name = "captain's camisole" - icon_state = "capcamisole" - item_state = "capcamisole" - item_color = "capcamisole" - -/obj/item/clothing/under/rank/goodman_shirt - name = "head of personnel's suit" - desc = "A good suit for good men." - icon_state = "gmshirt" - item_state = "gmshirt" - item_color = "gmshirt" - -/obj/item/clothing/under/rank/centcom/representative - desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Ensign\" and bears \"N.C.V. Fearless CV-286\" on the left shounder." - name = "\improper NanoTrasen navy uniform" - icon_state = "officer" - item_state = "g_suit" - item_color = "officer" - displays_id = 0 - -/obj/item/clothing/under/rank/centcom/officer - desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant Commander\" and bears \"N.C.V. Fearless CV-286\" on the left shounder." - name = "\improper NanoTrasen officers uniform" - icon_state = "officer" - item_state = "g_suit" - item_color = "officer" - displays_id = 0 - -/obj/item/clothing/under/rank/centcom/captain - desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Captain\" and bears \"N.C.V. Fearless CV-286\" on the left shounder." - name = "\improper NanoTrasen captains uniform" - icon_state = "centcom" - item_state = "dg_suit" - item_color = "centcom" - displays_id = 0 - -/obj/item/clothing/under/roman - name = "roman armor" - desc = "Ancient Roman armor. Made of metallic and leather straps." - icon_state = "roman" - item_state = "roman" - item_color = "roman" - -/obj/item/clothing/under/patient_gown - name = "patient gown" - desc = "A long loose piece of clothing worn in a hospital by someone doing or having an operation. It can be used as clothing for bedridden patients." - icon_state = "patient_gown" - item_color = "patient_gown" - -/obj/item/clothing/under/pretty_dress - name = "pretty dress" - desc = "An Enchanting blue dress." - icon_state = "pretty_dress" - item_color = "pretty_dress" - -/obj/item/clothing/under/sukeban_pants - name = "sukeban pants" - desc = "A white shirt with wide baggy pants" - icon_state = "sukeban_pants" - item_color = "sukeban_pants" - -/obj/item/clothing/under/sukeban_dress - name = "sukeban dress" - desc = "A Dress of Japanese schoolgirls" - icon_state = "sukeban_dress" - item_color = "sukeban_dress" - -/obj/item/clothing/under/karate - name = "karate underwear" - icon_state = "karate" - item_color = "karate" - -/obj/item/clothing/under/smoking - name = "smoking" - icon_state = "smoking_new" - item_color = "smoking_new" - -/obj/item/clothing/under/popking - name = "popking suit" - desc = "Classic costume of the King of Pop. A great choice if you want to twist again, watching Pretty Woman." - icon_state = "popking" - item_color = "popking" - -/obj/item/clothing/under/popking/alternate - icon_state = "popking2" - item_color = "popking2" - -/obj/item/clothing/under/pinkpolo - name = "pink polo" - desc = "The classic image of an American gangster 80. Hello from Miami." - icon_state = "pinkpolo" - item_color = "pinkpolo" - -/obj/item/clothing/under/bathrobe - name = "bath robe" - icon_state = "bathrobe" - item_color = "bathrobe" - -/obj/item/clothing/under/bathtowel - name = "bath towel" - icon_state = "bathtowel" - item_color = "bathtowel" - slot_flags = SLOT_HEAD | SLOT_ICLOTHING - -/obj/item/clothing/under/bathtowel/equipped(mob/living/carbon/human/user, slot) - ..() - if(slot == slot_w_uniform) - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - else if(slot == slot_head) - body_parts_covered = HEAD - +/obj/item/clothing/under/pj/red + name = "red pj's" + desc = "Sleepwear." + icon_state = "red_pyjamas" + item_color = "red_pyjamas" + item_state = "w_suit" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/pj/blue + name = "blue pj's" + desc = "Sleepwear." + icon_state = "blue_pyjamas" + item_color = "blue_pyjamas" + item_state = "w_suit" + flags = ONESIZEFITSALL + +/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" + item_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" + item_color = "scratch" + +/obj/item/clothing/under/sl_suit + desc = "It's a very amish looking suit." + name = "amish suit" + icon_state = "sl_suit" + item_color = "sl_suit" + +/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" + item_color = "waiter" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/tourist + name = "hawaiian shirt" + desc = "How gauche." + icon_state = "tourist" + item_state = "tourist" + item_color = "tourist" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/mailman + name = "mailman's jumpsuit" + desc = "'Special delivery!'" + icon_state = "mailman" + item_state = "b_suit" + item_color = "mailman" + +/obj/item/clothing/under/sexyclown + name = "sexy-clown suit" + desc = "It makes you look HONKable!" + icon_state = "sexyclown" + item_state = "sexyclown" + item_color = "sexyclown" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/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" + item_color = "vice" + flags = ONESIZEFITSALL + +/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" + item_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" + item_color = "centcom" + +/obj/item/clothing/under/ert + name = "ERT tactical uniform" + desc = "A short-sleeved black uniform, paired with grey digital-camo cargo pants. It looks very tactical." + icon_state = "ert_uniform" + item_state = "bl_suit" + item_color = "ert_uniform" + +/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" + item_color = "black" + w_class = 4//bulky item + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.02 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + 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" + item_color = "syndicate" + desc = "it's a cybernetically enhanced jumpsuit used for administrative duties." + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + armor = list(melee = 100, bullet = 100, laser = 100,energy = 100, bomb = 100, bio = 100, rad = 100) + cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | ARMS + 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" + item_color = "owl" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/johnny + name = "johnny~~ jumpsuit" + desc = "Johnny~~" + icon_state = "johnny" + item_color = "johnny" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rainbow + name = "rainbow" + desc = "rainbow" + icon_state = "rainbow" + item_state = "rainbow" + item_color = "rainbow" + flags = ONESIZEFITSALL + +/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" + item_color = "psysuit" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + +/obj/item/clothing/under/gentlesuit + name = "gentlemans suit" + desc = "A silk black shirt with a white tie and a matching gray vest and slacks. Feels proper." + icon_state = "gentlesuit" + item_state = "gentlesuit" + item_color = "gentlesuit" + +/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" + item_color = "green_suit" + flags = ONESIZEFITSALL + +/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" + item_color = "teal_suit" + flags = ONESIZEFITSALL + +/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" + item_color = "black_suit" + +/obj/item/clothing/under/suit_jacket/reinforced //armored jackets for special agents + name = "black suit" + desc = "A black suit and red tie. Very formal. This one looks a bit stronger than others." + icon_state = "black_suit" + item_state = "bl_suit" + item_color = "black_suit" + body_parts_covered = UPPER_TORSO|ARMS + armor = list(melee = 18, bullet = 12, laser = 5, energy = 5, bomb = 0, bio = 0, rad = 0) + +/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" + item_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" + item_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" + item_color = "red_suit" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/suit_jacket/charcoal + name = "charcoal suit" + desc = "A charcoal suit and red tie. Very professional." + icon_state = "charcoal_suit" + item_state = "charcoal_suit" + item_color = "charcoal_suit" + +/obj/item/clothing/under/suit_jacket/navy + name = "navy suit" + desc = "A navy suit and red tie, intended for the station's finest." + icon_state = "navy_suit" + item_state = "navy_suit" + item_color = "navy_suit" + +/obj/item/clothing/under/suit_jacket/burgundy + name = "burgundy suit" + desc = "A burgundy suit and black tie. Somewhat formal." + icon_state = "burgundy_suit" + item_state = "burgundy_suit" + item_color = "burgundy_suit" + +/obj/item/clothing/under/suit_jacket/checkered + name = "checkered suit" + desc = "That's a very nice suit you have there. Shame if something were to happen to it, eh?" + icon_state = "checkered_suit" + item_state = "checkered_suit" + item_color = "checkered_suit" + +/obj/item/clothing/under/suit_jacket/tan + name = "tan suit" + desc = "A tan suit with a yellow tie. Smart, but casual." + icon_state = "tan_suit" + item_state = "tan_suit" + item_color = "tan_suit" + +/obj/item/clothing/under/suit_jacket/white + name = "white suit" + desc = "A white suit and jacket with a blue shirt. You wanna play rough? OKAY!." + icon_state = "white_suit" + item_state = "white_suit" + item_color = "white_suit" + +/obj/item/clothing/under/suit_jacket/rouge + name = "rogue jacket" + desc = "A suit and jacket with a jeans. For the bad guy!" + icon_state = "rogue_jacket" + item_state = "rogue_jacket" + item_color = "rogue_jacket" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/blackskirt + name = "black skirt" + desc = "A black skirt, very fancy!" + icon_state = "blackskirt" + item_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" + item_color = "schoolgirl" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/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" + item_color = "overalls" + +/obj/item/clothing/under/pirate + name = "pirate outfit" + desc = "Yarr." + icon_state = "pirate" + item_state = "pirate" + item_color = "pirate" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS + +/obj/item/clothing/under/soviet + name = "soviet uniform" + desc = "For the Motherland!" + icon_state = "soviet" + item_state = "soviet" + item_color = "soviet" + +/obj/item/clothing/under/redcoat + name = "redcoat uniform" + desc = "Looks old." + icon_state = "redcoat" + item_state = "redcoat" + item_color = "redcoat" + +/obj/item/clothing/under/kilt + name = "kilt" + desc = "Includes shoes and plaid." + icon_state = "kilt" + item_state = "kilt" + item_color = "kilt" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/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" + item_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" + item_color = "gladiator" + body_parts_covered = LOWER_TORSO + +//dress +/obj/item/clothing/under/dress/ + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/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" + item_color = "dress_fire" + +/obj/item/clothing/under/dress/dress_green + name = "green dress" + desc = "A simple, tight fitting green dress." + icon_state = "dress_green" + item_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" + item_color = "dress_orange" + +/obj/item/clothing/under/dress/dress_pink + name = "pink dress" + desc = "A simple, tight fitting pink dress." + icon_state = "dress_pink" + item_color = "dress_pink" + +/obj/item/clothing/under/dress/dress_yellow + name = "yellow dress" + desc = "A flirty, little yellow dress." + icon_state = "dress_yellow" + item_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" + item_color = "dress_saloon" + +/obj/item/clothing/under/dress/dress_summer + name = "summer dress" + desc = "Ruffle your way through the season in this sweet, sunshine green dress." + icon_state = "dress_summer" + item_color = "dress_summer" + +/obj/item/clothing/under/dress/dress_vintage + name = "vintage dress" + desc = "Take a swan dive into vintage love, dames!" + icon_state = "dress_vintage" + item_color = "dress_vintage" + +/obj/item/clothing/under/dress/dress_evening + name = "elegant evening dress" + desc = "A stylish gown perfect for a wedding-guest dress, ball gown or your next formal celebration." + icon_state = "dress_evening" + item_color = "dress_evening" + +/obj/item/clothing/under/dress/dress_party + name = "party dress" + desc = "The party doesnt start til you walk in, so make an entrance no one can ignore." + icon_state = "dress_party" + item_color = "dress_party" + + +/obj/item/clothing/under/dress/dress_cap + name = "captain dress uniform" + desc = "Feminine fashion for the style concious captain." + icon_state = "dress_cap" + item_color = "dress_cap" + flags = ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/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" + item_color = "dress_hop" + flags = ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/under/dress/dress_hr + name = "human resources director uniform" + desc = "Superior class for the nosy H.R. Director." + icon_state = "huresource" + item_color = "huresource" + flags = ONESIZEFITSALL + body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS + +/obj/item/clothing/under/dress/plaid_blue + name = "blue plaid skirt" + desc = "A preppy blue skirt with a white blouse." + icon_state = "plaid_blue" + item_color = "plaid_blue" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/dress/plaid_red + name = "red plaid skirt" + desc = "A preppy red skirt with a white blouse." + icon_state = "plaid_red" + item_color = "plaid_red" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/dress/plaid_purple + name = "blue purple skirt" + desc = "A preppy purple skirt with a white blouse." + icon_state = "plaid_purple" + item_color = "plaid_purple" + flags = ONESIZEFITSALL + +//wedding stuff +/obj/item/clothing/under/wedding/ + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS + +/obj/item/clothing/under/wedding/bride_orange + name = "orange wedding dress" + desc = "A big and puffy orange dress." + icon_state = "bride_orange" + item_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" + item_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" + item_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" + item_color = "bride_red" + flags_inv = HIDESHOES + +/obj/item/clothing/under/wedding/bride_white + name = "silky wedding dress" + desc = "A white wedding gown made from the finest silk." + icon_state = "bride_white" + item_color = "bride_white" + flags_inv = HIDESHOES + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/obj/item/clothing/under/sundress + name = "sundress" + desc = "Makes you want to frolic in a field of daisies." + icon_state = "sundress" + item_state = "sundress" + item_color = "sundress" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/obj/item/clothing/under/rank/mecha_operator + desc = "It's a slimming black with reinforced seams." + name = "pilot's jumpsuit" + icon_state = "robotics2" + item_state = "robotics" + item_color = "robotics2" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/cadet + desc = "" + name = "security cadet's uniform" + icon_state = "officertanclothes" + item_state = "r_suit" + item_color = "officertanclothes" + flags = ONESIZEFITSALL + +/obj/item/clothing/under/rank/forensic_technician + desc = "It has a Forensics rank stripe on it." + name = "forensics jumpsuit" + icon_state = "forensicsred" + item_state = "r_suit" + item_color = "forensicsred" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + flags = ONESIZEFITSALL + siemens_coefficient = 0.9 + +/obj/item/clothing/under/rank/cargo_fem + name = "quartermaster's dress" + desc = "It's a jumpsuit worn by the quartermaster. It's specially designed to prevent back injuries caused by pushing paper." + icon_state = "qm_f" + item_state = "lb_suit" + item_color = "qm_f" + +/obj/item/clothing/under/rank/head_of_security_fem + 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 dress" + icon_state = "hos_f" + item_state = "r_suit" + item_color = "hos_f" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0.8 + +/obj/item/clothing/under/rank/warden_fem + 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 dress" + icon_state = "warden_f" + item_state = "r_suit" + item_color = "warden_f" + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0.9 + +/obj/item/clothing/under/rank/roboticist_fem + desc = "It's a slimming black with reinforced seams; great for industrial work." + name = "roboticist's female jumpsuit" + icon_state = "roboticist_f" + item_state = "robo" + item_color = "roboticist_f" + +/obj/item/clothing/under/rank/hydroponics_fem + desc = "It's a jumpsuit designed to protect against minor plant-related hazards." + name = "botanist's female jumpsuit" + icon_state = "hydroponics_f" + item_state = "g_suit" + item_color = "hydroponics_f" + permeability_coefficient = 0.50 + +/obj/item/clothing/under/rank/bartender_fem + desc = "It looks like it could use some more flair." + name = "bartender's female uniform" + icon_state = "bar_f" + item_state = "ba_suit" + item_color = "bar_f" + +/obj/item/clothing/under/kimono + name = "kimono" + icon_state = "kimono" + item_state = "kimono" + item_color = "kimono" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + +/obj/item/clothing/under/blacktango + name = "black tango dress" + desc = "Filled with latin fire." + icon_state = "tango" + item_state = "wcoat" + item_color = "tango" + +/obj/item/clothing/under/rank/centcom_officer_old + desc = "It's a jumpsuit worn by Centcom Officers." + name = "\improper Centcom officer's jumpsuit" + icon_state = "officer_old" + item_state = "g_suit" + item_color = "officer_old" + +/obj/item/clothing/under/rank/centcom_commander_old + desc = "It's a jumpsuit worn by Centcom's highest-tier Commanders." + name = "\improper Centcom officer's jumpsuit" + icon_state = "centcom_old" + item_state = "dg_suit" + item_color = "centcom_old" + +//Mafia +/obj/item/clothing/under/mafia + name = "mafia outfit" + desc = "The business of the mafia is business." + icon_state = "mafia" + item_state = "mafia" + item_color = "mafia" + +/obj/item/clothing/under/mafia/vest + name = "mafia vest" + desc = "Extreme problems often require extreme solutions." + icon_state = "mafia_vest" + item_state = "mafia_vest" + item_color = "mafia_vest" + +/obj/item/clothing/under/mafia/white + name = "white mafia outfit" + desc = "The best defense against the treacherous is treachery." + icon_state = "mafia_white" + item_state = "mafia_white" + item_color = "mafia_white" + +/obj/item/clothing/under/mafia/sue + name = "mafia vest" + desc = "The business is born into." + icon_state = "sue_vest" + item_state = "sue_vest" + item_color = "sue_vest" + +/obj/item/clothing/under/mafia/tan + name = "leather mafia outfit" + desc = "The big drum sounds good only from a distance." + icon_state = "mafia_tan" + item_state = "mafia_tan" + item_color = "mafia_tan" + +/obj/item/clothing/under/mafia/flappers + name = "flappers" + desc = "Nothing like the roaring 20s, flapping the night away on the dance floor." + icon_state = "flapper" + item_state = "flapper" + item_color = "flapper" + +/obj/item/clothing/under/det/max_payne + icon_state = "max" + item_color = "max" + +/obj/item/clothing/under/rank/capcamsole + desc = "It's a blue feminine camisole with some gold markings denoting the rank of \"Captain\" and gold aquila on it." + name = "captain's camisole" + icon_state = "capcamisole" + item_state = "capcamisole" + item_color = "capcamisole" + +/obj/item/clothing/under/rank/goodman_shirt + name = "head of personnel's suit" + desc = "A good suit for good men." + icon_state = "gmshirt" + item_state = "gmshirt" + item_color = "gmshirt" + +/obj/item/clothing/under/rank/centcom/representative + desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Ensign\" and bears \"N.C.V. Fearless CV-286\" on the left shounder." + name = "\improper NanoTrasen navy uniform" + icon_state = "officer" + item_state = "g_suit" + item_color = "officer" + displays_id = 0 + +/obj/item/clothing/under/rank/centcom/officer + desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant Commander\" and bears \"N.C.V. Fearless CV-286\" on the left shounder." + name = "\improper NanoTrasen officers uniform" + icon_state = "officer" + item_state = "g_suit" + item_color = "officer" + displays_id = 0 + +/obj/item/clothing/under/rank/centcom/captain + desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Captain\" and bears \"N.C.V. Fearless CV-286\" on the left shounder." + name = "\improper NanoTrasen captains uniform" + icon_state = "centcom" + item_state = "dg_suit" + item_color = "centcom" + displays_id = 0 + +/obj/item/clothing/under/roman + name = "roman armor" + desc = "Ancient Roman armor. Made of metallic and leather straps." + icon_state = "roman" + item_state = "roman" + item_color = "roman" + +/obj/item/clothing/under/patient_gown + name = "patient gown" + desc = "A long loose piece of clothing worn in a hospital by someone doing or having an operation. It can be used as clothing for bedridden patients." + icon_state = "patient_gown" + item_color = "patient_gown" + +/obj/item/clothing/under/pretty_dress + name = "pretty dress" + desc = "An Enchanting blue dress." + icon_state = "pretty_dress" + item_color = "pretty_dress" + +/obj/item/clothing/under/sukeban_pants + name = "sukeban pants" + desc = "A white shirt with wide baggy pants" + icon_state = "sukeban_pants" + item_color = "sukeban_pants" + +/obj/item/clothing/under/sukeban_dress + name = "sukeban dress" + desc = "A Dress of Japanese schoolgirls" + icon_state = "sukeban_dress" + item_color = "sukeban_dress" + +/obj/item/clothing/under/karate + name = "karate underwear" + icon_state = "karate" + item_color = "karate" + +/obj/item/clothing/under/smoking + name = "smoking" + icon_state = "smoking_new" + item_color = "smoking_new" + +/obj/item/clothing/under/popking + name = "popking suit" + desc = "Classic costume of the King of Pop. A great choice if you want to twist again, watching Pretty Woman." + icon_state = "popking" + item_color = "popking" + +/obj/item/clothing/under/popking/alternate + icon_state = "popking2" + item_color = "popking2" + +/obj/item/clothing/under/pinkpolo + name = "pink polo" + desc = "The classic image of an American gangster 80. Hello from Miami." + icon_state = "pinkpolo" + item_color = "pinkpolo" + +/obj/item/clothing/under/bathrobe + name = "bath robe" + icon_state = "bathrobe" + item_color = "bathrobe" + +/obj/item/clothing/under/bathtowel + name = "bath towel" + icon_state = "bathtowel" + item_color = "bathtowel" + slot_flags = SLOT_HEAD | SLOT_ICLOTHING + +/obj/item/clothing/under/bathtowel/equipped(mob/living/carbon/human/user, slot) + ..() + if(slot == slot_w_uniform) + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + else if(slot == slot_head) + body_parts_covered = HEAD + diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm index 9f163b44603c..b2a1d7ee332f 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 = ONESIZEFITSALL - body_parts_covered = LOWER_TORSO - -/obj/item/clothing/under/shorts/red - icon_state = "redshorts" - item_color = "redshorts" - -/obj/item/clothing/under/shorts/green - icon_state = "greenshorts" - item_color = "greenshorts" - -/obj/item/clothing/under/shorts/blue - icon_state = "blueshorts" - item_color = "blueshorts" - -/obj/item/clothing/under/shorts/black - icon_state = "blackshorts" - item_color = "blackshorts" - -/obj/item/clothing/under/shorts/grey - icon_state = "greyshorts" - item_color = "greyshorts" +/obj/item/clothing/under/shorts + name = "athletic shorts" + desc = "95% Polyester, 5% Spandex!" + gender = PLURAL + flags = ONESIZEFITSALL + body_parts_covered = LOWER_TORSO + +/obj/item/clothing/under/shorts/red + icon_state = "redshorts" + item_color = "redshorts" + +/obj/item/clothing/under/shorts/green + icon_state = "greenshorts" + item_color = "greenshorts" + +/obj/item/clothing/under/shorts/blue + icon_state = "blueshorts" + item_color = "blueshorts" + +/obj/item/clothing/under/shorts/black + icon_state = "blackshorts" + item_color = "blackshorts" + +/obj/item/clothing/under/shorts/grey + icon_state = "greyshorts" + item_color = "greyshorts" diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm index c9e2a4a0fe9a..8dd08ee3f52f 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" - item_color = "syndicate" - has_sensor = 0 - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) - siemens_coefficient = 0.9 - flags = ONESIZEFITSALL - -/obj/item/clothing/under/syndicate/equipped(mob/M) - if(M.gender == "male") - item_color = "syndicate" - else - item_color = "syndicate_f" - return ..() - -/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" - item_color = "tactifool" +/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" + item_color = "syndicate" + has_sensor = 0 + armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + siemens_coefficient = 0.9 + flags = ONESIZEFITSALL + +/obj/item/clothing/under/syndicate/equipped(mob/M) + if(M.gender == "male") + item_color = "syndicate" + else + item_color = "syndicate_f" + return ..() + +/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" + item_color = "tactifool" siemens_coefficient = 1 \ No newline at end of file diff --git a/code/modules/clothing/under/ties.dm b/code/modules/clothing/under/ties.dm index 20f240e93c2a..9d833e8c2d6a 100644 --- a/code/modules/clothing/under/ties.dm +++ b/code/modules/clothing/under/ties.dm @@ -1,474 +1,474 @@ -/obj/item/clothing/tie - name = "tie" - desc = "A neosilk clip-on tie." - icon = 'icons/obj/clothing/ties.dmi' - icon_state = "bluetie" - item_state = "" //no inhands - item_color = "bluetie" - slot_flags = 0 - w_class = 2.0 - var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to - var/image/inv_overlay = null //overlay used when attached to clothing. - -/obj/item/clothing/tie/atom_init() - . = ..() - inv_overlay = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[item_color? "[item_color]" : "[icon_state]"]") - -//when user attached an accessory to S -/obj/item/clothing/tie/proc/on_attached(obj/item/clothing/under/S, mob/user) - if(!istype(S)) - return - has_suit = S - loc = has_suit - has_suit.overlays += inv_overlay - - to_chat(user, "You attach [src] to [has_suit].") - src.add_fingerprint(user) - -/obj/item/clothing/tie/proc/on_removed(mob/user) - if(!has_suit) - return - has_suit.overlays -= inv_overlay - has_suit = null - usr.put_in_hands(src) - src.add_fingerprint(user) - -//default attackby behaviour -/obj/item/clothing/tie/attackby(obj/item/I, mob/user) - ..() - -//default attack_hand behaviour -/obj/item/clothing/tie/attack_hand(mob/user) - if(has_suit) - has_suit.remove_accessory(user) - return //we aren't an object on the ground so don't call parent - ..() - -/obj/item/clothing/tie/blue - name = "blue tie" - icon_state = "bluetie" - item_color = "bluetie" - -/obj/item/clothing/tie/red - name = "red tie" - icon_state = "redtie" - item_color = "redtie" - -/obj/item/clothing/tie/horrible - name = "horrible tie" - desc = "A neosilk clip-on tie. This one is disgusting." - icon_state = "horribletie" - item_color = "horribletie" - -/obj/item/clothing/tie/stethoscope - name = "stethoscope" - desc = "An outdated medical apparatus for listening to the sounds of the human body. It also makes you look like you know what you're doing." - icon_state = "stethoscope" - item_color = "stethoscope" - -/obj/item/clothing/tie/stethoscope/attack(mob/living/carbon/human/M, mob/living/user, def_zone) - if(ishuman(M) && isliving(user)) - if(user.a_intent == "help") - var/target_zone = parse_zone(def_zone) - if(target_zone) - var/their = "their" - switch(M.gender) - if(MALE) their = "his" - if(FEMALE) their = "her" - - var/sound = "pulse" - var/sound_strength - - if(M.stat == DEAD || (M.status_flags & FAKEDEATH)) - sound_strength = "cannot hear" - sound = "anything" - else - sound_strength = "hear a weak" - switch(target_zone) - if(BP_CHEST) - if(M.oxyloss < 50) - sound_strength = "hear a healthy" - sound = "pulse and respiration" - if(O_EYES, O_MOUTH) - sound_strength = "cannot hear" - sound = "anything" - else - sound_strength = "hear a weak" - - user.visible_message("[user] places [src] against [M]'s [target_zone] and listens attentively.", "You place [src] against [their] [target_zone]. You [sound_strength] [sound].") - return - return ..(M,user) - - -//Medals -/obj/item/clothing/tie/medal - name = "bronze medal" - desc = "A bronze medal." - icon_state = "bronze" - item_color = "bronze" - -/obj/item/clothing/tie/medal/conduct - name = "distinguished conduct medal" - desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew." - -/obj/item/clothing/tie/medal/bronze_heart - name = "bronze heart medal" - desc = "A bronze heart-shaped medal awarded for sacrifice. It is often awarded posthumously or for severe injury in the line of duty." - icon_state = "bronze_heart" - -/obj/item/clothing/tie/medal/nobel_science - name = "nobel sciences award" - desc = "A bronze medal which represents significant contributions to the field of science or engineering." - -/obj/item/clothing/tie/medal/silver - name = "silver medal" - desc = "A silver medal." - icon_state = "silver" - item_color = "silver" - -/obj/item/clothing/tie/medal/silver/valor - name = "medal of valor" - desc = "A silver medal awarded for acts of exceptional valor." - -/obj/item/clothing/tie/medal/silver/security - name = "robust security award" - desc = "An award for distinguished combat and sacrifice in defence of Nanotrasen's commercial interests. Often awarded to security staff." - -/obj/item/clothing/tie/medal/gold - name = "gold medal" - desc = "A prestigious golden medal." - icon_state = "gold" - item_color = "gold" - -/obj/item/clothing/tie/medal/gold/captain - name = "medal of captaincy" - desc = "A golden medal awarded exclusively to those promoted to the rank of captain. It signifies the codified responsibilities of a captain to Nanotrasen, and their undisputable authority over their crew." - icon_state = "gold_nt" - -/obj/item/clothing/tie/medal/gold/heroism - name = "medal of exceptional heroism" - desc = "An extremely rare golden medal awarded only by CentComm. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but commanders." - -//Armbands -/obj/item/clothing/tie/armband - name = "red armband" - desc = "A fancy red armband!" - icon_state = "red" - item_color = "red" - -/obj/item/clothing/tie/armband/cargo - name = "cargo bay guard armband" - desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is brown." - icon_state = "cargo" - item_color = "cargo" - -/obj/item/clothing/tie/armband/engine - name = "engineering guard armband" - desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is orange with a reflective strip!" - icon_state = "engie" - item_color = "engie" - -/obj/item/clothing/tie/armband/science - name = "science guard armband" - desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is purple." - icon_state = "rnd" - item_color = "rnd" - -/obj/item/clothing/tie/armband/hydro - name = "hydroponics guard armband" - desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is green and blue." - icon_state = "hydro" - item_color = "hydro" - -/obj/item/clothing/tie/armband/med - name = "medical guard armband" - desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is white." - icon_state = "med" - item_color = "med" - -/obj/item/clothing/tie/armband/medgreen - name = "medical guard armband" - desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is white and green." - icon_state = "medgreen" - item_color = "medgreen" - -//holsters -/obj/item/clothing/tie/holster - name = "shoulder holster" - desc = "A handgun holster." - icon_state = "holster" - item_color = "holster" - var/obj/item/weapon/gun/holstered = null - -//subtypes can override this to specify what can be holstered -/obj/item/clothing/tie/holster/proc/can_holster(obj/item/weapon/gun/W) - return W.isHandgun() - -/obj/item/clothing/tie/holster/proc/holster(obj/item/I, mob/user) - if(holstered) - to_chat(user, "\red There is already a [holstered] holstered here!") - return - - if (!istype(I, /obj/item/weapon/gun)) - to_chat(user, "\red Only guns can be holstered!") - return - - var/obj/item/weapon/gun/W = I - if (!can_holster(W)) - to_chat(user, "\red This [W] won't fit in the [src]!") - return - - holstered = W - user.drop_from_inventory(holstered) - holstered.loc = src - holstered.add_fingerprint(user) - user.visible_message("\blue [user] holsters the [holstered].", "You holster the [holstered].") - -/obj/item/clothing/tie/holster/proc/unholster(mob/user) - if(!holstered) - return - - if(istype(user.get_active_hand(),/obj) && istype(user.get_inactive_hand(),/obj)) - to_chat(user, "\red You need an empty hand to draw the [holstered]!") - else - if(user.a_intent == "hurt") - usr.visible_message("\red [user] draws the [holstered], ready to shoot!", \ - "\red You draw the [holstered], ready to shoot!") - else - user.visible_message("\blue [user] draws the [holstered], pointing it at the ground.", \ - "\blue You draw the [holstered], pointing it at the ground.") - user.put_in_hands(holstered) - holstered.add_fingerprint(user) - holstered = null - -/obj/item/clothing/tie/holster/attack_hand(mob/user) - if (has_suit) //if we are part of a suit - if (holstered) - unholster(user) - return - - ..(user) - -/obj/item/clothing/tie/holster/attackby(obj/item/W, mob/user) - holster(W, user) - -/obj/item/clothing/tie/holster/emp_act(severity) - if (holstered) - holstered.emp_act(severity) - ..() - -/obj/item/clothing/tie/holster/examine(mob/user) - ..() - if (holstered) - to_chat(user, "A [holstered] is holstered here.") - else - to_chat(user, "It is empty.") - -/obj/item/clothing/tie/holster/on_attached(obj/item/clothing/under/S, mob/user) - ..() - has_suit.verbs += /obj/item/clothing/tie/holster/verb/holster_verb - -/obj/item/clothing/tie/holster/on_removed(mob/user) - has_suit.verbs -= /obj/item/clothing/tie/holster/verb/holster_verb - ..() - -//For the holster hotkey -/obj/item/clothing/tie/holster/verb/holster_verb() - set name = "Holster" - set category = "Object" - set src in usr - if(!istype(usr, /mob/living)) return - if(usr.stat) return - - var/obj/item/clothing/tie/holster/H = null - if (istype(src, /obj/item/clothing/tie/holster)) - H = src - else if (istype(src, /obj/item/clothing/under)) - var/obj/item/clothing/under/S = src - if (S.hastie) - H = S.hastie - - if (!H) - to_chat(usr, "/red Something is very wrong.") - - if(!H.holstered) - if(!istype(usr.get_active_hand(), /obj/item/weapon/gun)) - to_chat(usr, "\blue You need your gun equiped to holster it.") - return - var/obj/item/weapon/gun/W = usr.get_active_hand() - H.holster(W, usr) - else - H.unholster(usr) - -/obj/item/clothing/tie/holster/armpit - name = "shoulder holster" - desc = "A worn-out handgun holster. Perfect for concealed carry." - icon_state = "holster" - item_color = "holster" - -/obj/item/clothing/tie/holster/waist - name = "shoulder holster" - desc = "A handgun holster. Made of expensive leather." - icon_state = "holster" - item_color = "holster_low" - -/obj/item/clothing/tie/storage - name = "load bearing equipment" - desc = "Used to hold things when you don't have enough hands." - icon_state = "webbing" - item_color = "webbing" - var/slots = 3 - var/obj/item/weapon/storage/internal/hold - -/obj/item/clothing/tie/storage/atom_init() - . = ..() - hold = new/obj/item/weapon/storage/internal(src) - hold.storage_slots = slots - -/obj/item/clothing/tie/storage/attack_hand(mob/user) - if (has_suit) //if we are part of a suit - hold.open(user) - return - - if (hold.handle_attack_hand(user)) //otherwise interact as a regular storage item - ..(user) - -/obj/item/clothing/tie/storage/MouseDrop(obj/over_object as obj) - if (has_suit) - return - - if (hold.handle_mousedrop(usr, over_object)) - ..(over_object) - -/obj/item/clothing/tie/storage/attackby(obj/item/W, mob/user) - hold.attackby(W, user) - -/obj/item/clothing/tie/storage/emp_act(severity) - hold.emp_act(severity) - ..() - -/obj/item/clothing/tie/storage/hear_talk(mob/M, msg, verb, datum/language/speaking) - hold.hear_talk(M, msg, verb, speaking) - ..() - -/obj/item/clothing/tie/storage/attack_self(mob/user) - to_chat(user, "You empty [src].") - var/turf/T = get_turf(src) - hold.hide_from(usr) - for(var/obj/item/I in hold.contents) - hold.remove_from_storage(I, T) - src.add_fingerprint(user) - -/obj/item/clothing/tie/storage/webbing - name = "webbing" - desc = "Strudy mess of synthcotton belts and buckles, ready to share your burden." - icon_state = "webbing" - item_color = "webbing" - -/obj/item/clothing/tie/storage/black_vest - name = "black webbing vest" - desc = "Robust black synthcotton vest with lots of pockets to hold whatever you need, but cannot hold in hands." - icon_state = "vest_black" - item_color = "vest_black" - slots = 5 - -/obj/item/clothing/tie/storage/brown_vest - name = "brown webbing vest" - desc = "Worn brownish synthcotton vest with lots of pockets to unload your hands." - icon_state = "vest_brown" - item_color = "vest_brown" - slots = 5 - -/obj/item/clothing/tie/storage/syndi_vest - name = "suspicious webbing vest" - desc = "A villainous red synthcotton vest with lots of pockets to unload your hands." - icon_state = "syndi_vest" - item_color = "syndi_vest" - slots = 5 -/* - Holobadges are worn on the belt or neck, and can be used to show that the holder is an authorized - Security agent - the user details can be imprinted on the badge with a Security-access ID card, - or they can be emagged to accept any ID for use in disguises. -*/ - -/obj/item/clothing/tie/holobadge - - name = "holobadge" - desc = "This glowing blue badge marks the holder as THE LAW." - icon_state = "holobadge" - item_color = "holobadge" - slot_flags = SLOT_BELT - - var/emagged = 0 //Emagging removes Sec check. - var/stored_name = null - -/obj/item/clothing/tie/holobadge/cord - icon_state = "holobadge-cord" - item_color = "holobadge-cord" - slot_flags = SLOT_MASK - -/obj/item/clothing/tie/holobadge/attack_self(mob/user) - if(!stored_name) - to_chat(user, "Waving around a badge before swiping an ID would be pretty pointless.") - return - if(isliving(user)) - user.visible_message("\red [user] displays their NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.","\red You display your NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.") - -/obj/item/clothing/tie/holobadge/attackby(obj/item/O, mob/user) - - if (istype(O, /obj/item/weapon/card/emag)) - if (emagged) - to_chat(user, "\red [src] is already cracked.") - return - else - emagged = 1 - to_chat(user, "\red You swipe [O] and crack the holobadge security checks.") - return - - else if(istype(O, /obj/item/weapon/card/id) || istype(O, /obj/item/device/pda)) - - var/obj/item/weapon/card/id/id_card = null - - if(istype(O, /obj/item/weapon/card/id)) - id_card = O - else - var/obj/item/device/pda/pda = O - id_card = pda.id - - if(access_security in id_card.access || emagged) - to_chat(user, "You imprint your ID details onto the badge.") - stored_name = id_card.registered_name - name = "holobadge ([stored_name])" - desc = "This glowing blue badge marks [stored_name] as THE LAW." - else - to_chat(user, "[src] rejects your insufficient access rights.") - return - ..() - -/obj/item/clothing/tie/holobadge/attack(mob/living/carbon/human/M, mob/living/user) - if(isliving(user)) - user.visible_message("\red [user] invades [M]'s personal space, thrusting [src] into their face insistently.","\red You invade [M]'s personal space, thrusting [src] into their face insistently. You are the law.") - -/obj/item/clothing/tie/storage/knifeharness - name = "decorated harness" - desc = "A heavily decorated harness of sinew and leather with two knife-loops." - icon_state = "unathiharness2" - item_color = "unathiharness2" - slots = 2 - -/obj/item/clothing/tie/storage/knifeharness/atom_init() - . = ..() - hold.max_combined_w_class = 4 - hold.can_hold = list("/obj/item/weapon/hatchet/unathiknife",\ - "/obj/item/weapon/kitchenknife/plastic",\ - "/obj/item/weapon/kitchenknife",\ - "/obj/item/weapon/kitchenknife/ritual") - - new /obj/item/weapon/hatchet/unathiknife(hold) - new /obj/item/weapon/hatchet/unathiknife(hold) - -/obj/item/clothing/tie/holster/mafia - name = "gun holster" - desc = "When you just HAVE to show off your guns." - icon_state = "mafia_holster" - item_color = "mafia_holster" +/obj/item/clothing/tie + name = "tie" + desc = "A neosilk clip-on tie." + icon = 'icons/obj/clothing/ties.dmi' + icon_state = "bluetie" + item_state = "" //no inhands + item_color = "bluetie" + slot_flags = 0 + w_class = 2.0 + var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to + var/image/inv_overlay = null //overlay used when attached to clothing. + +/obj/item/clothing/tie/atom_init() + . = ..() + inv_overlay = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[item_color? "[item_color]" : "[icon_state]"]") + +//when user attached an accessory to S +/obj/item/clothing/tie/proc/on_attached(obj/item/clothing/under/S, mob/user) + if(!istype(S)) + return + has_suit = S + loc = has_suit + has_suit.overlays += inv_overlay + + to_chat(user, "You attach [src] to [has_suit].") + src.add_fingerprint(user) + +/obj/item/clothing/tie/proc/on_removed(mob/user) + if(!has_suit) + return + has_suit.overlays -= inv_overlay + has_suit = null + usr.put_in_hands(src) + src.add_fingerprint(user) + +//default attackby behaviour +/obj/item/clothing/tie/attackby(obj/item/I, mob/user) + ..() + +//default attack_hand behaviour +/obj/item/clothing/tie/attack_hand(mob/user) + if(has_suit) + has_suit.remove_accessory(user) + return //we aren't an object on the ground so don't call parent + ..() + +/obj/item/clothing/tie/blue + name = "blue tie" + icon_state = "bluetie" + item_color = "bluetie" + +/obj/item/clothing/tie/red + name = "red tie" + icon_state = "redtie" + item_color = "redtie" + +/obj/item/clothing/tie/horrible + name = "horrible tie" + desc = "A neosilk clip-on tie. This one is disgusting." + icon_state = "horribletie" + item_color = "horribletie" + +/obj/item/clothing/tie/stethoscope + name = "stethoscope" + desc = "An outdated medical apparatus for listening to the sounds of the human body. It also makes you look like you know what you're doing." + icon_state = "stethoscope" + item_color = "stethoscope" + +/obj/item/clothing/tie/stethoscope/attack(mob/living/carbon/human/M, mob/living/user, def_zone) + if(ishuman(M) && isliving(user)) + if(user.a_intent == "help") + var/target_zone = parse_zone(def_zone) + if(target_zone) + var/their = "their" + switch(M.gender) + if(MALE) their = "his" + if(FEMALE) their = "her" + + var/sound = "pulse" + var/sound_strength + + if(M.stat == DEAD || (M.status_flags & FAKEDEATH)) + sound_strength = "cannot hear" + sound = "anything" + else + sound_strength = "hear a weak" + switch(target_zone) + if(BP_CHEST) + if(M.oxyloss < 50) + sound_strength = "hear a healthy" + sound = "pulse and respiration" + if(O_EYES, O_MOUTH) + sound_strength = "cannot hear" + sound = "anything" + else + sound_strength = "hear a weak" + + user.visible_message("[user] places [src] against [M]'s [target_zone] and listens attentively.", "You place [src] against [their] [target_zone]. You [sound_strength] [sound].") + return + return ..(M,user) + + +//Medals +/obj/item/clothing/tie/medal + name = "bronze medal" + desc = "A bronze medal." + icon_state = "bronze" + item_color = "bronze" + +/obj/item/clothing/tie/medal/conduct + name = "distinguished conduct medal" + desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew." + +/obj/item/clothing/tie/medal/bronze_heart + name = "bronze heart medal" + desc = "A bronze heart-shaped medal awarded for sacrifice. It is often awarded posthumously or for severe injury in the line of duty." + icon_state = "bronze_heart" + +/obj/item/clothing/tie/medal/nobel_science + name = "nobel sciences award" + desc = "A bronze medal which represents significant contributions to the field of science or engineering." + +/obj/item/clothing/tie/medal/silver + name = "silver medal" + desc = "A silver medal." + icon_state = "silver" + item_color = "silver" + +/obj/item/clothing/tie/medal/silver/valor + name = "medal of valor" + desc = "A silver medal awarded for acts of exceptional valor." + +/obj/item/clothing/tie/medal/silver/security + name = "robust security award" + desc = "An award for distinguished combat and sacrifice in defence of Nanotrasen's commercial interests. Often awarded to security staff." + +/obj/item/clothing/tie/medal/gold + name = "gold medal" + desc = "A prestigious golden medal." + icon_state = "gold" + item_color = "gold" + +/obj/item/clothing/tie/medal/gold/captain + name = "medal of captaincy" + desc = "A golden medal awarded exclusively to those promoted to the rank of captain. It signifies the codified responsibilities of a captain to Nanotrasen, and their undisputable authority over their crew." + icon_state = "gold_nt" + +/obj/item/clothing/tie/medal/gold/heroism + name = "medal of exceptional heroism" + desc = "An extremely rare golden medal awarded only by CentComm. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but commanders." + +//Armbands +/obj/item/clothing/tie/armband + name = "red armband" + desc = "A fancy red armband!" + icon_state = "red" + item_color = "red" + +/obj/item/clothing/tie/armband/cargo + name = "cargo bay guard armband" + desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is brown." + icon_state = "cargo" + item_color = "cargo" + +/obj/item/clothing/tie/armband/engine + name = "engineering guard armband" + desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is orange with a reflective strip!" + icon_state = "engie" + item_color = "engie" + +/obj/item/clothing/tie/armband/science + name = "science guard armband" + desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is purple." + icon_state = "rnd" + item_color = "rnd" + +/obj/item/clothing/tie/armband/hydro + name = "hydroponics guard armband" + desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is green and blue." + icon_state = "hydro" + item_color = "hydro" + +/obj/item/clothing/tie/armband/med + name = "medical guard armband" + desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is white." + icon_state = "med" + item_color = "med" + +/obj/item/clothing/tie/armband/medgreen + name = "medical guard armband" + desc = "An armband, worn by the station's security forces to display which department they're assigned to. This one is white and green." + icon_state = "medgreen" + item_color = "medgreen" + +//holsters +/obj/item/clothing/tie/holster + name = "shoulder holster" + desc = "A handgun holster." + icon_state = "holster" + item_color = "holster" + var/obj/item/weapon/gun/holstered = null + +//subtypes can override this to specify what can be holstered +/obj/item/clothing/tie/holster/proc/can_holster(obj/item/weapon/gun/W) + return W.isHandgun() + +/obj/item/clothing/tie/holster/proc/holster(obj/item/I, mob/user) + if(holstered) + to_chat(user, "\red There is already a [holstered] holstered here!") + return + + if (!istype(I, /obj/item/weapon/gun)) + to_chat(user, "\red Only guns can be holstered!") + return + + var/obj/item/weapon/gun/W = I + if (!can_holster(W)) + to_chat(user, "\red This [W] won't fit in the [src]!") + return + + holstered = W + user.drop_from_inventory(holstered) + holstered.loc = src + holstered.add_fingerprint(user) + user.visible_message("\blue [user] holsters the [holstered].", "You holster the [holstered].") + +/obj/item/clothing/tie/holster/proc/unholster(mob/user) + if(!holstered) + return + + if(istype(user.get_active_hand(),/obj) && istype(user.get_inactive_hand(),/obj)) + to_chat(user, "\red You need an empty hand to draw the [holstered]!") + else + if(user.a_intent == "hurt") + usr.visible_message("\red [user] draws the [holstered], ready to shoot!", \ + "\red You draw the [holstered], ready to shoot!") + else + user.visible_message("\blue [user] draws the [holstered], pointing it at the ground.", \ + "\blue You draw the [holstered], pointing it at the ground.") + user.put_in_hands(holstered) + holstered.add_fingerprint(user) + holstered = null + +/obj/item/clothing/tie/holster/attack_hand(mob/user) + if (has_suit) //if we are part of a suit + if (holstered) + unholster(user) + return + + ..(user) + +/obj/item/clothing/tie/holster/attackby(obj/item/W, mob/user) + holster(W, user) + +/obj/item/clothing/tie/holster/emp_act(severity) + if (holstered) + holstered.emp_act(severity) + ..() + +/obj/item/clothing/tie/holster/examine(mob/user) + ..() + if (holstered) + to_chat(user, "A [holstered] is holstered here.") + else + to_chat(user, "It is empty.") + +/obj/item/clothing/tie/holster/on_attached(obj/item/clothing/under/S, mob/user) + ..() + has_suit.verbs += /obj/item/clothing/tie/holster/verb/holster_verb + +/obj/item/clothing/tie/holster/on_removed(mob/user) + has_suit.verbs -= /obj/item/clothing/tie/holster/verb/holster_verb + ..() + +//For the holster hotkey +/obj/item/clothing/tie/holster/verb/holster_verb() + set name = "Holster" + set category = "Object" + set src in usr + if(!istype(usr, /mob/living)) return + if(usr.stat) return + + var/obj/item/clothing/tie/holster/H = null + if (istype(src, /obj/item/clothing/tie/holster)) + H = src + else if (istype(src, /obj/item/clothing/under)) + var/obj/item/clothing/under/S = src + if (S.hastie) + H = S.hastie + + if (!H) + to_chat(usr, "/red Something is very wrong.") + + if(!H.holstered) + if(!istype(usr.get_active_hand(), /obj/item/weapon/gun)) + to_chat(usr, "\blue You need your gun equiped to holster it.") + return + var/obj/item/weapon/gun/W = usr.get_active_hand() + H.holster(W, usr) + else + H.unholster(usr) + +/obj/item/clothing/tie/holster/armpit + name = "shoulder holster" + desc = "A worn-out handgun holster. Perfect for concealed carry." + icon_state = "holster" + item_color = "holster" + +/obj/item/clothing/tie/holster/waist + name = "shoulder holster" + desc = "A handgun holster. Made of expensive leather." + icon_state = "holster" + item_color = "holster_low" + +/obj/item/clothing/tie/storage + name = "load bearing equipment" + desc = "Used to hold things when you don't have enough hands." + icon_state = "webbing" + item_color = "webbing" + var/slots = 3 + var/obj/item/weapon/storage/internal/hold + +/obj/item/clothing/tie/storage/atom_init() + . = ..() + hold = new/obj/item/weapon/storage/internal(src) + hold.storage_slots = slots + +/obj/item/clothing/tie/storage/attack_hand(mob/user) + if (has_suit) //if we are part of a suit + hold.open(user) + return + + if (hold.handle_attack_hand(user)) //otherwise interact as a regular storage item + ..(user) + +/obj/item/clothing/tie/storage/MouseDrop(obj/over_object as obj) + if (has_suit) + return + + if (hold.handle_mousedrop(usr, over_object)) + ..(over_object) + +/obj/item/clothing/tie/storage/attackby(obj/item/W, mob/user) + hold.attackby(W, user) + +/obj/item/clothing/tie/storage/emp_act(severity) + hold.emp_act(severity) + ..() + +/obj/item/clothing/tie/storage/hear_talk(mob/M, msg, verb, datum/language/speaking) + hold.hear_talk(M, msg, verb, speaking) + ..() + +/obj/item/clothing/tie/storage/attack_self(mob/user) + to_chat(user, "You empty [src].") + var/turf/T = get_turf(src) + hold.hide_from(usr) + for(var/obj/item/I in hold.contents) + hold.remove_from_storage(I, T) + src.add_fingerprint(user) + +/obj/item/clothing/tie/storage/webbing + name = "webbing" + desc = "Strudy mess of synthcotton belts and buckles, ready to share your burden." + icon_state = "webbing" + item_color = "webbing" + +/obj/item/clothing/tie/storage/black_vest + name = "black webbing vest" + desc = "Robust black synthcotton vest with lots of pockets to hold whatever you need, but cannot hold in hands." + icon_state = "vest_black" + item_color = "vest_black" + slots = 5 + +/obj/item/clothing/tie/storage/brown_vest + name = "brown webbing vest" + desc = "Worn brownish synthcotton vest with lots of pockets to unload your hands." + icon_state = "vest_brown" + item_color = "vest_brown" + slots = 5 + +/obj/item/clothing/tie/storage/syndi_vest + name = "suspicious webbing vest" + desc = "A villainous red synthcotton vest with lots of pockets to unload your hands." + icon_state = "syndi_vest" + item_color = "syndi_vest" + slots = 5 +/* + Holobadges are worn on the belt or neck, and can be used to show that the holder is an authorized + Security agent - the user details can be imprinted on the badge with a Security-access ID card, + or they can be emagged to accept any ID for use in disguises. +*/ + +/obj/item/clothing/tie/holobadge + + name = "holobadge" + desc = "This glowing blue badge marks the holder as THE LAW." + icon_state = "holobadge" + item_color = "holobadge" + slot_flags = SLOT_BELT + + var/emagged = 0 //Emagging removes Sec check. + var/stored_name = null + +/obj/item/clothing/tie/holobadge/cord + icon_state = "holobadge-cord" + item_color = "holobadge-cord" + slot_flags = SLOT_MASK + +/obj/item/clothing/tie/holobadge/attack_self(mob/user) + if(!stored_name) + to_chat(user, "Waving around a badge before swiping an ID would be pretty pointless.") + return + if(isliving(user)) + user.visible_message("\red [user] displays their NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.","\red You display your NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.") + +/obj/item/clothing/tie/holobadge/attackby(obj/item/O, mob/user) + + if (istype(O, /obj/item/weapon/card/emag)) + if (emagged) + to_chat(user, "\red [src] is already cracked.") + return + else + emagged = 1 + to_chat(user, "\red You swipe [O] and crack the holobadge security checks.") + return + + else if(istype(O, /obj/item/weapon/card/id) || istype(O, /obj/item/device/pda)) + + var/obj/item/weapon/card/id/id_card = null + + if(istype(O, /obj/item/weapon/card/id)) + id_card = O + else + var/obj/item/device/pda/pda = O + id_card = pda.id + + if(access_security in id_card.access || emagged) + to_chat(user, "You imprint your ID details onto the badge.") + stored_name = id_card.registered_name + name = "holobadge ([stored_name])" + desc = "This glowing blue badge marks [stored_name] as THE LAW." + else + to_chat(user, "[src] rejects your insufficient access rights.") + return + ..() + +/obj/item/clothing/tie/holobadge/attack(mob/living/carbon/human/M, mob/living/user) + if(isliving(user)) + user.visible_message("\red [user] invades [M]'s personal space, thrusting [src] into their face insistently.","\red You invade [M]'s personal space, thrusting [src] into their face insistently. You are the law.") + +/obj/item/clothing/tie/storage/knifeharness + name = "decorated harness" + desc = "A heavily decorated harness of sinew and leather with two knife-loops." + icon_state = "unathiharness2" + item_color = "unathiharness2" + slots = 2 + +/obj/item/clothing/tie/storage/knifeharness/atom_init() + . = ..() + hold.max_combined_w_class = 4 + hold.can_hold = list("/obj/item/weapon/hatchet/unathiknife",\ + "/obj/item/weapon/kitchenknife/plastic",\ + "/obj/item/weapon/kitchenknife",\ + "/obj/item/weapon/kitchenknife/ritual") + + new /obj/item/weapon/hatchet/unathiknife(hold) + new /obj/item/weapon/hatchet/unathiknife(hold) + +/obj/item/clothing/tie/holster/mafia + name = "gun holster" + desc = "When you just HAVE to show off your guns." + icon_state = "mafia_holster" + item_color = "mafia_holster" diff --git a/code/modules/destilery/main.dm b/code/modules/destilery/main.dm index afb5c1f1aec5..e4be22236ca0 100644 --- a/code/modules/destilery/main.dm +++ b/code/modules/destilery/main.dm @@ -1,306 +1,306 @@ -//This dm file includes some food processing machines: -// - I. Mill -// - II. Fermenter -// - III. Still -// - IV. Squeezer -// - V. Centrifuge - - - -// I. The mill is intended to be loaded with produce and returns ground up items. For example: Wheat should become flour and grapes should become raisins. - -/obj/machinery/mill - var/list/obj/item/weapon/reagent_containers/food/input = list() - var/list/obj/item/weapon/reagent_containers/food/output = list() - var/obj/item/weapon/reagent_containers/food/milled_item - var/busy = 0 - var/progress = 0 - var/error = 0 - name = "\improper Mill" - desc = "It is a machine that grinds produce." - icon_state = "autolathe" - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 1000 - -/obj/machinery/mill/process() - if(error) - return - - if(!busy) - use_power = 1 - if(input.len) - milled_item = input[1] - input -= milled_item - progress = 0 - busy = 1 - use_power = 2 - return - - progress++ - if(progress < 10) //Edit this value to make milling faster or slower - return //Not done yet. - - switch(milled_item.type) - if(/obj/item/weapon/reagent_containers/food/snacks/grown/wheat) //Wheat becomes flour - var/obj/item/weapon/reagent_containers/food/condiment/flour/F = new(src) - output += F - if(/obj/item/weapon/reagent_containers/food/condiment/flour) //Flour is still flour - var/obj/item/weapon/reagent_containers/food/condiment/flour/F = new(src) - output += F - else - error = 1 - - qdel(milled_item) - busy = 0 - -/obj/machinery/mill/attackby(obj/item/weapon/W, mob/user) - if(istype(W,/obj/item/weapon/reagent_containers/food)) - user.u_equip(W) - W.loc = src - input += W - else - ..() - -/obj/machinery/mill/attack_hand(mob/user) - . = ..() - if(.) - return - - for(var/obj/item/weapon/reagent_containers/food/F in output) - F.loc = src.loc - output -= F - - - - - - -// II. The fermenter is intended to be loaded with food items and returns medium-strength alcohol items, sucha s wine and beer. - -/obj/machinery/fermenter - var/list/obj/item/weapon/reagent_containers/food/input = list() - var/list/obj/item/weapon/reagent_containers/food/output = list() - var/obj/item/weapon/reagent_containers/food/fermenting_item - var/water_level = 0 - var/busy = 0 - var/progress = 0 - var/error = 0 - name = "\improper Fermenter" - desc = "It is a machine that ferments produce into alcoholic drinks." - icon_state = "autolathe" - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 500 - -/obj/machinery/fermenter/process() - if(error) - return - - if(!busy) - use_power = 1 - if(input.len) - fermenting_item = input[1] - input -= fermenting_item - progress = 0 - busy = 1 - use_power = 2 - return - - if(!water_level) - return - - water_level-- - - progress++ - if(progress < 10) //Edit this value to make milling faster or slower - return //Not done yet. - - switch(fermenting_item.type) - if(/obj/item/weapon/reagent_containers/food/condiment/flour) //Flour is still flour - var/obj/item/weapon/reagent_containers/food/drinks/bottle/beer/B = new(src) - output += B - else - error = 1 - - qdel(fermenting_item) - busy = 0 - -/obj/machinery/fermenter/attackby(obj/item/weapon/W, mob/user) - if(istype(W,/obj/item/weapon/reagent_containers/food)) - user.u_equip(W) - W.loc = src - input += W - else - ..() - -/obj/machinery/fermenter/attack_hand(mob/user) - . = ..() - if(.) - return - - for(var/obj/item/weapon/reagent_containers/food/F in output) - F.loc = src.loc - output -= F - - - -// III. The still is a machine that is loaded with food items and returns hard liquor, such as vodka. - -/obj/machinery/still - var/list/obj/item/weapon/reagent_containers/food/input = list() - var/list/obj/item/weapon/reagent_containers/food/output = list() - var/obj/item/weapon/reagent_containers/food/destilling_item - var/busy = 0 - var/progress = 0 - var/error = 0 - name = "\improper Still" - desc = "It is a machine that produces hard liquor from alcoholic drinks." - icon_state = "autolathe" - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 10000 - -/obj/machinery/still/process() - if(error) - return - - if(!busy) - use_power = 1 - if(input.len) - destilling_item = input[1] - input -= destilling_item - progress = 0 - busy = 1 - use_power = 2 - return - - progress++ - if(progress < 10) //Edit this value to make distilling faster or slower - return //Not done yet. - - switch(destilling_item.type) - if(/obj/item/weapon/reagent_containers/food/drinks/bottle/beer) //Flour is still flour - var/obj/item/weapon/reagent_containers/food/drinks/bottle/vodka/V = new(src) - output += V - else - error = 1 - - qdel(destilling_item) - busy = 0 - -/obj/machinery/still/attackby(obj/item/weapon/W, mob/user) - if(istype(W,/obj/item/weapon/reagent_containers/food)) - user.u_equip(W) - W.loc = src - input += W - else - ..() - -/obj/machinery/still/attack_hand(mob/user) - . = ..() - if(.) - return - - for(var/obj/item/weapon/reagent_containers/food/F in output) - F.loc = src.loc - output -= F - - - - -// IV. The squeezer is intended to destroy inserted food items, but return some of the reagents they contain. - -/obj/machinery/squeezer - var/list/obj/item/weapon/reagent_containers/food/input = list() - var/obj/item/weapon/reagent_containers/food/squeezed_item - var/water_level = 0 - var/busy = 0 - var/progress = 0 - var/error = 0 - name = "\improper Squeezer" - desc = "It is a machine that squeezes extracts from produce." - icon_state = "autolathe" - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 500 - - - - - -// V. The centrifuge spins inserted food items. It is intended to squeeze out the reagents that are common food catalysts (enzymes currently) - -/obj/machinery/centrifuge - var/list/obj/item/weapon/reagent_containers/food/input = list() - var/list/obj/item/weapon/reagent_containers/food/output = list() - var/obj/item/weapon/reagent_containers/food/spinning_item - var/busy = 0 - var/progress = 0 - var/error = 0 - var/enzymes = 0 - var/water = 0 - name = "\improper Centrifuge" - desc = "It is a machine that spins produce." - icon_state = "autolathe" - density = 1 - anchored = 1 - use_power = 1 - idle_power_usage = 10 - active_power_usage = 10000 - -/obj/machinery/centrifuge/process() - if(error) - return - - if(!busy) - use_power = 1 - if(input.len) - spinning_item = input[1] - input -= spinning_item - progress = 0 - busy = 1 - use_power = 2 - return - - progress++ - if(progress < 10) //Edit this value to make milling faster or slower - return //Not done yet. - - var/transfer_enzymes = spinning_item.reagents.get_reagent_amount("enzyme") - - if(transfer_enzymes) - enzymes += transfer_enzymes - spinning_item.reagents.remove_reagent("enzyme",transfer_enzymes) - - output += spinning_item - busy = 0 - -/obj/machinery/centrifuge/attackby(obj/item/weapon/W, mob/user) - if(istype(W,/obj/item/weapon/reagent_containers/food)) - user.u_equip(W) - W.loc = src - input += W - else - ..() - -/obj/machinery/centrifuge/attack_hand(mob/user) - . = ..() - if(.) - return - - for(var/obj/item/weapon/reagent_containers/food/F in output) - F.loc = src.loc - output -= F - while(enzymes >= 50) - enzymes -= 50 - new/obj/item/weapon/reagent_containers/food/condiment/enzyme(src.loc) - +//This dm file includes some food processing machines: +// - I. Mill +// - II. Fermenter +// - III. Still +// - IV. Squeezer +// - V. Centrifuge + + + +// I. The mill is intended to be loaded with produce and returns ground up items. For example: Wheat should become flour and grapes should become raisins. + +/obj/machinery/mill + var/list/obj/item/weapon/reagent_containers/food/input = list() + var/list/obj/item/weapon/reagent_containers/food/output = list() + var/obj/item/weapon/reagent_containers/food/milled_item + var/busy = 0 + var/progress = 0 + var/error = 0 + name = "\improper Mill" + desc = "It is a machine that grinds produce." + icon_state = "autolathe" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 1000 + +/obj/machinery/mill/process() + if(error) + return + + if(!busy) + use_power = 1 + if(input.len) + milled_item = input[1] + input -= milled_item + progress = 0 + busy = 1 + use_power = 2 + return + + progress++ + if(progress < 10) //Edit this value to make milling faster or slower + return //Not done yet. + + switch(milled_item.type) + if(/obj/item/weapon/reagent_containers/food/snacks/grown/wheat) //Wheat becomes flour + var/obj/item/weapon/reagent_containers/food/condiment/flour/F = new(src) + output += F + if(/obj/item/weapon/reagent_containers/food/condiment/flour) //Flour is still flour + var/obj/item/weapon/reagent_containers/food/condiment/flour/F = new(src) + output += F + else + error = 1 + + qdel(milled_item) + busy = 0 + +/obj/machinery/mill/attackby(obj/item/weapon/W, mob/user) + if(istype(W,/obj/item/weapon/reagent_containers/food)) + user.u_equip(W) + W.loc = src + input += W + else + ..() + +/obj/machinery/mill/attack_hand(mob/user) + . = ..() + if(.) + return + + for(var/obj/item/weapon/reagent_containers/food/F in output) + F.loc = src.loc + output -= F + + + + + + +// II. The fermenter is intended to be loaded with food items and returns medium-strength alcohol items, sucha s wine and beer. + +/obj/machinery/fermenter + var/list/obj/item/weapon/reagent_containers/food/input = list() + var/list/obj/item/weapon/reagent_containers/food/output = list() + var/obj/item/weapon/reagent_containers/food/fermenting_item + var/water_level = 0 + var/busy = 0 + var/progress = 0 + var/error = 0 + name = "\improper Fermenter" + desc = "It is a machine that ferments produce into alcoholic drinks." + icon_state = "autolathe" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 500 + +/obj/machinery/fermenter/process() + if(error) + return + + if(!busy) + use_power = 1 + if(input.len) + fermenting_item = input[1] + input -= fermenting_item + progress = 0 + busy = 1 + use_power = 2 + return + + if(!water_level) + return + + water_level-- + + progress++ + if(progress < 10) //Edit this value to make milling faster or slower + return //Not done yet. + + switch(fermenting_item.type) + if(/obj/item/weapon/reagent_containers/food/condiment/flour) //Flour is still flour + var/obj/item/weapon/reagent_containers/food/drinks/bottle/beer/B = new(src) + output += B + else + error = 1 + + qdel(fermenting_item) + busy = 0 + +/obj/machinery/fermenter/attackby(obj/item/weapon/W, mob/user) + if(istype(W,/obj/item/weapon/reagent_containers/food)) + user.u_equip(W) + W.loc = src + input += W + else + ..() + +/obj/machinery/fermenter/attack_hand(mob/user) + . = ..() + if(.) + return + + for(var/obj/item/weapon/reagent_containers/food/F in output) + F.loc = src.loc + output -= F + + + +// III. The still is a machine that is loaded with food items and returns hard liquor, such as vodka. + +/obj/machinery/still + var/list/obj/item/weapon/reagent_containers/food/input = list() + var/list/obj/item/weapon/reagent_containers/food/output = list() + var/obj/item/weapon/reagent_containers/food/destilling_item + var/busy = 0 + var/progress = 0 + var/error = 0 + name = "\improper Still" + desc = "It is a machine that produces hard liquor from alcoholic drinks." + icon_state = "autolathe" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 10000 + +/obj/machinery/still/process() + if(error) + return + + if(!busy) + use_power = 1 + if(input.len) + destilling_item = input[1] + input -= destilling_item + progress = 0 + busy = 1 + use_power = 2 + return + + progress++ + if(progress < 10) //Edit this value to make distilling faster or slower + return //Not done yet. + + switch(destilling_item.type) + if(/obj/item/weapon/reagent_containers/food/drinks/bottle/beer) //Flour is still flour + var/obj/item/weapon/reagent_containers/food/drinks/bottle/vodka/V = new(src) + output += V + else + error = 1 + + qdel(destilling_item) + busy = 0 + +/obj/machinery/still/attackby(obj/item/weapon/W, mob/user) + if(istype(W,/obj/item/weapon/reagent_containers/food)) + user.u_equip(W) + W.loc = src + input += W + else + ..() + +/obj/machinery/still/attack_hand(mob/user) + . = ..() + if(.) + return + + for(var/obj/item/weapon/reagent_containers/food/F in output) + F.loc = src.loc + output -= F + + + + +// IV. The squeezer is intended to destroy inserted food items, but return some of the reagents they contain. + +/obj/machinery/squeezer + var/list/obj/item/weapon/reagent_containers/food/input = list() + var/obj/item/weapon/reagent_containers/food/squeezed_item + var/water_level = 0 + var/busy = 0 + var/progress = 0 + var/error = 0 + name = "\improper Squeezer" + desc = "It is a machine that squeezes extracts from produce." + icon_state = "autolathe" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 500 + + + + + +// V. The centrifuge spins inserted food items. It is intended to squeeze out the reagents that are common food catalysts (enzymes currently) + +/obj/machinery/centrifuge + var/list/obj/item/weapon/reagent_containers/food/input = list() + var/list/obj/item/weapon/reagent_containers/food/output = list() + var/obj/item/weapon/reagent_containers/food/spinning_item + var/busy = 0 + var/progress = 0 + var/error = 0 + var/enzymes = 0 + var/water = 0 + name = "\improper Centrifuge" + desc = "It is a machine that spins produce." + icon_state = "autolathe" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 10000 + +/obj/machinery/centrifuge/process() + if(error) + return + + if(!busy) + use_power = 1 + if(input.len) + spinning_item = input[1] + input -= spinning_item + progress = 0 + busy = 1 + use_power = 2 + return + + progress++ + if(progress < 10) //Edit this value to make milling faster or slower + return //Not done yet. + + var/transfer_enzymes = spinning_item.reagents.get_reagent_amount("enzyme") + + if(transfer_enzymes) + enzymes += transfer_enzymes + spinning_item.reagents.remove_reagent("enzyme",transfer_enzymes) + + output += spinning_item + busy = 0 + +/obj/machinery/centrifuge/attackby(obj/item/weapon/W, mob/user) + if(istype(W,/obj/item/weapon/reagent_containers/food)) + user.u_equip(W) + W.loc = src + input += W + else + ..() + +/obj/machinery/centrifuge/attack_hand(mob/user) + . = ..() + if(.) + return + + for(var/obj/item/weapon/reagent_containers/food/F in output) + F.loc = src.loc + output -= F + while(enzymes >= 50) + enzymes -= 50 + new/obj/item/weapon/reagent_containers/food/condiment/enzyme(src.loc) + diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index ba249fb97576..99b47725a7c7 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -1,50 +1,50 @@ -/var/global/sent_aliens_to_station = 0 - -/datum/event/alien_infestation - announceWhen = 400 - oneShot = 1 - - var/spawncount = 1 - var/successSpawn = 0 //So we don't make a command report if nothing gets spawned. - - -/datum/event/alien_infestation/setup() - announceWhen = rand(announceWhen, announceWhen + 50) - spawncount = rand(1, 2) - 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") - world << sound('sound/AI/aliens.ogg') - - -/datum/event/alien_infestation/start() - var/list/vents = list() - for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in machines) - if(QDELETED(temp_vent)) - continue - if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded) - var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1 - //Stops Aliens getting stuck in small networks. - //See: Security, Virology - if(temp_vent_parent.other_atmosmch.len > 50) - vents += temp_vent - - if(!vents.len) - message_admins("An event attempted to spawn an alien but no suitable vents were found. Shutting down.") - return - - var/list/candidates = get_alien_candidates() - - while(spawncount > 0 && candidates.len) - var/obj/vent = pick(vents) - var/candidate = pick(candidates) - - var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc) - new_xeno.key = candidate - - candidates -= candidate - vents -= vent - spawncount-- - successSpawn = 1 +/var/global/sent_aliens_to_station = 0 + +/datum/event/alien_infestation + announceWhen = 400 + oneShot = 1 + + var/spawncount = 1 + var/successSpawn = 0 //So we don't make a command report if nothing gets spawned. + + +/datum/event/alien_infestation/setup() + announceWhen = rand(announceWhen, announceWhen + 50) + spawncount = rand(1, 2) + 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") + world << sound('sound/AI/aliens.ogg') + + +/datum/event/alien_infestation/start() + var/list/vents = list() + for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in machines) + if(QDELETED(temp_vent)) + continue + if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded) + var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1 + //Stops Aliens getting stuck in small networks. + //See: Security, Virology + if(temp_vent_parent.other_atmosmch.len > 50) + vents += temp_vent + + if(!vents.len) + message_admins("An event attempted to spawn an alien but no suitable vents were found. Shutting down.") + return + + var/list/candidates = get_alien_candidates() + + while(spawncount > 0 && candidates.len) + var/obj/vent = pick(vents) + var/candidate = pick(candidates) + + var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc) + new_xeno.key = candidate + + candidates -= candidate + vents -= vent + spawncount-- + successSpawn = 1 diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm index 38944a7a5a0f..b534db90218b 100644 --- a/code/modules/events/blob.dm +++ b/code/modules/events/blob.dm @@ -1,28 +1,28 @@ -/datum/event/blob - announceWhen = 12 - endWhen = 120 - - var/obj/effect/blob/core/Blob - - -/datum/event/blob/announce() - command_alert("Confirmed outbreak of level 7 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - world << sound('sound/AI/outbreak7.ogg') - - -/datum/event/blob/start() - var/turf/T = pick(blobstart) - if(!T) - kill() - return - Blob = new /obj/effect/blob/core(T, 120) - for(var/i = 1; i < rand(3, 4), i++) - Blob.process() - - -/datum/event/blob/tick() - if(!Blob) - kill() - return - if(IsMultiple(activeFor, 3)) - Blob.process() +/datum/event/blob + announceWhen = 12 + endWhen = 120 + + var/obj/effect/blob/core/Blob + + +/datum/event/blob/announce() + command_alert("Confirmed outbreak of level 7 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") + world << sound('sound/AI/outbreak7.ogg') + + +/datum/event/blob/start() + var/turf/T = pick(blobstart) + if(!T) + kill() + return + Blob = new /obj/effect/blob/core(T, 120) + for(var/i = 1; i < rand(3, 4), i++) + Blob.process() + + +/datum/event/blob/tick() + if(!Blob) + 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 bec52b11f1fa..6bf841ec3aa0 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -1,56 +1,56 @@ -/datum/event/brand_intelligence - announceWhen = 21 - endWhen = 1000 //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 != ZLEVEL_STATION) 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(15)) - 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 obsession!", \ - "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) - infectedMachine.shut_up = 1 - infectedMachine.shoot_inventory = 0 +/datum/event/brand_intelligence + announceWhen = 21 + endWhen = 1000 //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 != ZLEVEL_STATION) 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(15)) + 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 obsession!", \ + "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) + 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 fbf8363f17e2..a3201ac83041 100644 --- a/code/modules/events/carp_migration.dm +++ b/code/modules/events/carp_migration.dm @@ -1,28 +1,28 @@ -/datum/event/carp_migration - announceWhen = 50 - oneShot = 1 - endWhen = 900 - var/list/spawned_carp = list() - -/datum/event/carp_migration/setup() - announceWhen = rand(40, 60) - 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(95)) - spawned_carp.Add(new /mob/living/simple_animal/hostile/carp(C.loc)) - else - spawned_carp.Add(new /mob/living/simple_animal/hostile/carp/megacarp(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) +/datum/event/carp_migration + announceWhen = 50 + oneShot = 1 + endWhen = 900 + var/list/spawned_carp = list() + +/datum/event/carp_migration/setup() + announceWhen = rand(40, 60) + 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(95)) + spawned_carp.Add(new /mob/living/simple_animal/hostile/carp(C.loc)) + else + spawned_carp.Add(new /mob/living/simple_animal/hostile/carp/megacarp(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) diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm index cbb369694a95..cf666a08e4de 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. - 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) - T.emp_act(1) +/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) + T.emp_act(1) diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index f97ac9e8d881..e47dde0260ff 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -1,46 +1,46 @@ -/datum/event/disease_outbreak - announceWhen = 15 - oneShot = 1 - - -/datum/event/disease_outbreak/announce() - command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") - world << sound('sound/AI/outbreak7.ogg') - -/datum/event/disease_outbreak/setup() - announceWhen = rand(15, 30) - -/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(human_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 != ZLEVEL_STATION) - continue - for(var/datum/disease/D in H.viruses) - foundAlready = 1 - if(H.stat == DEAD || 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 +/datum/event/disease_outbreak + announceWhen = 15 + oneShot = 1 + + +/datum/event/disease_outbreak/announce() + command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") + world << sound('sound/AI/outbreak7.ogg') + +/datum/event/disease_outbreak/setup() + announceWhen = rand(15, 30) + +/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(human_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 != ZLEVEL_STATION) + continue + for(var/datum/disease/D in H.viruses) + foundAlready = 1 + if(H.stat == DEAD || 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 diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm index 38454200694b..5444867bd7ae 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)) - apc.overload_lighting() +/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() diff --git a/code/modules/events/event.dm b/code/modules/events/event.dm index 4c7ba2de9ff1..69c8bf217e86 100644 --- a/code/modules/events/event.dm +++ b/code/modules/events/event.dm @@ -1,111 +1,111 @@ -/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/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() - SSevent.running -= src - - -//Adds the event to the global events list, and removes it from the list -//of potential events. -/datum/event/New() - setup() - SSevent.running += src - /*if(oneShot) - potentialRandomEvents.Remove(type)*/ - ..() - -/datum/event/proc/findEventArea() //Here's a nice proc to use to find an area for your event to land in! (TG-stuff) - var/list/safe_areas = list( - /area/ai_monitored/storage/secure, - /area/turret_protected/ai, - /area/turret_protected/ai_upload, - /area/engine, - /area/solar, - /area/holodeck, - /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/administration/station, - /area/shuttle/specops/station, - /area/atmos) - - //These are needed because /area/engine has to be removed from the list, but we still want these areas to get fucked up. - var/list/danger_areas = list( - /area/engine/break_room, - /area/engine/chiefs_office) - - //Need to locate() as it's just a list of paths. - return locate(pick((the_station_areas - safe_areas) + danger_areas)) +/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/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() + SSevent.running -= src + + +//Adds the event to the global events list, and removes it from the list +//of potential events. +/datum/event/New() + setup() + SSevent.running += src + /*if(oneShot) + potentialRandomEvents.Remove(type)*/ + ..() + +/datum/event/proc/findEventArea() //Here's a nice proc to use to find an area for your event to land in! (TG-stuff) + var/list/safe_areas = list( + /area/ai_monitored/storage/secure, + /area/turret_protected/ai, + /area/turret_protected/ai_upload, + /area/engine, + /area/solar, + /area/holodeck, + /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/administration/station, + /area/shuttle/specops/station, + /area/atmos) + + //These are needed because /area/engine has to be removed from the list, but we still want these areas to get fucked up. + var/list/danger_areas = list( + /area/engine/break_room, + /area/engine/chiefs_office) + + //Need to locate() as it's just a list of paths. + return locate(pick((the_station_areas - safe_areas) + danger_areas)) diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm index 209dd9edfa5d..a76840158e3f 100644 --- a/code/modules/events/prison_break.dm +++ b/code/modules/events/prison_break.dm @@ -1,53 +1,53 @@ -/datum/event/prison_break - announceWhen = 50 - 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 all_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/security/glass/temp_glassairlock in A) - temp_glassairlock.prison_open() - - for(var/obj/machinery/door_timer/temp_timer in A) - temp_timer.releasetime = 1 +/datum/event/prison_break + announceWhen = 50 + 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 all_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/security/glass/temp_glassairlock in A) + temp_glassairlock.prison_open() + + for(var/obj/machinery/door_timer/temp_timer in A) + temp_timer.releasetime = 1 diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm index 0d46f0908acf..7c7d9ffadf73 100644 --- a/code/modules/events/radiation_storm.dm +++ b/code/modules/events/radiation_storm.dm @@ -1,13 +1,13 @@ -/datum/event/radiation_storm - announceWhen = 1 - oneShot = 1 - - -/datum/event/radiation_storm/announce() - - -/datum/event/radiation_storm/start() - world << sound('sound/AI/radiation.ogg') - command_alert("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert") - make_maint_all_access(FALSE) +/datum/event/radiation_storm + announceWhen = 1 + oneShot = 1 + + +/datum/event/radiation_storm/announce() + + +/datum/event/radiation_storm/start() + world << sound('sound/AI/radiation.ogg') + command_alert("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert") + make_maint_all_access(FALSE) SSweather.run_weather("radiation storm",ZLEVEL_STATION) \ No newline at end of file diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 8f248f85922a..137a62280763 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -1,12 +1,12 @@ -/var/global/spacevines_spawned = 0 - -/datum/event/spacevine - oneShot = 1 - -/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 + oneShot = 1 + +/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 229e3712d9d9..429f661c1a68 100644 --- a/code/modules/events/spider_infestation.dm +++ b/code/modules/events/spider_infestation.dm @@ -1,38 +1,38 @@ -/var/global/sent_spiders_to_station = 0 - -/datum/event/spider_infestation - announceWhen = 400 - oneShot = 1 - - var/spawncount = 1 - - -/datum/event/spider_infestation/setup() - announceWhen = rand(announceWhen, announceWhen + 50) - 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") - world << sound('sound/AI/aliens.ogg') - - -/datum/event/spider_infestation/start() - var/list/vents = list() - for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in machines) - if(QDELETED(temp_vent)) - continue - if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded) - var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1 - if(temp_vent_parent.other_atmosmch.len > 50) - vents += temp_vent - - if(!vents.len) - message_admins("An event attempted to spawn an alien but no suitable vents were found. Shutting down.") - return - - while(spawncount >= 1) - var/obj/vent = pick(vents) - new /obj/effect/spider/spiderling(vent.loc) - vents -= vent - spawncount-- +/var/global/sent_spiders_to_station = 0 + +/datum/event/spider_infestation + announceWhen = 400 + oneShot = 1 + + var/spawncount = 1 + + +/datum/event/spider_infestation/setup() + announceWhen = rand(announceWhen, announceWhen + 50) + 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") + world << sound('sound/AI/aliens.ogg') + + +/datum/event/spider_infestation/start() + var/list/vents = list() + for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in machines) + if(QDELETED(temp_vent)) + continue + if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded) + var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1 + if(temp_vent_parent.other_atmosmch.len > 50) + vents += temp_vent + + if(!vents.len) + message_admins("An event attempted to spawn an alien but no suitable vents were found. Shutting down.") + return + + while(spawncount >= 1) + var/obj/vent = pick(vents) + new /obj/effect/spider/spiderling(vent.loc) + vents -= vent + spawncount-- diff --git a/code/modules/events/spontaneous_appendicitis.dm b/code/modules/events/spontaneous_appendicitis.dm index 57639a85ec7b..f2307bae0ed6 100644 --- a/code/modules/events/spontaneous_appendicitis.dm +++ b/code/modules/events/spontaneous_appendicitis.dm @@ -1,13 +1,13 @@ -/datum/event/spontaneous_appendicitis/start() - for(var/mob/living/carbon/human/H in shuffle(human_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 == DEAD || foundAlready) - 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(human_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 == DEAD || foundAlready) + 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 1bae27f2d506..b228d0b17e7b 100644 --- a/code/modules/genetics/side_effects.dm +++ b/code/modules/genetics/side_effects.dm @@ -1,111 +1,111 @@ -/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 = "None." - effect = "Subject's skin burns." - duration = 10*30 - -/datum/genetics/side_effect/genetic_burn/start(mob/living/carbon/human/H) - H.emote("me", 1, "starts turning very red..") - -/datum/genetics/side_effect/genetic_burn/finish(mob/living/carbon/human/H) - for(var/bodypart in list(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_R_LEG , BP_L_LEG , BP_HEAD , BP_GROIN)) - var/obj/item/organ/external/BP = H.bodyparts_by_name[bodypart] - if(prob(85))//#Z2 - now 15% chance even for more burn - BP.take_damage(0, 5, 0) - else - BP.take_damage(0, 20, 0) - -/datum/genetics/side_effect/bone_snap - name = "Bone Snap" - symptom = "Subject's limbs tremble notably." - treatment = "None." - effect = "Subject's bone breaks." - duration = 10*60 - -/datum/genetics/side_effect/bone_snap/start(mob/living/carbon/human/H) - H.emote("me", 1, "'s limbs start shivering uncontrollably.") - -/datum/genetics/side_effect/bone_snap/finish(mob/living/carbon/human/H) - var/bodypart = pick(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_R_LEG , BP_L_LEG , BP_HEAD , BP_GROIN) - var/obj/item/organ/external/BP = H.bodyparts_by_name[bodypart] - if(prob(85)) - BP.take_damage(20) - BP.fracture() - else - BP.take_damage(70) - -/datum/genetics/side_effect/monkey //#Z2 Random monkey transform is back - name = "Monkey" - symptom = "Subject starts drooling uncontrollably." - treatment = "None." - effect = "Subject turns into monkey." - duration = 10*120 - -/datum/genetics/side_effect/monkey/start(mob/living/carbon/human/H) - H.emote("me", 1, "has drool running down from his mouth and hair starts to cover whole body.") - -/datum/genetics/side_effect/monkey/finish(mob/living/carbon/human/H) - H.monkeyize() - -/datum/genetics/side_effect/confuse - name = "Confuse" - symptom = "Subject starts drooling uncontrollably." - treatment = "None." - effect = "Subject becomes confused." - duration = 10*30 - -/datum/genetics/side_effect/confuse/start(mob/living/carbon/human/H) - H.emote("me", 1, "has drool running down from his mouth.") - -/datum/genetics/side_effect/confuse/finish(mob/living/carbon/human/H) - H.confused += 100 - -/datum/genetics/side_effect/bald_madness - name = "Bald madness" - symptom = "Subject becomes bald.." - treatment = "None." - effect = "Subject's head turns bald." - duration = 10*5 - -/datum/genetics/side_effect/bald_madness/start(mob/living/carbon/human/H) - H.emote("me", 1, "starts loosing his hair..") - -/datum/genetics/side_effect/bald_madness/finish(mob/living/carbon/human/H) - H.f_style = "Shaved" - H.h_style = "Skinhead" - H.update_hair() - -proc/trigger_side_effect(mob/living/carbon/human/H) - set waitfor = 0 - if(!H || !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) - - sleep(20) - if(!H || !istype(H)) - return - H.Weaken(rand(0, S.duration / 50)) - - sleep(S.duration) - if(!H || !istype(H)) - return - H.SetWeakened(0) - S.finish(H) +/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 = "None." + effect = "Subject's skin burns." + duration = 10*30 + +/datum/genetics/side_effect/genetic_burn/start(mob/living/carbon/human/H) + H.emote("me", 1, "starts turning very red..") + +/datum/genetics/side_effect/genetic_burn/finish(mob/living/carbon/human/H) + for(var/bodypart in list(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_R_LEG , BP_L_LEG , BP_HEAD , BP_GROIN)) + var/obj/item/organ/external/BP = H.bodyparts_by_name[bodypart] + if(prob(85))//#Z2 - now 15% chance even for more burn + BP.take_damage(0, 5, 0) + else + BP.take_damage(0, 20, 0) + +/datum/genetics/side_effect/bone_snap + name = "Bone Snap" + symptom = "Subject's limbs tremble notably." + treatment = "None." + effect = "Subject's bone breaks." + duration = 10*60 + +/datum/genetics/side_effect/bone_snap/start(mob/living/carbon/human/H) + H.emote("me", 1, "'s limbs start shivering uncontrollably.") + +/datum/genetics/side_effect/bone_snap/finish(mob/living/carbon/human/H) + var/bodypart = pick(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_R_LEG , BP_L_LEG , BP_HEAD , BP_GROIN) + var/obj/item/organ/external/BP = H.bodyparts_by_name[bodypart] + if(prob(85)) + BP.take_damage(20) + BP.fracture() + else + BP.take_damage(70) + +/datum/genetics/side_effect/monkey //#Z2 Random monkey transform is back + name = "Monkey" + symptom = "Subject starts drooling uncontrollably." + treatment = "None." + effect = "Subject turns into monkey." + duration = 10*120 + +/datum/genetics/side_effect/monkey/start(mob/living/carbon/human/H) + H.emote("me", 1, "has drool running down from his mouth and hair starts to cover whole body.") + +/datum/genetics/side_effect/monkey/finish(mob/living/carbon/human/H) + H.monkeyize() + +/datum/genetics/side_effect/confuse + name = "Confuse" + symptom = "Subject starts drooling uncontrollably." + treatment = "None." + effect = "Subject becomes confused." + duration = 10*30 + +/datum/genetics/side_effect/confuse/start(mob/living/carbon/human/H) + H.emote("me", 1, "has drool running down from his mouth.") + +/datum/genetics/side_effect/confuse/finish(mob/living/carbon/human/H) + H.confused += 100 + +/datum/genetics/side_effect/bald_madness + name = "Bald madness" + symptom = "Subject becomes bald.." + treatment = "None." + effect = "Subject's head turns bald." + duration = 10*5 + +/datum/genetics/side_effect/bald_madness/start(mob/living/carbon/human/H) + H.emote("me", 1, "starts loosing his hair..") + +/datum/genetics/side_effect/bald_madness/finish(mob/living/carbon/human/H) + H.f_style = "Shaved" + H.h_style = "Skinhead" + H.update_hair() + +proc/trigger_side_effect(mob/living/carbon/human/H) + set waitfor = 0 + if(!H || !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) + + sleep(20) + if(!H || !istype(H)) + return + H.Weaken(rand(0, S.duration / 50)) + + sleep(S.duration) + if(!H || !istype(H)) + return + H.SetWeakened(0) + S.finish(H) diff --git a/code/modules/holidays/new_year/new_year_mate.dm b/code/modules/holidays/new_year/new_year_mate.dm index ea7d7f6c5d1b..61dfd48235da 100644 --- a/code/modules/holidays/new_year/new_year_mate.dm +++ b/code/modules/holidays/new_year/new_year_mate.dm @@ -1,20 +1,20 @@ -////////////////////////////////////////////// -////////////////NewYearMate!////////////////// -////////////////////////////////////////////// - -/obj/machinery/vending/newyearmate - name = "NewYearMate" - desc = "A vending machine for new year clothing and decorations!" - icon = 'code/modules/holidays/new_year/new_year_mate.dmi' - icon_state = "NYM" - vend_delay = 10 - vend_reply = "Thank you for using the NewYearMate!" - products = list(/obj/item/clothing/head/santa = 50, /obj/item/clothing/head/santahat = 10, /obj/item/clothing/suit/santa = 10, /obj/item/clothing/head/ushanka = 30, /obj/item/clothing/under/sexy_santa = 10, /obj/item/weapon/present = 50, - /obj/item/decoration/garland = 30, /obj/item/decoration/tinsel = 30, /obj/item/decoration/snowflake = 10, /obj/item/decoration/snowman = 10, /obj/item/snowball = 500, /obj/item/clothing/suit/wintercoat = 40, /obj/item/clothing/shoes/winterboots = 40) - - contraband = list(/obj/item/clothing/suit/wintercoat/captain = 10, /obj/item/snowball = 100) - - premium = list(/obj/item/clothing/suit/wintercoat/captain = 3) - - prices = list(/obj/item/clothing/head/santa = 50, /obj/item/clothing/head/santahat = 200, /obj/item/clothing/suit/santa = 400, /obj/item/clothing/head/ushanka = 50, /obj/item/clothing/under/sexy_santa = 500, /obj/item/weapon/present = 500, - /obj/item/decoration/garland = 20, /obj/item/decoration/tinsel = 20, /obj/item/decoration/snowflake = 50, /obj/item/decoration/snowman = 300, /obj/item/snowball = 20, /obj/item/clothing/suit/wintercoat = 100, /obj/item/clothing/shoes/winterboots = 100) +////////////////////////////////////////////// +////////////////NewYearMate!////////////////// +////////////////////////////////////////////// + +/obj/machinery/vending/newyearmate + name = "NewYearMate" + desc = "A vending machine for new year clothing and decorations!" + icon = 'code/modules/holidays/new_year/new_year_mate.dmi' + icon_state = "NYM" + vend_delay = 10 + vend_reply = "Thank you for using the NewYearMate!" + products = list(/obj/item/clothing/head/santa = 50, /obj/item/clothing/head/santahat = 10, /obj/item/clothing/suit/santa = 10, /obj/item/clothing/head/ushanka = 30, /obj/item/clothing/under/sexy_santa = 10, /obj/item/weapon/present = 50, + /obj/item/decoration/garland = 30, /obj/item/decoration/tinsel = 30, /obj/item/decoration/snowflake = 10, /obj/item/decoration/snowman = 10, /obj/item/snowball = 500, /obj/item/clothing/suit/wintercoat = 40, /obj/item/clothing/shoes/winterboots = 40) + + contraband = list(/obj/item/clothing/suit/wintercoat/captain = 10, /obj/item/snowball = 100) + + premium = list(/obj/item/clothing/suit/wintercoat/captain = 3) + + prices = list(/obj/item/clothing/head/santa = 50, /obj/item/clothing/head/santahat = 200, /obj/item/clothing/suit/santa = 400, /obj/item/clothing/head/ushanka = 50, /obj/item/clothing/under/sexy_santa = 500, /obj/item/weapon/present = 500, + /obj/item/decoration/garland = 20, /obj/item/decoration/tinsel = 20, /obj/item/decoration/snowflake = 50, /obj/item/decoration/snowman = 300, /obj/item/snowball = 20, /obj/item/clothing/suit/wintercoat = 100, /obj/item/clothing/shoes/winterboots = 100) diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 2fb2180815fa..0594d93fd3aa 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -1,306 +1,306 @@ -/* Library Items - * - * Contains: - * Bookcase - * Book - * Barcode Scanner - */ - - -/* - * Bookcase - */ - -/obj/structure/bookcase - name = "bookcase" - icon = 'icons/obj/objects.dmi' - icon_state = "book-0" - anchored = 1 - density = 1 - opacity = 1 - -/obj/structure/bookcase/atom_init() - . = ..() - for(var/obj/item/I in loc) - if(istype(I, /obj/item/weapon/book)) - I.loc = src - update_icon() - -/obj/structure/bookcase/attackby(obj/O, mob/user) - if(istype(O, /obj/item/weapon/book)) - user.drop_item() - O.loc = src - update_icon() - else if(istype(O, /obj/item/weapon/pen)) - var/newname = sanitize_safe(input(usr, "What would you like to title this bookshelf?")) - if(!newname) - return - else - name = ("bookcase ([sanitize(newname)])") - else - ..() - -/obj/structure/bookcase/attack_hand(mob/user) - if(contents.len) - var/obj/item/weapon/book/choice = input("Which book would you like to remove from the shelf?") in contents as obj|null - if(choice) - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - return - if(ishuman(user)) - if(!user.get_active_hand()) - user.put_in_hands(choice) - else - choice.loc = get_turf(src) - update_icon() - -/obj/structure/bookcase/ex_act(severity) - switch(severity) - if(1.0) - for(var/obj/item/weapon/book/b in contents) - qdel(b) - qdel(src) - return - if(2.0) - for(var/obj/item/weapon/book/b in contents) - if (prob(50)) b.loc = (get_turf(src)) - else del(b) - qdel(src) - return - if(3.0) - if (prob(50)) - for(var/obj/item/weapon/book/b in contents) - b.loc = (get_turf(src)) - qdel(src) - return - else - return - -/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" - -/obj/structure/bookcase/manuals/medical/atom_init() - . = ..() - new /obj/item/weapon/book/manual/wiki/medical_surgery(src) - new /obj/item/weapon/book/manual/wiki/medical_genetics(src) - new /obj/item/weapon/book/manual/wiki/medical_virology(src) - new /obj/item/weapon/book/manual/wiki/medical_chemistry(src) - for (var/i in 1 to 3) - new /obj/item/weapon/book/manual/wiki/medical_guide_to_medicine(src) - update_icon() - - -/obj/structure/bookcase/manuals/engineering - name = "Engineering Manuals bookcase" - -/obj/structure/bookcase/manuals/engineering/atom_init() - . = ..() - new /obj/item/weapon/book/manual/wiki/basic_engineering(src) - new /obj/item/weapon/book/manual/wiki/construction(src) - new /obj/item/weapon/book/manual/wiki/atmospipes(src) - new /obj/item/weapon/book/manual/wiki/supermatter_engine(src) - new /obj/item/weapon/book/manual/wiki/engineering_hacking(src) - new /obj/item/weapon/book/manual/wiki/engineering_singularity(src) - new /obj/item/weapon/book/manual/wiki/engineering_solars(src) - new /obj/item/weapon/book/manual/wiki/engineering_tesla(src) - update_icon() - - -/obj/structure/bookcase/manuals/research_and_development - name = "R&D Manuals bookcase" - -/obj/structure/bookcase/manuals/research_and_development/atom_init() - . = ..() - new /obj/item/weapon/book/manual/wiki/research_and_development(src) - new /obj/item/weapon/book/manual/wiki/guide_to_robotics(src) - new /obj/item/weapon/book/manual/wiki/guide_to_toxins(src) - new /obj/item/weapon/book/manual/wiki/guide_to_xenobiology(src) - new /obj/item/weapon/book/manual/wiki/guide_to_exosuits(src) - new /obj/item/weapon/book/manual/wiki/guide_to_telescience(src) - update_icon() - -/obj/structure/bookcase/manuals/security - name = "Law and Order bookcase" - -/obj/structure/bookcase/manuals/security/atom_init() - . = ..() - for (var/i in 1 to 3) - new /obj/item/weapon/book/manual/wiki/security_space_law(src) - for (var/i in 1 to 2) - new /obj/item/weapon/book/manual/wiki/sop(src) - new /obj/item/weapon/book/manual/detective(src) - new /obj/item/weapon/book/manual/wiki/lsop(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) - attack_verb = list("bashed", "whacked", "educated") - 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/window_size - var/obj/item/store //What's in the book? - -/obj/item/weapon/book/attack_self(mob/user) - if(carved) - if(store) - to_chat(user, "[store] falls out of [title]!") - store.loc = get_turf(src.loc) - store = null - return - else - to_chat(user, "The pages of [title] have been cut out!") - return - if(src.dat) - user << browse(entity_ja("Penned by [author].
                    [dat]"), "window=book[window_size != null ? ";size=[window_size]" : ""]") - 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/attackby(obj/item/weapon/W, mob/user) - if(carved) - if(!store) - if(W.w_class < 3) - user.drop_item() - W.loc = 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 = sanitize_safe(input(usr, "Write a new title:"), MAX_NAME_LEN) - 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, MAX_BOOK_MESSAGE_LEN) - if(!content) - to_chat(usr, "The content is invalid.") - return - else - src.dat += content//infiniti books? - if("Author") - var/newauthor = sanitize(input(usr, "Write the author's name:"), MAX_NAME_LEN) - 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/kitchenknife) || istype(W, /obj/item/weapon/wirecutters)) - if(carved) return - if(user.is_busy()) return - to_chat(user, "You begin to carve out [title].") - if(do_after(user, 30, target = user)) - to_chat(user, "You carve out the pages from [title]! You didn't want to read it anyway.") - carved = 1 - return - else - ..() - -/obj/item/weapon/book/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) - if(def_zone == O_EYES) - user.visible_message("You open up the book and show it to [M]. ", \ - " [user] opens up a book and shows it to [M]. ") - M << browse(entity_ja("Penned by [author].
                    [dat]"), "window=book") - - -/* - * 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 = 2.0 - var/obj/machinery/computer/libraryconsole/bookmanagement/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) - 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/objects.dmi' + icon_state = "book-0" + anchored = 1 + density = 1 + opacity = 1 + +/obj/structure/bookcase/atom_init() + . = ..() + for(var/obj/item/I in loc) + if(istype(I, /obj/item/weapon/book)) + I.loc = src + update_icon() + +/obj/structure/bookcase/attackby(obj/O, mob/user) + if(istype(O, /obj/item/weapon/book)) + user.drop_item() + O.loc = src + update_icon() + else if(istype(O, /obj/item/weapon/pen)) + var/newname = sanitize_safe(input(usr, "What would you like to title this bookshelf?")) + if(!newname) + return + else + name = ("bookcase ([sanitize(newname)])") + else + ..() + +/obj/structure/bookcase/attack_hand(mob/user) + if(contents.len) + var/obj/item/weapon/book/choice = input("Which book would you like to remove from the shelf?") in contents as obj|null + if(choice) + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + return + if(ishuman(user)) + if(!user.get_active_hand()) + user.put_in_hands(choice) + else + choice.loc = get_turf(src) + update_icon() + +/obj/structure/bookcase/ex_act(severity) + switch(severity) + if(1.0) + for(var/obj/item/weapon/book/b in contents) + qdel(b) + qdel(src) + return + if(2.0) + for(var/obj/item/weapon/book/b in contents) + if (prob(50)) b.loc = (get_turf(src)) + else del(b) + qdel(src) + return + if(3.0) + if (prob(50)) + for(var/obj/item/weapon/book/b in contents) + b.loc = (get_turf(src)) + qdel(src) + return + else + return + +/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" + +/obj/structure/bookcase/manuals/medical/atom_init() + . = ..() + new /obj/item/weapon/book/manual/wiki/medical_surgery(src) + new /obj/item/weapon/book/manual/wiki/medical_genetics(src) + new /obj/item/weapon/book/manual/wiki/medical_virology(src) + new /obj/item/weapon/book/manual/wiki/medical_chemistry(src) + for (var/i in 1 to 3) + new /obj/item/weapon/book/manual/wiki/medical_guide_to_medicine(src) + update_icon() + + +/obj/structure/bookcase/manuals/engineering + name = "Engineering Manuals bookcase" + +/obj/structure/bookcase/manuals/engineering/atom_init() + . = ..() + new /obj/item/weapon/book/manual/wiki/basic_engineering(src) + new /obj/item/weapon/book/manual/wiki/construction(src) + new /obj/item/weapon/book/manual/wiki/atmospipes(src) + new /obj/item/weapon/book/manual/wiki/supermatter_engine(src) + new /obj/item/weapon/book/manual/wiki/engineering_hacking(src) + new /obj/item/weapon/book/manual/wiki/engineering_singularity(src) + new /obj/item/weapon/book/manual/wiki/engineering_solars(src) + new /obj/item/weapon/book/manual/wiki/engineering_tesla(src) + update_icon() + + +/obj/structure/bookcase/manuals/research_and_development + name = "R&D Manuals bookcase" + +/obj/structure/bookcase/manuals/research_and_development/atom_init() + . = ..() + new /obj/item/weapon/book/manual/wiki/research_and_development(src) + new /obj/item/weapon/book/manual/wiki/guide_to_robotics(src) + new /obj/item/weapon/book/manual/wiki/guide_to_toxins(src) + new /obj/item/weapon/book/manual/wiki/guide_to_xenobiology(src) + new /obj/item/weapon/book/manual/wiki/guide_to_exosuits(src) + new /obj/item/weapon/book/manual/wiki/guide_to_telescience(src) + update_icon() + +/obj/structure/bookcase/manuals/security + name = "Law and Order bookcase" + +/obj/structure/bookcase/manuals/security/atom_init() + . = ..() + for (var/i in 1 to 3) + new /obj/item/weapon/book/manual/wiki/security_space_law(src) + for (var/i in 1 to 2) + new /obj/item/weapon/book/manual/wiki/sop(src) + new /obj/item/weapon/book/manual/detective(src) + new /obj/item/weapon/book/manual/wiki/lsop(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) + attack_verb = list("bashed", "whacked", "educated") + 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/window_size + var/obj/item/store //What's in the book? + +/obj/item/weapon/book/attack_self(mob/user) + if(carved) + if(store) + to_chat(user, "[store] falls out of [title]!") + store.loc = get_turf(src.loc) + store = null + return + else + to_chat(user, "The pages of [title] have been cut out!") + return + if(src.dat) + user << browse(entity_ja("Penned by [author].
                    [dat]"), "window=book[window_size != null ? ";size=[window_size]" : ""]") + 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/attackby(obj/item/weapon/W, mob/user) + if(carved) + if(!store) + if(W.w_class < 3) + user.drop_item() + W.loc = 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 = sanitize_safe(input(usr, "Write a new title:"), MAX_NAME_LEN) + 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, MAX_BOOK_MESSAGE_LEN) + if(!content) + to_chat(usr, "The content is invalid.") + return + else + src.dat += content//infiniti books? + if("Author") + var/newauthor = sanitize(input(usr, "Write the author's name:"), MAX_NAME_LEN) + 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/kitchenknife) || istype(W, /obj/item/weapon/wirecutters)) + if(carved) return + if(user.is_busy()) return + to_chat(user, "You begin to carve out [title].") + if(do_after(user, 30, target = user)) + to_chat(user, "You carve out the pages from [title]! You didn't want to read it anyway.") + carved = 1 + return + else + ..() + +/obj/item/weapon/book/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) + if(def_zone == O_EYES) + user.visible_message("You open up the book and show it to [M]. ", \ + " [user] opens up a book and shows it to [M]. ") + M << browse(entity_ja("Penned by [author].
                    [dat]"), "window=book") + + +/* + * 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 = 2.0 + var/obj/machinery/computer/libraryconsole/bookmanagement/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) + 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 1b1bd734c986..03598d9a2126 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -1,540 +1,540 @@ -/* Library Machines - * - * Contains: - * Borrowbook datum - * Library Public Computer - * Library Computer - * Library Scanner - * Book Binder - */ - -#define LIBRETURNLIMIT 15 // how many entries we will display to the user per page. - -/* - * 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 - - -/* - * Library Public Computer - */ -/obj/machinery/computer/libraryconsole - name = "visitor computer" - icon = 'icons/obj/computer.dmi' - icon_state = "library" - circuit = /obj/item/weapon/circuitboard/libraryconsole - var/screenstate = 0 - var/title - var/category = "Any" - var/author - var/page = 0 - -/obj/machinery/computer/libraryconsole/ui_interact(mob/user) - var/dat = "Library Visitor\n" // - switch(screenstate) - if(0) - dat += {"

                    Search Settings


                    - Filter by Title: [title]
                    - Filter by Category: [category]
                    - Filter by Author: [author]
                    - \[Start Search\]
                    "} - if(1) - establish_old_db_connection() - if(!dbcon_old.IsConnected()) - dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance.
                    " - else - var/SQLquery = "SELECT author, title, category, id FROM library WHERE " - if(category == "Any") - SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%' LIMIT [page], [LIBRETURNLIMIT]" - else - SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%' AND category='[category]' LIMIT [page], [LIBRETURNLIMIT]" - dat += {" - "} - - var/DBQuery/query = dbcon_old.NewQuery(SQLquery) - query.Execute() - - while(query.NextRow()) - var/author = query.item[1] - var/title = query.item[2] - var/category = query.item[3] - var/id = query.item[4] - dat += "" - dat += "
                    AUTHORTITLECATEGORYSS13BN
                    [author][title][category][id]

                    " - dat += {" - \[Go Back\] - \[<< Page\] - \[< Page\] - \[Reset\] - \[Page >\] - \[Page >>\]
                    "} - - var/datum/browser/popup = new(user, "publiclibrary", name, 600, 600) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/libraryconsole/Topic(href, href_list) - . = ..() - if(!.) - return - - if(href_list["settitle"]) - var/newtitle = sanitize_safe(input("Enter a title to search for:") as text|null) - if(newtitle) - title = newtitle - else - title = null - title = sanitize_sql(title) - if(href_list["setcategory"]) - var/newcategory = input("Choose a category to search for:") in list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion") - if(newcategory) - category = newcategory - else - category = "Any" - category = sanitize_sql(category) - if(href_list["setauthor"]) - var/newauthor = sanitize(input("Enter an author to search for:") as text|null) - if(newauthor) - author = newauthor - else - author = null - author = sanitize_sql(author) - if(href_list["search"]) - screenstate = 1 - - if(href_list["back"]) - screenstate = 0 - - if(href_list["pageprev"] == "1") - page = max(0, page - LIBRETURNLIMIT) - - if(href_list["pageprev"] == "2") - page = max(0, page - (LIBRETURNLIMIT * 5)) - - if(href_list["pagereset"]) - page = 0 - - if(href_list["pagenext"] == "1") - page = min(page + LIBRETURNLIMIT, 10000) - - if(href_list["pagenext"] == "2") - page = min(page + (LIBRETURNLIMIT * 5), 10000) - - src.updateUsrDialog() - -/* - * Library Computer - * After 860 days, it's finally a buildable computer. - */ -/obj/machinery/computer/libraryconsole/bookmanagement - name = "Check-In/Out Computer" - var/arcanecheckout = 0 - screenstate = 0 // 0 - Main Menu, 1 - Inventory, 2 - Checked Out, 3 - Check Out a Book - var/buffer_book - var/buffer_mob - var/upload_category = "Fiction" - var/list/checkouts = list() - var/list/inventory = list() - var/checkoutperiod = 5 // In minutes - var/obj/machinery/libraryscanner/scanner // Book scanner that will be used when uploading books to the Archive - - var/bibledelay = 0 - -/obj/machinery/computer/libraryconsole/bookmanagement/atom_init() - . = ..() - if(circuit) - circuit.name = "circuit board (Book Inventory Management Console)" - circuit.build_path = /obj/machinery/computer/libraryconsole/bookmanagement - -/obj/machinery/computer/libraryconsole/bookmanagement/interact(mob/user) - user.set_machine(src) - var/dat = "Book Inventory Management\n" // - switch(screenstate) - if(0) - // Main Menu - dat += {"1. View General Inventory
                    - 2. View Checked Out Inventory
                    - 3. Check out a Book
                    - 4. Connect to External Archive
                    - 5. Upload New Title to Archive
                    - 6. Print a Bible
                    "} - if(src.emagged) - dat += "7. Access the Forbidden Lore Vault
                    " - if(src.arcanecheckout) - new /obj/item/weapon/book/tome/old(src.loc) - to_chat(user, "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a dusty old tome sitting on the desk. You don't really remember printing it.") - user.visible_message("[user] stares at the blank screen for a few moments, his expression frozen in fear. When he finally awakens from it, he looks a lot older.", 2) - src.arcanecheckout = 0 - if(1) - // Inventory - dat += "

                    Inventory


                    " - for(var/obj/item/weapon/book/b in inventory) - dat += "[b.name] (Delete)
                    " - dat += "(Return to main menu)
                    " - if(2) - // Checked Out - dat += "

                    Checked Out Books


                    " - for(var/datum/borrowbook/b in checkouts) - var/timetaken = world.time - b.getdate - //timetaken *= 10 - timetaken /= 600 - timetaken = round(timetaken) - var/timedue = b.duedate - world.time - //timedue *= 10 - timedue /= 600 - if(timedue <= 0) - timedue = "(OVERDUE) [timedue]" - else - timedue = round(timedue) - dat += {"\"[b.bookname]\", Checked out to: [b.mobname]
                    --- Taken: [timetaken] minutes ago, Due: in [timedue] minutes
                    - (Check In)

                    "} - dat += "(Return to main menu)
                    " - if(3) - // Check Out a Book - dat += {"

                    Check Out a Book


                    - Book: [src.buffer_book] - \[Edit\]
                    - Recipient: [src.buffer_mob] - \[Edit\]
                    - Checkout Date : [world.time/600]
                    - Due Date: [(world.time + checkoutperiod)/600]
                    - (Checkout Period: [checkoutperiod] minutes) (+/-) - (Commit Entry)
                    - (Return to main menu)
                    "} - if(4) - dat += "

                    External Archive

                    " - establish_old_db_connection() - if(!dbcon_old.IsConnected()) - dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance." - else - var/DBQuery/query = dbcon_old.NewQuery("SELECT id, author, title, category, deletereason FROM library LIMIT [page], [LIBRETURNLIMIT]") - query.Execute() - - var/first_id = null - var/last_id = null - - while(query.NextRow()) - last_id = query.item[1] - if(!first_id) - first_id = last_id - var/author = query.item[2] - var/title = query.item[3] - var/category = query.item[4] - var/deletereason = query.item[5] - dat += "[last_id][author][title][category]\[Order\][(deletereason == null) ? "\[Send removal request\]" : "MARKED FOR REMOVAL"]" - dat += "" - dat = {"(Order book by SS13BN)([first_id] - [last_id])

                    - - "} + dat - dat += {" -
                    (Return to main menu) - \[<< Page\] - \[< Page\] - \[Reset\] - \[Page >\] - \[Page >>\]
                    "} - if(5) - dat += "

                    Upload a New Title

                    " - if(!scanner) - for(var/obj/machinery/libraryscanner/S in range(9)) - scanner = S - break - if(!scanner) - dat += "No scanner found within wireless network range.
                    " - else if(!scanner.cache) - dat += "No data found in scanner memory.
                    " - else - dat += {"Data marked for upload...
                    - Title: [sanitize(scanner.cache.name)]
                    "} - if(!scanner.cache.author) - scanner.cache.author = "Anonymous" - dat += {"Author: [scanner.cache.author]
                    - Category: [upload_category]
                    - \[Upload\]
                    "} - dat += "(Return to main menu)
                    " - if(7) - dat += {"

                    Accessing Forbidden Lore Vault v 1.3

                    - Are you absolutely sure you want to proceed? EldritchTomes Inc. takes no responsibilities for loss of sanity resulting from this action.

                    - Yes.
                    - No.
                    "} - - var/datum/browser/popup = new(user, "library", name, 600, 600) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/libraryconsole/bookmanagement/attackby(obj/item/weapon/W, mob/user) - if (src.density && istype(W, /obj/item/weapon/card/emag)) - src.emagged = 1 - user.SetNextMove(CLICK_CD_INTERACT) - if(istype(W, /obj/item/weapon/barcodescanner)) - var/obj/item/weapon/barcodescanner/scanner = W - scanner.computer = src - to_chat(user, "[scanner]'s associated machine has been set to [src].") - for (var/mob/V in hearers(src)) - V.show_message("[src] lets out a low, short blip.", 2) - else - ..() - -/obj/machinery/computer/libraryconsole/bookmanagement/Topic(href, href_list) - . = ..() - if(!.) - return - - if(href_list["switchscreen"]) - switch(href_list["switchscreen"]) - if("0") - screenstate = 0 - if("1") - screenstate = 1 - if("2") - screenstate = 2 - if("3") - screenstate = 3 - if("4") - screenstate = 4 - if("5") - screenstate = 5 - if("6") - if(!bibledelay) - - var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(src.loc) - if(ticker && ( ticker.Bible_icon_state && ticker.Bible_item_state) ) - B.icon_state = ticker.Bible_icon_state - B.item_state = ticker.Bible_item_state - B.name = ticker.Bible_name - B.deity_name = ticker.Bible_deity_name - - bibledelay = 1 - spawn(60) - bibledelay = 0 - - else - for (var/mob/V in hearers(src)) - V.show_message("[src]'s monitor flashes, \"Bible printer currently unavailable, please wait a moment.\"") - - if("7") - screenstate = 7 - if(href_list["arccheckout"]) - if(src.emagged) - src.arcanecheckout = 1 - src.screenstate = 0 - if(href_list["increasetime"]) - checkoutperiod += 1 - if(href_list["decreasetime"]) - checkoutperiod -= 1 - if(checkoutperiod < 1) - checkoutperiod = 1 - if(href_list["editbook"]) - buffer_book = sanitize_safe(input("Enter the book's title:") as text|null, MAX_NAME_LEN) - if(href_list["editmob"]) - buffer_mob = sanitize(input("Enter the recipient's name:") as text|null, MAX_NAME_LEN) - if(href_list["checkout"]) - var/datum/borrowbook/b = new /datum/borrowbook - b.bookname = buffer_book - b.mobname = buffer_mob - b.getdate = world.time - b.duedate = world.time + (checkoutperiod * 600) - checkouts.Add(b) - if(href_list["checkin"]) - var/datum/borrowbook/b = locate(href_list["checkin"]) - checkouts.Remove(b) - if(href_list["delbook"]) - var/obj/item/weapon/book/b = locate(href_list["delbook"]) - inventory.Remove(b) - if(href_list["setauthor"]) - var/newauthor = sanitize(input("Enter the author's name: ") as text|null, MAX_NAME_LEN) - if(newauthor) - scanner.cache.author = newauthor - if(href_list["setcategory"]) - var/newcategory = input("Choose a category: ") in list("Fiction", "Non-Fiction", "Adult", "Reference", "Religion") - if(newcategory) - upload_category = newcategory - if(href_list["upload"]) - if(scanner) - if(scanner.cache) - var/choice = input("Are you certain you wish to upload this title to the Archive?") in list("Confirm", "Abort") - if(choice == "Confirm") - if(scanner.cache.unique) - alert("This book has been rejected from the database. Aborting!") - else - establish_old_db_connection() - if(!dbcon_old.IsConnected()) - alert("Connection to Archive has been severed. Aborting.") - else - /* - var/sqltitle = dbcon.Quote(scanner.cache.name) - var/sqlauthor = dbcon.Quote(scanner.cache.author) - var/sqlcontent = dbcon.Quote(scanner.cache.dat) - var/sqlcategory = dbcon.Quote(upload_category) - */ - var/sqltitle = sanitize_sql(scanner.cache.name) - var/sqlauthor = sanitize_sql(scanner.cache.author) - var/sqlcontent = sanitize_sql(scanner.cache.dat) - var/sqlcategory = sanitize_sql(upload_category) - var/sqlckey = sanitize_sql(usr.ckey) - var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO library (author, title, content, category, ckey) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[sqlckey]')") - if(!query.Execute()) - to_chat(usr, query.ErrorMsg()) - else - log_game("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] signs") - alert("Upload Complete.") - - if(href_list["targetid"]) - var/sqlid = sanitize_sql(href_list["targetid"]) - if(!sqlid) - return - - establish_old_db_connection() - if(!dbcon_old.IsConnected()) - alert("Connection to Archive has been severed. Aborting.") - if(bibledelay) - for (var/mob/V in hearers(src)) - V.show_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"") - else - bibledelay = 1 - spawn(60) - bibledelay = 0 - var/DBQuery/query = dbcon_old.NewQuery("SELECT * FROM library WHERE id='[sqlid]'") - query.Execute() - - while(query.NextRow()) - var/author = query.item[2] - var/title = query.item[3] - var/content = query.item[4] - var/obj/item/weapon/book/B = new(src.loc) - B.name = "Book: [title]" - B.title = title - B.author = author - B.dat = content - B.icon_state = "book[rand(1,10)]" - src.visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?") - break - - if(href_list["deleteid"]) - var/sqlid = sanitize_sql(href_list["deleteid"]) - if(!sqlid) - return - - establish_old_db_connection() - if(!dbcon_old.IsConnected()) - alert("Connection to Archive has been severed. Aborting.") - return - - var/DBQuery/query = dbcon_old.NewQuery("SELECT title, deletereason FROM library WHERE id='[sqlid]'") - if(!query.Execute()) - return - - - var/title - if(query.NextRow()) - title = query.item[1] - if(query.item[2] != null) - return - - var/reason = sanitize_sql(sanitize(input(usr,"Reason for removal","Enter reason (max 60 characters)") as text)) - if(length(reason) > 60) - alert("The reason is more than 60 characters long") - return - - if(!reason) - return - - query = dbcon_old.NewQuery("UPDATE library SET deletereason = '[reason]' WHERE id = '[sqlid]'") - query.Execute() - - message_admins("[usr.name]/[usr.ckey] requested removal of [title] from the library database") - - alert("Delete request sent.") - - if(href_list["orderbyid"]) - var/orderid = input("Enter your order:") as num|null - if(orderid) - if(isnum(orderid)) - var/nhref = "src=\ref[src];targetid=[orderid]" - spawn() src.Topic(nhref, params2list(nhref), src) - src.updateUsrDialog() - -/* - * Library 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 - -/obj/machinery/libraryscanner/attackby(obj/O, mob/user) - if(istype(O, /obj/item/weapon/book)) - user.drop_item() - O.loc = src - -/obj/machinery/libraryscanner/ui_interact(mob/user) - var/dat = "Scanner Control Interface\n" // - if(cache) - dat += "Data stored in memory.
                    " - else - dat += "No data stored in memory.
                    " - dat += "\[Scan\]" - if(contents.len) - dat += " \[Remove Book\]
                    " - - if(cache) - dat += " \[Clear Memory\]
                    " - else - dat += "
                    " - user << browse(entity_ja(dat), "window=scanner") - onclose(user, "scanner") - -/obj/machinery/libraryscanner/Topic(href, href_list) - . = ..() - if(!.) - 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.updateUsrDialog() - -/* - * Book binder - */ -/obj/machinery/bookbinder - name = "Book Binder" - icon = 'icons/obj/library.dmi' - icon_state = "binder" - anchored = 1 - density = 1 - -/obj/machinery/bookbinder/attackby(obj/O, mob/user) - if(istype(O, /obj/item/weapon/paper)) - user.drop_item() - O.loc = src - user.SetNextMove(CLICK_CD_MELEE) - 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,10)]" - qdel(O) - else - ..() - -#undef LIBRETURNLIMIT +/* Library Machines + * + * Contains: + * Borrowbook datum + * Library Public Computer + * Library Computer + * Library Scanner + * Book Binder + */ + +#define LIBRETURNLIMIT 15 // how many entries we will display to the user per page. + +/* + * 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 + + +/* + * Library Public Computer + */ +/obj/machinery/computer/libraryconsole + name = "visitor computer" + icon = 'icons/obj/computer.dmi' + icon_state = "library" + circuit = /obj/item/weapon/circuitboard/libraryconsole + var/screenstate = 0 + var/title + var/category = "Any" + var/author + var/page = 0 + +/obj/machinery/computer/libraryconsole/ui_interact(mob/user) + var/dat = "Library Visitor\n" // + switch(screenstate) + if(0) + dat += {"

                    Search Settings


                    + Filter by Title: [title]
                    + Filter by Category: [category]
                    + Filter by Author: [author]
                    + \[Start Search\]
                    "} + if(1) + establish_old_db_connection() + if(!dbcon_old.IsConnected()) + dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance.
                    " + else + var/SQLquery = "SELECT author, title, category, id FROM library WHERE " + if(category == "Any") + SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%' LIMIT [page], [LIBRETURNLIMIT]" + else + SQLquery += "author LIKE '%[author]%' AND title LIKE '%[title]%' AND category='[category]' LIMIT [page], [LIBRETURNLIMIT]" + dat += {"
                    IDAUTHORTITLECATEGORY
                    + "} + + var/DBQuery/query = dbcon_old.NewQuery(SQLquery) + query.Execute() + + while(query.NextRow()) + var/author = query.item[1] + var/title = query.item[2] + var/category = query.item[3] + var/id = query.item[4] + dat += "" + dat += "
                    AUTHORTITLECATEGORYSS13BN
                    [author][title][category][id]

                    " + dat += {" + \[Go Back\] + \[<< Page\] + \[< Page\] + \[Reset\] + \[Page >\] + \[Page >>\]
                    "} + + var/datum/browser/popup = new(user, "publiclibrary", name, 600, 600) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + +/obj/machinery/computer/libraryconsole/Topic(href, href_list) + . = ..() + if(!.) + return + + if(href_list["settitle"]) + var/newtitle = sanitize_safe(input("Enter a title to search for:") as text|null) + if(newtitle) + title = newtitle + else + title = null + title = sanitize_sql(title) + if(href_list["setcategory"]) + var/newcategory = input("Choose a category to search for:") in list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion") + if(newcategory) + category = newcategory + else + category = "Any" + category = sanitize_sql(category) + if(href_list["setauthor"]) + var/newauthor = sanitize(input("Enter an author to search for:") as text|null) + if(newauthor) + author = newauthor + else + author = null + author = sanitize_sql(author) + if(href_list["search"]) + screenstate = 1 + + if(href_list["back"]) + screenstate = 0 + + if(href_list["pageprev"] == "1") + page = max(0, page - LIBRETURNLIMIT) + + if(href_list["pageprev"] == "2") + page = max(0, page - (LIBRETURNLIMIT * 5)) + + if(href_list["pagereset"]) + page = 0 + + if(href_list["pagenext"] == "1") + page = min(page + LIBRETURNLIMIT, 10000) + + if(href_list["pagenext"] == "2") + page = min(page + (LIBRETURNLIMIT * 5), 10000) + + src.updateUsrDialog() + +/* + * Library Computer + * After 860 days, it's finally a buildable computer. + */ +/obj/machinery/computer/libraryconsole/bookmanagement + name = "Check-In/Out Computer" + var/arcanecheckout = 0 + screenstate = 0 // 0 - Main Menu, 1 - Inventory, 2 - Checked Out, 3 - Check Out a Book + var/buffer_book + var/buffer_mob + var/upload_category = "Fiction" + var/list/checkouts = list() + var/list/inventory = list() + var/checkoutperiod = 5 // In minutes + var/obj/machinery/libraryscanner/scanner // Book scanner that will be used when uploading books to the Archive + + var/bibledelay = 0 + +/obj/machinery/computer/libraryconsole/bookmanagement/atom_init() + . = ..() + if(circuit) + circuit.name = "circuit board (Book Inventory Management Console)" + circuit.build_path = /obj/machinery/computer/libraryconsole/bookmanagement + +/obj/machinery/computer/libraryconsole/bookmanagement/interact(mob/user) + user.set_machine(src) + var/dat = "Book Inventory Management\n" // + switch(screenstate) + if(0) + // Main Menu + dat += {"1. View General Inventory
                    + 2. View Checked Out Inventory
                    + 3. Check out a Book
                    + 4. Connect to External Archive
                    + 5. Upload New Title to Archive
                    + 6. Print a Bible
                    "} + if(src.emagged) + dat += "7. Access the Forbidden Lore Vault
                    " + if(src.arcanecheckout) + new /obj/item/weapon/book/tome/old(src.loc) + to_chat(user, "Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a dusty old tome sitting on the desk. You don't really remember printing it.") + user.visible_message("[user] stares at the blank screen for a few moments, his expression frozen in fear. When he finally awakens from it, he looks a lot older.", 2) + src.arcanecheckout = 0 + if(1) + // Inventory + dat += "

                    Inventory


                    " + for(var/obj/item/weapon/book/b in inventory) + dat += "[b.name] (Delete)
                    " + dat += "(Return to main menu)
                    " + if(2) + // Checked Out + dat += "

                    Checked Out Books


                    " + for(var/datum/borrowbook/b in checkouts) + var/timetaken = world.time - b.getdate + //timetaken *= 10 + timetaken /= 600 + timetaken = round(timetaken) + var/timedue = b.duedate - world.time + //timedue *= 10 + timedue /= 600 + if(timedue <= 0) + timedue = "(OVERDUE) [timedue]" + else + timedue = round(timedue) + dat += {"\"[b.bookname]\", Checked out to: [b.mobname]
                    --- Taken: [timetaken] minutes ago, Due: in [timedue] minutes
                    + (Check In)

                    "} + dat += "(Return to main menu)
                    " + if(3) + // Check Out a Book + dat += {"

                    Check Out a Book


                    + Book: [src.buffer_book] + \[Edit\]
                    + Recipient: [src.buffer_mob] + \[Edit\]
                    + Checkout Date : [world.time/600]
                    + Due Date: [(world.time + checkoutperiod)/600]
                    + (Checkout Period: [checkoutperiod] minutes) (+/-) + (Commit Entry)
                    + (Return to main menu)
                    "} + if(4) + dat += "

                    External Archive

                    " + establish_old_db_connection() + if(!dbcon_old.IsConnected()) + dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance." + else + var/DBQuery/query = dbcon_old.NewQuery("SELECT id, author, title, category, deletereason FROM library LIMIT [page], [LIBRETURNLIMIT]") + query.Execute() + + var/first_id = null + var/last_id = null + + while(query.NextRow()) + last_id = query.item[1] + if(!first_id) + first_id = last_id + var/author = query.item[2] + var/title = query.item[3] + var/category = query.item[4] + var/deletereason = query.item[5] + dat += "[last_id][author][title][category]\[Order\][(deletereason == null) ? "\[Send removal request\]" : "MARKED FOR REMOVAL"]" + dat += "" + dat = {"(Order book by SS13BN)([first_id] - [last_id])

                    + + "} + dat + dat += {" +
                    (Return to main menu) + \[<< Page\] + \[< Page\] + \[Reset\] + \[Page >\] + \[Page >>\]
                    "} + if(5) + dat += "

                    Upload a New Title

                    " + if(!scanner) + for(var/obj/machinery/libraryscanner/S in range(9)) + scanner = S + break + if(!scanner) + dat += "No scanner found within wireless network range.
                    " + else if(!scanner.cache) + dat += "No data found in scanner memory.
                    " + else + dat += {"Data marked for upload...
                    + Title: [sanitize(scanner.cache.name)]
                    "} + if(!scanner.cache.author) + scanner.cache.author = "Anonymous" + dat += {"Author: [scanner.cache.author]
                    + Category: [upload_category]
                    + \[Upload\]
                    "} + dat += "(Return to main menu)
                    " + if(7) + dat += {"

                    Accessing Forbidden Lore Vault v 1.3

                    + Are you absolutely sure you want to proceed? EldritchTomes Inc. takes no responsibilities for loss of sanity resulting from this action.

                    + Yes.
                    + No.
                    "} + + var/datum/browser/popup = new(user, "library", name, 600, 600) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + +/obj/machinery/computer/libraryconsole/bookmanagement/attackby(obj/item/weapon/W, mob/user) + if (src.density && istype(W, /obj/item/weapon/card/emag)) + src.emagged = 1 + user.SetNextMove(CLICK_CD_INTERACT) + if(istype(W, /obj/item/weapon/barcodescanner)) + var/obj/item/weapon/barcodescanner/scanner = W + scanner.computer = src + to_chat(user, "[scanner]'s associated machine has been set to [src].") + for (var/mob/V in hearers(src)) + V.show_message("[src] lets out a low, short blip.", 2) + else + ..() + +/obj/machinery/computer/libraryconsole/bookmanagement/Topic(href, href_list) + . = ..() + if(!.) + return + + if(href_list["switchscreen"]) + switch(href_list["switchscreen"]) + if("0") + screenstate = 0 + if("1") + screenstate = 1 + if("2") + screenstate = 2 + if("3") + screenstate = 3 + if("4") + screenstate = 4 + if("5") + screenstate = 5 + if("6") + if(!bibledelay) + + var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(src.loc) + if(ticker && ( ticker.Bible_icon_state && ticker.Bible_item_state) ) + B.icon_state = ticker.Bible_icon_state + B.item_state = ticker.Bible_item_state + B.name = ticker.Bible_name + B.deity_name = ticker.Bible_deity_name + + bibledelay = 1 + spawn(60) + bibledelay = 0 + + else + for (var/mob/V in hearers(src)) + V.show_message("[src]'s monitor flashes, \"Bible printer currently unavailable, please wait a moment.\"") + + if("7") + screenstate = 7 + if(href_list["arccheckout"]) + if(src.emagged) + src.arcanecheckout = 1 + src.screenstate = 0 + if(href_list["increasetime"]) + checkoutperiod += 1 + if(href_list["decreasetime"]) + checkoutperiod -= 1 + if(checkoutperiod < 1) + checkoutperiod = 1 + if(href_list["editbook"]) + buffer_book = sanitize_safe(input("Enter the book's title:") as text|null, MAX_NAME_LEN) + if(href_list["editmob"]) + buffer_mob = sanitize(input("Enter the recipient's name:") as text|null, MAX_NAME_LEN) + if(href_list["checkout"]) + var/datum/borrowbook/b = new /datum/borrowbook + b.bookname = buffer_book + b.mobname = buffer_mob + b.getdate = world.time + b.duedate = world.time + (checkoutperiod * 600) + checkouts.Add(b) + if(href_list["checkin"]) + var/datum/borrowbook/b = locate(href_list["checkin"]) + checkouts.Remove(b) + if(href_list["delbook"]) + var/obj/item/weapon/book/b = locate(href_list["delbook"]) + inventory.Remove(b) + if(href_list["setauthor"]) + var/newauthor = sanitize(input("Enter the author's name: ") as text|null, MAX_NAME_LEN) + if(newauthor) + scanner.cache.author = newauthor + if(href_list["setcategory"]) + var/newcategory = input("Choose a category: ") in list("Fiction", "Non-Fiction", "Adult", "Reference", "Religion") + if(newcategory) + upload_category = newcategory + if(href_list["upload"]) + if(scanner) + if(scanner.cache) + var/choice = input("Are you certain you wish to upload this title to the Archive?") in list("Confirm", "Abort") + if(choice == "Confirm") + if(scanner.cache.unique) + alert("This book has been rejected from the database. Aborting!") + else + establish_old_db_connection() + if(!dbcon_old.IsConnected()) + alert("Connection to Archive has been severed. Aborting.") + else + /* + var/sqltitle = dbcon.Quote(scanner.cache.name) + var/sqlauthor = dbcon.Quote(scanner.cache.author) + var/sqlcontent = dbcon.Quote(scanner.cache.dat) + var/sqlcategory = dbcon.Quote(upload_category) + */ + var/sqltitle = sanitize_sql(scanner.cache.name) + var/sqlauthor = sanitize_sql(scanner.cache.author) + var/sqlcontent = sanitize_sql(scanner.cache.dat) + var/sqlcategory = sanitize_sql(upload_category) + var/sqlckey = sanitize_sql(usr.ckey) + var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO library (author, title, content, category, ckey) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[sqlckey]')") + if(!query.Execute()) + to_chat(usr, query.ErrorMsg()) + else + log_game("[usr.name]/[usr.key] has uploaded the book titled [scanner.cache.name], [length(scanner.cache.dat)] signs") + alert("Upload Complete.") + + if(href_list["targetid"]) + var/sqlid = sanitize_sql(href_list["targetid"]) + if(!sqlid) + return + + establish_old_db_connection() + if(!dbcon_old.IsConnected()) + alert("Connection to Archive has been severed. Aborting.") + if(bibledelay) + for (var/mob/V in hearers(src)) + V.show_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"") + else + bibledelay = 1 + spawn(60) + bibledelay = 0 + var/DBQuery/query = dbcon_old.NewQuery("SELECT * FROM library WHERE id='[sqlid]'") + query.Execute() + + while(query.NextRow()) + var/author = query.item[2] + var/title = query.item[3] + var/content = query.item[4] + var/obj/item/weapon/book/B = new(src.loc) + B.name = "Book: [title]" + B.title = title + B.author = author + B.dat = content + B.icon_state = "book[rand(1,10)]" + src.visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?") + break + + if(href_list["deleteid"]) + var/sqlid = sanitize_sql(href_list["deleteid"]) + if(!sqlid) + return + + establish_old_db_connection() + if(!dbcon_old.IsConnected()) + alert("Connection to Archive has been severed. Aborting.") + return + + var/DBQuery/query = dbcon_old.NewQuery("SELECT title, deletereason FROM library WHERE id='[sqlid]'") + if(!query.Execute()) + return + + + var/title + if(query.NextRow()) + title = query.item[1] + if(query.item[2] != null) + return + + var/reason = sanitize_sql(sanitize(input(usr,"Reason for removal","Enter reason (max 60 characters)") as text)) + if(length(reason) > 60) + alert("The reason is more than 60 characters long") + return + + if(!reason) + return + + query = dbcon_old.NewQuery("UPDATE library SET deletereason = '[reason]' WHERE id = '[sqlid]'") + query.Execute() + + message_admins("[usr.name]/[usr.ckey] requested removal of [title] from the library database") + + alert("Delete request sent.") + + if(href_list["orderbyid"]) + var/orderid = input("Enter your order:") as num|null + if(orderid) + if(isnum(orderid)) + var/nhref = "src=\ref[src];targetid=[orderid]" + spawn() src.Topic(nhref, params2list(nhref), src) + src.updateUsrDialog() + +/* + * Library 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 + +/obj/machinery/libraryscanner/attackby(obj/O, mob/user) + if(istype(O, /obj/item/weapon/book)) + user.drop_item() + O.loc = src + +/obj/machinery/libraryscanner/ui_interact(mob/user) + var/dat = "Scanner Control Interface\n" // + if(cache) + dat += "Data stored in memory.
                    " + else + dat += "No data stored in memory.
                    " + dat += "\[Scan\]" + if(contents.len) + dat += " \[Remove Book\]
                    " + + if(cache) + dat += " \[Clear Memory\]
                    " + else + dat += "
                    " + user << browse(entity_ja(dat), "window=scanner") + onclose(user, "scanner") + +/obj/machinery/libraryscanner/Topic(href, href_list) + . = ..() + if(!.) + 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.updateUsrDialog() + +/* + * Book binder + */ +/obj/machinery/bookbinder + name = "Book Binder" + icon = 'icons/obj/library.dmi' + icon_state = "binder" + anchored = 1 + density = 1 + +/obj/machinery/bookbinder/attackby(obj/O, mob/user) + if(istype(O, /obj/item/weapon/paper)) + user.drop_item() + O.loc = src + user.SetNextMove(CLICK_CD_MELEE) + 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,10)]" + qdel(O) + else + ..() + +#undef LIBRETURNLIMIT diff --git a/code/modules/library/lib_readme.dm b/code/modules/library/lib_readme.dm index 4237687dfff8..0150ed6ba8a7 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 0713f28e9372..8ab3ecc82aa3 100644 --- a/code/modules/liquid/splash_simulation.dm +++ b/code/modules/liquid/splash_simulation.dm @@ -1,206 +1,206 @@ -#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/process() - //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/Destroy() - puddles -= src - for(var/obj/O in liquid_objects) - qdel(O) - return ..() - -/client/proc/splash() - 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, volume) - 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/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/effect/liquid/atom_init_late() - if( !isturf(loc) ) - qdel(src) - return - - for( var/obj/effect/liquid/L in loc ) - if(L != src) - qdel(L) - -/obj/effect/liquid/proc/spread() - - //world << "DEBUG: liquid spread!" - var/surrounding_volume = 0 - var/list/spread_directions = list(1,2,4,8) - var/turf/loc_turf = loc - for(var/direction in spread_directions) - var/turf/T = get_step(src,direction) - if(!T) - spread_directions.Remove(direction) - //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) - //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. - //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) - //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) - new_volume = 0 - update_icon2() - -/obj/effect/liquid/Move() - return 0 - -/obj/effect/liquid/Destroy() - src.controller.liquid_objects.Remove(src) - return ..() - -/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.dir in list(5,6,9,10)) - 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.dir in list(5,6,9,10)) - 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 +#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/process() + //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/Destroy() + puddles -= src + for(var/obj/O in liquid_objects) + qdel(O) + return ..() + +/client/proc/splash() + 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, volume) + 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/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/effect/liquid/atom_init_late() + if( !isturf(loc) ) + qdel(src) + return + + for( var/obj/effect/liquid/L in loc ) + if(L != src) + qdel(L) + +/obj/effect/liquid/proc/spread() + + //world << "DEBUG: liquid spread!" + var/surrounding_volume = 0 + var/list/spread_directions = list(1,2,4,8) + var/turf/loc_turf = loc + for(var/direction in spread_directions) + var/turf/T = get_step(src,direction) + if(!T) + spread_directions.Remove(direction) + //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) + //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. + //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) + //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) + new_volume = 0 + update_icon2() + +/obj/effect/liquid/Move() + return 0 + +/obj/effect/liquid/Destroy() + src.controller.liquid_objects.Remove(src) + return ..() + +/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.dir in list(5,6,9,10)) + 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.dir in list(5,6,9,10)) + 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/mining/machine_input_output_plates.dm b/code/modules/mining/machine_input_output_plates.dm index 134dc699f7c9..11bb289598b7 100644 --- a/code/modules/mining/machine_input_output_plates.dm +++ b/code/modules/mining/machine_input_output_plates.dm @@ -1,33 +1,33 @@ -/**********************Input and output plates**************************/ - -/obj/machinery/mineral/input - icon = 'icons/mob/screen1.dmi' - icon_state = "x2" - name = "Input area" - density = 0 - anchored = 1.0 - -/obj/machinery/mineral/input/atom_init() - . = ..() - icon_state = "blank" - -/obj/machinery/mineral/output - icon = 'icons/mob/screen1.dmi' - icon_state = "x" - name = "Output area" - density = 0 - anchored = 1.0 - -/obj/machinery/mineral/output/atom_init() - . = ..() - icon_state = "blank" - -/obj/machinery/mineral - var/input_dir = NORTH - var/output_dir = SOUTH - -/obj/machinery/mineral/proc/unload_mineral(atom/movable/S) - S.loc = loc - var/turf/T = get_step(src,output_dir) - if(T) - S.loc = T +/**********************Input and output plates**************************/ + +/obj/machinery/mineral/input + icon = 'icons/mob/screen1.dmi' + icon_state = "x2" + name = "Input area" + density = 0 + anchored = 1.0 + +/obj/machinery/mineral/input/atom_init() + . = ..() + icon_state = "blank" + +/obj/machinery/mineral/output + icon = 'icons/mob/screen1.dmi' + icon_state = "x" + name = "Output area" + density = 0 + anchored = 1.0 + +/obj/machinery/mineral/output/atom_init() + . = ..() + icon_state = "blank" + +/obj/machinery/mineral + var/input_dir = NORTH + var/output_dir = SOUTH + +/obj/machinery/mineral/proc/unload_mineral(atom/movable/S) + S.loc = loc + var/turf/T = get_step(src,output_dir) + if(T) + S.loc = T diff --git a/code/modules/mining/mine_areas.dm b/code/modules/mining/mine_areas.dm index 4506500fa29c..d949c08ad8ae 100644 --- a/code/modules/mining/mine_areas.dm +++ b/code/modules/mining/mine_areas.dm @@ -1,52 +1,52 @@ -/**********************Mine areas**************************/ - -/area/mine - icon_state = "mining" - music = 'sound/ambience/song_game.ogg' - -/area/mine/explored - name = "Mine" - icon_state = "explored" - -/area/mine/unexplored - name = "Mine" - icon_state = "unexplored" - -/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" +/**********************Mine areas**************************/ + +/area/mine + icon_state = "mining" + music = 'sound/ambience/song_game.ogg' + +/area/mine/explored + name = "Mine" + icon_state = "explored" + +/area/mine/unexplored + name = "Mine" + icon_state = "unexplored" + +/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" diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm index 427f69cdb06c..8d542c5cefe2 100644 --- a/code/modules/mining/money_bag.dm +++ b/code/modules/mining/money_bag.dm @@ -1,111 +1,111 @@ -/*****************************Money bag********************************/ - -/obj/item/weapon/moneybag - icon = 'icons/obj/storage.dmi' - name = "Money bag" - icon_state = "moneybag" - flags = CONDUCT - force = 10.0 - throwforce = 2.0 - w_class = 4.0 - -/obj/item/weapon/moneybag/attack_hand(user) - var/amt_gold = 0 - var/amt_silver = 0 - var/amt_diamond = 0 - var/amt_iron = 0 - var/amt_phoron = 0 - var/amt_uranium = 0 - var/amt_clown = 0 - - for (var/obj/item/weapon/coin/C in contents) - if (istype(C,/obj/item/weapon/coin/diamond)) - amt_diamond++; - if (istype(C,/obj/item/weapon/coin/phoron)) - amt_phoron++; - if (istype(C,/obj/item/weapon/coin/iron)) - amt_iron++; - if (istype(C,/obj/item/weapon/coin/silver)) - amt_silver++; - if (istype(C,/obj/item/weapon/coin/gold)) - amt_gold++; - if (istype(C,/obj/item/weapon/coin/uranium)) - amt_uranium++; - if (istype(C,/obj/item/weapon/coin/clown)) - amt_clown++; - if (istype(C,/obj/item/weapon/coin/platinum)) - amt_clown++; - - var/dat = text("The contents of the moneybag reveal...
                    ") - if (amt_gold) - dat += text("Gold coins: [amt_gold] Remove one
                    ") - if (amt_silver) - dat += text("Silver coins: [amt_silver] Remove one
                    ") - if (amt_iron) - dat += text("Metal coins: [amt_iron] Remove one
                    ") - if (amt_diamond) - dat += text("Diamond coins: [amt_diamond] Remove one
                    ") - if (amt_phoron) - dat += text("Phoron coins: [amt_phoron] Remove one
                    ") - if (amt_uranium) - dat += text("Uranium coins: [amt_uranium] Remove one
                    ") - if (amt_clown) - dat += text("Bananium coins: [amt_clown] Remove one
                    ") - if (amt_clown) - dat += text("Platinum coins: [amt_clown] Remove one
                    ") - user << browse("[entity_ja(dat)]", "window=moneybag") - -/obj/item/weapon/moneybag/attackby(obj/item/weapon/W, mob/user) - ..() - if (istype(W, /obj/item/weapon/coin)) - var/obj/item/weapon/coin/C = W - to_chat(user, "\blue You add the [C.name] into the bag.") - user.drop_item() - contents += C - 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, "\blue 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/obj/item/weapon/coin/COIN - switch(href_list["remove"]) - if("gold") - COIN = locate(/obj/item/weapon/coin/gold,src.contents) - if("silver") - COIN = locate(/obj/item/weapon/coin/silver,src.contents) - if("iron") - COIN = locate(/obj/item/weapon/coin/iron,src.contents) - if("diamond") - COIN = locate(/obj/item/weapon/coin/diamond,src.contents) - if("phoron") - COIN = locate(/obj/item/weapon/coin/phoron,src.contents) - if("uranium") - COIN = locate(/obj/item/weapon/coin/uranium,src.contents) - if("clown") - COIN = locate(/obj/item/weapon/coin/clown,src.contents) - if("platinum") - COIN = locate(/obj/item/weapon/coin/platinum,src.contents) - if(!COIN) - return - COIN.loc = src.loc - return - - - -/obj/item/weapon/moneybag/vault - -/obj/item/weapon/moneybag/vault/atom_init() - . = ..() - for (var/i in 1 to 4) - new /obj/item/weapon/coin/silver(src) - for (var/i in 1 to 2) - new /obj/item/weapon/coin/gold(src) - new /obj/item/weapon/coin/platinum(src) +/*****************************Money bag********************************/ + +/obj/item/weapon/moneybag + icon = 'icons/obj/storage.dmi' + name = "Money bag" + icon_state = "moneybag" + flags = CONDUCT + force = 10.0 + throwforce = 2.0 + w_class = 4.0 + +/obj/item/weapon/moneybag/attack_hand(user) + var/amt_gold = 0 + var/amt_silver = 0 + var/amt_diamond = 0 + var/amt_iron = 0 + var/amt_phoron = 0 + var/amt_uranium = 0 + var/amt_clown = 0 + + for (var/obj/item/weapon/coin/C in contents) + if (istype(C,/obj/item/weapon/coin/diamond)) + amt_diamond++; + if (istype(C,/obj/item/weapon/coin/phoron)) + amt_phoron++; + if (istype(C,/obj/item/weapon/coin/iron)) + amt_iron++; + if (istype(C,/obj/item/weapon/coin/silver)) + amt_silver++; + if (istype(C,/obj/item/weapon/coin/gold)) + amt_gold++; + if (istype(C,/obj/item/weapon/coin/uranium)) + amt_uranium++; + if (istype(C,/obj/item/weapon/coin/clown)) + amt_clown++; + if (istype(C,/obj/item/weapon/coin/platinum)) + amt_clown++; + + var/dat = text("The contents of the moneybag reveal...
                    ") + if (amt_gold) + dat += text("Gold coins: [amt_gold] Remove one
                    ") + if (amt_silver) + dat += text("Silver coins: [amt_silver] Remove one
                    ") + if (amt_iron) + dat += text("Metal coins: [amt_iron] Remove one
                    ") + if (amt_diamond) + dat += text("Diamond coins: [amt_diamond] Remove one
                    ") + if (amt_phoron) + dat += text("Phoron coins: [amt_phoron] Remove one
                    ") + if (amt_uranium) + dat += text("Uranium coins: [amt_uranium] Remove one
                    ") + if (amt_clown) + dat += text("Bananium coins: [amt_clown] Remove one
                    ") + if (amt_clown) + dat += text("Platinum coins: [amt_clown] Remove one
                    ") + user << browse("[entity_ja(dat)]", "window=moneybag") + +/obj/item/weapon/moneybag/attackby(obj/item/weapon/W, mob/user) + ..() + if (istype(W, /obj/item/weapon/coin)) + var/obj/item/weapon/coin/C = W + to_chat(user, "\blue You add the [C.name] into the bag.") + user.drop_item() + contents += C + 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, "\blue 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/obj/item/weapon/coin/COIN + switch(href_list["remove"]) + if("gold") + COIN = locate(/obj/item/weapon/coin/gold,src.contents) + if("silver") + COIN = locate(/obj/item/weapon/coin/silver,src.contents) + if("iron") + COIN = locate(/obj/item/weapon/coin/iron,src.contents) + if("diamond") + COIN = locate(/obj/item/weapon/coin/diamond,src.contents) + if("phoron") + COIN = locate(/obj/item/weapon/coin/phoron,src.contents) + if("uranium") + COIN = locate(/obj/item/weapon/coin/uranium,src.contents) + if("clown") + COIN = locate(/obj/item/weapon/coin/clown,src.contents) + if("platinum") + COIN = locate(/obj/item/weapon/coin/platinum,src.contents) + if(!COIN) + return + COIN.loc = src.loc + return + + + +/obj/item/weapon/moneybag/vault + +/obj/item/weapon/moneybag/vault/atom_init() + . = ..() + for (var/i in 1 to 4) + new /obj/item/weapon/coin/silver(src) + for (var/i in 1 to 2) + new /obj/item/weapon/coin/gold(src) + new /obj/item/weapon/coin/platinum(src) diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm index d77e19022859..ec9438334e14 100644 --- a/code/modules/mob/camera/camera.dm +++ b/code/modules/mob/camera/camera.dm @@ -1,7 +1,7 @@ -/mob/camera - name = "camera mob" - density = 0 - status_flags = GODMODE // You can't damage it. - mouse_opacity = 0 - see_in_dark = 7 - invisibility = 101 // No one can see us +/mob/camera + name = "camera mob" + density = 0 + status_flags = GODMODE // You can't damage it. + mouse_opacity = 0 + see_in_dark = 7 + invisibility = 101 // No one can see us diff --git a/code/modules/mob/dead/new_player/sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories.dm index 16f8a8707a30..0340696b71ca 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories.dm @@ -1,1466 +1,1466 @@ -/* - 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 - -/* -//////////////////////////// -/ =--------------------= / -/ == Hair Definitions == / -/ =--------------------= / -//////////////////////////// -*/ - -/datum/sprite_accessory/hair - icon = 'icons/mob/human_face.dmi' // default icon for all hairs - -/datum/sprite_accessory/hair/bald - name = "Bald" - icon_state = "bald" - gender = MALE - -/datum/sprite_accessory/hair/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 - -/datum/sprite_accessory/hair/shorthair2 - name = "Short Hair 2" - icon_state = "hair_shorthair2" - -//datum/sprite_accessory/hair/shorthair3 -// name = "Short Hair 3" -// icon_state = "hair_shorthair3" - -/datum/sprite_accessory/hair/cut - name = "Cut Hair" - icon_state = "hair_c" - -/datum/sprite_accessory/hair/long - name = "Shoulder-length Hair" - icon_state = "hair_b" - -/datum/sprite_accessory/hair/longer - name = "Long Hair" - icon_state = "hair_vlong" - -//datum/sprite_accessory/hair/over_eye -// name = "Over Eye" -// icon_state = "hair_shortovereye" - -/datum/sprite_accessory/hair/long_over_eye - name = "Long Over Eye" - icon_state = "hair_longovereye" - -//datum/sprite_accessory/hair/longest2 -// name = "Very Long Over Eye" -// icon_state = "hair_longest2" - -/datum/sprite_accessory/hair/longest - name = "Very Long Hair" - icon_state = "hair_longest" - -/datum/sprite_accessory/hair/longfringe - name = "Long Fringe" - icon_state = "hair_longfringe" - -/datum/sprite_accessory/hair/longestalt - name = "Longer Fringe" - icon_state = "hair_vlongfringe" - -/datum/sprite_accessory/hair/gentle - name = "Gentle" - icon_state = "hair_gentle" - -/datum/sprite_accessory/hair/halfbang - name = "Half-banged Hair" - icon_state = "hair_halfbang" - -/datum/sprite_accessory/hair/halfbang2 - name = "Half-banged Hair 2" - icon_state = "hair_halfbang2" - -/datum/sprite_accessory/hair/ponytail1 - name = "Ponytail" - icon_state = "hair_ponytail" - -/datum/sprite_accessory/hair/ponytail2 - name = "Ponytail 2" - icon_state = "hair_ponytail2" - -/datum/sprite_accessory/hair/ponytail3 - name = "Ponytail 3" - icon_state = "hair_ponytail3" - -//datum/sprite_accessory/hair/ponytail4 -// name = "Ponytail 4" -// icon_state = "hair_ponytail4" - -//datum/sprite_accessory/hair/ponytail5 -// name = "Ponytail 5" -// icon_state = "hair_ponytail5" - -/datum/sprite_accessory/hair/sidetail - name = "Side Pony" - icon_state = "hair_sidetail" - -/datum/sprite_accessory/hair/sidetail2 - name = "Side Pony 2" - icon_state = "hair_sidetail2" - -//datum/sprite_accessory/hair/sidetail3 -// name = "Side Pony 3" -// icon_state = "hair_sidetail3" - -//datum/sprite_accessory/hair/sidetail4 -// name = "Side Pony 4" -// icon_state = "hair_sidetail4" - -/datum/sprite_accessory/hair/sideponytail - name = "Side Pony tail" - icon_state = "hair_poofy" - -/datum/sprite_accessory/hair/oneshoulder - name = "One Shoulder" - icon_state = "hair_oneshoulder" - -/datum/sprite_accessory/hair/tressshoulder - name = "Tress Shoulder" - icon_state = "hair_tressshoulder" - -/datum/sprite_accessory/hair/parted - name = "Parted" - icon_state = "hair_parted" - -/datum/sprite_accessory/hair/pompadour - name = "Pompadour" - icon_state = "hair_pompadour" - gender = MALE - -/datum/sprite_accessory/hair/bigpompadour - name = "Big Pompadour" - icon_state = "hair_bigpompadour" - gender = MALE - -/datum/sprite_accessory/hair/quiff - name = "Quiff" - icon_state = "hair_quiff" - gender = MALE - -/datum/sprite_accessory/hair/bedhead - name = "Bedhead" - icon_state = "hair_bedhead" - -/datum/sprite_accessory/hair/bedhead2 - name = "Bedhead 2" - icon_state = "hair_bedheadv2" - -/datum/sprite_accessory/hair/bedhead3 - name = "Bedhead 3" - icon_state = "hair_bedheadv3" - -/datum/sprite_accessory/hair/messy - name = "Messy" - icon_state = "hair_messy" - -/datum/sprite_accessory/hair/beehive - name = "Beehive" - icon_state = "hair_beehive" - gender = FEMALE - -//datum/sprite_accessory/hair/beehive2 -// name = "Beehive 2" -// icon_state = "hair_beehivev2" -// gender = FEMALE - -/datum/sprite_accessory/hair/bobcurl - name = "Bobcurl" - icon_state = "hair_bobcurl" - gender = FEMALE - -/datum/sprite_accessory/hair/bob - name = "Bob" - icon_state = "hair_bobcut" - gender = FEMALE - -/datum/sprite_accessory/hair/bowl - name = "Bowl" - icon_state = "hair_bowlcut" - gender = MALE - -/datum/sprite_accessory/hair/buzz - name = "Buzzcut" - icon_state = "hair_buzzcut" - gender = MALE - -/datum/sprite_accessory/hair/crew - name = "Crewcut" - icon_state = "hair_crewcut" - gender = MALE - -/datum/sprite_accessory/hair/combover - name = "Combover" - icon_state = "hair_combover" - gender = MALE - -/datum/sprite_accessory/hair/devillock - name = "Devil Lock" - icon_state = "hair_devilock" - -/datum/sprite_accessory/hair/dreadlocks - name = "Dreadlocks" - icon_state = "hair_dreads" - -/datum/sprite_accessory/hair/curls - name = "Curls" - icon_state = "hair_curls" - -/datum/sprite_accessory/hair/afro - name = "Afro" - icon_state = "hair_afro" - -/datum/sprite_accessory/hair/afro2 - name = "Afro 2" - icon_state = "hair_afro2" - -/datum/sprite_accessory/hair/afro_large - name = "Big Afro" - icon_state = "hair_bigafro" - gender = MALE - -/datum/sprite_accessory/hair/sargeant - name = "Flat Top" - icon_state = "hair_sargeant" - gender = MALE - -/datum/sprite_accessory/hair/emo - name = "Emo" - icon_state = "hair_emo" - -//datum/sprite_accessory/hair/longemo -// name = "Long Emo" -// icon_state = "hair_longemo" - -/datum/sprite_accessory/hair/fag - name = "Flow Hair" - icon_state = "hair_f" - -/datum/sprite_accessory/hair/feather - name = "Feather" - icon_state = "hair_feather" - -/datum/sprite_accessory/hair/hitop - name = "Hitop" - icon_state = "hair_hitop" - gender = MALE - -/datum/sprite_accessory/hair/mohawk - name = "Mohawk" - icon_state = "hair_d" - -//datum/sprite_accessory/hair/reversemohawk -// name = "Reverse Mohawk" -// icon_state = "hair_reversemohawk" - -/datum/sprite_accessory/hair/jensen - name = "Jensen Hair" - icon_state = "hair_jensen" - gender = MALE - -/datum/sprite_accessory/hair/gelled - name = "Gelled Back" - icon_state = "hair_gelled" - gender = FEMALE - -/datum/sprite_accessory/hair/spiky - name = "Spiky" - icon_state = "hair_spikey" - -/datum/sprite_accessory/hair/spiky2 - name = "Spiky 2" - icon_state = "hair_crono" - -/datum/sprite_accessory/hair/spiky3 - name = "Spiky 3" - icon_state = "hair_vegeta" - -/datum/sprite_accessory/hair/protagonist - name = "Slightly long" - icon_state = "hair_protagonist" - -/datum/sprite_accessory/hair/kusangi - name = "Kusanagi Hair" - icon_state = "hair_kusanagi" - -/datum/sprite_accessory/hair/kagami - name = "Kagami Hair" - icon_state = "hair_kagami" - gender = FEMALE - -/datum/sprite_accessory/hair/pigtail - name = "Pigtails" - icon_state = "hair_pigtails" - gender = FEMALE - -/datum/sprite_accessory/hair/pigtail2 - name = "Pigtails 2" - icon_state = "hair_nitori" - gender = FEMALE - -//datum/sprite_accessory/hair/pigtail3 -// name = "Pigtails 3" -// icon_state = "hair_pigtails3" -// gender = FEMALE - -/datum/sprite_accessory/hair/himecut - name = "Hime Cut" - icon_state = "hair_himecut" - gender = FEMALE - -//datum/sprite_accessory/hair/himecut2 -// name = "Hime Cut 2" -// icon_state = "hair_himecut2" -// gender = FEMALE - -//datum/sprite_accessory/hair/himeup -// name = "Hime Updo" -// icon_state = "hair_himeup" - -/datum/sprite_accessory/hair/antenna - name = "Ahoge" - icon_state = "hair_antenna" - -/datum/sprite_accessory/hair/lowbraid - name = "Low Braid" - icon_state = "hair_hbraid" - gender = FEMALE - -/datum/sprite_accessory/hair/not_floorlength_braid - name = "High Braid" - icon_state = "hair_braid2" - gender = FEMALE - -//datum/sprite_accessory/hair/shortbraid -// name = "Short Braid" -// icon_state = "hair_shortbraid" -// gender = FEMALE - -/datum/sprite_accessory/hair/braid - name = "Floorlength Braid" - icon_state = "hair_braid" - gender = FEMALE - -/datum/sprite_accessory/hair/odango - name = "Odango" - icon_state = "hair_odango" - gender = FEMALE - -/datum/sprite_accessory/hair/ombre - name = "Ombre" - icon_state = "hair_ombre" - gender = FEMALE - -/datum/sprite_accessory/hair/updo - name = "Updo" - icon_state = "hair_updo" - gender = FEMALE - -/datum/sprite_accessory/hair/skinhead - name = "Skinhead" - icon_state = "hair_skinhead" - -//datum/sprite_accessory/hair/longbangs -// name = "Long Bangs" -// icon_state = "hair_lbangs" - -/datum/sprite_accessory/hair/balding - name = "Balding Hair" - icon_state = "hair_e" - gender = MALE // turnoff! - -//datum/sprite_accessory/hair/parted -// name = "Side Part" -// icon_state = "hair_part" - -//datum/sprite_accessory/hair/braided -// name = "Braided" -// icon_state = "hair_braided" - -/datum/sprite_accessory/hair/bun - name = "Bun Head" - icon_state = "hair_bun" - -//datum/sprite_accessory/hair/bun2 -// name = "Bun Head 2" -// icon_state = "hair_bunhead2" - -/datum/sprite_accessory/hair/braidtail - name = "Braided Tail" - icon_state = "hair_braidtail" - -//datum/sprite_accessory/hair/bigflattop -// name = "Big Flat Top" -// icon_state = "hair_bigflattop" - -/datum/sprite_accessory/hair/drillhair - name = "Drill Hair" - icon_state = "hair_drillhair" - -/datum/sprite_accessory/hair/keanu - name = "Keanu Hair" - icon_state = "hair_edgeworth" - -//datum/sprite_accessory/hair/swept -// name = "Swept Back Hair" -// icon_state = "hair_swept" - -/datum/sprite_accessory/hair/swept2 - name = "Swept Back Hair 2" - icon_state = "hair_joestar" - -//datum/sprite_accessory/hair/business -// name = "Business Hair" -// icon_state = "hair_business" - -//datum/sprite_accessory/hair/business2 -// name = "Business Hair 2" -// icon_state = "hair_business2" - -/datum/sprite_accessory/hair/business3 - name = "Business Hair 3" - icon_state = "hair_cia" - -/datum/sprite_accessory/hair/business4 - name = "Business Hair 4" - icon_state = "hair_mulder" - -/datum/sprite_accessory/hair/hedgehog - name = "Hedgehog Hair" - icon_state = "hair_blackswordsman" - -/datum/sprite_accessory/hair/bob - name = "Bob Hair" - icon_state = "hair_schierke" - -/datum/sprite_accessory/hair/bob2 - name = "Bob Hair 2" - icon_state = "hair_scully" - -/datum/sprite_accessory/hair/long - name = "Long Hair 1" - icon_state = "hair_nia" - -//datum/sprite_accessory/hair/long2 -// name = "Long Hair 2" -// icon_state = "hair_long2" - -//datum/sprite_accessory/hair/pixie -// name = "Pixie Cut" -// icon_state = "hair_pixie" - -/datum/sprite_accessory/hair/megaeyebrows - name = "Mega Eyebrows" - icon_state = "hair_megaeyebrows" - -//datum/sprite_accessory/hair/highponytail -// name = "High Ponytail" -// icon_state = "hair_highponytail" - -//datum/sprite_accessory/hair/longponytail -// name = "Long Ponytail" -// icon_state = "hair_longstraightponytail" - -//datum/sprite_accessory/hair/sidepartlongalt -// name = "Long Side Part" -// icon_state = "hair_longsidepart" - -/datum/sprite_accessory/hair/flair - name = "Flaired Hair" - icon_state = "hair_flair" - -//datum/sprite_accessory/hair/himecut3 -// name = "Hime Cut 3" -// icon_state = "hair_himecut3" -// gender = FEMALE - -/datum/sprite_accessory/hair/big_tails - name = "Big tails" - icon_state = "hair_long_d_tails" - gender = FEMALE - -/datum/sprite_accessory/hair/long_bedhead - name = "Long bedhead" - icon_state = "hair_long_bedhead" - gender = FEMALE - -/datum/sprite_accessory/hair/fluttershy - name = "Fluttershy" - icon_state = "hair_fluttershy" - gender = FEMALE - -/datum/sprite_accessory/hair/judge - name = "Judge" - icon_state = "hair_judge" - gender = FEMALE - -/datum/sprite_accessory/hair/long_braid - name = "Long braid" - icon_state = "hair_long_braid" - gender = FEMALE - -/datum/sprite_accessory/hair/elize - name = "Elize" - icon_state = "hair_elize" - gender = FEMALE - -/datum/sprite_accessory/hair/elize2 - name = "Elize2" - icon_state = "hair_elize_2" - gender = FEMALE - -/datum/sprite_accessory/hair/undercut_fem - name = "Female undercut" - icon_state = "hair_undercut_fem" - gender = FEMALE - -/datum/sprite_accessory/hair/emo_right - name = "Emo right" - icon_state = "hair_emo_r" - -/datum/sprite_accessory/hair/applejack - name = "Applejack" - icon_state = "hair_applejack" - gender = FEMALE - -/datum/sprite_accessory/hair/rosa - name = "Rosa" - icon_state = "hair_rosa" - gender = FEMALE - -//TC trap powah -/datum/sprite_accessory/hair/dave - name = "Dave" - icon_state = "hair_dave" - -/datum/sprite_accessory/hair/aradia - name = "Aradia" - icon_state = "hair_aradia" - -/datum/sprite_accessory/hair/nepeta - name = "Nepeta" - icon_state = "hair_nepeta" - -/datum/sprite_accessory/hair/kanaya - name = "Kanaya" - icon_state = "hair_kanaya" - -/datum/sprite_accessory/hair/terezi - name = "Terezi" - icon_state = "hair_terezi" - -/datum/sprite_accessory/hair/vriska - name = "Vriska" - icon_state = "hair_vriska" - -/datum/sprite_accessory/hair/equius - name = "Equius" - icon_state = "hair_equius" - -/datum/sprite_accessory/hair/gamzee - name = "Gamzee" - icon_state = "hair_gamzee" - -/datum/sprite_accessory/hair/feferi - name = "Feferi" - icon_state = "hair_feferi" - -/datum/sprite_accessory/hair/rose - name = "Rose" - icon_state = "hair_rose" - -/datum/sprite_accessory/hair/ramona - name = "Ramona" - icon_state = "hair_ramona" - -/datum/sprite_accessory/hair/dirk - name = "Dirk" - icon_state = "hair_dirk" - -/datum/sprite_accessory/hair/jade - name = "Jade" - icon_state = "hair_jade" - -/datum/sprite_accessory/hair/roxy - name = "Roxy" - icon_state = "hair_roxy" - -/datum/sprite_accessory/hair/side_tail3 - name = "Side tail 3" - icon_state = "hair_stail" - -/datum/sprite_accessory/hair/familyman - name = "Big Flat Top" - icon_state = "hair_thefamilyman" - -/datum/sprite_accessory/hair/dubsman - name = "Dubs Hair " - icon_state = "hair_dubs" - -/datum/sprite_accessory/hair/objection - name = "Swept Back Hair" - icon_state = "hair_objection" - -/datum/sprite_accessory/hair/metal - name = "Metal" - icon_state = "hair_80s" - -/datum/sprite_accessory/hair/mentalist - name = "Mentalist" - icon_state = "hair_mentalist" - -/datum/sprite_accessory/hair/fujisaki - name = "fujisaki" - icon_state = "hair_fujisaki" - -/datum/sprite_accessory/hair/akari - name = "Twin Buns" - icon_state = "hair_akari" - -/datum/sprite_accessory/hair/fujiyabashi - name = "Fujiyabashi" - icon_state = "hair_fujiyabashi" - -/datum/sprite_accessory/hair/shinobu - name = "Shinibu" - icon_state = "hair_shinobu" - -/datum/sprite_accessory/hair/combed - name = "Combed Hair" - icon_state = "hair_combed" - -/datum/sprite_accessory/hair/longsidepart - name = "Long Sideparts" - icon_state = "hair_longsidepartstraight" - -/datum/sprite_accessory/hair/bluntbangs - name = "Blunt Bangs" - icon_state = "hair_bluntbangs" - -/datum/sprite_accessory/hair/combedbob - name = "Combed Bob" - icon_state = "hair_combedbob" - -/datum/sprite_accessory/hair/halfshavedlong - name = "Long Half Shaved" - icon_state = "hair_halfshaved" - -/datum/sprite_accessory/hair/slighlymessy - name = "Slightly Messed" - icon_state = "hair_slightlymessy" - -/datum/sprite_accessory/hair/gypsy - name = "Long Gypsy" - icon_state = "hair_gipsy" - -/datum/sprite_accessory/hair/geisha - name = "Geisha" - icon_state = "hair_geisha" - -/datum/sprite_accessory/hair/fullovereye - name = "Hair Over Eye" - icon_state = "hair_baum" - -/datum/sprite_accessory/hair/chub - name = "Chub" - icon_state = "hair_chub" - -/datum/sprite_accessory/hair/ponytail6 - name = "Ponytail female" - icon_state = "hair_ponytailf" - gender = FEMALE - -/datum/sprite_accessory/hair/wisp - name = "Wisp" - icon_state = "hair_wisp" - gender = FEMALE - -/datum/sprite_accessory/hair/halfshaved - name = "Half-Shaved Emo" - icon_state = "hair_halfshaved2" - -/datum/sprite_accessory/hair/longeralt2 - name = "Long Hair Alt 2" - icon_state = "hair_longeralt2" - -/datum/sprite_accessory/hair/bun4 - name = "Bun 4" - icon_state = "hair_bun4" - -/datum/sprite_accessory/hair/doublebun - name = "Double-Bun" - icon_state = "hair_doublebun" - -/datum/sprite_accessory/hair/rows - name = "Rows" - icon_state = "hair_rows1" - -/datum/sprite_accessory/hair/rows2 - name = "Rows 2" - icon_state = "hair_rows2" - -/datum/sprite_accessory/hair/twintail - name = "Twintail" - icon_state = "hair_twintail" - -/datum/sprite_accessory/hair/coffeehouse - name = "Coffee House Cut" - icon_state = "hair_coffeehouse" - gender = MALE - -/datum/sprite_accessory/hair/veryshortovereye - name = "Overeye Very Short" - icon_state = "hair_veryshortovereye" - -/datum/sprite_accessory/hair/oxton - name = "Oxton" - icon_state = "hair_oxton" - -/datum/sprite_accessory/hair/zieglertail - name = "Zieglertail" - icon_state = "hair_ziegler" - -/datum/sprite_accessory/hair/fringeemo - name = "Emo Fringe" - icon_state = "hair_emofringe" - -/datum/sprite_accessory/hair/poofy2 - name = "Poofy2" - icon_state = "hair_poofy2" - -/datum/sprite_accessory/hair/fringetail - name = "Fringetail" - icon_state = "hair_fringetail" - -/datum/sprite_accessory/hair/bun3 - name = "Bun 3" - icon_state = "hair_bun3" - -/datum/sprite_accessory/hair/veryshortovereyealternate - name = "Overeye Very Short, Alternate" - icon_state = "hair_veryshortovereyealternate" - -/datum/sprite_accessory/hair/undercut2 - name = "Undercut Swept Right" - icon_state = "hair_undercut2" - gender = MALE - -/datum/sprite_accessory/hair/spikyponytail - name = "Spiky Ponytail" - icon_state = "hair_spikyponytail" - -/datum/sprite_accessory/hair/grandebraid - name = "Grande Braid" - icon_state = "hair_grande" - -/datum/sprite_accessory/hair/fringetail - name = "Fringetail" - icon_state = "hair_fringetail" - -/datum/sprite_accessory/hair/rowbun - name = "Row Bun" - icon_state = "hair_rowbun" - -/datum/sprite_accessory/hair/rowdualbraid - name = "Row Dual Braid" - icon_state = "hair_rowdualtail" - -/datum/sprite_accessory/hair/rowbraid - name = "Row Braid" - icon_state = "hair_rowbraid" - -/datum/sprite_accessory/hair/regulationmohawk - name = "Regulation Mohawk" - icon_state = "hair_shavedmohawk" - -/datum/sprite_accessory/hair/topknot - name = "Topknot" - icon_state = "hair_topknot" - -/datum/sprite_accessory/hair/ronin - name = "Ronin" - icon_state = "hair_ronin" - -/datum/sprite_accessory/hair/bowlcut2 - name = "Bowl 2" - icon_state = "hair_bowlcut2" - -/datum/sprite_accessory/hair/manbun - name = "Manbun" - icon_state = "hair_manbun" - -/datum/sprite_accessory/hair/country - name = "Country" - icon_state = "hair_country" - -/datum/sprite_accessory/hair/ougi - name = "Ougi" - icon_state = "hair_ougi" - -//datum/sprite_accessory/hair/modern -// name = "Modern" -// icon_state = "hair_modern" -// gender = FEMALE - -//datum/sprite_accessory/hair/twincurl -// name = "Twincurl" -// icon_state = "hair_twincurl" -// gender = FEMALE - -//datum/sprite_accessory/hair/rapunzel -// name = "Rapunzel" -// icon_state = "hair_rapunzel" -// gender = FEMALE - -//datum/sprite_accessory/hair/quadcurls -// name = "Quadcurls" -// icon_state = "hair_quadcurls" -// gender = FEMALE - -//datum/sprite_accessory/hair/twincurl2 -// name = "Twincurl 2" -// icon_state = "hair_twincurl2" -// gender = FEMALE - -//datum/sprite_accessory/hair/birdnest -// name = "Birdnest " -// icon_state = "hair_birdnest" - -//datum/sprite_accessory/hair/unkept -// name = "Unkept" -// icon_state = "hair_unkept" - -//datum/sprite_accessory/hair/fastline -// name = "Fastline" -// icon_state = "hair_fastline" -// gender = MALE - -//datum/sprite_accessory/hair/duelist -// name = "Duelist " -// icon_state = "hair_duelist" - -//datum/sprite_accessory/hair/sparta -// name = "Sparta hair" -// icon_state = "hair_sparta" - - -/* -/////////////////////////////////// -/ =---------------------------= / -/ == 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) - -/datum/sprite_accessory/facial_hair/shaved - name = "Shaved" - icon_state = "bald" - gender = NEUTER - species_allowed = list(HUMAN , UNATHI , TAJARAN , SKRELL , VOX , IPC, DIONA) - -/datum/sprite_accessory/facial_hair/watson - name = "Watson Mustache" - icon_state = "facial_watson" - -/datum/sprite_accessory/facial_hair/hogan - name = "Hulk Hogan Mustache" - icon_state = "facial_hogan" //-Neek - -/datum/sprite_accessory/facial_hair/vandyke - name = "Van Dyke Mustache" - icon_state = "facial_vandyke" - -/datum/sprite_accessory/facial_hair/chaplin - name = "Square Mustache" - icon_state = "facial_chaplin" - -/datum/sprite_accessory/facial_hair/selleck - name = "Selleck Mustache" - icon_state = "facial_selleck" - -/datum/sprite_accessory/facial_hair/neckbeard - name = "Neckbeard" - icon_state = "facial_neckbeard" - -/datum/sprite_accessory/facial_hair/fullbeard - name = "Full Beard" - icon_state = "facial_fullbeard" - -/datum/sprite_accessory/facial_hair/longbeard - name = "Long Beard" - icon_state = "facial_longbeard" - -/datum/sprite_accessory/facial_hair/vlongbeard - name = "Very Long Beard" - icon_state = "facial_wise" - -/datum/sprite_accessory/facial_hair/elvis - name = "Elvis Sideburns" - icon_state = "facial_elvis" - -/datum/sprite_accessory/facial_hair/abe - name = "Abraham Lincoln Beard" - icon_state = "facial_abe" - -/datum/sprite_accessory/facial_hair/chinstrap - name = "Chinstrap" - icon_state = "facial_chin" - -/datum/sprite_accessory/facial_hair/hip - name = "Hipster Beard" - icon_state = "facial_hip" - -/datum/sprite_accessory/facial_hair/gt - name = "Goatee" - icon_state = "facial_gt" - -/datum/sprite_accessory/facial_hair/jensen - name = "Jensen Beard" - icon_state = "facial_jensen" - -/datum/sprite_accessory/facial_hair/dwarf - name = "Dwarf Beard" - icon_state = "facial_dwarf" - -//datum/sprite_accessory/facial_hair/fiveoclock -// name = "Five o Clock Shadow" -// icon_state = "facial_fiveoclock" - -//datum/sprite_accessory/facial_hair/fu -// name = "Fu Manchu" -// icon_state = "facial_fumanchu" - -/datum/sprite_accessory/facial_hair/postal - name = "Goat Beard" - icon_state = "facial_goatbeard" - -//datum/sprite_accessory/facial_hair/britstache -// name = "Britstache" -// icon_state = "facial_britstache" - -//datum/sprite_accessory/facial_hair/martial_artist -// name = "Martial Artist" -// icon_state = "facial_martialartist" - -//datum/sprite_accessory/facial_hair/moonshiner -// name = "Moonshiner" -// icon_state = "facial_moonshiner" - -//datum/sprite_accessory/facial_hair/tribeard -// name = "Tri-Beard" -// icon_state = "facial_tribeard" - -//datum/sprite_accessory/facial_hair/unshaven -// name = "Unshaven" -// icon_state = "facial_unshaven" - - -/* -/////////////////////////////////// -/ =---------------------------= / -/ == Alien Style Definitions == / -/ =---------------------------= / -/////////////////////////////////// -*/ - -/datum/sprite_accessory/hair/ipc_screen_pink - name = "pink IPC screen" - icon_state = "ipc_pink" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_red - name = "red IPC screen" - icon_state = "ipc_red" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_green - name = "green IPC screen" - icon_state = "ipc_green" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_blue - name = "blue IPC screen" - icon_state = "ipc_blue" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_breakout - name = "breakout IPC screen" - icon_state = "ipc_breakout" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_eight - name = "eight IPC screen" - icon_state = "ipc_eight" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_goggles - name = "goggles IPC screen" - icon_state = "ipc_goggles" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_heart - name = "heart IPC screen" - icon_state = "ipc_heart" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_monoeye - name = "monoeye IPC screen" - icon_state = "ipc_monoeye" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_nature - name = "nature IPC screen" - icon_state = "ipc_nature" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_orange - name = "orange IPC screen" - icon_state = "ipc_orange" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_purple - name = "purple IPC screen" - icon_state = "ipc_purple" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_shower - name = "shower IPC screen" - icon_state = "ipc_shower" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_static - name = "static IPC screen" - icon_state = "ipc_static" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_yellow - name = "yellow IPC screen" - icon_state = "ipc_yellow" - species_allowed = list(IPC) - do_colouration = FALSE - -/datum/sprite_accessory/hair/ipc_screen_dot - name = "dot IPC screen" - icon_state = "ipc_dot" - species_allowed = list(IPC) - -/datum/sprite_accessory/hair/ipc_screen_four - name = "four IPC screen" - icon_state = "ipc_four" - species_allowed = list(IPC) - -/datum/sprite_accessory/hair/ipc_screen_eye - name = "eye IPC screen" - icon_state = "ipc_eye" - species_allowed = list(IPC) - -/datum/sprite_accessory/hair/ipc_screen_eyes - name = "eyes IPC screen" - icon_state = "ipc_eyes" - species_allowed = list(IPC) - -/datum/sprite_accessory/hair/unathi_warrior_horns - name = "Warrior Horns" - icon_state = "una_warrior_horns" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/unathi_smallhorns - name = "Small Horns" - icon_state = "una_smallhorns" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/unathi_dreads - name = "Dreads" - icon_state = "una_dreads" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/unathi_dreads_long - name = "Long Dreads" - icon_state = "una_dreads_long" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/unathi_dreads_short - name = "Short Dreads" - icon_state = "una_dreads_short" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/unathi_dreads_predator - name = "Predator Dreads" - icon_state = "una_dreads_predator" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/unathi_hiss_collinss - name = "Hiss Collinss" - icon_state = "una_hiss_collinss" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/unathi_horns_curled - name = "Curled Horns" - icon_state = "una_horns_curled" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/unathi_horns_ram - name = "Ram Horns" - icon_state = "una_horns_ram" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/una_spines_long - name = "Long Unathi Spines" - icon_state = "una_longspines" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/una_spines_short - name = "Short Unathi Spines" - icon_state = "una_shortspines" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/una_frills_long - name = "Long Unathi Frills" - icon_state = "una_longfrills" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/una_frills_short - name = "Short Unathi Frills" - icon_state = "una_shortfrills" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/una_horns - name = "Unathi Horns" - icon_state = "una_horns" - species_allowed = list(UNATHI) - -/datum/sprite_accessory/hair/skr_tentacle_m - name = "Skrell Male Tentacles" - icon_state = "skr_hair_m" - species_allowed = list(SKRELL) - gender = MALE - -/datum/sprite_accessory/hair/skr_tentacle_f - name = "Skrell Female Tentacles" - icon_state = "skr_hair_f" - species_allowed = list(SKRELL) - gender = FEMALE - -/datum/sprite_accessory/hair/skr_gold_m - name = "Gold plated Skrell Male Tentacles" - icon_state = "skr_goldhair_m" - species_allowed = list(SKRELL) - gender = MALE - -/datum/sprite_accessory/hair/skr_gold_f - name = "Gold chained Skrell Female Tentacles" - icon_state = "skr_goldhair_f" - species_allowed = list(SKRELL) - gender = FEMALE - -/datum/sprite_accessory/hair/skr_clothtentacle_m - name = "Cloth draped Skrell Male Tentacles" - icon_state = "skr_clothhair_m" - species_allowed = list(SKRELL) - gender = MALE - -/datum/sprite_accessory/hair/skr_clothtentacle_f - name = "Cloth draped Skrell Female Tentacles" - icon_state = "skr_clothhair_f" - species_allowed = list(SKRELL) - gender = FEMALE - -/datum/sprite_accessory/hair/taj_ears - name = "Tajaran Ears" - icon_state = "taj_ears_plain" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_clean - name = "Tajara Clean" - icon_state = "taj_hair_clean" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_bangs - name = "Tajara Bangs" - icon_state = "taj_hair_bangs" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_braid - name = "Tajara Braid" - icon_state = "taj_hair_tbraid" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_shaggy - name = "Tajara Shaggy" - icon_state = "taj_hair_shaggy" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_mohawk - name = "Tajaran Mohawk" - icon_state = "taj_hair_mohawk" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_plait - name = "Tajara Plait" - icon_state = "taj_hair_plait" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_straight - name = "Tajara Straight" - icon_state = "taj_hair_straight" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_long - name = "Tajara Long" - icon_state = "taj_hair_long" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_rattail - name = "Tajara Rat Tail" - icon_state = "taj_hair_rattail" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_spiky - name = "Tajara Spiky" - icon_state = "taj_hair_tajspiky" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_messy - name = "Tajara Messy" - icon_state = "taj_hair_messy" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_tailshort - name = "Tajara Short Tail" - icon_state = "taj_hair_shorttail" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ears_messylong - name = "Tajara Long Messy" - icon_state = "taj_hair_messylong" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_sidebraid - name = "Tajara Side Braid" - icon_state = "taj_hair_sidebraid" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ribbons - name = "Tajara Ribbons" - icon_state = "taj_hair_ribbons" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_earrings - name = "Tajara Ear Rings" - icon_state = "taj_hair_earrings" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_combedback - name = "Tajara Combed Back" - icon_state = "taj_hair_combedback" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_tailedbangs - name = "Tajara Tailed Bangs" - icon_state = "taj_hair_tailedbangs" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_punk - name = "Tajara Punk" - icon_state = "taj_hair_punk" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_marmalade - name = "Tajara Marmalade" - icon_state = "taj_hair_marmalade" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_lynx - name = "Tajara Lynx" - icon_state = "taj_hair_lynx" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_longtail - name = "Tajara Long Tail" - icon_state = "taj_hair_longtail" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_shy - name = "Tajara Shy" - icon_state = "taj_hair_shy" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_metal - name = "Tajara Metal" - icon_state = "taj_hair_metal" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_ponytail - name = "Tajara Ponytail" - icon_state = "taj_hair_ponytail" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_overeye - name = "Tajara Over Eye" - icon_state = "taj_hair_overeye" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_tough - name = "Tajara Tough" - icon_state = "taj_hair_tough" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_cuttail - name = "Tajara Cut Tail" - icon_state = "taj_hair_cuttail" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/taj_dreadlocks - name = "Tajara Dreadlocks" - icon_state = "taj_hair_dreadlocks" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/vox_quills_short - name = "Short Vox Quills" - icon_state = "vox_shortquills" - species_allowed = list(VOX) - -/datum/sprite_accessory/facial_hair/taj_sideburns - name = "Tajara Sideburns" - icon_state = "taj_facial_sideburns" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/facial_hair/taj_mutton - name = "Tajara Mutton" - icon_state = "taj_facial_mutton" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/facial_hair/taj_pencilstache - name = "Tajara Pencilstache" - icon_state = "taj_facial_pencilstache" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/facial_hair/taj_moustache - name = "Tajara Moustache" - icon_state = "taj_facial_moustache" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/facial_hair/taj_goatee - name = "Tajara Goatee" - icon_state = "taj_facial_goatee" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/facial_hair/taj_smallstache - name = "Tajara Smallsatche" - icon_state = "taj_facial_smallstache" - species_allowed = list(TAJARAN) - -/datum/sprite_accessory/hair/dio_bloom - name = "Diona Everbloom" - icon_state = "dio_bloom" - do_colouration = FALSE - species_allowed = list(DIONA) - -/datum/sprite_accessory/hair/dio_rose - name = "Diona Rose" - icon_state = "dio_rose" - do_colouration = FALSE - species_allowed = list(DIONA) - -/datum/sprite_accessory/hair/dio_king - name = "Diona Flowerking" - icon_state = "dio_king" - do_colouration = FALSE - species_allowed = list(DIONA) - -/datum/sprite_accessory/hair/dio_vines - name = "Diona Vines Short" - icon_state = "dio_vines" - do_colouration = FALSE - species_allowed = list(DIONA) - -/datum/sprite_accessory/hair/dio_vinel - name = "Diona Vines Long" - icon_state = "dio_vinel" - do_colouration = FALSE - species_allowed = list(DIONA) - -/datum/sprite_accessory/hair/dio_lotus - name = "Diona Lotus" - icon_state = "dio_lotus" - do_colouration = FALSE - species_allowed = list(DIONA) - -/datum/sprite_accessory/hair/dio_palm - name = "Diona Palmhead" - icon_state = "dio_palm" - do_colouration = FALSE - species_allowed = list(DIONA) - -/datum/sprite_accessory/hair/dio_garland - name = "Diona Garland" - icon_state = "dio_garland" - do_colouration = FALSE - species_allowed = list(DIONA) - -/datum/sprite_accessory/hair/dio_shrub - name = "Diona Shrub" - icon_state = "dio_shrub" - do_colouration = FALSE - species_allowed = list(DIONA) - -/datum/sprite_accessory/hair/dio_ficus - name = "Diona Ficus" - icon_state = "dio_ficus" - do_colouration = FALSE +/* + 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 + +/* +//////////////////////////// +/ =--------------------= / +/ == Hair Definitions == / +/ =--------------------= / +//////////////////////////// +*/ + +/datum/sprite_accessory/hair + icon = 'icons/mob/human_face.dmi' // default icon for all hairs + +/datum/sprite_accessory/hair/bald + name = "Bald" + icon_state = "bald" + gender = MALE + +/datum/sprite_accessory/hair/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 + +/datum/sprite_accessory/hair/shorthair2 + name = "Short Hair 2" + icon_state = "hair_shorthair2" + +//datum/sprite_accessory/hair/shorthair3 +// name = "Short Hair 3" +// icon_state = "hair_shorthair3" + +/datum/sprite_accessory/hair/cut + name = "Cut Hair" + icon_state = "hair_c" + +/datum/sprite_accessory/hair/long + name = "Shoulder-length Hair" + icon_state = "hair_b" + +/datum/sprite_accessory/hair/longer + name = "Long Hair" + icon_state = "hair_vlong" + +//datum/sprite_accessory/hair/over_eye +// name = "Over Eye" +// icon_state = "hair_shortovereye" + +/datum/sprite_accessory/hair/long_over_eye + name = "Long Over Eye" + icon_state = "hair_longovereye" + +//datum/sprite_accessory/hair/longest2 +// name = "Very Long Over Eye" +// icon_state = "hair_longest2" + +/datum/sprite_accessory/hair/longest + name = "Very Long Hair" + icon_state = "hair_longest" + +/datum/sprite_accessory/hair/longfringe + name = "Long Fringe" + icon_state = "hair_longfringe" + +/datum/sprite_accessory/hair/longestalt + name = "Longer Fringe" + icon_state = "hair_vlongfringe" + +/datum/sprite_accessory/hair/gentle + name = "Gentle" + icon_state = "hair_gentle" + +/datum/sprite_accessory/hair/halfbang + name = "Half-banged Hair" + icon_state = "hair_halfbang" + +/datum/sprite_accessory/hair/halfbang2 + name = "Half-banged Hair 2" + icon_state = "hair_halfbang2" + +/datum/sprite_accessory/hair/ponytail1 + name = "Ponytail" + icon_state = "hair_ponytail" + +/datum/sprite_accessory/hair/ponytail2 + name = "Ponytail 2" + icon_state = "hair_ponytail2" + +/datum/sprite_accessory/hair/ponytail3 + name = "Ponytail 3" + icon_state = "hair_ponytail3" + +//datum/sprite_accessory/hair/ponytail4 +// name = "Ponytail 4" +// icon_state = "hair_ponytail4" + +//datum/sprite_accessory/hair/ponytail5 +// name = "Ponytail 5" +// icon_state = "hair_ponytail5" + +/datum/sprite_accessory/hair/sidetail + name = "Side Pony" + icon_state = "hair_sidetail" + +/datum/sprite_accessory/hair/sidetail2 + name = "Side Pony 2" + icon_state = "hair_sidetail2" + +//datum/sprite_accessory/hair/sidetail3 +// name = "Side Pony 3" +// icon_state = "hair_sidetail3" + +//datum/sprite_accessory/hair/sidetail4 +// name = "Side Pony 4" +// icon_state = "hair_sidetail4" + +/datum/sprite_accessory/hair/sideponytail + name = "Side Pony tail" + icon_state = "hair_poofy" + +/datum/sprite_accessory/hair/oneshoulder + name = "One Shoulder" + icon_state = "hair_oneshoulder" + +/datum/sprite_accessory/hair/tressshoulder + name = "Tress Shoulder" + icon_state = "hair_tressshoulder" + +/datum/sprite_accessory/hair/parted + name = "Parted" + icon_state = "hair_parted" + +/datum/sprite_accessory/hair/pompadour + name = "Pompadour" + icon_state = "hair_pompadour" + gender = MALE + +/datum/sprite_accessory/hair/bigpompadour + name = "Big Pompadour" + icon_state = "hair_bigpompadour" + gender = MALE + +/datum/sprite_accessory/hair/quiff + name = "Quiff" + icon_state = "hair_quiff" + gender = MALE + +/datum/sprite_accessory/hair/bedhead + name = "Bedhead" + icon_state = "hair_bedhead" + +/datum/sprite_accessory/hair/bedhead2 + name = "Bedhead 2" + icon_state = "hair_bedheadv2" + +/datum/sprite_accessory/hair/bedhead3 + name = "Bedhead 3" + icon_state = "hair_bedheadv3" + +/datum/sprite_accessory/hair/messy + name = "Messy" + icon_state = "hair_messy" + +/datum/sprite_accessory/hair/beehive + name = "Beehive" + icon_state = "hair_beehive" + gender = FEMALE + +//datum/sprite_accessory/hair/beehive2 +// name = "Beehive 2" +// icon_state = "hair_beehivev2" +// gender = FEMALE + +/datum/sprite_accessory/hair/bobcurl + name = "Bobcurl" + icon_state = "hair_bobcurl" + gender = FEMALE + +/datum/sprite_accessory/hair/bob + name = "Bob" + icon_state = "hair_bobcut" + gender = FEMALE + +/datum/sprite_accessory/hair/bowl + name = "Bowl" + icon_state = "hair_bowlcut" + gender = MALE + +/datum/sprite_accessory/hair/buzz + name = "Buzzcut" + icon_state = "hair_buzzcut" + gender = MALE + +/datum/sprite_accessory/hair/crew + name = "Crewcut" + icon_state = "hair_crewcut" + gender = MALE + +/datum/sprite_accessory/hair/combover + name = "Combover" + icon_state = "hair_combover" + gender = MALE + +/datum/sprite_accessory/hair/devillock + name = "Devil Lock" + icon_state = "hair_devilock" + +/datum/sprite_accessory/hair/dreadlocks + name = "Dreadlocks" + icon_state = "hair_dreads" + +/datum/sprite_accessory/hair/curls + name = "Curls" + icon_state = "hair_curls" + +/datum/sprite_accessory/hair/afro + name = "Afro" + icon_state = "hair_afro" + +/datum/sprite_accessory/hair/afro2 + name = "Afro 2" + icon_state = "hair_afro2" + +/datum/sprite_accessory/hair/afro_large + name = "Big Afro" + icon_state = "hair_bigafro" + gender = MALE + +/datum/sprite_accessory/hair/sargeant + name = "Flat Top" + icon_state = "hair_sargeant" + gender = MALE + +/datum/sprite_accessory/hair/emo + name = "Emo" + icon_state = "hair_emo" + +//datum/sprite_accessory/hair/longemo +// name = "Long Emo" +// icon_state = "hair_longemo" + +/datum/sprite_accessory/hair/fag + name = "Flow Hair" + icon_state = "hair_f" + +/datum/sprite_accessory/hair/feather + name = "Feather" + icon_state = "hair_feather" + +/datum/sprite_accessory/hair/hitop + name = "Hitop" + icon_state = "hair_hitop" + gender = MALE + +/datum/sprite_accessory/hair/mohawk + name = "Mohawk" + icon_state = "hair_d" + +//datum/sprite_accessory/hair/reversemohawk +// name = "Reverse Mohawk" +// icon_state = "hair_reversemohawk" + +/datum/sprite_accessory/hair/jensen + name = "Jensen Hair" + icon_state = "hair_jensen" + gender = MALE + +/datum/sprite_accessory/hair/gelled + name = "Gelled Back" + icon_state = "hair_gelled" + gender = FEMALE + +/datum/sprite_accessory/hair/spiky + name = "Spiky" + icon_state = "hair_spikey" + +/datum/sprite_accessory/hair/spiky2 + name = "Spiky 2" + icon_state = "hair_crono" + +/datum/sprite_accessory/hair/spiky3 + name = "Spiky 3" + icon_state = "hair_vegeta" + +/datum/sprite_accessory/hair/protagonist + name = "Slightly long" + icon_state = "hair_protagonist" + +/datum/sprite_accessory/hair/kusangi + name = "Kusanagi Hair" + icon_state = "hair_kusanagi" + +/datum/sprite_accessory/hair/kagami + name = "Kagami Hair" + icon_state = "hair_kagami" + gender = FEMALE + +/datum/sprite_accessory/hair/pigtail + name = "Pigtails" + icon_state = "hair_pigtails" + gender = FEMALE + +/datum/sprite_accessory/hair/pigtail2 + name = "Pigtails 2" + icon_state = "hair_nitori" + gender = FEMALE + +//datum/sprite_accessory/hair/pigtail3 +// name = "Pigtails 3" +// icon_state = "hair_pigtails3" +// gender = FEMALE + +/datum/sprite_accessory/hair/himecut + name = "Hime Cut" + icon_state = "hair_himecut" + gender = FEMALE + +//datum/sprite_accessory/hair/himecut2 +// name = "Hime Cut 2" +// icon_state = "hair_himecut2" +// gender = FEMALE + +//datum/sprite_accessory/hair/himeup +// name = "Hime Updo" +// icon_state = "hair_himeup" + +/datum/sprite_accessory/hair/antenna + name = "Ahoge" + icon_state = "hair_antenna" + +/datum/sprite_accessory/hair/lowbraid + name = "Low Braid" + icon_state = "hair_hbraid" + gender = FEMALE + +/datum/sprite_accessory/hair/not_floorlength_braid + name = "High Braid" + icon_state = "hair_braid2" + gender = FEMALE + +//datum/sprite_accessory/hair/shortbraid +// name = "Short Braid" +// icon_state = "hair_shortbraid" +// gender = FEMALE + +/datum/sprite_accessory/hair/braid + name = "Floorlength Braid" + icon_state = "hair_braid" + gender = FEMALE + +/datum/sprite_accessory/hair/odango + name = "Odango" + icon_state = "hair_odango" + gender = FEMALE + +/datum/sprite_accessory/hair/ombre + name = "Ombre" + icon_state = "hair_ombre" + gender = FEMALE + +/datum/sprite_accessory/hair/updo + name = "Updo" + icon_state = "hair_updo" + gender = FEMALE + +/datum/sprite_accessory/hair/skinhead + name = "Skinhead" + icon_state = "hair_skinhead" + +//datum/sprite_accessory/hair/longbangs +// name = "Long Bangs" +// icon_state = "hair_lbangs" + +/datum/sprite_accessory/hair/balding + name = "Balding Hair" + icon_state = "hair_e" + gender = MALE // turnoff! + +//datum/sprite_accessory/hair/parted +// name = "Side Part" +// icon_state = "hair_part" + +//datum/sprite_accessory/hair/braided +// name = "Braided" +// icon_state = "hair_braided" + +/datum/sprite_accessory/hair/bun + name = "Bun Head" + icon_state = "hair_bun" + +//datum/sprite_accessory/hair/bun2 +// name = "Bun Head 2" +// icon_state = "hair_bunhead2" + +/datum/sprite_accessory/hair/braidtail + name = "Braided Tail" + icon_state = "hair_braidtail" + +//datum/sprite_accessory/hair/bigflattop +// name = "Big Flat Top" +// icon_state = "hair_bigflattop" + +/datum/sprite_accessory/hair/drillhair + name = "Drill Hair" + icon_state = "hair_drillhair" + +/datum/sprite_accessory/hair/keanu + name = "Keanu Hair" + icon_state = "hair_edgeworth" + +//datum/sprite_accessory/hair/swept +// name = "Swept Back Hair" +// icon_state = "hair_swept" + +/datum/sprite_accessory/hair/swept2 + name = "Swept Back Hair 2" + icon_state = "hair_joestar" + +//datum/sprite_accessory/hair/business +// name = "Business Hair" +// icon_state = "hair_business" + +//datum/sprite_accessory/hair/business2 +// name = "Business Hair 2" +// icon_state = "hair_business2" + +/datum/sprite_accessory/hair/business3 + name = "Business Hair 3" + icon_state = "hair_cia" + +/datum/sprite_accessory/hair/business4 + name = "Business Hair 4" + icon_state = "hair_mulder" + +/datum/sprite_accessory/hair/hedgehog + name = "Hedgehog Hair" + icon_state = "hair_blackswordsman" + +/datum/sprite_accessory/hair/bob + name = "Bob Hair" + icon_state = "hair_schierke" + +/datum/sprite_accessory/hair/bob2 + name = "Bob Hair 2" + icon_state = "hair_scully" + +/datum/sprite_accessory/hair/long + name = "Long Hair 1" + icon_state = "hair_nia" + +//datum/sprite_accessory/hair/long2 +// name = "Long Hair 2" +// icon_state = "hair_long2" + +//datum/sprite_accessory/hair/pixie +// name = "Pixie Cut" +// icon_state = "hair_pixie" + +/datum/sprite_accessory/hair/megaeyebrows + name = "Mega Eyebrows" + icon_state = "hair_megaeyebrows" + +//datum/sprite_accessory/hair/highponytail +// name = "High Ponytail" +// icon_state = "hair_highponytail" + +//datum/sprite_accessory/hair/longponytail +// name = "Long Ponytail" +// icon_state = "hair_longstraightponytail" + +//datum/sprite_accessory/hair/sidepartlongalt +// name = "Long Side Part" +// icon_state = "hair_longsidepart" + +/datum/sprite_accessory/hair/flair + name = "Flaired Hair" + icon_state = "hair_flair" + +//datum/sprite_accessory/hair/himecut3 +// name = "Hime Cut 3" +// icon_state = "hair_himecut3" +// gender = FEMALE + +/datum/sprite_accessory/hair/big_tails + name = "Big tails" + icon_state = "hair_long_d_tails" + gender = FEMALE + +/datum/sprite_accessory/hair/long_bedhead + name = "Long bedhead" + icon_state = "hair_long_bedhead" + gender = FEMALE + +/datum/sprite_accessory/hair/fluttershy + name = "Fluttershy" + icon_state = "hair_fluttershy" + gender = FEMALE + +/datum/sprite_accessory/hair/judge + name = "Judge" + icon_state = "hair_judge" + gender = FEMALE + +/datum/sprite_accessory/hair/long_braid + name = "Long braid" + icon_state = "hair_long_braid" + gender = FEMALE + +/datum/sprite_accessory/hair/elize + name = "Elize" + icon_state = "hair_elize" + gender = FEMALE + +/datum/sprite_accessory/hair/elize2 + name = "Elize2" + icon_state = "hair_elize_2" + gender = FEMALE + +/datum/sprite_accessory/hair/undercut_fem + name = "Female undercut" + icon_state = "hair_undercut_fem" + gender = FEMALE + +/datum/sprite_accessory/hair/emo_right + name = "Emo right" + icon_state = "hair_emo_r" + +/datum/sprite_accessory/hair/applejack + name = "Applejack" + icon_state = "hair_applejack" + gender = FEMALE + +/datum/sprite_accessory/hair/rosa + name = "Rosa" + icon_state = "hair_rosa" + gender = FEMALE + +//TC trap powah +/datum/sprite_accessory/hair/dave + name = "Dave" + icon_state = "hair_dave" + +/datum/sprite_accessory/hair/aradia + name = "Aradia" + icon_state = "hair_aradia" + +/datum/sprite_accessory/hair/nepeta + name = "Nepeta" + icon_state = "hair_nepeta" + +/datum/sprite_accessory/hair/kanaya + name = "Kanaya" + icon_state = "hair_kanaya" + +/datum/sprite_accessory/hair/terezi + name = "Terezi" + icon_state = "hair_terezi" + +/datum/sprite_accessory/hair/vriska + name = "Vriska" + icon_state = "hair_vriska" + +/datum/sprite_accessory/hair/equius + name = "Equius" + icon_state = "hair_equius" + +/datum/sprite_accessory/hair/gamzee + name = "Gamzee" + icon_state = "hair_gamzee" + +/datum/sprite_accessory/hair/feferi + name = "Feferi" + icon_state = "hair_feferi" + +/datum/sprite_accessory/hair/rose + name = "Rose" + icon_state = "hair_rose" + +/datum/sprite_accessory/hair/ramona + name = "Ramona" + icon_state = "hair_ramona" + +/datum/sprite_accessory/hair/dirk + name = "Dirk" + icon_state = "hair_dirk" + +/datum/sprite_accessory/hair/jade + name = "Jade" + icon_state = "hair_jade" + +/datum/sprite_accessory/hair/roxy + name = "Roxy" + icon_state = "hair_roxy" + +/datum/sprite_accessory/hair/side_tail3 + name = "Side tail 3" + icon_state = "hair_stail" + +/datum/sprite_accessory/hair/familyman + name = "Big Flat Top" + icon_state = "hair_thefamilyman" + +/datum/sprite_accessory/hair/dubsman + name = "Dubs Hair " + icon_state = "hair_dubs" + +/datum/sprite_accessory/hair/objection + name = "Swept Back Hair" + icon_state = "hair_objection" + +/datum/sprite_accessory/hair/metal + name = "Metal" + icon_state = "hair_80s" + +/datum/sprite_accessory/hair/mentalist + name = "Mentalist" + icon_state = "hair_mentalist" + +/datum/sprite_accessory/hair/fujisaki + name = "fujisaki" + icon_state = "hair_fujisaki" + +/datum/sprite_accessory/hair/akari + name = "Twin Buns" + icon_state = "hair_akari" + +/datum/sprite_accessory/hair/fujiyabashi + name = "Fujiyabashi" + icon_state = "hair_fujiyabashi" + +/datum/sprite_accessory/hair/shinobu + name = "Shinibu" + icon_state = "hair_shinobu" + +/datum/sprite_accessory/hair/combed + name = "Combed Hair" + icon_state = "hair_combed" + +/datum/sprite_accessory/hair/longsidepart + name = "Long Sideparts" + icon_state = "hair_longsidepartstraight" + +/datum/sprite_accessory/hair/bluntbangs + name = "Blunt Bangs" + icon_state = "hair_bluntbangs" + +/datum/sprite_accessory/hair/combedbob + name = "Combed Bob" + icon_state = "hair_combedbob" + +/datum/sprite_accessory/hair/halfshavedlong + name = "Long Half Shaved" + icon_state = "hair_halfshaved" + +/datum/sprite_accessory/hair/slighlymessy + name = "Slightly Messed" + icon_state = "hair_slightlymessy" + +/datum/sprite_accessory/hair/gypsy + name = "Long Gypsy" + icon_state = "hair_gipsy" + +/datum/sprite_accessory/hair/geisha + name = "Geisha" + icon_state = "hair_geisha" + +/datum/sprite_accessory/hair/fullovereye + name = "Hair Over Eye" + icon_state = "hair_baum" + +/datum/sprite_accessory/hair/chub + name = "Chub" + icon_state = "hair_chub" + +/datum/sprite_accessory/hair/ponytail6 + name = "Ponytail female" + icon_state = "hair_ponytailf" + gender = FEMALE + +/datum/sprite_accessory/hair/wisp + name = "Wisp" + icon_state = "hair_wisp" + gender = FEMALE + +/datum/sprite_accessory/hair/halfshaved + name = "Half-Shaved Emo" + icon_state = "hair_halfshaved2" + +/datum/sprite_accessory/hair/longeralt2 + name = "Long Hair Alt 2" + icon_state = "hair_longeralt2" + +/datum/sprite_accessory/hair/bun4 + name = "Bun 4" + icon_state = "hair_bun4" + +/datum/sprite_accessory/hair/doublebun + name = "Double-Bun" + icon_state = "hair_doublebun" + +/datum/sprite_accessory/hair/rows + name = "Rows" + icon_state = "hair_rows1" + +/datum/sprite_accessory/hair/rows2 + name = "Rows 2" + icon_state = "hair_rows2" + +/datum/sprite_accessory/hair/twintail + name = "Twintail" + icon_state = "hair_twintail" + +/datum/sprite_accessory/hair/coffeehouse + name = "Coffee House Cut" + icon_state = "hair_coffeehouse" + gender = MALE + +/datum/sprite_accessory/hair/veryshortovereye + name = "Overeye Very Short" + icon_state = "hair_veryshortovereye" + +/datum/sprite_accessory/hair/oxton + name = "Oxton" + icon_state = "hair_oxton" + +/datum/sprite_accessory/hair/zieglertail + name = "Zieglertail" + icon_state = "hair_ziegler" + +/datum/sprite_accessory/hair/fringeemo + name = "Emo Fringe" + icon_state = "hair_emofringe" + +/datum/sprite_accessory/hair/poofy2 + name = "Poofy2" + icon_state = "hair_poofy2" + +/datum/sprite_accessory/hair/fringetail + name = "Fringetail" + icon_state = "hair_fringetail" + +/datum/sprite_accessory/hair/bun3 + name = "Bun 3" + icon_state = "hair_bun3" + +/datum/sprite_accessory/hair/veryshortovereyealternate + name = "Overeye Very Short, Alternate" + icon_state = "hair_veryshortovereyealternate" + +/datum/sprite_accessory/hair/undercut2 + name = "Undercut Swept Right" + icon_state = "hair_undercut2" + gender = MALE + +/datum/sprite_accessory/hair/spikyponytail + name = "Spiky Ponytail" + icon_state = "hair_spikyponytail" + +/datum/sprite_accessory/hair/grandebraid + name = "Grande Braid" + icon_state = "hair_grande" + +/datum/sprite_accessory/hair/fringetail + name = "Fringetail" + icon_state = "hair_fringetail" + +/datum/sprite_accessory/hair/rowbun + name = "Row Bun" + icon_state = "hair_rowbun" + +/datum/sprite_accessory/hair/rowdualbraid + name = "Row Dual Braid" + icon_state = "hair_rowdualtail" + +/datum/sprite_accessory/hair/rowbraid + name = "Row Braid" + icon_state = "hair_rowbraid" + +/datum/sprite_accessory/hair/regulationmohawk + name = "Regulation Mohawk" + icon_state = "hair_shavedmohawk" + +/datum/sprite_accessory/hair/topknot + name = "Topknot" + icon_state = "hair_topknot" + +/datum/sprite_accessory/hair/ronin + name = "Ronin" + icon_state = "hair_ronin" + +/datum/sprite_accessory/hair/bowlcut2 + name = "Bowl 2" + icon_state = "hair_bowlcut2" + +/datum/sprite_accessory/hair/manbun + name = "Manbun" + icon_state = "hair_manbun" + +/datum/sprite_accessory/hair/country + name = "Country" + icon_state = "hair_country" + +/datum/sprite_accessory/hair/ougi + name = "Ougi" + icon_state = "hair_ougi" + +//datum/sprite_accessory/hair/modern +// name = "Modern" +// icon_state = "hair_modern" +// gender = FEMALE + +//datum/sprite_accessory/hair/twincurl +// name = "Twincurl" +// icon_state = "hair_twincurl" +// gender = FEMALE + +//datum/sprite_accessory/hair/rapunzel +// name = "Rapunzel" +// icon_state = "hair_rapunzel" +// gender = FEMALE + +//datum/sprite_accessory/hair/quadcurls +// name = "Quadcurls" +// icon_state = "hair_quadcurls" +// gender = FEMALE + +//datum/sprite_accessory/hair/twincurl2 +// name = "Twincurl 2" +// icon_state = "hair_twincurl2" +// gender = FEMALE + +//datum/sprite_accessory/hair/birdnest +// name = "Birdnest " +// icon_state = "hair_birdnest" + +//datum/sprite_accessory/hair/unkept +// name = "Unkept" +// icon_state = "hair_unkept" + +//datum/sprite_accessory/hair/fastline +// name = "Fastline" +// icon_state = "hair_fastline" +// gender = MALE + +//datum/sprite_accessory/hair/duelist +// name = "Duelist " +// icon_state = "hair_duelist" + +//datum/sprite_accessory/hair/sparta +// name = "Sparta hair" +// icon_state = "hair_sparta" + + +/* +/////////////////////////////////// +/ =---------------------------= / +/ == 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) + +/datum/sprite_accessory/facial_hair/shaved + name = "Shaved" + icon_state = "bald" + gender = NEUTER + species_allowed = list(HUMAN , UNATHI , TAJARAN , SKRELL , VOX , IPC, DIONA) + +/datum/sprite_accessory/facial_hair/watson + name = "Watson Mustache" + icon_state = "facial_watson" + +/datum/sprite_accessory/facial_hair/hogan + name = "Hulk Hogan Mustache" + icon_state = "facial_hogan" //-Neek + +/datum/sprite_accessory/facial_hair/vandyke + name = "Van Dyke Mustache" + icon_state = "facial_vandyke" + +/datum/sprite_accessory/facial_hair/chaplin + name = "Square Mustache" + icon_state = "facial_chaplin" + +/datum/sprite_accessory/facial_hair/selleck + name = "Selleck Mustache" + icon_state = "facial_selleck" + +/datum/sprite_accessory/facial_hair/neckbeard + name = "Neckbeard" + icon_state = "facial_neckbeard" + +/datum/sprite_accessory/facial_hair/fullbeard + name = "Full Beard" + icon_state = "facial_fullbeard" + +/datum/sprite_accessory/facial_hair/longbeard + name = "Long Beard" + icon_state = "facial_longbeard" + +/datum/sprite_accessory/facial_hair/vlongbeard + name = "Very Long Beard" + icon_state = "facial_wise" + +/datum/sprite_accessory/facial_hair/elvis + name = "Elvis Sideburns" + icon_state = "facial_elvis" + +/datum/sprite_accessory/facial_hair/abe + name = "Abraham Lincoln Beard" + icon_state = "facial_abe" + +/datum/sprite_accessory/facial_hair/chinstrap + name = "Chinstrap" + icon_state = "facial_chin" + +/datum/sprite_accessory/facial_hair/hip + name = "Hipster Beard" + icon_state = "facial_hip" + +/datum/sprite_accessory/facial_hair/gt + name = "Goatee" + icon_state = "facial_gt" + +/datum/sprite_accessory/facial_hair/jensen + name = "Jensen Beard" + icon_state = "facial_jensen" + +/datum/sprite_accessory/facial_hair/dwarf + name = "Dwarf Beard" + icon_state = "facial_dwarf" + +//datum/sprite_accessory/facial_hair/fiveoclock +// name = "Five o Clock Shadow" +// icon_state = "facial_fiveoclock" + +//datum/sprite_accessory/facial_hair/fu +// name = "Fu Manchu" +// icon_state = "facial_fumanchu" + +/datum/sprite_accessory/facial_hair/postal + name = "Goat Beard" + icon_state = "facial_goatbeard" + +//datum/sprite_accessory/facial_hair/britstache +// name = "Britstache" +// icon_state = "facial_britstache" + +//datum/sprite_accessory/facial_hair/martial_artist +// name = "Martial Artist" +// icon_state = "facial_martialartist" + +//datum/sprite_accessory/facial_hair/moonshiner +// name = "Moonshiner" +// icon_state = "facial_moonshiner" + +//datum/sprite_accessory/facial_hair/tribeard +// name = "Tri-Beard" +// icon_state = "facial_tribeard" + +//datum/sprite_accessory/facial_hair/unshaven +// name = "Unshaven" +// icon_state = "facial_unshaven" + + +/* +/////////////////////////////////// +/ =---------------------------= / +/ == Alien Style Definitions == / +/ =---------------------------= / +/////////////////////////////////// +*/ + +/datum/sprite_accessory/hair/ipc_screen_pink + name = "pink IPC screen" + icon_state = "ipc_pink" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_red + name = "red IPC screen" + icon_state = "ipc_red" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_green + name = "green IPC screen" + icon_state = "ipc_green" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_blue + name = "blue IPC screen" + icon_state = "ipc_blue" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_breakout + name = "breakout IPC screen" + icon_state = "ipc_breakout" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_eight + name = "eight IPC screen" + icon_state = "ipc_eight" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_goggles + name = "goggles IPC screen" + icon_state = "ipc_goggles" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_heart + name = "heart IPC screen" + icon_state = "ipc_heart" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_monoeye + name = "monoeye IPC screen" + icon_state = "ipc_monoeye" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_nature + name = "nature IPC screen" + icon_state = "ipc_nature" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_orange + name = "orange IPC screen" + icon_state = "ipc_orange" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_purple + name = "purple IPC screen" + icon_state = "ipc_purple" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_shower + name = "shower IPC screen" + icon_state = "ipc_shower" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_static + name = "static IPC screen" + icon_state = "ipc_static" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_yellow + name = "yellow IPC screen" + icon_state = "ipc_yellow" + species_allowed = list(IPC) + do_colouration = FALSE + +/datum/sprite_accessory/hair/ipc_screen_dot + name = "dot IPC screen" + icon_state = "ipc_dot" + species_allowed = list(IPC) + +/datum/sprite_accessory/hair/ipc_screen_four + name = "four IPC screen" + icon_state = "ipc_four" + species_allowed = list(IPC) + +/datum/sprite_accessory/hair/ipc_screen_eye + name = "eye IPC screen" + icon_state = "ipc_eye" + species_allowed = list(IPC) + +/datum/sprite_accessory/hair/ipc_screen_eyes + name = "eyes IPC screen" + icon_state = "ipc_eyes" + species_allowed = list(IPC) + +/datum/sprite_accessory/hair/unathi_warrior_horns + name = "Warrior Horns" + icon_state = "una_warrior_horns" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/unathi_smallhorns + name = "Small Horns" + icon_state = "una_smallhorns" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/unathi_dreads + name = "Dreads" + icon_state = "una_dreads" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/unathi_dreads_long + name = "Long Dreads" + icon_state = "una_dreads_long" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/unathi_dreads_short + name = "Short Dreads" + icon_state = "una_dreads_short" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/unathi_dreads_predator + name = "Predator Dreads" + icon_state = "una_dreads_predator" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/unathi_hiss_collinss + name = "Hiss Collinss" + icon_state = "una_hiss_collinss" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/unathi_horns_curled + name = "Curled Horns" + icon_state = "una_horns_curled" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/unathi_horns_ram + name = "Ram Horns" + icon_state = "una_horns_ram" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/una_spines_long + name = "Long Unathi Spines" + icon_state = "una_longspines" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/una_spines_short + name = "Short Unathi Spines" + icon_state = "una_shortspines" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/una_frills_long + name = "Long Unathi Frills" + icon_state = "una_longfrills" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/una_frills_short + name = "Short Unathi Frills" + icon_state = "una_shortfrills" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/una_horns + name = "Unathi Horns" + icon_state = "una_horns" + species_allowed = list(UNATHI) + +/datum/sprite_accessory/hair/skr_tentacle_m + name = "Skrell Male Tentacles" + icon_state = "skr_hair_m" + species_allowed = list(SKRELL) + gender = MALE + +/datum/sprite_accessory/hair/skr_tentacle_f + name = "Skrell Female Tentacles" + icon_state = "skr_hair_f" + species_allowed = list(SKRELL) + gender = FEMALE + +/datum/sprite_accessory/hair/skr_gold_m + name = "Gold plated Skrell Male Tentacles" + icon_state = "skr_goldhair_m" + species_allowed = list(SKRELL) + gender = MALE + +/datum/sprite_accessory/hair/skr_gold_f + name = "Gold chained Skrell Female Tentacles" + icon_state = "skr_goldhair_f" + species_allowed = list(SKRELL) + gender = FEMALE + +/datum/sprite_accessory/hair/skr_clothtentacle_m + name = "Cloth draped Skrell Male Tentacles" + icon_state = "skr_clothhair_m" + species_allowed = list(SKRELL) + gender = MALE + +/datum/sprite_accessory/hair/skr_clothtentacle_f + name = "Cloth draped Skrell Female Tentacles" + icon_state = "skr_clothhair_f" + species_allowed = list(SKRELL) + gender = FEMALE + +/datum/sprite_accessory/hair/taj_ears + name = "Tajaran Ears" + icon_state = "taj_ears_plain" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_clean + name = "Tajara Clean" + icon_state = "taj_hair_clean" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_bangs + name = "Tajara Bangs" + icon_state = "taj_hair_bangs" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_braid + name = "Tajara Braid" + icon_state = "taj_hair_tbraid" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_shaggy + name = "Tajara Shaggy" + icon_state = "taj_hair_shaggy" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_mohawk + name = "Tajaran Mohawk" + icon_state = "taj_hair_mohawk" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_plait + name = "Tajara Plait" + icon_state = "taj_hair_plait" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_straight + name = "Tajara Straight" + icon_state = "taj_hair_straight" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_long + name = "Tajara Long" + icon_state = "taj_hair_long" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_rattail + name = "Tajara Rat Tail" + icon_state = "taj_hair_rattail" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_spiky + name = "Tajara Spiky" + icon_state = "taj_hair_tajspiky" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_messy + name = "Tajara Messy" + icon_state = "taj_hair_messy" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_tailshort + name = "Tajara Short Tail" + icon_state = "taj_hair_shorttail" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ears_messylong + name = "Tajara Long Messy" + icon_state = "taj_hair_messylong" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_sidebraid + name = "Tajara Side Braid" + icon_state = "taj_hair_sidebraid" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ribbons + name = "Tajara Ribbons" + icon_state = "taj_hair_ribbons" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_earrings + name = "Tajara Ear Rings" + icon_state = "taj_hair_earrings" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_combedback + name = "Tajara Combed Back" + icon_state = "taj_hair_combedback" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_tailedbangs + name = "Tajara Tailed Bangs" + icon_state = "taj_hair_tailedbangs" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_punk + name = "Tajara Punk" + icon_state = "taj_hair_punk" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_marmalade + name = "Tajara Marmalade" + icon_state = "taj_hair_marmalade" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_lynx + name = "Tajara Lynx" + icon_state = "taj_hair_lynx" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_longtail + name = "Tajara Long Tail" + icon_state = "taj_hair_longtail" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_shy + name = "Tajara Shy" + icon_state = "taj_hair_shy" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_metal + name = "Tajara Metal" + icon_state = "taj_hair_metal" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_ponytail + name = "Tajara Ponytail" + icon_state = "taj_hair_ponytail" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_overeye + name = "Tajara Over Eye" + icon_state = "taj_hair_overeye" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_tough + name = "Tajara Tough" + icon_state = "taj_hair_tough" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_cuttail + name = "Tajara Cut Tail" + icon_state = "taj_hair_cuttail" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/taj_dreadlocks + name = "Tajara Dreadlocks" + icon_state = "taj_hair_dreadlocks" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/vox_quills_short + name = "Short Vox Quills" + icon_state = "vox_shortquills" + species_allowed = list(VOX) + +/datum/sprite_accessory/facial_hair/taj_sideburns + name = "Tajara Sideburns" + icon_state = "taj_facial_sideburns" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/facial_hair/taj_mutton + name = "Tajara Mutton" + icon_state = "taj_facial_mutton" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/facial_hair/taj_pencilstache + name = "Tajara Pencilstache" + icon_state = "taj_facial_pencilstache" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/facial_hair/taj_moustache + name = "Tajara Moustache" + icon_state = "taj_facial_moustache" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/facial_hair/taj_goatee + name = "Tajara Goatee" + icon_state = "taj_facial_goatee" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/facial_hair/taj_smallstache + name = "Tajara Smallsatche" + icon_state = "taj_facial_smallstache" + species_allowed = list(TAJARAN) + +/datum/sprite_accessory/hair/dio_bloom + name = "Diona Everbloom" + icon_state = "dio_bloom" + do_colouration = FALSE + species_allowed = list(DIONA) + +/datum/sprite_accessory/hair/dio_rose + name = "Diona Rose" + icon_state = "dio_rose" + do_colouration = FALSE + species_allowed = list(DIONA) + +/datum/sprite_accessory/hair/dio_king + name = "Diona Flowerking" + icon_state = "dio_king" + do_colouration = FALSE + species_allowed = list(DIONA) + +/datum/sprite_accessory/hair/dio_vines + name = "Diona Vines Short" + icon_state = "dio_vines" + do_colouration = FALSE + species_allowed = list(DIONA) + +/datum/sprite_accessory/hair/dio_vinel + name = "Diona Vines Long" + icon_state = "dio_vinel" + do_colouration = FALSE + species_allowed = list(DIONA) + +/datum/sprite_accessory/hair/dio_lotus + name = "Diona Lotus" + icon_state = "dio_lotus" + do_colouration = FALSE + species_allowed = list(DIONA) + +/datum/sprite_accessory/hair/dio_palm + name = "Diona Palmhead" + icon_state = "dio_palm" + do_colouration = FALSE + species_allowed = list(DIONA) + +/datum/sprite_accessory/hair/dio_garland + name = "Diona Garland" + icon_state = "dio_garland" + do_colouration = FALSE + species_allowed = list(DIONA) + +/datum/sprite_accessory/hair/dio_shrub + name = "Diona Shrub" + icon_state = "dio_shrub" + do_colouration = FALSE + species_allowed = list(DIONA) + +/datum/sprite_accessory/hair/dio_ficus + name = "Diona Ficus" + icon_state = "dio_ficus" + do_colouration = FALSE species_allowed = list(DIONA) \ 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 ef18527422c3..4e383247db60 100644 --- a/code/modules/mob/dead/observer/login.dm +++ b/code/modules/mob/dead/observer/login.dm @@ -1,17 +1,17 @@ -/mob/dead/observer/Login() - ..() - - if(check_rights(R_ADMIN, 0)) - has_unlimited_silicon_privilege = 1 - - if(ghostimage) - ghostimage.icon_state = src.icon_state - ghost_orbit = client.prefs.ghost_orbit - - updateghostimages() - - if(client.media) - client.media.stop_music() - - if(is_alien_whitelisted(src, "ian") || (client.supporter && !is_alien_whitelisted_banned(src, "ian"))) - verbs += /mob/dead/observer/proc/ianize +/mob/dead/observer/Login() + ..() + + if(check_rights(R_ADMIN, 0)) + has_unlimited_silicon_privilege = 1 + + if(ghostimage) + ghostimage.icon_state = src.icon_state + ghost_orbit = client.prefs.ghost_orbit + + updateghostimages() + + if(client.media) + client.media.stop_music() + + if(is_alien_whitelisted(src, "ian") || (client.supporter && !is_alien_whitelisted_banned(src, "ian"))) + verbs += /mob/dead/observer/proc/ianize diff --git a/code/modules/mob/dead/observer/logout.dm b/code/modules/mob/dead/observer/logout.dm index 11c6c3c834ca..b1ec761136fb 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/observer.dm b/code/modules/mob/dead/observer/observer.dm index 6018d91521cd..1869e33521e4 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -1,680 +1,680 @@ -var/global/list/image/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness -var/global/list/image/ghost_sightless_images = list() //this is a list of images for things ghosts should still be able to see even without ghost sight - -/mob/dead/observer - name = "ghost" - desc = "It's a g-g-g-g-ghooooost!" //jinkies! - icon = 'icons/mob/mob.dmi' - icon_state = "blank" - layer = MOB_LAYER // on tg it is FLOAT LAYER - plane = FLOAT_PLANE - stat = DEAD - density = 0 - canmove = 0 - blinded = 0 - anchored = 1 // don't get pushed around - see_invisible = SEE_INVISIBLE_OBSERVER - see_in_dark = 100 - invisibility = INVISIBILITY_OBSERVER - var/can_reenter_corpse - var/datum/hud/living/carbon/hud = null // hud - var/bootime = 0 - var/started_as_observer //This variable is set to 1 when you enter the game as an observer. - //If you died in the game and are a ghsot - this will remain as null. - //Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot. - var/has_enabled_antagHUD = 0 - var/medHUD = 0 - var/antagHUD = 0 - universal_speak = 1 - var/golem_rune = null //Used to check, if we already queued as a golem. - - var/image/ghostimage = null //this mobs ghost image, for deleting and stuff - var/ghostvision = 1 //is the ghost able to see things humans can't? - var/seedarkness = 1 - var/ghost_orbit = GHOST_ORBIT_CIRCLE - - var/obj/item/device/multitool/adminMulti = null //Wew, personal multiotool for ghosts! - -/mob/dead/observer/atom_init() - invisibility = INVISIBILITY_OBSERVER - - verbs += /mob/dead/observer/proc/dead_tele - - ghostimage = image(icon, src, "ghost") - ghost_darkness_images |= ghostimage - updateallghostimages() - - var/turf/T - var/mob/body = loc - if(ismob(body)) - T = get_turf(body) //Where is the body located? - attack_log = body.attack_log //preserve our attack logs by copying them to our ghost - - if(ishuman(body)) - overlays = body.overlays - else - icon = body.icon - icon_state = body.icon_state - overlays = body.overlays - - alpha = 127 - - gender = body.gender - if(body.mind && body.mind.name) - name = body.mind.name - else - if(body.real_name) - name = body.real_name - else - if(gender == MALE) - name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) - else - name = capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names)) - - mind = body.mind //we don't transfer the mind but we keep a reference to it. - - if(!T) - T = pick(latejoin) //Safety in case we cannot find the body's position - - loc = T - - if(!name) //To prevent nameless ghosts - name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) - real_name = name - - dead_mob_list += src - - . = ..() - - observer_list += src - -/mob/dead/observer/Destroy() - observer_list -= src - if (ghostimage) - ghost_darkness_images -= ghostimage - qdel(ghostimage) - ghostimage = null - updateallghostimages() - QDEL_NULL(adminMulti) - return ..() - -//this is called when a ghost is drag clicked to something. -/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 ..() - -/mob/dead/observer/Topic(href, href_list) - if(href_list["track"]) - var/mob/target = locate(href_list["track"]) in mob_list - if(target) - ManualFollow(target) - - if(href_list["ghostplayerobservejump"]) - var/atom/movable/target = locate(href_list["ghostplayerobservejump"]) - if(!target) - return - - var/turf/T = get_turf(target) - forceMove(T) - -/mob/dead/attackby(obj/item/W, mob/user) - if(istype(W,/obj/item/weapon/book/tome)) - user.SetNextMove(CLICK_CD_MELEE) - var/mob/dead/M = src - if(src.invisibility != 0) - M.invisibility = 0 - user.visible_message( \ - "[user] drags ghost, [M], to our plan of reality!", \ - "You drag [M] to our plan of reality!" \ - ) - else - user.visible_message ( \ - "[user] just tried to smash his book into that ghost! It's not very effective.", \ - "You get the feeling that the ghost can't become any more visible." \ - ) - - -/mob/dead/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - return 1 -/* -Transfer_mind is there to check if mob is being deleted/not going to have a body. -Works together with spawning an observer, noted above. -*/ - -/mob/dead/observer/Life() - ..() - if(!loc) return - if(!client) return 0 - - - if(client.images.len) - for(var/image/hud in client.images) - if(copytext(hud.icon_state,1,4) == "hud") - client.images.Remove(hud) - - if(antagHUD) - var/list/target_list = list() - for(var/mob/living/target in oview(src, 14)) - if(target.mind&&(target.mind.special_role||issilicon(target)) ) - target_list += target - if(target_list.len) - assess_targets(target_list, src) - if(medHUD) - process_medHUD(src) - - -/mob/dead/proc/process_medHUD(mob/M) - var/client/C = M.client - for(var/mob/living/carbon/human/patient in oview(M, 14)) - C.images += patient.hud_list[HEALTH_HUD] - C.images += patient.hud_list[STATUS_HUD_OOC] - -/mob/dead/proc/assess_targets(list/target_list, mob/dead/observer/U) - var/client/C = U.client - for(var/mob/living/carbon/human/target in target_list) - C.images += target.hud_list[SPECIALROLE_HUD] - - -/* - else//If the silicon mob has no law datum, no inherent laws, or a law zero, add them to the hud. - var/mob/living/silicon/silicon_target = target - if(!silicon_target.laws||(silicon_target.laws&&(silicon_target.laws.zeroth||!silicon_target.laws.inherent.len))||silicon_target.mind.special_role=="traitor") - if(isrobot(silicon_target))//Different icons for robutts and AI. - U.client.images += image(tempHud,silicon_target,"hudmalborg") - else - U.client.images += image(tempHud,silicon_target,"hudmalai") -*/ - return 1 - -/mob/proc/ghostize(can_reenter_corpse = TRUE, bancheck = FALSE) - if(key) - if(!(ckey in admin_datums) && bancheck == TRUE && jobban_isbanned(src, "Observer")) - var/mob/M = mousize() - if((config.allow_drone_spawn) || !jobban_isbanned(src, ROLE_DRONE)) - var/response = alert(M, "Do you want to become a maintenance drone?","Are you sure you want to beep?","Beep!","Nope!") - if(response == "Beep!") - M.dronize() - qdel(M) - return - var/mob/dead/observer/ghost = new(src) //Transfer safety to observer spawning proc. - ghost.can_reenter_corpse = can_reenter_corpse - ghost.timeofdeath = src.timeofdeath //BS12 EDIT - ghost.key = key - if(client && !ghost.client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed. - ghost.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing! - return ghost - -/* -This is the proc mobs get to turn into a ghost. Forked from ghostize due to compatibility issues. -*/ -/mob/living/verb/ghost() - set category = "OOC" - set name = "Ghost" - set desc = "Relinquish your life and enter the land of the dead." - - if(!(ckey in admin_datums) && jobban_isbanned(src, "Observer")) - to_chat(src, "You have been banned from observing.") - return - if(stat == DEAD) - if(fake_death) - var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another 30 minutes! You can't change your mind so choose wisely!)","Are you sure you want to ghost?","Stay in body","Ghost") - if(response != "Ghost") - return //didn't want to ghost after-all - var/mob/dead/observer/ghost = ghostize(can_reenter_corpse = FALSE) - ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. - else - ghostize(can_reenter_corpse = TRUE) - else - var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another 30 minutes! You can't change your mind so choose wisely!)","Are you sure you want to ghost?","Stay in body","Ghost") - if(response != "Ghost") - return //didn't want to ghost after-all - - if(isrobot(usr)) - var/mob/living/silicon/robot/robot = usr - robot.toggle_all_components() - else - resting = 1 - var/mob/dead/observer/ghost = ghostize(can_reenter_corpse = FALSE) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 - ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. - return - - -/mob/dead/observer/Move(NewLoc, direct) - dir = direct - if(NewLoc) - loc = NewLoc - for(var/obj/effect/step_trigger/S in NewLoc) - S.Crossed(src) - update_parallax_contents() - return - loc = get_turf(src) //Get out of closets and such as a ghost - if((direct & NORTH) && y < world.maxy) - y++ - else if((direct & SOUTH) && y > 1) - y-- - if((direct & EAST) && x < world.maxx) - x++ - else if((direct & WEST) && x > 1) - x-- - - for(var/obj/effect/step_trigger/S in locate(x, y, z)) //<-- this is dumb - S.Crossed(src) - - -/mob/dead/observer/can_use_hands() return 0 -/mob/dead/observer/is_active() return 0 - -/mob/dead/observer/Stat() - ..() - if(statpanel("Status")) - stat(null, "Station Time: [worldtime2text()]") - if(ticker.mode && ticker.mode.config_tag == "gang") - var/datum/game_mode/gang/mode = ticker.mode - if(isnum(mode.A_timer)) - stat(null, "[gang_name("A")] Gang Takeover: [max(mode.A_timer, 0)]") - if(isnum(mode.B_timer)) - stat(null, "[gang_name("B")] Gang Takeover: [max(mode.B_timer, 0)]") - -/mob/dead/observer/verb/reenter_corpse() - set category = "Ghost" - set name = "Re-enter Corpse" - if(!client) return - if(!(mind && mind.current && can_reenter_corpse)) - to_chat(src, "You have no body.") - return - if(mind.current.key && copytext(mind.current.key,1,2)!="@") //makes sure we don't accidentally kick any clients - to_chat(usr, "Another consciousness is in your body... it is resisting you.") - return - mind.current.key = key - return 1 - -/mob/dead/observer/verb/toggle_medHUD() - set category = "Ghost" - set name = "Toggle MedicHUD" - set desc = "Toggles Medical HUD allowing you to see how everyone is doing." - if(!client) - return - if(medHUD) - medHUD = 0 - to_chat(src, "Medical HUD Disabled") - else - medHUD = 1 - to_chat(src, "Medical HUD Enabled") - -/mob/dead/observer/verb/toggle_antagHUD() - set category = "Ghost" - set name = "Toggle AntagHUD" - set desc = "Toggles AntagHUD allowing you to see who is the antagonist." - - if(!client) - return - if(!config.antag_hud_allowed && !client.holder) - to_chat(src, "Admins have disabled this for this round.") - return - var/mob/dead/observer/M = src - if(jobban_isbanned(M, "AntagHUD")) - to_chat(src, "You have been banned from using this feature.") - return - if(config.antag_hud_restricted && !M.has_enabled_antagHUD && !client.holder) - var/response = alert(src, "If you turn this on, you will not be able to take any part in the round.","Are you sure you want to turn this feature on?","Yes","No") - if(response == "No") - return - M.can_reenter_corpse = 0 - if(!M.has_enabled_antagHUD && !client.holder) - M.has_enabled_antagHUD = 1 - if(M.antagHUD) - M.antagHUD = 0 - to_chat(src, "AntagHUD Disabled") - else - M.antagHUD = 1 - to_chat(src, "AntagHUD Enabled") - -/mob/dead/observer/proc/dead_tele(A in ghostteleportlocs) - set category = "Ghost" - set name = "Teleport" - set desc= "Teleport to a location" - if(!istype(usr, /mob/dead/observer)) - to_chat(usr, "Not when you're not dead!") - return - usr.verbs -= /mob/dead/observer/proc/dead_tele - spawn(30) - usr.verbs += /mob/dead/observer/proc/dead_tele - var/area/thearea = ghostteleportlocs[A] - if(!thearea) - return - - var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - L += T - - if(!L || !L.len) - to_chat(usr, "No area available.") - - usr.forceMove(pick(L)) - update_parallax_contents() - -/mob/dead/observer/verb/follow() - set category = "Ghost" - set name = "Orbit" // "Haunt" - set desc = "Follow and orbit a mob." - - var/list/mobs = getpois(skip_mindless=1) - var/input = input("Please, select a mob!", "Haunt", null, null) as null|anything in mobs - var/mob/target = mobs[input] - if(!target) - return - ManualFollow(target) - -// This is the ghost's follow verb with an argument -/mob/dead/observer/proc/ManualFollow(atom/movable/target) - if (!istype(target)) - return - - var/icon/I = icon(target.icon,target.icon_state,target.dir) - - var/orbitsize = (I.Width() + I.Height()) * 0.5 - orbitsize -= (orbitsize / world.icon_size) * (world.icon_size * 0.25) - - if(orbiting && orbiting.orbiting != target) - to_chat(src, "Now orbiting [target].") - - var/rot_seg - - switch(ghost_orbit) - if(GHOST_ORBIT_TRIANGLE) - rot_seg = 3 - if(GHOST_ORBIT_SQUARE) - rot_seg = 4 - if(GHOST_ORBIT_PENTAGON) - rot_seg = 5 - if(GHOST_ORBIT_HEXAGON) - rot_seg = 6 - else //Circular - rot_seg = 36 //360/10 bby, smooth enough aproximation of a circle - - forceMove(target) - orbit(target, orbitsize, FALSE, 20, rot_seg) - -/mob/dead/observer/orbit() - dir = SOUTH // Reset dir so the right directional sprites show up - ..() - -/mob/dead/observer/stop_orbit() - ..() - pixel_y = 0 - -/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak - set category = "Ghost" - set name = "Jump to Mob" - set desc = "Teleport to a mob." - - if(istype(usr, /mob/dead/observer)) //Make sure they're an observer! - var/list/dest = list() //List of possible destinations (mobs) - var/target = null //Chosen target. - - dest += getpois(mobs_only=1) //Fill list, prompt user with list - target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest - - if (!target)//Make sure we actually have a target - return - else - var/mob/M = dest[target] //Destination mob - var/mob/A = src //Source mob - var/turf/T = get_turf(M) //Turf of the destination mob - - if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination. - A.forceMove(T) - A.update_parallax_contents() - else - to_chat(A, "This mob is not located in the game world.") - -/* -/mob/dead/observer/verb/boo() - set category = "Ghost" - set name = "Boo!" - set desc= "Scare your crew members because of boredom!" - - if(bootime > world.time) return - var/obj/machinery/light/L = locate(/obj/machinery/light) in view(1, src) - if(L) - L.flicker() - bootime = world.time + 600 - return - //Maybe in the future we can add more spooky code here! - return -*/ - -/mob/dead/observer/memory() - set hidden = 1 - to_chat(src, "You are dead! You have no mind to store memory!") - -/mob/dead/observer/add_memory() - set hidden = 1 - to_chat(src, "You are dead! You have no mind to store memory!") - -/mob/dead/observer/verb/analyze_air() - set name = "Analyze Air" - set category = "Ghost" - - if(!istype(usr, /mob/dead/observer)) return - - var/turf/t = get_turf(src) - if(t) - print_atmos_analysis(src, atmosanalyzer_scan(t)) - -/mob/dead/observer/verb/become_mouse() - set name = "Become mouse" - set category = "Ghost" - - if(jobban_isbanned(src, "Mouse")) - to_chat(src, "You have been banned from being mouse.") - return - - if(config.disable_player_mice) - to_chat(src, "Spawning as a mouse is currently disabled.") - return - - var/mob/dead/observer/M = usr - if(config.antag_hud_restricted && M.has_enabled_antagHUD == 1) - to_chat(src, "antagHUD restrictions prevent you from spawning in as a mouse.") - return - - var/timedifference = world.time - client.time_died_as_mouse - if(client.time_died_as_mouse && timedifference <= mouse_respawn_time * 600) - var/timedifference_text - timedifference_text = time2text(mouse_respawn_time * 600 - timedifference,"mm:ss") - to_chat(src, "You may only spawn again as a mouse more than [mouse_respawn_time] minutes after your death. You have [timedifference_text] left.") - return - - var/response = alert(src, "Are you -sure- you want to become a mouse?","Are you sure you want to squeek?","Squeek!","Nope!") - if(response != "Squeek!") - return //Hit the wrong key...again. - - mousize() - -/mob/proc/mousize() - //find a viable mouse candidate - var/mob/living/simple_animal/mouse/host - var/obj/machinery/atmospherics/components/unary/vent_pump/vent_found - var/list/found_vents = list() - for(var/obj/machinery/atmospherics/components/unary/vent_pump/v in machines) - if(!v.welded && v.z == src.z) - found_vents.Add(v) - if(found_vents.len) - vent_found = pick(found_vents) - host = new /mob/living/simple_animal/mouse(vent_found.loc) - else - to_chat(src, "Unable to find any unwelded vents to spawn mice at.") - - if(host) - if(config.uneducated_mice) - host.universal_understand = 0 - host.ckey = src.ckey - to_chat(host, "You are now a mouse. Try to avoid interaction with players, and do not give hints away that you are more than a simple rodent.") - return host - -/mob/dead/observer/proc/ianize() - set name = "Become Ian" - set category = "Ghost" - - if(!abandon_allowed) - to_chat(src, "Respawn is disabled.") - return - - if(has_enabled_antagHUD == 1 && config.antag_hud_restricted) - to_chat(src, "Upon using the antagHUD you forfeighted the ability to join the round.") - return - - if(!ticker.mode) - to_chat(src, "Please wait until game is started.") - return - - var/response = alert(src, "Are you -sure- you want to find Bag Boss?","Are you sure you want to become II?","Soap Pain!","Nope!") - if(response != "Soap Pain!") - return - - var/mob/living/carbon/ian/phoron_dog - for(var/mob/living/carbon/ian/IAN in alive_mob_list) // Incase there is multi_ians, what should NOT ever happen normally! - if(IAN.mind) // Mind means someone was or is in a body. - continue - phoron_dog = IAN - break - - if(phoron_dog) - message_admins("[src.ckey] joined the game as [phoron_dog] [ADMIN_JMP(phoron_dog)] [ADMIN_FLW(phoron_dog)].") - phoron_dog.ckey = src.ckey - else - to_chat(src, "Living and available Ian not found.") - -/mob/dead/observer/verb/view_manfiest() - set name = "View Crew Manifest" - set category = "Ghost" - - var/dat - dat += "

                    Crew Manifest

                    " - dat += data_core.get_manifest() - - src << browse(entity_ja(dat), "window=manifest;size=370x420;can_close=1") - -//Used for drawing on walls with blood puddles as a spooky ghost. -/mob/dead/observer/verb/bloody_doodle() - - set category = "Ghost" - set name = "Write in blood" - set desc = "If the round is sufficiently spooky, write a short message in blood on the floor or a wall. Remember, no IC in OOC or OOC in IC." - - if(!(config.cult_ghostwriter)) - to_chat(src, "That verb is not currently permitted.") - return - - if (!src.stat) - return - - if (usr != src) - return 0 //something is terribly wrong - - var/ghosts_can_write - if(ticker.mode.name == "cult") - var/datum/game_mode/cult/C = ticker.mode - if(C.cult.len > config.cult_ghostwriter_req_cultists) - ghosts_can_write = 1 - - if(!ghosts_can_write) - to_chat(src, "The veil is not thin enough for you to do that.") - return - - var/list/choices = list() - for(var/obj/effect/decal/cleanable/blood/B in view(1,src)) - if(B.amount > 0) - choices += B - - if(!choices.len) - to_chat(src, "There is no blood to use nearby.") - return - - var/obj/effect/decal/cleanable/blood/choice = input(src,"What blood would you like to use?") in null|choices - - var/direction = input(src,"Which way?","Tile selection") as anything in list("Here","North","South","East","West") - var/turf/simulated/T = src.loc - if (direction != "Here") - T = get_step(T,text2dir(direction)) - - if (!istype(T)) - to_chat(src, "You cannot doodle there.") - return - - if(!choice || choice.amount == 0 || !(src.Adjacent(choice))) - return - - var/datum/dirt_cover/doodle_color = new/datum/dirt_cover(choice.basedatum) - - var/num_doodles = 0 - for (var/obj/effect/decal/cleanable/blood/writing/W in T) - num_doodles++ - if (num_doodles > 4) - to_chat(src, "There is no space to write on!") - return - - var/max_length = 50 - - var/message = sanitize_safe(input(src,"Write a message. It cannot be longer than [max_length] characters.","Blood writing", "")) - - if (message) - - if (length(message) > max_length) - message += "-"//Should crop any letters? No? - to_chat(src, "You ran out of blood to write with!") - - var/obj/effect/decal/cleanable/blood/writing/W = new(T) - W.basedatum = new/datum/dirt_cover(doodle_color) - W.update_icon() - W.message = message - W.add_hiddenprint(src) - W.visible_message("Invisible fingers crudely paint something in blood on [T]...") - -/mob/dead/observer/verb/toggle_ghostsee() - set name = "Toggle Ghost Vision" - set desc = "Toggles your ability to see things only ghosts can see, like other ghosts." - set category = "Ghost" - ghostvision = !(ghostvision) - updateghostsight() - to_chat(usr, "You [(ghostvision?"now":"no longer")] have ghost vision.") - -/mob/dead/observer/verb/toggle_darkness() - set name = "Toggle Darkness" - set category = "Ghost" - seedarkness = !(seedarkness) - updateghostsight() - -/mob/dead/observer/proc/updateghostsight() - if (!seedarkness) - see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING - else - see_invisible = SEE_INVISIBLE_OBSERVER - if (!ghostvision) - see_invisible = SEE_INVISIBLE_LIVING; - updateghostimages() - -/proc/updateallghostimages() - for (var/mob/dead/observer/O in player_list) - O.updateghostimages() - -/mob/dead/observer/proc/updateghostimages() - if (!client) - return - if (seedarkness || !ghostvision) - client.images -= ghost_darkness_images - client.images |= ghost_sightless_images - else - //add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now - client.images -= ghost_sightless_images - client.images |= ghost_darkness_images - if (ghostimage) - client.images -= ghostimage //remove ourself - -/mob/dead/observer/IsAdvancedToolUser() - return IsAdminGhost(src) +var/global/list/image/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness +var/global/list/image/ghost_sightless_images = list() //this is a list of images for things ghosts should still be able to see even without ghost sight + +/mob/dead/observer + name = "ghost" + desc = "It's a g-g-g-g-ghooooost!" //jinkies! + icon = 'icons/mob/mob.dmi' + icon_state = "blank" + layer = MOB_LAYER // on tg it is FLOAT LAYER + plane = FLOAT_PLANE + stat = DEAD + density = 0 + canmove = 0 + blinded = 0 + anchored = 1 // don't get pushed around + see_invisible = SEE_INVISIBLE_OBSERVER + see_in_dark = 100 + invisibility = INVISIBILITY_OBSERVER + var/can_reenter_corpse + var/datum/hud/living/carbon/hud = null // hud + var/bootime = 0 + var/started_as_observer //This variable is set to 1 when you enter the game as an observer. + //If you died in the game and are a ghsot - this will remain as null. + //Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot. + var/has_enabled_antagHUD = 0 + var/medHUD = 0 + var/antagHUD = 0 + universal_speak = 1 + var/golem_rune = null //Used to check, if we already queued as a golem. + + var/image/ghostimage = null //this mobs ghost image, for deleting and stuff + var/ghostvision = 1 //is the ghost able to see things humans can't? + var/seedarkness = 1 + var/ghost_orbit = GHOST_ORBIT_CIRCLE + + var/obj/item/device/multitool/adminMulti = null //Wew, personal multiotool for ghosts! + +/mob/dead/observer/atom_init() + invisibility = INVISIBILITY_OBSERVER + + verbs += /mob/dead/observer/proc/dead_tele + + ghostimage = image(icon, src, "ghost") + ghost_darkness_images |= ghostimage + updateallghostimages() + + var/turf/T + var/mob/body = loc + if(ismob(body)) + T = get_turf(body) //Where is the body located? + attack_log = body.attack_log //preserve our attack logs by copying them to our ghost + + if(ishuman(body)) + overlays = body.overlays + else + icon = body.icon + icon_state = body.icon_state + overlays = body.overlays + + alpha = 127 + + gender = body.gender + if(body.mind && body.mind.name) + name = body.mind.name + else + if(body.real_name) + name = body.real_name + else + if(gender == MALE) + name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) + else + name = capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names)) + + mind = body.mind //we don't transfer the mind but we keep a reference to it. + + if(!T) + T = pick(latejoin) //Safety in case we cannot find the body's position + + loc = T + + if(!name) //To prevent nameless ghosts + name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names)) + real_name = name + + dead_mob_list += src + + . = ..() + + observer_list += src + +/mob/dead/observer/Destroy() + observer_list -= src + if (ghostimage) + ghost_darkness_images -= ghostimage + qdel(ghostimage) + ghostimage = null + updateallghostimages() + QDEL_NULL(adminMulti) + return ..() + +//this is called when a ghost is drag clicked to something. +/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 ..() + +/mob/dead/observer/Topic(href, href_list) + if(href_list["track"]) + var/mob/target = locate(href_list["track"]) in mob_list + if(target) + ManualFollow(target) + + if(href_list["ghostplayerobservejump"]) + var/atom/movable/target = locate(href_list["ghostplayerobservejump"]) + if(!target) + return + + var/turf/T = get_turf(target) + forceMove(T) + +/mob/dead/attackby(obj/item/W, mob/user) + if(istype(W,/obj/item/weapon/book/tome)) + user.SetNextMove(CLICK_CD_MELEE) + var/mob/dead/M = src + if(src.invisibility != 0) + M.invisibility = 0 + user.visible_message( \ + "[user] drags ghost, [M], to our plan of reality!", \ + "You drag [M] to our plan of reality!" \ + ) + else + user.visible_message ( \ + "[user] just tried to smash his book into that ghost! It's not very effective.", \ + "You get the feeling that the ghost can't become any more visible." \ + ) + + +/mob/dead/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + return 1 +/* +Transfer_mind is there to check if mob is being deleted/not going to have a body. +Works together with spawning an observer, noted above. +*/ + +/mob/dead/observer/Life() + ..() + if(!loc) return + if(!client) return 0 + + + if(client.images.len) + for(var/image/hud in client.images) + if(copytext(hud.icon_state,1,4) == "hud") + client.images.Remove(hud) + + if(antagHUD) + var/list/target_list = list() + for(var/mob/living/target in oview(src, 14)) + if(target.mind&&(target.mind.special_role||issilicon(target)) ) + target_list += target + if(target_list.len) + assess_targets(target_list, src) + if(medHUD) + process_medHUD(src) + + +/mob/dead/proc/process_medHUD(mob/M) + var/client/C = M.client + for(var/mob/living/carbon/human/patient in oview(M, 14)) + C.images += patient.hud_list[HEALTH_HUD] + C.images += patient.hud_list[STATUS_HUD_OOC] + +/mob/dead/proc/assess_targets(list/target_list, mob/dead/observer/U) + var/client/C = U.client + for(var/mob/living/carbon/human/target in target_list) + C.images += target.hud_list[SPECIALROLE_HUD] + + +/* + else//If the silicon mob has no law datum, no inherent laws, or a law zero, add them to the hud. + var/mob/living/silicon/silicon_target = target + if(!silicon_target.laws||(silicon_target.laws&&(silicon_target.laws.zeroth||!silicon_target.laws.inherent.len))||silicon_target.mind.special_role=="traitor") + if(isrobot(silicon_target))//Different icons for robutts and AI. + U.client.images += image(tempHud,silicon_target,"hudmalborg") + else + U.client.images += image(tempHud,silicon_target,"hudmalai") +*/ + return 1 + +/mob/proc/ghostize(can_reenter_corpse = TRUE, bancheck = FALSE) + if(key) + if(!(ckey in admin_datums) && bancheck == TRUE && jobban_isbanned(src, "Observer")) + var/mob/M = mousize() + if((config.allow_drone_spawn) || !jobban_isbanned(src, ROLE_DRONE)) + var/response = alert(M, "Do you want to become a maintenance drone?","Are you sure you want to beep?","Beep!","Nope!") + if(response == "Beep!") + M.dronize() + qdel(M) + return + var/mob/dead/observer/ghost = new(src) //Transfer safety to observer spawning proc. + ghost.can_reenter_corpse = can_reenter_corpse + ghost.timeofdeath = src.timeofdeath //BS12 EDIT + ghost.key = key + if(client && !ghost.client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed. + ghost.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing! + return ghost + +/* +This is the proc mobs get to turn into a ghost. Forked from ghostize due to compatibility issues. +*/ +/mob/living/verb/ghost() + set category = "OOC" + set name = "Ghost" + set desc = "Relinquish your life and enter the land of the dead." + + if(!(ckey in admin_datums) && jobban_isbanned(src, "Observer")) + to_chat(src, "You have been banned from observing.") + return + if(stat == DEAD) + if(fake_death) + var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another 30 minutes! You can't change your mind so choose wisely!)","Are you sure you want to ghost?","Stay in body","Ghost") + if(response != "Ghost") + return //didn't want to ghost after-all + var/mob/dead/observer/ghost = ghostize(can_reenter_corpse = FALSE) + ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. + else + ghostize(can_reenter_corpse = TRUE) + else + var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another 30 minutes! You can't change your mind so choose wisely!)","Are you sure you want to ghost?","Stay in body","Ghost") + if(response != "Ghost") + return //didn't want to ghost after-all + + if(isrobot(usr)) + var/mob/living/silicon/robot/robot = usr + robot.toggle_all_components() + else + resting = 1 + var/mob/dead/observer/ghost = ghostize(can_reenter_corpse = FALSE) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 + ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly. + return + + +/mob/dead/observer/Move(NewLoc, direct) + dir = direct + if(NewLoc) + loc = NewLoc + for(var/obj/effect/step_trigger/S in NewLoc) + S.Crossed(src) + update_parallax_contents() + return + loc = get_turf(src) //Get out of closets and such as a ghost + if((direct & NORTH) && y < world.maxy) + y++ + else if((direct & SOUTH) && y > 1) + y-- + if((direct & EAST) && x < world.maxx) + x++ + else if((direct & WEST) && x > 1) + x-- + + for(var/obj/effect/step_trigger/S in locate(x, y, z)) //<-- this is dumb + S.Crossed(src) + + +/mob/dead/observer/can_use_hands() return 0 +/mob/dead/observer/is_active() return 0 + +/mob/dead/observer/Stat() + ..() + if(statpanel("Status")) + stat(null, "Station Time: [worldtime2text()]") + if(ticker.mode && ticker.mode.config_tag == "gang") + var/datum/game_mode/gang/mode = ticker.mode + if(isnum(mode.A_timer)) + stat(null, "[gang_name("A")] Gang Takeover: [max(mode.A_timer, 0)]") + if(isnum(mode.B_timer)) + stat(null, "[gang_name("B")] Gang Takeover: [max(mode.B_timer, 0)]") + +/mob/dead/observer/verb/reenter_corpse() + set category = "Ghost" + set name = "Re-enter Corpse" + if(!client) return + if(!(mind && mind.current && can_reenter_corpse)) + to_chat(src, "You have no body.") + return + if(mind.current.key && copytext(mind.current.key,1,2)!="@") //makes sure we don't accidentally kick any clients + to_chat(usr, "Another consciousness is in your body... it is resisting you.") + return + mind.current.key = key + return 1 + +/mob/dead/observer/verb/toggle_medHUD() + set category = "Ghost" + set name = "Toggle MedicHUD" + set desc = "Toggles Medical HUD allowing you to see how everyone is doing." + if(!client) + return + if(medHUD) + medHUD = 0 + to_chat(src, "Medical HUD Disabled") + else + medHUD = 1 + to_chat(src, "Medical HUD Enabled") + +/mob/dead/observer/verb/toggle_antagHUD() + set category = "Ghost" + set name = "Toggle AntagHUD" + set desc = "Toggles AntagHUD allowing you to see who is the antagonist." + + if(!client) + return + if(!config.antag_hud_allowed && !client.holder) + to_chat(src, "Admins have disabled this for this round.") + return + var/mob/dead/observer/M = src + if(jobban_isbanned(M, "AntagHUD")) + to_chat(src, "You have been banned from using this feature.") + return + if(config.antag_hud_restricted && !M.has_enabled_antagHUD && !client.holder) + var/response = alert(src, "If you turn this on, you will not be able to take any part in the round.","Are you sure you want to turn this feature on?","Yes","No") + if(response == "No") + return + M.can_reenter_corpse = 0 + if(!M.has_enabled_antagHUD && !client.holder) + M.has_enabled_antagHUD = 1 + if(M.antagHUD) + M.antagHUD = 0 + to_chat(src, "AntagHUD Disabled") + else + M.antagHUD = 1 + to_chat(src, "AntagHUD Enabled") + +/mob/dead/observer/proc/dead_tele(A in ghostteleportlocs) + set category = "Ghost" + set name = "Teleport" + set desc= "Teleport to a location" + if(!istype(usr, /mob/dead/observer)) + to_chat(usr, "Not when you're not dead!") + return + usr.verbs -= /mob/dead/observer/proc/dead_tele + spawn(30) + usr.verbs += /mob/dead/observer/proc/dead_tele + var/area/thearea = ghostteleportlocs[A] + if(!thearea) + return + + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + L += T + + if(!L || !L.len) + to_chat(usr, "No area available.") + + usr.forceMove(pick(L)) + update_parallax_contents() + +/mob/dead/observer/verb/follow() + set category = "Ghost" + set name = "Orbit" // "Haunt" + set desc = "Follow and orbit a mob." + + var/list/mobs = getpois(skip_mindless=1) + var/input = input("Please, select a mob!", "Haunt", null, null) as null|anything in mobs + var/mob/target = mobs[input] + if(!target) + return + ManualFollow(target) + +// This is the ghost's follow verb with an argument +/mob/dead/observer/proc/ManualFollow(atom/movable/target) + if (!istype(target)) + return + + var/icon/I = icon(target.icon,target.icon_state,target.dir) + + var/orbitsize = (I.Width() + I.Height()) * 0.5 + orbitsize -= (orbitsize / world.icon_size) * (world.icon_size * 0.25) + + if(orbiting && orbiting.orbiting != target) + to_chat(src, "Now orbiting [target].") + + var/rot_seg + + switch(ghost_orbit) + if(GHOST_ORBIT_TRIANGLE) + rot_seg = 3 + if(GHOST_ORBIT_SQUARE) + rot_seg = 4 + if(GHOST_ORBIT_PENTAGON) + rot_seg = 5 + if(GHOST_ORBIT_HEXAGON) + rot_seg = 6 + else //Circular + rot_seg = 36 //360/10 bby, smooth enough aproximation of a circle + + forceMove(target) + orbit(target, orbitsize, FALSE, 20, rot_seg) + +/mob/dead/observer/orbit() + dir = SOUTH // Reset dir so the right directional sprites show up + ..() + +/mob/dead/observer/stop_orbit() + ..() + pixel_y = 0 + +/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak + set category = "Ghost" + set name = "Jump to Mob" + set desc = "Teleport to a mob." + + if(istype(usr, /mob/dead/observer)) //Make sure they're an observer! + var/list/dest = list() //List of possible destinations (mobs) + var/target = null //Chosen target. + + dest += getpois(mobs_only=1) //Fill list, prompt user with list + target = input("Please, select a player!", "Jump to Mob", null, null) as null|anything in dest + + if (!target)//Make sure we actually have a target + return + else + var/mob/M = dest[target] //Destination mob + var/mob/A = src //Source mob + var/turf/T = get_turf(M) //Turf of the destination mob + + if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination. + A.forceMove(T) + A.update_parallax_contents() + else + to_chat(A, "This mob is not located in the game world.") + +/* +/mob/dead/observer/verb/boo() + set category = "Ghost" + set name = "Boo!" + set desc= "Scare your crew members because of boredom!" + + if(bootime > world.time) return + var/obj/machinery/light/L = locate(/obj/machinery/light) in view(1, src) + if(L) + L.flicker() + bootime = world.time + 600 + return + //Maybe in the future we can add more spooky code here! + return +*/ + +/mob/dead/observer/memory() + set hidden = 1 + to_chat(src, "You are dead! You have no mind to store memory!") + +/mob/dead/observer/add_memory() + set hidden = 1 + to_chat(src, "You are dead! You have no mind to store memory!") + +/mob/dead/observer/verb/analyze_air() + set name = "Analyze Air" + set category = "Ghost" + + if(!istype(usr, /mob/dead/observer)) return + + var/turf/t = get_turf(src) + if(t) + print_atmos_analysis(src, atmosanalyzer_scan(t)) + +/mob/dead/observer/verb/become_mouse() + set name = "Become mouse" + set category = "Ghost" + + if(jobban_isbanned(src, "Mouse")) + to_chat(src, "You have been banned from being mouse.") + return + + if(config.disable_player_mice) + to_chat(src, "Spawning as a mouse is currently disabled.") + return + + var/mob/dead/observer/M = usr + if(config.antag_hud_restricted && M.has_enabled_antagHUD == 1) + to_chat(src, "antagHUD restrictions prevent you from spawning in as a mouse.") + return + + var/timedifference = world.time - client.time_died_as_mouse + if(client.time_died_as_mouse && timedifference <= mouse_respawn_time * 600) + var/timedifference_text + timedifference_text = time2text(mouse_respawn_time * 600 - timedifference,"mm:ss") + to_chat(src, "You may only spawn again as a mouse more than [mouse_respawn_time] minutes after your death. You have [timedifference_text] left.") + return + + var/response = alert(src, "Are you -sure- you want to become a mouse?","Are you sure you want to squeek?","Squeek!","Nope!") + if(response != "Squeek!") + return //Hit the wrong key...again. + + mousize() + +/mob/proc/mousize() + //find a viable mouse candidate + var/mob/living/simple_animal/mouse/host + var/obj/machinery/atmospherics/components/unary/vent_pump/vent_found + var/list/found_vents = list() + for(var/obj/machinery/atmospherics/components/unary/vent_pump/v in machines) + if(!v.welded && v.z == src.z) + found_vents.Add(v) + if(found_vents.len) + vent_found = pick(found_vents) + host = new /mob/living/simple_animal/mouse(vent_found.loc) + else + to_chat(src, "Unable to find any unwelded vents to spawn mice at.") + + if(host) + if(config.uneducated_mice) + host.universal_understand = 0 + host.ckey = src.ckey + to_chat(host, "You are now a mouse. Try to avoid interaction with players, and do not give hints away that you are more than a simple rodent.") + return host + +/mob/dead/observer/proc/ianize() + set name = "Become Ian" + set category = "Ghost" + + if(!abandon_allowed) + to_chat(src, "Respawn is disabled.") + return + + if(has_enabled_antagHUD == 1 && config.antag_hud_restricted) + to_chat(src, "Upon using the antagHUD you forfeighted the ability to join the round.") + return + + if(!ticker.mode) + to_chat(src, "Please wait until game is started.") + return + + var/response = alert(src, "Are you -sure- you want to find Bag Boss?","Are you sure you want to become II?","Soap Pain!","Nope!") + if(response != "Soap Pain!") + return + + var/mob/living/carbon/ian/phoron_dog + for(var/mob/living/carbon/ian/IAN in alive_mob_list) // Incase there is multi_ians, what should NOT ever happen normally! + if(IAN.mind) // Mind means someone was or is in a body. + continue + phoron_dog = IAN + break + + if(phoron_dog) + message_admins("[src.ckey] joined the game as [phoron_dog] [ADMIN_JMP(phoron_dog)] [ADMIN_FLW(phoron_dog)].") + phoron_dog.ckey = src.ckey + else + to_chat(src, "Living and available Ian not found.") + +/mob/dead/observer/verb/view_manfiest() + set name = "View Crew Manifest" + set category = "Ghost" + + var/dat + dat += "

                    Crew Manifest

                    " + dat += data_core.get_manifest() + + src << browse(entity_ja(dat), "window=manifest;size=370x420;can_close=1") + +//Used for drawing on walls with blood puddles as a spooky ghost. +/mob/dead/observer/verb/bloody_doodle() + + set category = "Ghost" + set name = "Write in blood" + set desc = "If the round is sufficiently spooky, write a short message in blood on the floor or a wall. Remember, no IC in OOC or OOC in IC." + + if(!(config.cult_ghostwriter)) + to_chat(src, "That verb is not currently permitted.") + return + + if (!src.stat) + return + + if (usr != src) + return 0 //something is terribly wrong + + var/ghosts_can_write + if(ticker.mode.name == "cult") + var/datum/game_mode/cult/C = ticker.mode + if(C.cult.len > config.cult_ghostwriter_req_cultists) + ghosts_can_write = 1 + + if(!ghosts_can_write) + to_chat(src, "The veil is not thin enough for you to do that.") + return + + var/list/choices = list() + for(var/obj/effect/decal/cleanable/blood/B in view(1,src)) + if(B.amount > 0) + choices += B + + if(!choices.len) + to_chat(src, "There is no blood to use nearby.") + return + + var/obj/effect/decal/cleanable/blood/choice = input(src,"What blood would you like to use?") in null|choices + + var/direction = input(src,"Which way?","Tile selection") as anything in list("Here","North","South","East","West") + var/turf/simulated/T = src.loc + if (direction != "Here") + T = get_step(T,text2dir(direction)) + + if (!istype(T)) + to_chat(src, "You cannot doodle there.") + return + + if(!choice || choice.amount == 0 || !(src.Adjacent(choice))) + return + + var/datum/dirt_cover/doodle_color = new/datum/dirt_cover(choice.basedatum) + + var/num_doodles = 0 + for (var/obj/effect/decal/cleanable/blood/writing/W in T) + num_doodles++ + if (num_doodles > 4) + to_chat(src, "There is no space to write on!") + return + + var/max_length = 50 + + var/message = sanitize_safe(input(src,"Write a message. It cannot be longer than [max_length] characters.","Blood writing", "")) + + if (message) + + if (length(message) > max_length) + message += "-"//Should crop any letters? No? + to_chat(src, "You ran out of blood to write with!") + + var/obj/effect/decal/cleanable/blood/writing/W = new(T) + W.basedatum = new/datum/dirt_cover(doodle_color) + W.update_icon() + W.message = message + W.add_hiddenprint(src) + W.visible_message("Invisible fingers crudely paint something in blood on [T]...") + +/mob/dead/observer/verb/toggle_ghostsee() + set name = "Toggle Ghost Vision" + set desc = "Toggles your ability to see things only ghosts can see, like other ghosts." + set category = "Ghost" + ghostvision = !(ghostvision) + updateghostsight() + to_chat(usr, "You [(ghostvision?"now":"no longer")] have ghost vision.") + +/mob/dead/observer/verb/toggle_darkness() + set name = "Toggle Darkness" + set category = "Ghost" + seedarkness = !(seedarkness) + updateghostsight() + +/mob/dead/observer/proc/updateghostsight() + if (!seedarkness) + see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING + else + see_invisible = SEE_INVISIBLE_OBSERVER + if (!ghostvision) + see_invisible = SEE_INVISIBLE_LIVING; + updateghostimages() + +/proc/updateallghostimages() + for (var/mob/dead/observer/O in player_list) + O.updateghostimages() + +/mob/dead/observer/proc/updateghostimages() + if (!client) + return + if (seedarkness || !ghostvision) + client.images -= ghost_darkness_images + client.images |= ghost_sightless_images + else + //add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now + client.images -= ghost_sightless_images + client.images |= ghost_darkness_images + if (ghostimage) + client.images -= ghostimage //remove ourself + +/mob/dead/observer/IsAdvancedToolUser() + return IsAdminGhost(src) diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index 181ff5e2c540..3f33df9d634d 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -1,65 +1,65 @@ -/mob/dead/observer/say(var/message) - message = sanitize(message) - - if (!message) - return - - log_say("Ghost/[src.key] : [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/emote(act, type, message) - message = sanitize(message) - - if(!message) - return - - if(act != "me") - return - - log_emote("Ghost/[src.key] : [message]") - - if(src.client) - if(src.client.prefs.muted & MUTE_DEADCHAT) - to_chat(src, "You cannot emote in deadchat (muted).") - return - - if(src.client.handle_spam_prevention(message, MUTE_DEADCHAT)) - return - - . = src.emote_dead(message) - -/* - for (var/mob/M in hearers(null, null)) - if (!M.stat) - if(M.job == "Chaplain") - if (prob (49)) - M.show_message("You hear muffled speech... but nothing is there...", 2) - if(prob(20)) - playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) - else - M.show_message("You hear muffled speech... you can almost make out some words...", 2) -// M.show_message("[stutter(message)]", 2) - if(prob(30)) - playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) - else - if (prob(50)) - return - else if (prob (95)) - M.show_message("You hear muffled speech... but nothing is there...", 2) - if(prob(20)) - playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) - else - M.show_message("You hear muffled speech... you can almost make out some words...", 2) -// M.show_message("[stutter(message)]", 2) - playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) -*/ +/mob/dead/observer/say(var/message) + message = sanitize(message) + + if (!message) + return + + log_say("Ghost/[src.key] : [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/emote(act, type, message) + message = sanitize(message) + + if(!message) + return + + if(act != "me") + return + + log_emote("Ghost/[src.key] : [message]") + + if(src.client) + if(src.client.prefs.muted & MUTE_DEADCHAT) + to_chat(src, "You cannot emote in deadchat (muted).") + return + + if(src.client.handle_spam_prevention(message, MUTE_DEADCHAT)) + return + + . = src.emote_dead(message) + +/* + for (var/mob/M in hearers(null, null)) + if (!M.stat) + if(M.job == "Chaplain") + if (prob (49)) + M.show_message("You hear muffled speech... but nothing is there...", 2) + if(prob(20)) + playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) + else + M.show_message("You hear muffled speech... you can almost make out some words...", 2) +// M.show_message("[stutter(message)]", 2) + if(prob(30)) + playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) + else + if (prob(50)) + return + else if (prob (95)) + M.show_message("You hear muffled speech... but nothing is there...", 2) + if(prob(20)) + playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) + else + M.show_message("You hear muffled speech... you can almost make out some words...", 2) +// M.show_message("[stutter(message)]", 2) + playsound(src.loc, pick('sound/effects/ghost.ogg','sound/effects/ghost2.ogg'), 10, 1) +*/ diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 9b857e315b62..95f5e13b98c9 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -1,85 +1,85 @@ -// All mobs should have custom emote, really.. -/mob/proc/custom_emote(m_type=1,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 - - if(!message) - message = sanitize(input(src,"Choose an emote to display.") as text|null) - - if(message) - message = "[src] [message]" - else - return - - - if (message) - log_emote("[name]/[key] : [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. - if(findtext(message," snores.") == 0) - for(var/mob/M in player_list) - if(isnewplayer(M)) - continue - if(M.stat == DEAD && (M.client.prefs.chat_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) - for (var/mob/O in viewers(src, null)) - if(O.status_flags & PASSEMOTES) - for(var/obj/item/weapon/holder/thing in O.contents) - thing.show_message(message, m_type) - O.show_message(message, m_type) - - // Type 2 (Audible) emotes are sent to anyone in hear range - // of the *LOCATION* -- this is important for pAIs to be heard - else if (m_type & 2) - for (var/mob/O in hearers(get_turf(src), null)) - if(O.status_flags & PASSEMOTES) - for(var/obj/item/weapon/holder/thing in O.contents) - thing.show_message(message, m_type) - O.show_message(message, m_type) - -/mob/proc/emote_dead(message) - - if(client.prefs.muted & MUTE_DEADCHAT) - to_chat(src, "\red You cannot send deadchat emotes (muted).") - return - - if(!(client.prefs.chat_toggles & CHAT_DEAD)) - to_chat(src, "\red You have deadchat muted.") - return - - if(!src.client.holder) - if(!dsay_allowed) - to_chat(src, "\red Deadchat is globally muted") - return - - - if(!message) - message = sanitize(input(src, "Choose an emote to display.") as text|null) - - if(message) - message = "DEAD: [src] [message]" - else - return - - - if(message) - log_emote("Ghost/[src.key] : [message]") - - for(var/mob/M in player_list) - if(isnewplayer(M)) - continue - - if(M.client && M.client.holder && (M.client.holder.rights & R_ADMIN) && (M.client.prefs.chat_toggles & CHAT_DEAD)) // Show the emote to admins - to_chat(M, message) - - else if(M.stat == DEAD && (M.client.prefs.chat_toggles & CHAT_DEAD)) // Show the emote to regular ghosts with deadchat toggled on - M.show_message(message, 2) +// All mobs should have custom emote, really.. +/mob/proc/custom_emote(m_type=1,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 + + if(!message) + message = sanitize(input(src,"Choose an emote to display.") as text|null) + + if(message) + message = "[src] [message]" + else + return + + + if (message) + log_emote("[name]/[key] : [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. + if(findtext(message," snores.") == 0) + for(var/mob/M in player_list) + if(isnewplayer(M)) + continue + if(M.stat == DEAD && (M.client.prefs.chat_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) + for (var/mob/O in viewers(src, null)) + if(O.status_flags & PASSEMOTES) + for(var/obj/item/weapon/holder/thing in O.contents) + thing.show_message(message, m_type) + O.show_message(message, m_type) + + // Type 2 (Audible) emotes are sent to anyone in hear range + // of the *LOCATION* -- this is important for pAIs to be heard + else if (m_type & 2) + for (var/mob/O in hearers(get_turf(src), null)) + if(O.status_flags & PASSEMOTES) + for(var/obj/item/weapon/holder/thing in O.contents) + thing.show_message(message, m_type) + O.show_message(message, m_type) + +/mob/proc/emote_dead(message) + + if(client.prefs.muted & MUTE_DEADCHAT) + to_chat(src, "\red You cannot send deadchat emotes (muted).") + return + + if(!(client.prefs.chat_toggles & CHAT_DEAD)) + to_chat(src, "\red You have deadchat muted.") + return + + if(!src.client.holder) + if(!dsay_allowed) + to_chat(src, "\red Deadchat is globally muted") + return + + + if(!message) + message = sanitize(input(src, "Choose an emote to display.") as text|null) + + if(message) + message = "DEAD: [src] [message]" + else + return + + + if(message) + log_emote("Ghost/[src.key] : [message]") + + for(var/mob/M in player_list) + if(isnewplayer(M)) + continue + + if(M.client && M.client.holder && (M.client.holder.rights & R_ADMIN) && (M.client.prefs.chat_toggles & CHAT_DEAD)) // Show the emote to admins + to_chat(M, message) + + else if(M.stat == DEAD && (M.client.prefs.chat_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 9de246dcf12d..461af0c6b998 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -1,421 +1,421 @@ -//This proc is called whenever someone clicks an inventory ui slot. -/mob/proc/attack_ui(slot) - var/obj/item/W = get_active_hand() - if(istype(W)) - if(isIAN(src)) - switch(slot) - if(slot_head, slot_back) - to_chat(src, "You have no idea how humans do this.") - return - if (istype(W, /obj/item/clothing)) - var/obj/item/clothing/C = W - if(C.rig_restrict_helmet) - to_chat(src, "You must fasten the helmet to a hardsuit first. (Target the head)")// Stop eva helms equipping. - else - if(C.equip_time > 0) - delay_clothing_equip_to_slot_if_possible(C, slot) - else - equip_to_slot_if_possible(C, slot) - else - equip_to_slot_if_possible(W, slot) - -/mob/proc/put_in_any_hand_if_possible(obj/item/W, del_on_fail = 0, disable_warning = 1, redraw_mob = 1) - if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning, redraw_mob)) - return 1 - else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning, redraw_mob)) - return 1 - return 0 - -//This is a SAFE proc. Use this instead of equip_to_slot()! -//set del_on_fail to have it delete W if it fails to equip -//set disable_warning to disable the 'you are unable to equip that' warning. -//unset redraw_mob to prevent the mob from being redrawn at the end. -/mob/proc/equip_to_slot_if_possible(obj/item/W, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1) - if(!istype(W)) return 0 - - if(!W.mob_can_equip(src, slot, disable_warning)) - if(del_on_fail) - qdel(W) - else - if(!disable_warning) - to_chat(src, "You are unable to equip that.")//Only print if del_on_fail is false - return 0 - - equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail. - return 1 - -//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't eqip need to be done before! Use mob_can_equip() for that task. -//In most cases you will want to use equip_to_slot_if_possible() -/mob/proc/equip_to_slot(obj/item/W, slot) - return - -//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the rounds tarts and when events happen and such. -/mob/proc/equip_to_slot_or_del(obj/item/W, slot) - return equip_to_slot_if_possible(W, slot, 1, 1, 0) - -//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot. -var/list/slot_equipment_priority = list( - slot_back, - slot_wear_id, - slot_w_uniform, - slot_wear_suit, - slot_wear_mask, - slot_head, - slot_shoes, - slot_gloves, - slot_l_ear, - slot_r_ear, - slot_glasses, - slot_belt, - slot_s_store, - slot_tie, - slot_l_store, - slot_r_store - ) - -//puts the item "W" into an appropriate slot in a human's inventory -//returns 0 if it cannot, 1 if successful -/mob/proc/equip_to_appropriate_slot(obj/item/W) - if(!istype(W)) return 0 - - for(var/slot in slot_equipment_priority) - if(equip_to_slot_if_possible(W, slot, del_on_fail=0, disable_warning=1, redraw_mob=1)) - return 1 - - return 0 - -// Convinience proc. Collects crap that fails to equip either onto the mob's back, or drops it. -// Used in job equipping so shit doesn't pile up at the start loc. -/mob/living/carbon/human/proc/equip_or_collect(obj/item/W, slot) - if(W.mob_can_equip(src, slot, 1)) - //Mob can equip. Equip it. - equip_to_slot_or_del(W, slot) - else - //Mob can't equip it. Put it in a bag B. - // Do I have a backpack? - var/obj/item/weapon/storage/B - if(istype(back,/obj/item/weapon/storage)) - //Mob is wearing backpack - B = back - else - //not wearing backpack. Check if player holding plastic bag - B=is_in_hands(/obj/item/weapon/storage/bag/plasticbag) - if(!B) //If not holding plastic bag, give plastic bag - B=new /obj/item/weapon/storage/bag/plasticbag(null) // Null in case of failed equip. - if(!put_in_hands(B)) - return // Bag could not be placed in players hands. I don't know what to do here... - //Now, B represents a container we can insert W into. - B.handle_item_insertion(W,1) - return B - - -//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 - - -//Returns the thing in our active hand -/mob/proc/get_active_hand() - if(hand) return l_hand - else return r_hand - -//Returns the thing in our inactive hand -/mob/proc/get_inactive_hand() - if(hand) return r_hand - else return l_hand - -//Checks if thing in mob's hands -/mob/living/carbon/human/proc/is_in_hands(typepath) - if(istype(l_hand,typepath)) - return l_hand - if(istype(r_hand,typepath)) - return r_hand - return 0 - -//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(obj/item/W) - if(lying && !(W.flags&ABSTRACT)) return 0 - if(!istype(W)) return 0 - if(W.anchored) return 0 //Anchored things shouldn't be picked up because they... anchored?! - if(!l_hand) - W.loc = src //TODO: move to equipped? - l_hand = W - W.layer = ABOVE_HUD_LAYER //TODO: move to equipped? - W.plane = ABOVE_HUD_PLANE - W.appearance_flags = APPEARANCE_UI -// 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.pixel_x = initial(W.pixel_x) - W.pixel_y = initial(W.pixel_y) - 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(obj/item/W) - if(lying && !(W.flags&ABSTRACT)) return 0 - if(!istype(W)) return 0 - if(W.anchored) return 0 //Anchored things shouldn't be picked up because they... anchored?! - if(!r_hand) - W.loc = src - r_hand = W - W.layer = ABOVE_HUD_LAYER - W.plane = ABOVE_HUD_PLANE - W.appearance_flags = APPEARANCE_UI -// 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.pixel_x = initial(W.pixel_x) - W.pixel_y = initial(W.pixel_y) - return 1 - return 0 - -//Puts the item into our active hand if possible. returns 1 on success. -/mob/proc/put_in_active_hand(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(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(obj/item/W) - if(!W) return 0 - if(put_in_active_hand(W)) - return 1 - else if(put_in_inactive_hand(W)) - return 1 - else - W.forceMove(get_turf(src)) - W.layer = initial(W.layer) - W.plane = initial(W.plane) - W.appearance_flags = initial(W.appearance_flags) - W.dropped() - return 0 - -// Removes an item from inventory and places it in the target atom -/mob/proc/drop_from_inventory(obj/item/W, atom/target = null) - if(W) - remove_from_mob(W, target) - if(!(W && W.loc)) - return 1 // self destroying objects (tk, grabs) - update_icons() - return 1 - return 0 - -//Drops the item in our left hand -/mob/proc/drop_l_hand(atom/Target) - if(istype(l_hand, /obj/item)) - var/obj/item/W = l_hand - if(W.flags & NODROP) - return FALSE - return drop_from_inventory(l_hand, Target) - -//Drops the item in our right hand -/mob/proc/drop_r_hand(atom/Target) - if(istype(r_hand, /obj/item)) - var/obj/item/W = r_hand - if(W.flags & NODROP) - return FALSE - return drop_from_inventory(r_hand, Target) - -//Drops the item in our active hand. -/mob/proc/drop_item(atom/Target) - if(hand) return drop_l_hand(Target) - else return drop_r_hand(Target) - -/* - Removes the object from any slots the mob might have, calling the appropriate icon update proc. - Does nothing else. - - DO NOT CALL THIS PROC DIRECTLY. It is meant to be called only by other inventory procs. - It's probably okay to use it if you are transferring the item between slots on the same mob, - but chances are you're safer calling remove_from_mob() or drop_from_inventory() anyways. - - As far as I can tell the proc exists so that mobs with different inventory slots can override - the search through all the slots, without having to duplicate the rest of the item dropping. -*/ -/mob/proc/u_equip(obj/W) - if (W == r_hand) - r_hand = null - update_inv_r_hand() - else if (W == l_hand) - l_hand = null - update_inv_l_hand() - else if (W == back) - back = null - update_inv_back() - else if (W == wear_mask) - wear_mask = null - update_inv_wear_mask() - return - -//This differs from remove_from_mob() in that it checks canremove first. -/mob/proc/unEquip(obj/item/I, force = 0) //Force overrides NODROP for things like wizarditis and admin undress. - if(!I) //If there's nothing to drop, the drop is automatically successful. - return 1 - - if(!I.canremove && !force) - return 0 - - drop_from_inventory(I) - return 1 - -// Attemps to remove an object on a mob. Will drop item to ground or move into target. -/mob/proc/remove_from_mob(obj/O, atom/target) - if(!O) return - src.u_equip(O) - if (src.client) - src.client.screen -= O - O.layer = initial(O.layer) - O.plane = initial(O.plane) - O.appearance_flags = initial(O.appearance_flags) - O.screen_loc = null - if(istype(O, /obj/item)) - var/obj/item/I = O - if(target) - I.forceMove(target) - else - I.forceMove(loc) - I.dropped(src) - return 1 - -//Returns the item equipped to the specified slot, if any. -/mob/proc/get_equipped_item(var/slot) - return null - -/mob/living/carbon/get_equipped_item(var/slot) - switch(slot) - if(slot_back) return back - if(slot_wear_mask) return wear_mask - if(slot_l_hand) return l_hand - if(slot_r_hand) return r_hand - return null - -/mob/living/carbon/human/get_equipped_item(var/slot) - switch(slot) - if(slot_belt) return belt - if(slot_l_ear) return l_ear - if(slot_r_ear) return r_ear - if(slot_glasses) return glasses - if(slot_gloves) return gloves - if(slot_head) return head - if(slot_shoes) return shoes - if(slot_wear_id) return wear_id - if(slot_wear_suit) return wear_suit - if(slot_w_uniform) return w_uniform - if(slot_back) return back - if(slot_wear_mask) return wear_mask - if(slot_l_hand) return l_hand - if(slot_r_hand) return r_hand - return null - -/mob/proc/get_equipped_items() - return null - -/mob/living/carbon/get_equipped_items() - var/list/items = list() - - if(back) - items += back - if(wear_mask) - items += wear_mask - if(l_hand) - items += l_hand - if(r_hand) - items += r_hand - - return items - -/mob/living/carbon/human/get_equipped_items() - var/list/items = ..() - - if(belt) - items += belt - if(l_ear) - items += l_ear - if(r_ear) - items += r_ear - if(glasses) - items += glasses - if(gloves) - items += gloves - if(head) - items += head - if(shoes) - items += shoes - if(wear_id) - items += wear_id - if(wear_suit) - items += wear_suit - if(w_uniform) - items += w_uniform - - return items - -//Create delay for equipping -/mob/proc/delay_clothing_u_equip(obj/item/clothing/C) // Bone White - delays unequipping by parameter. Requires W to be /obj/item/clothing/ - - if(!istype(C)) return 0 - - if(C.equipping) return 0 // Item is already being (un)equipped - - var/tempX = usr.x - var/tempY = usr.y - to_chat(usr, "You start unequipping the [C].") - C.equipping = 1 - var/equip_time = round(C.equip_time/10) - var/i - for(i=1; i<=equip_time; i++) - sleep (10) // Check if they've moved every 10 time units - if ((tempX != usr.x) || (tempY != usr.y)) - to_chat(src, "\The [C] is too fiddly to unequip whilst moving.") - C.equipping = 0 - return 0 - remove_from_mob(C) - to_chat(usr, "You have finished unequipping the [C].") - C.equipping = 0 - -/mob/proc/delay_clothing_equip_to_slot_if_possible(obj/item/clothing/C, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1, delay_time = 0) - if(!istype(C)) return 0 - - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - if(H.wear_suit) - to_chat(H, "You need to take off [H.wear_suit.name] first.") - return - - if(C.equipping) return 0 // Item is already being equipped - - var/tempX = usr.x - var/tempY = usr.y - to_chat(usr, "You start equipping the [C].") - C.equipping = 1 - var/equip_time = round(C.equip_time/10) - var/i - for(i=1; i<=equip_time; i++) - sleep (10) // Check if they've moved every 10 time units - if ((tempX != usr.x) || (tempY != usr.y)) - to_chat(src, "\The [C] is too fiddly to fasten whilst moving.") - C.equipping = 0 - return 0 - equip_to_slot_if_possible(C, slot) - to_chat(usr, "You have finished equipping the [C].") - C.equipping = 0 - -/mob/proc/get_item_by_slot(slot_id) - switch(slot_id) - if(slot_l_hand) - return l_hand - if(slot_r_hand) - return r_hand - return null +//This proc is called whenever someone clicks an inventory ui slot. +/mob/proc/attack_ui(slot) + var/obj/item/W = get_active_hand() + if(istype(W)) + if(isIAN(src)) + switch(slot) + if(slot_head, slot_back) + to_chat(src, "You have no idea how humans do this.") + return + if (istype(W, /obj/item/clothing)) + var/obj/item/clothing/C = W + if(C.rig_restrict_helmet) + to_chat(src, "You must fasten the helmet to a hardsuit first. (Target the head)")// Stop eva helms equipping. + else + if(C.equip_time > 0) + delay_clothing_equip_to_slot_if_possible(C, slot) + else + equip_to_slot_if_possible(C, slot) + else + equip_to_slot_if_possible(W, slot) + +/mob/proc/put_in_any_hand_if_possible(obj/item/W, del_on_fail = 0, disable_warning = 1, redraw_mob = 1) + if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning, redraw_mob)) + return 1 + else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning, redraw_mob)) + return 1 + return 0 + +//This is a SAFE proc. Use this instead of equip_to_slot()! +//set del_on_fail to have it delete W if it fails to equip +//set disable_warning to disable the 'you are unable to equip that' warning. +//unset redraw_mob to prevent the mob from being redrawn at the end. +/mob/proc/equip_to_slot_if_possible(obj/item/W, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1) + if(!istype(W)) return 0 + + if(!W.mob_can_equip(src, slot, disable_warning)) + if(del_on_fail) + qdel(W) + else + if(!disable_warning) + to_chat(src, "You are unable to equip that.")//Only print if del_on_fail is false + return 0 + + equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail. + return 1 + +//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't eqip need to be done before! Use mob_can_equip() for that task. +//In most cases you will want to use equip_to_slot_if_possible() +/mob/proc/equip_to_slot(obj/item/W, slot) + return + +//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the rounds tarts and when events happen and such. +/mob/proc/equip_to_slot_or_del(obj/item/W, slot) + return equip_to_slot_if_possible(W, slot, 1, 1, 0) + +//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot. +var/list/slot_equipment_priority = list( + slot_back, + slot_wear_id, + slot_w_uniform, + slot_wear_suit, + slot_wear_mask, + slot_head, + slot_shoes, + slot_gloves, + slot_l_ear, + slot_r_ear, + slot_glasses, + slot_belt, + slot_s_store, + slot_tie, + slot_l_store, + slot_r_store + ) + +//puts the item "W" into an appropriate slot in a human's inventory +//returns 0 if it cannot, 1 if successful +/mob/proc/equip_to_appropriate_slot(obj/item/W) + if(!istype(W)) return 0 + + for(var/slot in slot_equipment_priority) + if(equip_to_slot_if_possible(W, slot, del_on_fail=0, disable_warning=1, redraw_mob=1)) + return 1 + + return 0 + +// Convinience proc. Collects crap that fails to equip either onto the mob's back, or drops it. +// Used in job equipping so shit doesn't pile up at the start loc. +/mob/living/carbon/human/proc/equip_or_collect(obj/item/W, slot) + if(W.mob_can_equip(src, slot, 1)) + //Mob can equip. Equip it. + equip_to_slot_or_del(W, slot) + else + //Mob can't equip it. Put it in a bag B. + // Do I have a backpack? + var/obj/item/weapon/storage/B + if(istype(back,/obj/item/weapon/storage)) + //Mob is wearing backpack + B = back + else + //not wearing backpack. Check if player holding plastic bag + B=is_in_hands(/obj/item/weapon/storage/bag/plasticbag) + if(!B) //If not holding plastic bag, give plastic bag + B=new /obj/item/weapon/storage/bag/plasticbag(null) // Null in case of failed equip. + if(!put_in_hands(B)) + return // Bag could not be placed in players hands. I don't know what to do here... + //Now, B represents a container we can insert W into. + B.handle_item_insertion(W,1) + return B + + +//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 + + +//Returns the thing in our active hand +/mob/proc/get_active_hand() + if(hand) return l_hand + else return r_hand + +//Returns the thing in our inactive hand +/mob/proc/get_inactive_hand() + if(hand) return r_hand + else return l_hand + +//Checks if thing in mob's hands +/mob/living/carbon/human/proc/is_in_hands(typepath) + if(istype(l_hand,typepath)) + return l_hand + if(istype(r_hand,typepath)) + return r_hand + return 0 + +//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(obj/item/W) + if(lying && !(W.flags&ABSTRACT)) return 0 + if(!istype(W)) return 0 + if(W.anchored) return 0 //Anchored things shouldn't be picked up because they... anchored?! + if(!l_hand) + W.loc = src //TODO: move to equipped? + l_hand = W + W.layer = ABOVE_HUD_LAYER //TODO: move to equipped? + W.plane = ABOVE_HUD_PLANE + W.appearance_flags = APPEARANCE_UI +// 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.pixel_x = initial(W.pixel_x) + W.pixel_y = initial(W.pixel_y) + 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(obj/item/W) + if(lying && !(W.flags&ABSTRACT)) return 0 + if(!istype(W)) return 0 + if(W.anchored) return 0 //Anchored things shouldn't be picked up because they... anchored?! + if(!r_hand) + W.loc = src + r_hand = W + W.layer = ABOVE_HUD_LAYER + W.plane = ABOVE_HUD_PLANE + W.appearance_flags = APPEARANCE_UI +// 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.pixel_x = initial(W.pixel_x) + W.pixel_y = initial(W.pixel_y) + return 1 + return 0 + +//Puts the item into our active hand if possible. returns 1 on success. +/mob/proc/put_in_active_hand(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(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(obj/item/W) + if(!W) return 0 + if(put_in_active_hand(W)) + return 1 + else if(put_in_inactive_hand(W)) + return 1 + else + W.forceMove(get_turf(src)) + W.layer = initial(W.layer) + W.plane = initial(W.plane) + W.appearance_flags = initial(W.appearance_flags) + W.dropped() + return 0 + +// Removes an item from inventory and places it in the target atom +/mob/proc/drop_from_inventory(obj/item/W, atom/target = null) + if(W) + remove_from_mob(W, target) + if(!(W && W.loc)) + return 1 // self destroying objects (tk, grabs) + update_icons() + return 1 + return 0 + +//Drops the item in our left hand +/mob/proc/drop_l_hand(atom/Target) + if(istype(l_hand, /obj/item)) + var/obj/item/W = l_hand + if(W.flags & NODROP) + return FALSE + return drop_from_inventory(l_hand, Target) + +//Drops the item in our right hand +/mob/proc/drop_r_hand(atom/Target) + if(istype(r_hand, /obj/item)) + var/obj/item/W = r_hand + if(W.flags & NODROP) + return FALSE + return drop_from_inventory(r_hand, Target) + +//Drops the item in our active hand. +/mob/proc/drop_item(atom/Target) + if(hand) return drop_l_hand(Target) + else return drop_r_hand(Target) + +/* + Removes the object from any slots the mob might have, calling the appropriate icon update proc. + Does nothing else. + + DO NOT CALL THIS PROC DIRECTLY. It is meant to be called only by other inventory procs. + It's probably okay to use it if you are transferring the item between slots on the same mob, + but chances are you're safer calling remove_from_mob() or drop_from_inventory() anyways. + + As far as I can tell the proc exists so that mobs with different inventory slots can override + the search through all the slots, without having to duplicate the rest of the item dropping. +*/ +/mob/proc/u_equip(obj/W) + if (W == r_hand) + r_hand = null + update_inv_r_hand() + else if (W == l_hand) + l_hand = null + update_inv_l_hand() + else if (W == back) + back = null + update_inv_back() + else if (W == wear_mask) + wear_mask = null + update_inv_wear_mask() + return + +//This differs from remove_from_mob() in that it checks canremove first. +/mob/proc/unEquip(obj/item/I, force = 0) //Force overrides NODROP for things like wizarditis and admin undress. + if(!I) //If there's nothing to drop, the drop is automatically successful. + return 1 + + if(!I.canremove && !force) + return 0 + + drop_from_inventory(I) + return 1 + +// Attemps to remove an object on a mob. Will drop item to ground or move into target. +/mob/proc/remove_from_mob(obj/O, atom/target) + if(!O) return + src.u_equip(O) + if (src.client) + src.client.screen -= O + O.layer = initial(O.layer) + O.plane = initial(O.plane) + O.appearance_flags = initial(O.appearance_flags) + O.screen_loc = null + if(istype(O, /obj/item)) + var/obj/item/I = O + if(target) + I.forceMove(target) + else + I.forceMove(loc) + I.dropped(src) + return 1 + +//Returns the item equipped to the specified slot, if any. +/mob/proc/get_equipped_item(var/slot) + return null + +/mob/living/carbon/get_equipped_item(var/slot) + switch(slot) + if(slot_back) return back + if(slot_wear_mask) return wear_mask + if(slot_l_hand) return l_hand + if(slot_r_hand) return r_hand + return null + +/mob/living/carbon/human/get_equipped_item(var/slot) + switch(slot) + if(slot_belt) return belt + if(slot_l_ear) return l_ear + if(slot_r_ear) return r_ear + if(slot_glasses) return glasses + if(slot_gloves) return gloves + if(slot_head) return head + if(slot_shoes) return shoes + if(slot_wear_id) return wear_id + if(slot_wear_suit) return wear_suit + if(slot_w_uniform) return w_uniform + if(slot_back) return back + if(slot_wear_mask) return wear_mask + if(slot_l_hand) return l_hand + if(slot_r_hand) return r_hand + return null + +/mob/proc/get_equipped_items() + return null + +/mob/living/carbon/get_equipped_items() + var/list/items = list() + + if(back) + items += back + if(wear_mask) + items += wear_mask + if(l_hand) + items += l_hand + if(r_hand) + items += r_hand + + return items + +/mob/living/carbon/human/get_equipped_items() + var/list/items = ..() + + if(belt) + items += belt + if(l_ear) + items += l_ear + if(r_ear) + items += r_ear + if(glasses) + items += glasses + if(gloves) + items += gloves + if(head) + items += head + if(shoes) + items += shoes + if(wear_id) + items += wear_id + if(wear_suit) + items += wear_suit + if(w_uniform) + items += w_uniform + + return items + +//Create delay for equipping +/mob/proc/delay_clothing_u_equip(obj/item/clothing/C) // Bone White - delays unequipping by parameter. Requires W to be /obj/item/clothing/ + + if(!istype(C)) return 0 + + if(C.equipping) return 0 // Item is already being (un)equipped + + var/tempX = usr.x + var/tempY = usr.y + to_chat(usr, "You start unequipping the [C].") + C.equipping = 1 + var/equip_time = round(C.equip_time/10) + var/i + for(i=1; i<=equip_time; i++) + sleep (10) // Check if they've moved every 10 time units + if ((tempX != usr.x) || (tempY != usr.y)) + to_chat(src, "\The [C] is too fiddly to unequip whilst moving.") + C.equipping = 0 + return 0 + remove_from_mob(C) + to_chat(usr, "You have finished unequipping the [C].") + C.equipping = 0 + +/mob/proc/delay_clothing_equip_to_slot_if_possible(obj/item/clothing/C, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1, delay_time = 0) + if(!istype(C)) return 0 + + if(ishuman(usr)) + var/mob/living/carbon/human/H = usr + if(H.wear_suit) + to_chat(H, "You need to take off [H.wear_suit.name] first.") + return + + if(C.equipping) return 0 // Item is already being equipped + + var/tempX = usr.x + var/tempY = usr.y + to_chat(usr, "You start equipping the [C].") + C.equipping = 1 + var/equip_time = round(C.equip_time/10) + var/i + for(i=1; i<=equip_time; i++) + sleep (10) // Check if they've moved every 10 time units + if ((tempX != usr.x) || (tempY != usr.y)) + to_chat(src, "\The [C] is too fiddly to fasten whilst moving.") + C.equipping = 0 + return 0 + equip_to_slot_if_possible(C, slot) + to_chat(usr, "You have finished equipping the [C].") + C.equipping = 0 + +/mob/proc/get_item_by_slot(slot_id) + switch(slot_id) + if(slot_l_hand) + return l_hand + if(slot_r_hand) + return r_hand + return null diff --git a/code/modules/mob/living/blob/blob.dm b/code/modules/mob/living/blob/blob.dm index 323dac87cff0..cf07c31ce5e4 100644 --- a/code/modules/mob/living/blob/blob.dm +++ b/code/modules/mob/living/blob/blob.dm @@ -1,259 +1,259 @@ -/mob/living/blob - name = "blob fragment" - real_name = "blob fragment" - icon = 'icons/mob/blob.dmi' - icon_state = "blob_spore_temp" - pass_flags = PASSBLOB - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - var/ghost_name = "Unknown" - var/creating_blob = 0 - faction = "blob" - use_me = 0 //Blobs can't emote - - -/mob/living/blob/atom_init() - real_name += " [pick(rand(1, 99))]" - name = real_name - . = ..() - - -/mob/living/blob/say(var/message) - return//No talking for you - - -/mob/living/blob/emote(act,m_type=1,message = null) - return - - -/mob/living/blob/Life() - set invisibility = 0 - //set background = 1 - - clamp_values() - UpdateDamage() - if(health < 0) - src.dust() - - -/mob/living/blob/proc/clamp_values() - AdjustStunned(0) - AdjustParalysis(0) - AdjustWeakened(0) - sleeping = 0 - if(stat) - stat = CONSCIOUS - return - - -/mob/living/blob/proc/UpdateDamage() - health = 60 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) - return - - -/mob/living/blob/death(gibbed) - if(key) - var/mob/dead/observer/ghost = new(src) - ghost.name = ghost_name - ghost.real_name = ghost_name - ghost.key = key - if (ghost.client) - ghost.client.eye = ghost - return ..(gibbed) - - -/mob/living/blob/blob_act() - to_chat(src, "The blob attempts to reabsorb you.") - adjustToxLoss(20) - return - - -/mob/living/blob/Process_Spacemove() - if(locate(/obj/effect/blob) in oview(1,src)) - return 1 - return (..()) - - -/mob/living/blob/verb/create_node() - set category = "Blob" - set name = "Create Node" - set desc = "Create a Node." - if(creating_blob) return - var/turf/T = get_turf(src) - creating_blob = 1 - if(!T) - creating_blob = 0 - return - var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) - if(!B)//We are on a blob - to_chat(usr, "There is no blob here!") - creating_blob = 0 - return - if(istype(B,/obj/effect/blob/node)||istype(B,/obj/effect/blob/core)||istype(B,/obj/effect/blob/factory)) - to_chat(usr, "Unable to use this blob, find a normal one.") - creating_blob = 0 - return - for(var/obj/effect/blob/node/blob in orange(5)) - to_chat(usr, "There is another node nearby, move more than 5 tiles away from it!") - creating_blob = 0 - return - for(var/obj/effect/blob/factory/blob in orange(2)) - to_chat(usr, "There is a porus blob nearby, move more than 2 tiles away from it!") - creating_blob = 0 - B.change_to("Node") - src.dust() - return - - -/mob/living/blob/verb/create_factory() - set category = "Blob" - set name = "Create Defense" - set desc = "Create a Spore producing blob." - if(creating_blob) return - var/turf/T = get_turf(src) - creating_blob = 1 - if(!T) - creating_blob = 0 - return - var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) - if(!B) - to_chat(usr, "You must be on a blob!") - creating_blob = 0 - return - if(istype(B,/obj/effect/blob/node)||istype(B,/obj/effect/blob/core)||istype(B,/obj/effect/blob/factory)) - to_chat(usr, "Unable to use this blob, find a normal one.") - creating_blob = 0 - return - for(var/obj/effect/blob/blob in orange(2))//Not right next to nodes/cores - if(istype(B,/obj/effect/blob/node)) - to_chat(usr, "There is a node nearby, move away from it!") - creating_blob = 0 - return - if(istype(B,/obj/effect/blob/core)) - to_chat(usr, "There is a core nearby, move away from it!") - creating_blob = 0 - return - if(istype(B,/obj/effect/blob/factory)) - to_chat(usr, "There is another porous blob nearby, move away from it!") - creating_blob = 0 - return - B.change_to("Factory") - src.dust() - return - - -/mob/living/blob/verb/revert() - set category = "Blob" - set name = "Purge Defense" - set desc = "Removes a porous blob." - if(creating_blob) return - var/turf/T = get_turf(src) - creating_blob = 1 - if(!T) - creating_blob = 0 - return - var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) - if(!B) - to_chat(usr, "You must be on a blob!") - creating_blob = 0 - return - if(!istype(B,/obj/effect/blob/factory)) - to_chat(usr, "Unable to use this blob, find another one.") - creating_blob = 0 - return - B.change_to("Normal") - src.dust() - return - - -/mob/living/blob/verb/spawn_blob() - set category = "Blob" - set name = "Create new blob" - set desc = "Attempts to create a new blob in this tile." - if(creating_blob) return - var/turf/T = get_turf(src) - creating_blob = 1 - if(!T) - creating_blob = 0 - return - var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) - if(B) - to_chat(usr, "There is a blob here!") - creating_blob = 0 - return - new/obj/effect/blob(src.loc) - src.dust() - return - - -///mob/proc/Blobize() -/client/proc/Blobcount() - set category = "Debug" - set name = "blobreport" - set desc = "blob report." - set hidden = 1 - - if(!holder) - to_chat(src, "Only administrators may use this command.") - return - if(ticker && ticker.mode) - to_chat(src, "blobs: [blobs.len]") - to_chat(src, "cores: [blob_cores.len]") - to_chat(src, "nodes: [blob_nodes.len]") - return - - -/client/proc/Blobize()//Mostly stolen from the respawn command - set category = "Debug" - set name = "Ghostblob" - set desc = "Ghost into blobthing." - set hidden = 1 - - if(!holder) - to_chat(src, "Only administrators may use this command.") - return - var/input = ckey(input(src, "Please specify which key will be turned into a bloby.", "Key", "")) - - var/mob/dead/observer/G_found - if(!input) - var/list/ghosts = list() - for(var/mob/dead/observer/G in player_list) - ghosts += G - if(ghosts.len) - G_found = pick(ghosts) - - else - for(var/mob/dead/observer/G in player_list) - if(G.client&&ckey(G.key)==input) - G_found = G - break - - if(!G_found)//If a ghost was not found. - alert("There is no active key like that in the game or the person is not currently a ghost. Aborting command.") - return - - if(G_found.client) - G_found.client.screen.len = null - var/mob/living/blob/B = new/mob/living/blob(locate(0,0,1))//temp area also just in case should do this better but tired - if(blob_cores.len > 0) - var/obj/effect/blob/core/core = pick(blob_cores) - if(core) - B.loc = core.loc - B.ghost_name = G_found.real_name - if (G_found.client) - G_found.client.mob = B - B.verbs += /mob/living/blob/verb/create_node - B.verbs += /mob/living/blob/verb/create_factory - to_chat(B, "You are now a blob fragment.") - to_chat(B, "You are a weak bit that has temporarily broken off of the blob.") - to_chat(B, "If you stay on the blob for too long you will likely be reabsorbed.") - to_chat(B, "If you stray from the blob you will likely be killed by other organisms.") - to_chat(B, "You have the power to create a new blob node that will help expand the blob.") - to_chat(B, "To create this node you will have to be on a normal blob tile and far enough away from any other node.") - to_chat(B, "Check your Blob verbs and hit Create Node to build a node.") - spawn(10) - qdel(G_found) - - - - +/mob/living/blob + name = "blob fragment" + real_name = "blob fragment" + icon = 'icons/mob/blob.dmi' + icon_state = "blob_spore_temp" + pass_flags = PASSBLOB + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + var/ghost_name = "Unknown" + var/creating_blob = 0 + faction = "blob" + use_me = 0 //Blobs can't emote + + +/mob/living/blob/atom_init() + real_name += " [pick(rand(1, 99))]" + name = real_name + . = ..() + + +/mob/living/blob/say(var/message) + return//No talking for you + + +/mob/living/blob/emote(act,m_type=1,message = null) + return + + +/mob/living/blob/Life() + set invisibility = 0 + //set background = 1 + + clamp_values() + UpdateDamage() + if(health < 0) + src.dust() + + +/mob/living/blob/proc/clamp_values() + AdjustStunned(0) + AdjustParalysis(0) + AdjustWeakened(0) + sleeping = 0 + if(stat) + stat = CONSCIOUS + return + + +/mob/living/blob/proc/UpdateDamage() + health = 60 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) + return + + +/mob/living/blob/death(gibbed) + if(key) + var/mob/dead/observer/ghost = new(src) + ghost.name = ghost_name + ghost.real_name = ghost_name + ghost.key = key + if (ghost.client) + ghost.client.eye = ghost + return ..(gibbed) + + +/mob/living/blob/blob_act() + to_chat(src, "The blob attempts to reabsorb you.") + adjustToxLoss(20) + return + + +/mob/living/blob/Process_Spacemove() + if(locate(/obj/effect/blob) in oview(1,src)) + return 1 + return (..()) + + +/mob/living/blob/verb/create_node() + set category = "Blob" + set name = "Create Node" + set desc = "Create a Node." + if(creating_blob) return + var/turf/T = get_turf(src) + creating_blob = 1 + if(!T) + creating_blob = 0 + return + var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) + if(!B)//We are on a blob + to_chat(usr, "There is no blob here!") + creating_blob = 0 + return + if(istype(B,/obj/effect/blob/node)||istype(B,/obj/effect/blob/core)||istype(B,/obj/effect/blob/factory)) + to_chat(usr, "Unable to use this blob, find a normal one.") + creating_blob = 0 + return + for(var/obj/effect/blob/node/blob in orange(5)) + to_chat(usr, "There is another node nearby, move more than 5 tiles away from it!") + creating_blob = 0 + return + for(var/obj/effect/blob/factory/blob in orange(2)) + to_chat(usr, "There is a porus blob nearby, move more than 2 tiles away from it!") + creating_blob = 0 + B.change_to("Node") + src.dust() + return + + +/mob/living/blob/verb/create_factory() + set category = "Blob" + set name = "Create Defense" + set desc = "Create a Spore producing blob." + if(creating_blob) return + var/turf/T = get_turf(src) + creating_blob = 1 + if(!T) + creating_blob = 0 + return + var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) + if(!B) + to_chat(usr, "You must be on a blob!") + creating_blob = 0 + return + if(istype(B,/obj/effect/blob/node)||istype(B,/obj/effect/blob/core)||istype(B,/obj/effect/blob/factory)) + to_chat(usr, "Unable to use this blob, find a normal one.") + creating_blob = 0 + return + for(var/obj/effect/blob/blob in orange(2))//Not right next to nodes/cores + if(istype(B,/obj/effect/blob/node)) + to_chat(usr, "There is a node nearby, move away from it!") + creating_blob = 0 + return + if(istype(B,/obj/effect/blob/core)) + to_chat(usr, "There is a core nearby, move away from it!") + creating_blob = 0 + return + if(istype(B,/obj/effect/blob/factory)) + to_chat(usr, "There is another porous blob nearby, move away from it!") + creating_blob = 0 + return + B.change_to("Factory") + src.dust() + return + + +/mob/living/blob/verb/revert() + set category = "Blob" + set name = "Purge Defense" + set desc = "Removes a porous blob." + if(creating_blob) return + var/turf/T = get_turf(src) + creating_blob = 1 + if(!T) + creating_blob = 0 + return + var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) + if(!B) + to_chat(usr, "You must be on a blob!") + creating_blob = 0 + return + if(!istype(B,/obj/effect/blob/factory)) + to_chat(usr, "Unable to use this blob, find another one.") + creating_blob = 0 + return + B.change_to("Normal") + src.dust() + return + + +/mob/living/blob/verb/spawn_blob() + set category = "Blob" + set name = "Create new blob" + set desc = "Attempts to create a new blob in this tile." + if(creating_blob) return + var/turf/T = get_turf(src) + creating_blob = 1 + if(!T) + creating_blob = 0 + return + var/obj/effect/blob/B = (locate(/obj/effect/blob) in T) + if(B) + to_chat(usr, "There is a blob here!") + creating_blob = 0 + return + new/obj/effect/blob(src.loc) + src.dust() + return + + +///mob/proc/Blobize() +/client/proc/Blobcount() + set category = "Debug" + set name = "blobreport" + set desc = "blob report." + set hidden = 1 + + if(!holder) + to_chat(src, "Only administrators may use this command.") + return + if(ticker && ticker.mode) + to_chat(src, "blobs: [blobs.len]") + to_chat(src, "cores: [blob_cores.len]") + to_chat(src, "nodes: [blob_nodes.len]") + return + + +/client/proc/Blobize()//Mostly stolen from the respawn command + set category = "Debug" + set name = "Ghostblob" + set desc = "Ghost into blobthing." + set hidden = 1 + + if(!holder) + to_chat(src, "Only administrators may use this command.") + return + var/input = ckey(input(src, "Please specify which key will be turned into a bloby.", "Key", "")) + + var/mob/dead/observer/G_found + if(!input) + var/list/ghosts = list() + for(var/mob/dead/observer/G in player_list) + ghosts += G + if(ghosts.len) + G_found = pick(ghosts) + + else + for(var/mob/dead/observer/G in player_list) + if(G.client&&ckey(G.key)==input) + G_found = G + break + + if(!G_found)//If a ghost was not found. + alert("There is no active key like that in the game or the person is not currently a ghost. Aborting command.") + return + + if(G_found.client) + G_found.client.screen.len = null + var/mob/living/blob/B = new/mob/living/blob(locate(0,0,1))//temp area also just in case should do this better but tired + if(blob_cores.len > 0) + var/obj/effect/blob/core/core = pick(blob_cores) + if(core) + B.loc = core.loc + B.ghost_name = G_found.real_name + if (G_found.client) + G_found.client.mob = B + B.verbs += /mob/living/blob/verb/create_node + B.verbs += /mob/living/blob/verb/create_factory + to_chat(B, "You are now a blob fragment.") + to_chat(B, "You are a weak bit that has temporarily broken off of the blob.") + to_chat(B, "If you stay on the blob for too long you will likely be reabsorbed.") + to_chat(B, "If you stray from the blob you will likely be killed by other organisms.") + to_chat(B, "You have the power to create a new blob node that will help expand the blob.") + to_chat(B, "To create this node you will have to be on a normal blob tile and far enough away from any other node.") + to_chat(B, "Check your Blob verbs and hit Create Node to build a node.") + spawn(10) + qdel(G_found) + + + + diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 37a00525ab7c..7b7cf9bb1c49 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -1,362 +1,362 @@ -#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 - -/mob/living/carbon/alien - name = "alien" - voice_name = "alien" - icon = 'icons/mob/xenomorph.dmi' - gender = NEUTER - dna = null - faction = "alien" - - alien_talk_understand = 1 - speak_emote = list("hisses") - var/nightvision = 1 - 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 = 1 - var/plasma_rate = 5 - - var/heat_protection = 0.5 - var/leaping = 0 - ventcrawler = 2 - -/mob/living/carbon/alien/atom_init() - . = ..() - alien_list += src - -/mob/living/carbon/alien/Destroy() - alien_list -= src - return ..() - -/mob/living/carbon/alien/adjustToxLoss(amount) - storedPlasma = min(max(storedPlasma + amount,0),max_plasma) //upper limit of max_plasma, lower limit of 0 - updatePlasmaDisplay() - return - -/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire - if(amount > 0) - ..(amount * 2) - else - ..(amount) - return - -/mob/living/carbon/alien/proc/getPlasma() - return storedPlasma - -/mob/living/carbon/alien/eyecheck() - return 2 - -/mob/living/carbon/alien/getToxLoss() - return 0 - -/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/handle_environment(datum/gas_mixture/environment) - - //If there are alien weeds on the ground then heal if needed or give some plasma - if(locate(/obj/structure/alien/weeds) in loc) - if(health >= maxHealth) - adjustToxLoss(plasma_rate) - else - if(storedPlasma >= max_plasma) - adjustBruteLoss(-heal_rate*2) - adjustFireLoss(-heal_rate*2) - adjustOxyLoss(-heal_rate*2) - adjustCloneLoss(-heal_rate*2) - else - adjustBruteLoss(-heal_rate) - adjustFireLoss(-heal_rate) - adjustOxyLoss(-heal_rate) - adjustCloneLoss(-heal_rate) - adjustToxLoss(plasma_rate/2) - - if(!environment) - return - - var/loc_temp = get_temperature(environment) - - //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) - - // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. - if(bodytemperature > 700) - //Body temperature is too hot. - throw_alert("alien_fire") - switch(bodytemperature) - if(700 to 850) - apply_damage(HEAT_DAMAGE_LEVEL_1, BURN) - if(850 to 1000) - apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) - if(1000 to INFINITY) - if(on_fire) - apply_damage(HEAT_DAMAGE_LEVEL_3, BURN) - else - apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) - else - clear_alert("alien_fire") - -/mob/living/carbon/alien/proc/handle_mutations_and_radiation() - - // 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/IsAdvancedToolUser() - return has_fine_manipulation - -/mob/living/carbon/alien/Stat() - ..() - - if(statpanel("Status")) - if(isalienqueen(src)) - var/hugger = 0 - var/larva = 0 - var/drone = 0 - var/sentinel = 0 - var/hunter = 0 - - for(var/mob/living/carbon/alien/A in alien_list) - if(A.stat == DEAD) - continue - if(!A.key && A.brain_op_stage != 4) - continue - - if(isfacehugger(A)) - hugger++ - else if(islarva(A)) - larva++ - else if(isaliendrone(A)) - drone++ - else if(isaliensentinel(A)) - sentinel++ - else if(isalienhunter(A)) - hunter++ - - stat(null, "Hive Status:") - stat(null, "Huggers: [hugger]") - stat(null, "Larvas: [larva]") - stat(null, "Drones: [drone]") - stat(null, "Sentinels: [sentinel]") - stat(null, "Hunters: [hunter]") - else - var/no_queen = 1 - var/mob/living/carbon/alien/queen - for(var/mob/living/carbon/alien/humanoid/queen/Q in queen_list) - if(Q.stat == DEAD || !Q.key && Q.brain_op_stage != 4) - continue - no_queen = 0 - queen = Q - - if(no_queen) - stat(null, "Queen: No.") - else - stat(null, "Queen Status:") - stat(null, "Conscious: [queen.stat ? "No":"Yes"]") - stat(null, "Health: [queen.health]/[queen.maxHealth]") - stat(null, "Location: [queen.loc.loc.name]") - -/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 - -/*---------------------------------------- -Hit Procs ------------------------------------------*/ -/mob/living/carbon/alien/ex_act(severity) - if(!blinded) - flash_eyes() - - var/shielded = 0 - - var/b_loss = null - var/f_loss = null - switch (severity) - if (1.0) - b_loss += 500 - gib() - return - - if (2.0) - if (!shielded) - b_loss += 60 - - f_loss += 60 - - ear_damage += 30 - ear_deaf += 120 - - if(3.0) - b_loss += 30 - if (prob(50) && !shielded) - Paralyse(1) - ear_damage += 15 - ear_deaf += 60 - - adjustBruteLoss(b_loss) - adjustFireLoss(f_loss) - - updatehealth() - -/mob/living/carbon/alien/blob_act() - if (stat == DEAD) - return - var/shielded = 0 - var/damage = null - if (stat != DEAD) - damage = rand(30,40) - - if(shielded) - damage /= 4 - - - show_message("\red The blob attacks!") - - adjustFireLoss(damage) - - updatehealth() - return - -/mob/living/carbon/alien/meteorhit(O) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message(text("\red [] has been hit by []", src, O), 1) - if (health > 0) - adjustFireLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25)) - adjustFireLoss(30) - - updatehealth() - return - -/mob/living/carbon/alien/emp_act(severity) - return - -/mob/living/carbon/alien/attack_ui(slot_id) - return - -/mob/living/carbon/alien/restrained() - return 0 - -/mob/living/carbon/alien/show_inv(mob/user) - - user.set_machine(src) - var/dat = {" -
                    [name]
                    -


                    -
                    Close -
                    "} - user << browse(entity_ja(dat), text("window=mob[name];size=340x480")) - onclose(user, "mob[name]") - return - -/mob/living/carbon/alien/getTrail() - return "xltrails" - -/*---------------------------------------- -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 living_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")) - qdel(I) - return - -/mob/living/carbon/alien/swap_hand() - var/obj/item/item_in_hand = src.get_active_hand() - if(item_in_hand) //this segment checks if the item in your hand is twohanded. - if(istype(item_in_hand,/obj/item/weapon/twohanded)) - if(item_in_hand:wielded == 1) - to_chat(usr, "Your other hand is too busy holding the [item_in_hand.name]") - return - 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_l_active" - hud_used.r_hand_hud_object.icon_state = "hand_r_inactive" - else - hud_used.l_hand_hud_object.icon_state = "hand_l_inactive" - hud_used.r_hand_hud_object.icon_state = "hand_r_active" - /*if (!( src.hand )) - src.hands.dir = NORTH - else - src.hands.dir = SOUTH*/ - return - -/mob/living/carbon/alien/get_standard_pixel_y_offset(lying = 0) - return initial(pixel_y) - -#undef HEAT_DAMAGE_LEVEL_1 -#undef HEAT_DAMAGE_LEVEL_2 -#undef HEAT_DAMAGE_LEVEL_3 +#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 + +/mob/living/carbon/alien + name = "alien" + voice_name = "alien" + icon = 'icons/mob/xenomorph.dmi' + gender = NEUTER + dna = null + faction = "alien" + + alien_talk_understand = 1 + speak_emote = list("hisses") + var/nightvision = 1 + 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 = 1 + var/plasma_rate = 5 + + var/heat_protection = 0.5 + var/leaping = 0 + ventcrawler = 2 + +/mob/living/carbon/alien/atom_init() + . = ..() + alien_list += src + +/mob/living/carbon/alien/Destroy() + alien_list -= src + return ..() + +/mob/living/carbon/alien/adjustToxLoss(amount) + storedPlasma = min(max(storedPlasma + amount,0),max_plasma) //upper limit of max_plasma, lower limit of 0 + updatePlasmaDisplay() + return + +/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire + if(amount > 0) + ..(amount * 2) + else + ..(amount) + return + +/mob/living/carbon/alien/proc/getPlasma() + return storedPlasma + +/mob/living/carbon/alien/eyecheck() + return 2 + +/mob/living/carbon/alien/getToxLoss() + return 0 + +/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/handle_environment(datum/gas_mixture/environment) + + //If there are alien weeds on the ground then heal if needed or give some plasma + if(locate(/obj/structure/alien/weeds) in loc) + if(health >= maxHealth) + adjustToxLoss(plasma_rate) + else + if(storedPlasma >= max_plasma) + adjustBruteLoss(-heal_rate*2) + adjustFireLoss(-heal_rate*2) + adjustOxyLoss(-heal_rate*2) + adjustCloneLoss(-heal_rate*2) + else + adjustBruteLoss(-heal_rate) + adjustFireLoss(-heal_rate) + adjustOxyLoss(-heal_rate) + adjustCloneLoss(-heal_rate) + adjustToxLoss(plasma_rate/2) + + if(!environment) + return + + var/loc_temp = get_temperature(environment) + + //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) + + // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. + if(bodytemperature > 700) + //Body temperature is too hot. + throw_alert("alien_fire") + switch(bodytemperature) + if(700 to 850) + apply_damage(HEAT_DAMAGE_LEVEL_1, BURN) + if(850 to 1000) + apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) + if(1000 to INFINITY) + if(on_fire) + apply_damage(HEAT_DAMAGE_LEVEL_3, BURN) + else + apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) + else + clear_alert("alien_fire") + +/mob/living/carbon/alien/proc/handle_mutations_and_radiation() + + // 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/IsAdvancedToolUser() + return has_fine_manipulation + +/mob/living/carbon/alien/Stat() + ..() + + if(statpanel("Status")) + if(isalienqueen(src)) + var/hugger = 0 + var/larva = 0 + var/drone = 0 + var/sentinel = 0 + var/hunter = 0 + + for(var/mob/living/carbon/alien/A in alien_list) + if(A.stat == DEAD) + continue + if(!A.key && A.brain_op_stage != 4) + continue + + if(isfacehugger(A)) + hugger++ + else if(islarva(A)) + larva++ + else if(isaliendrone(A)) + drone++ + else if(isaliensentinel(A)) + sentinel++ + else if(isalienhunter(A)) + hunter++ + + stat(null, "Hive Status:") + stat(null, "Huggers: [hugger]") + stat(null, "Larvas: [larva]") + stat(null, "Drones: [drone]") + stat(null, "Sentinels: [sentinel]") + stat(null, "Hunters: [hunter]") + else + var/no_queen = 1 + var/mob/living/carbon/alien/queen + for(var/mob/living/carbon/alien/humanoid/queen/Q in queen_list) + if(Q.stat == DEAD || !Q.key && Q.brain_op_stage != 4) + continue + no_queen = 0 + queen = Q + + if(no_queen) + stat(null, "Queen: No.") + else + stat(null, "Queen Status:") + stat(null, "Conscious: [queen.stat ? "No":"Yes"]") + stat(null, "Health: [queen.health]/[queen.maxHealth]") + stat(null, "Location: [queen.loc.loc.name]") + +/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 + +/*---------------------------------------- +Hit Procs +-----------------------------------------*/ +/mob/living/carbon/alien/ex_act(severity) + if(!blinded) + flash_eyes() + + var/shielded = 0 + + var/b_loss = null + var/f_loss = null + switch (severity) + if (1.0) + b_loss += 500 + gib() + return + + if (2.0) + if (!shielded) + b_loss += 60 + + f_loss += 60 + + ear_damage += 30 + ear_deaf += 120 + + if(3.0) + b_loss += 30 + if (prob(50) && !shielded) + Paralyse(1) + ear_damage += 15 + ear_deaf += 60 + + adjustBruteLoss(b_loss) + adjustFireLoss(f_loss) + + updatehealth() + +/mob/living/carbon/alien/blob_act() + if (stat == DEAD) + return + var/shielded = 0 + var/damage = null + if (stat != DEAD) + damage = rand(30,40) + + if(shielded) + damage /= 4 + + + show_message("\red The blob attacks!") + + adjustFireLoss(damage) + + updatehealth() + return + +/mob/living/carbon/alien/meteorhit(O) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message(text("\red [] has been hit by []", src, O), 1) + if (health > 0) + adjustFireLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25)) + adjustFireLoss(30) + + updatehealth() + return + +/mob/living/carbon/alien/emp_act(severity) + return + +/mob/living/carbon/alien/attack_ui(slot_id) + return + +/mob/living/carbon/alien/restrained() + return 0 + +/mob/living/carbon/alien/show_inv(mob/user) + + user.set_machine(src) + var/dat = {" +
                    [name]
                    +


                    +
                    Close +
                    "} + user << browse(entity_ja(dat), text("window=mob[name];size=340x480")) + onclose(user, "mob[name]") + return + +/mob/living/carbon/alien/getTrail() + return "xltrails" + +/*---------------------------------------- +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 living_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")) + qdel(I) + return + +/mob/living/carbon/alien/swap_hand() + var/obj/item/item_in_hand = src.get_active_hand() + if(item_in_hand) //this segment checks if the item in your hand is twohanded. + if(istype(item_in_hand,/obj/item/weapon/twohanded)) + if(item_in_hand:wielded == 1) + to_chat(usr, "Your other hand is too busy holding the [item_in_hand.name]") + return + 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_l_active" + hud_used.r_hand_hud_object.icon_state = "hand_r_inactive" + else + hud_used.l_hand_hud_object.icon_state = "hand_l_inactive" + hud_used.r_hand_hud_object.icon_state = "hand_r_active" + /*if (!( src.hand )) + src.hands.dir = NORTH + else + src.hands.dir = SOUTH*/ + return + +/mob/living/carbon/alien/get_standard_pixel_y_offset(lying = 0) + return initial(pixel_y) + +#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 ee1d750bc23e..da4aebda8ca6 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -1,324 +1,324 @@ -/*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, "\green You must be conscious to do this.") - return 0 - else if(X && getPlasma() < X) - to_chat(src, "\green Not enough plasma stored.") - return 0 - else if(Y && (!isturf(src.loc) || istype(src.loc, /turf/space))) - to_chat(src, "\green 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) - for(var/mob/O in viewers(src, null)) - O.show_message(text("\green [src] has planted some alien weeds!"), 1) - new /obj/structure/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) - log_say("AlienWhisper: [key_name(src)]->[M.key] : [msg]") - to_chat(M, "\green You hear a strange, alien voice in your head... \italic [msg]") - to_chat(src, {"\green 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, "\green [src] has transfered [amount] plasma to you.") - to_chat(src, {"\green You have trasferred [amount] plasma to [M]"}) - else - to_chat(src, "\green You need to be closer.") - return - - -/mob/living/carbon/alien/humanoid/proc/corrosive_acid(O 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, "\green 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, "\green You cannot dissolve this object.") - return - // R FLOOR - if(istype(T, /turf/simulated/floor/engine)) - to_chat(src, "\green 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("\green [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, "\green Target is too far away.") - return - -/* -/mob/living/carbon/alien/humanoid/proc/neurotoxin(mob/target 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, "\green Your allies are not a valid target.") - return - adjustToxLoss(-50) - to_chat(src, "\green You spit neurotoxin at [target].") - for(var/mob/O in oviewers()) - if ((O.client && !( O.blinded ))) - to_chat(O, "\red [src] spits neurotoxin at [target]!") - //I'm not motivated enough to revise this. Prjectile code in general needs update. - var/turf/T = loc - var/turf/U = (istype(target, /atom/movable) ? target.loc : 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), ran_zone(zone_sel.selecting) - return - if(!istype(U, /turf)) - return - - var/obj/item/projectile/energy/neurotoxin/A = new /obj/item/projectile/energy/neurotoxin(usr.loc) - A.current = U - A.yo = U.y - T.y - A.xo = U.x - T.x - A.process() - return -*/ - -/mob/living/carbon/alien/humanoid/proc/screech() - set name = "Screech!" - set desc = "Emit a screech that stuns prey." - set category = "Alien" - - if(world.time < last_screech + screech_delay) - return - - playsound(src, 'sound/effects/screech2.ogg', 100, 1) - for(var/mob/living/carbon/human/H in oviewers()) - if(H.sdisabilities & DEAF || istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs)) - continue - - to_chat(H, "HISSSSSS") - H.SetSleeping(0) - H.stuttering += 20 - H.ear_deaf += 30 - H.Weaken(3) - if(prob(30)) - H.Stun(10) - H.Paralyse(4) - else - H.Stun(5) - H.Paralyse(2) - last_screech = world.time -#define ALIEN_NEUROTOXIN 1 -#define ALIEN_ACID 2 -/mob/living/carbon/alien/humanoid/proc/toggle_neurotoxin(message = 1) - switch(neurotoxin_on_click) - - if(0) - neurotoxin_on_click = ALIEN_NEUROTOXIN - if(message) - to_chat(src, "You will now fire neurotoxin in enemies!") - - if(ALIEN_NEUROTOXIN) - neurotoxin_on_click = ALIEN_ACID - if(message) - to_chat(src, "You will now fire acid in enemies!") - - if(ALIEN_ACID) - neurotoxin_on_click = 0 - if(message) - to_chat(src, "You will not fire in enemies!") - neurotoxin_icon.icon_state = "neurotoxin[neurotoxin_on_click]" - update_icons() - return - -/mob/living/carbon/alien/humanoid/proc/neurotoxin() - set name = "Spit Neurotoxin" - set desc = "Spits neurotoxin at someone, paralyzing them for a short time if they are not wearing protective gear." - set category = "Alien" - toggle_neurotoxin(1) - return - -/mob/living/carbon/alien/humanoid/ClickOn(atom/A, params) - face_atom(A) - if(neurotoxin_on_click) - split_neurotoxin(A) - else - ..() - -/mob/living/carbon/alien/humanoid/proc/split_neurotoxin(atom/target) - if(neurotoxin_next_shot > world.time) - to_chat(src, "You are not ready.") - return - - //I'm not motivated enough to revise this. Prjectile code in general needs update. - var/turf/T = loc - var/turf/U = (istype(target, /atom/movable) ? target.loc : target) - - if(!U || !T) - return - while(U && !istype(U,/turf)) - U = U.loc - if(!istype(T, /turf)) - return - if (U == T) - return - if(!istype(U, /turf)) - return - - var/obj/item/projectile/BB - - switch(neurotoxin_on_click) - if(ALIEN_NEUROTOXIN) - if(!powerc(50)) - return - BB = new /obj/item/projectile/neurotoxin(usr.loc) - adjustToxLoss(-50) - neurotoxin_next_shot = world.time + neurotoxin_delay - if(ALIEN_ACID) - if(!powerc(150)) - return - BB = new /obj/item/projectile/acid_special(usr.loc) - neurotoxin_next_shot = world.time + (neurotoxin_delay * 4) - adjustToxLoss(-150) - - visible_message("\red [src] spits [BB.name] at [target]!") - - //prepare "bullet" - BB.original = target - BB.firer = src - BB.def_zone = src.zone_sel.selecting - //shoot - BB.loc = T - BB.starting = T - BB.current = loc - BB.yo = U.y - loc.y - BB.xo = U.x - loc.x - - if(BB) - BB.process() - - last_neurotoxin = world.time - return -#undef ALIEN_NEUROTOXIN -#undef ALIEN_ACID -/mob/living/carbon/alien/humanoid/proc/resin() // -- TLE - set name = "Secrete Resin (75)" - set desc = "Secrete tough malleable resin." - set category = "Alien" - - if((locate(/obj/effect/alien/air_plant) in get_turf(src)) || (locate(/obj/effect/alien/egg) in get_turf(src)) || (locate(/obj/structure/mineral_door/resin) in get_turf(src)) || (locate( /obj/effect/alien/resin/wall) in get_turf(src)) || (locate(/obj/effect/alien/resin/membrane) in get_turf(src)) || (locate(/obj/structure/stool/bed/nest) in get_turf(src))) - to_chat (src, "There is already a structure there.") - return - - 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) - to_chat(src, "\green You shape a [choice].") - for(var/mob/O in viewers(src, null)) - O.show_message(text("\red [src] vomits up a thick purple substance and begins to shape it!"), 1) - switch(choice) - if("resin door") - new /obj/structure/mineral_door/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/stool/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 - //M.update_pipe_vision() - //Paralyse(10) - src.visible_message("\green [src] hurls out the contents of their stomach!") - return - -/mob/living/carbon/alien/humanoid/verb/air_plant() - set name = "Plant Air Generator (250)" - set desc = "Plants some alien weeds." - set category = "Alien" - - if(powerc(250,1)) - adjustToxLoss(-250) - for(var/mob/O in viewers(src, null)) - O.show_message(text("\green [src] has planted some alien weeds!"), 1) - new /obj/effect/alien/air_plant(loc) - 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, "\green You must be conscious to do this.") + return 0 + else if(X && getPlasma() < X) + to_chat(src, "\green Not enough plasma stored.") + return 0 + else if(Y && (!isturf(src.loc) || istype(src.loc, /turf/space))) + to_chat(src, "\green 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) + for(var/mob/O in viewers(src, null)) + O.show_message(text("\green [src] has planted some alien weeds!"), 1) + new /obj/structure/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) + log_say("AlienWhisper: [key_name(src)]->[M.key] : [msg]") + to_chat(M, "\green You hear a strange, alien voice in your head... \italic [msg]") + to_chat(src, {"\green 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, "\green [src] has transfered [amount] plasma to you.") + to_chat(src, {"\green You have trasferred [amount] plasma to [M]"}) + else + to_chat(src, "\green You need to be closer.") + return + + +/mob/living/carbon/alien/humanoid/proc/corrosive_acid(O 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, "\green 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, "\green You cannot dissolve this object.") + return + // R FLOOR + if(istype(T, /turf/simulated/floor/engine)) + to_chat(src, "\green 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("\green [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, "\green Target is too far away.") + return + +/* +/mob/living/carbon/alien/humanoid/proc/neurotoxin(mob/target 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, "\green Your allies are not a valid target.") + return + adjustToxLoss(-50) + to_chat(src, "\green You spit neurotoxin at [target].") + for(var/mob/O in oviewers()) + if ((O.client && !( O.blinded ))) + to_chat(O, "\red [src] spits neurotoxin at [target]!") + //I'm not motivated enough to revise this. Prjectile code in general needs update. + var/turf/T = loc + var/turf/U = (istype(target, /atom/movable) ? target.loc : 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), ran_zone(zone_sel.selecting) + return + if(!istype(U, /turf)) + return + + var/obj/item/projectile/energy/neurotoxin/A = new /obj/item/projectile/energy/neurotoxin(usr.loc) + A.current = U + A.yo = U.y - T.y + A.xo = U.x - T.x + A.process() + return +*/ + +/mob/living/carbon/alien/humanoid/proc/screech() + set name = "Screech!" + set desc = "Emit a screech that stuns prey." + set category = "Alien" + + if(world.time < last_screech + screech_delay) + return + + playsound(src, 'sound/effects/screech2.ogg', 100, 1) + for(var/mob/living/carbon/human/H in oviewers()) + if(H.sdisabilities & DEAF || istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs)) + continue + + to_chat(H, "HISSSSSS") + H.SetSleeping(0) + H.stuttering += 20 + H.ear_deaf += 30 + H.Weaken(3) + if(prob(30)) + H.Stun(10) + H.Paralyse(4) + else + H.Stun(5) + H.Paralyse(2) + last_screech = world.time +#define ALIEN_NEUROTOXIN 1 +#define ALIEN_ACID 2 +/mob/living/carbon/alien/humanoid/proc/toggle_neurotoxin(message = 1) + switch(neurotoxin_on_click) + + if(0) + neurotoxin_on_click = ALIEN_NEUROTOXIN + if(message) + to_chat(src, "You will now fire neurotoxin in enemies!") + + if(ALIEN_NEUROTOXIN) + neurotoxin_on_click = ALIEN_ACID + if(message) + to_chat(src, "You will now fire acid in enemies!") + + if(ALIEN_ACID) + neurotoxin_on_click = 0 + if(message) + to_chat(src, "You will not fire in enemies!") + neurotoxin_icon.icon_state = "neurotoxin[neurotoxin_on_click]" + update_icons() + return + +/mob/living/carbon/alien/humanoid/proc/neurotoxin() + set name = "Spit Neurotoxin" + set desc = "Spits neurotoxin at someone, paralyzing them for a short time if they are not wearing protective gear." + set category = "Alien" + toggle_neurotoxin(1) + return + +/mob/living/carbon/alien/humanoid/ClickOn(atom/A, params) + face_atom(A) + if(neurotoxin_on_click) + split_neurotoxin(A) + else + ..() + +/mob/living/carbon/alien/humanoid/proc/split_neurotoxin(atom/target) + if(neurotoxin_next_shot > world.time) + to_chat(src, "You are not ready.") + return + + //I'm not motivated enough to revise this. Prjectile code in general needs update. + var/turf/T = loc + var/turf/U = (istype(target, /atom/movable) ? target.loc : target) + + if(!U || !T) + return + while(U && !istype(U,/turf)) + U = U.loc + if(!istype(T, /turf)) + return + if (U == T) + return + if(!istype(U, /turf)) + return + + var/obj/item/projectile/BB + + switch(neurotoxin_on_click) + if(ALIEN_NEUROTOXIN) + if(!powerc(50)) + return + BB = new /obj/item/projectile/neurotoxin(usr.loc) + adjustToxLoss(-50) + neurotoxin_next_shot = world.time + neurotoxin_delay + if(ALIEN_ACID) + if(!powerc(150)) + return + BB = new /obj/item/projectile/acid_special(usr.loc) + neurotoxin_next_shot = world.time + (neurotoxin_delay * 4) + adjustToxLoss(-150) + + visible_message("\red [src] spits [BB.name] at [target]!") + + //prepare "bullet" + BB.original = target + BB.firer = src + BB.def_zone = src.zone_sel.selecting + //shoot + BB.loc = T + BB.starting = T + BB.current = loc + BB.yo = U.y - loc.y + BB.xo = U.x - loc.x + + if(BB) + BB.process() + + last_neurotoxin = world.time + return +#undef ALIEN_NEUROTOXIN +#undef ALIEN_ACID +/mob/living/carbon/alien/humanoid/proc/resin() // -- TLE + set name = "Secrete Resin (75)" + set desc = "Secrete tough malleable resin." + set category = "Alien" + + if((locate(/obj/effect/alien/air_plant) in get_turf(src)) || (locate(/obj/effect/alien/egg) in get_turf(src)) || (locate(/obj/structure/mineral_door/resin) in get_turf(src)) || (locate( /obj/effect/alien/resin/wall) in get_turf(src)) || (locate(/obj/effect/alien/resin/membrane) in get_turf(src)) || (locate(/obj/structure/stool/bed/nest) in get_turf(src))) + to_chat (src, "There is already a structure there.") + return + + 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) + to_chat(src, "\green You shape a [choice].") + for(var/mob/O in viewers(src, null)) + O.show_message(text("\red [src] vomits up a thick purple substance and begins to shape it!"), 1) + switch(choice) + if("resin door") + new /obj/structure/mineral_door/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/stool/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 + //M.update_pipe_vision() + //Paralyse(10) + src.visible_message("\green [src] hurls out the contents of their stomach!") + return + +/mob/living/carbon/alien/humanoid/verb/air_plant() + set name = "Plant Air Generator (250)" + set desc = "Plants some alien weeds." + set category = "Alien" + + if(powerc(250,1)) + adjustToxLoss(-250) + for(var/mob/O in viewers(src, null)) + O.show_message(text("\green [src] has planted some alien weeds!"), 1) + new /obj/effect/alien/air_plant(loc) + 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 8b12a0d04847..de5e634b0824 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm @@ -1,76 +1,76 @@ -/mob/living/carbon/alien/humanoid/drone - name = "alien drone" - caste = "d" - maxHealth = 120 - health = 120 - icon_state = "aliend_s" - plasma_rate = 15 - -/mob/living/carbon/alien/humanoid/drone/atom_init() - 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) - . = ..() - -/mob/living/carbon/alien/humanoid/drone/handle_hud_icons_health() - if(healths) - if (stat != DEAD) - switch(health) - if(120 to INFINITY) - healths.icon_state = "health0" - if(100 to 120) - healths.icon_state = "health1" - if(75 to 100) - healths.icon_state = "health2" - if(50 to 75) - healths.icon_state = "health3" - if(25 to 50) - healths.icon_state = "health4" - if(0 to 25) - healths.icon_state = "health5" - else - healths.icon_state = "health6" - else - healths.icon_state = "health7" - -//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(!isturf(src.loc)) - to_chat(src, "\red You cannot evolve when you are inside something.")//Silly aliens! - return - - if(powerc(500)) - // Queen check - var/no_queen = 1 - for(var/mob/living/carbon/alien/humanoid/queen/Q in queen_list) - if(Q.stat == DEAD || !Q.key && Q.brain_op_stage != 4) - continue - no_queen = 0 - - if(src.has_brain_worms()) - to_chat(src, "We cannot perform this ability at the present time!") - return - - if(no_queen) - adjustToxLoss(-500) - to_chat(src, "\green You begin to evolve!") - for(var/mob/O in viewers(src, null)) - O.show_message(text("\green [src] begins to twist and contort!"), 1) - var/mob/living/carbon/alien/humanoid/queen/new_xeno = new (loc) - mind.transfer_to(new_xeno) - qdel(src) - else - to_chat(src, "We already have an alive queen.") - return - -/mob/living/carbon/alien/humanoid/drone/movement_delay() - return(1 + move_delay_add + config.alien_delay) +/mob/living/carbon/alien/humanoid/drone + name = "alien drone" + caste = "d" + maxHealth = 120 + health = 120 + icon_state = "aliend_s" + plasma_rate = 15 + +/mob/living/carbon/alien/humanoid/drone/atom_init() + 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) + . = ..() + +/mob/living/carbon/alien/humanoid/drone/handle_hud_icons_health() + if(healths) + if (stat != DEAD) + switch(health) + if(120 to INFINITY) + healths.icon_state = "health0" + if(100 to 120) + healths.icon_state = "health1" + if(75 to 100) + healths.icon_state = "health2" + if(50 to 75) + healths.icon_state = "health3" + if(25 to 50) + healths.icon_state = "health4" + if(0 to 25) + healths.icon_state = "health5" + else + healths.icon_state = "health6" + else + healths.icon_state = "health7" + +//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(!isturf(src.loc)) + to_chat(src, "\red You cannot evolve when you are inside something.")//Silly aliens! + return + + if(powerc(500)) + // Queen check + var/no_queen = 1 + for(var/mob/living/carbon/alien/humanoid/queen/Q in queen_list) + if(Q.stat == DEAD || !Q.key && Q.brain_op_stage != 4) + continue + no_queen = 0 + + if(src.has_brain_worms()) + to_chat(src, "We cannot perform this ability at the present time!") + return + + if(no_queen) + adjustToxLoss(-500) + to_chat(src, "\green You begin to evolve!") + for(var/mob/O in viewers(src, null)) + O.show_message(text("\green [src] begins to twist and contort!"), 1) + var/mob/living/carbon/alien/humanoid/queen/new_xeno = new (loc) + mind.transfer_to(new_xeno) + qdel(src) + else + to_chat(src, "We already have an alive queen.") + return + +/mob/living/carbon/alien/humanoid/drone/movement_delay() + return(1 + move_delay_add + config.alien_delay) 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 69a0b5b3ccb3..ddadeb18a533 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -1,156 +1,156 @@ -/mob/living/carbon/alien/humanoid/hunter - name = "alien hunter" - caste = "h" - maxHealth = 180 - health = 180 - storedPlasma = 100 - max_plasma = 150 - icon_state = "alienh_s" - plasma_rate = 5 - heal_rate = 3 - -/mob/living/carbon/alien/humanoid/hunter/atom_init() - 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 - . = ..() - -/mob/living/carbon/alien/humanoid/hunter - handle_environment() - if(m_intent == "run" || resting) - ..() - else - adjustToxLoss(-heal_rate) - -/mob/living/carbon/alien/humanoid/hunter/handle_hud_icons_health() - if (healths) - if (stat != DEAD) - switch(health) - if(150 to INFINITY) - healths.icon_state = "health0" - if(120 to 150) - healths.icon_state = "health1" - if(90 to 120) - healths.icon_state = "health2" - if(60 to 90) - healths.icon_state = "health3" - if(30 to 60) - healths.icon_state = "health4" - if(0 to 30) - healths.icon_state = "health5" - else - healths.icon_state = "health6" - else - healths.icon_state = "health7" - - -//Hunter verbs -/* -/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, "\green You are now invisible.") - for(var/mob/O in oviewers(src, null)) - O.show_message(text("\red [src] fades into the surroundings!"), 1) - 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, "\green You are no longer invisible.") - return -*/ - -//Hunter verbs - - -/mob/living/carbon/alien/humanoid/hunter/proc/toggle_leap(message = 1) - leap_on_click = !leap_on_click - leap_icon.icon_state = "leap_[leap_on_click ? "on":"off"]" - update_icons() - if(message) - to_chat(src, "You will now [leap_on_click ? "leap at":"slash at"] enemies!") - else - return - - -/mob/living/carbon/alien/humanoid/hunter/ClickOn(atom/A, params) - face_atom(A) - if(leap_on_click) - leap_at(A) - else - ..() - - -#define MAX_ALIEN_LEAP_DIST 7 - -/mob/living/carbon/alien/humanoid/hunter/proc/leap_at(atom/A) - - if(buckled) - to_chat(src, "You cannot leap in your current state.") - return - - if(pounce_cooldown) - to_chat(src, "You are too fatigued to pounce right now!") - return - - if(leaping) //Leap while you leap, so you can leap while you leap - return - - if((istype(src.loc, /turf/space)) || (istype(A.loc, /turf/space))) - to_chat(src, "It is unsafe to leap without gravity!") - //It's also extremely buggy visually, so it's balance+bugfix - return - if(lying) - return - - else //Maybe uses plasma in the future, although that wouldn't make any sense... - stop_pulling() - leaping = TRUE - update_icons() - throw_at(A, MAX_ALIEN_LEAP_DIST, 2, spin = FALSE, diagonals_first = TRUE, callback = CALLBACK(src, .leap_end)) - -/mob/living/carbon/alien/humanoid/hunter/proc/leap_end() - leaping = FALSE - update_icons() - -/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A) - if(!leaping) - return ..() - - if(isliving(A)) - var/mob/living/L = A - L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") - if(issilicon(A)) - L.Weaken(1) //Only brief stun - else - L.Weaken(5) - sleep(2) // Runtime prevention (infinite bump() calls on hulks) - step_towards(src, L) - toggle_leap(FALSE) - pounce_cooldown = TRUE - addtimer(CALLBACK(src, .proc/refresh_pounce_cooldown), pounce_cooldown_time) - else if(A.density) - visible_message("[src] smashes into [A]!", "You smashes into [A]!") - weakened = 2 - - update_canmove() - -/mob/living/carbon/alien/humanoid/hunter/proc/refresh_pounce_cooldown() - pounce_cooldown = FALSE - -#undef MAX_ALIEN_LEAP_DIST - -/mob/living/carbon/alien/humanoid/hunter/movement_delay() - return(-1 + move_delay_add + config.alien_delay) +/mob/living/carbon/alien/humanoid/hunter + name = "alien hunter" + caste = "h" + maxHealth = 180 + health = 180 + storedPlasma = 100 + max_plasma = 150 + icon_state = "alienh_s" + plasma_rate = 5 + heal_rate = 3 + +/mob/living/carbon/alien/humanoid/hunter/atom_init() + 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 + . = ..() + +/mob/living/carbon/alien/humanoid/hunter + handle_environment() + if(m_intent == "run" || resting) + ..() + else + adjustToxLoss(-heal_rate) + +/mob/living/carbon/alien/humanoid/hunter/handle_hud_icons_health() + if (healths) + if (stat != DEAD) + switch(health) + if(150 to INFINITY) + healths.icon_state = "health0" + if(120 to 150) + healths.icon_state = "health1" + if(90 to 120) + healths.icon_state = "health2" + if(60 to 90) + healths.icon_state = "health3" + if(30 to 60) + healths.icon_state = "health4" + if(0 to 30) + healths.icon_state = "health5" + else + healths.icon_state = "health6" + else + healths.icon_state = "health7" + + +//Hunter verbs +/* +/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, "\green You are now invisible.") + for(var/mob/O in oviewers(src, null)) + O.show_message(text("\red [src] fades into the surroundings!"), 1) + 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, "\green You are no longer invisible.") + return +*/ + +//Hunter verbs + + +/mob/living/carbon/alien/humanoid/hunter/proc/toggle_leap(message = 1) + leap_on_click = !leap_on_click + leap_icon.icon_state = "leap_[leap_on_click ? "on":"off"]" + update_icons() + if(message) + to_chat(src, "You will now [leap_on_click ? "leap at":"slash at"] enemies!") + else + return + + +/mob/living/carbon/alien/humanoid/hunter/ClickOn(atom/A, params) + face_atom(A) + if(leap_on_click) + leap_at(A) + else + ..() + + +#define MAX_ALIEN_LEAP_DIST 7 + +/mob/living/carbon/alien/humanoid/hunter/proc/leap_at(atom/A) + + if(buckled) + to_chat(src, "You cannot leap in your current state.") + return + + if(pounce_cooldown) + to_chat(src, "You are too fatigued to pounce right now!") + return + + if(leaping) //Leap while you leap, so you can leap while you leap + return + + if((istype(src.loc, /turf/space)) || (istype(A.loc, /turf/space))) + to_chat(src, "It is unsafe to leap without gravity!") + //It's also extremely buggy visually, so it's balance+bugfix + return + if(lying) + return + + else //Maybe uses plasma in the future, although that wouldn't make any sense... + stop_pulling() + leaping = TRUE + update_icons() + throw_at(A, MAX_ALIEN_LEAP_DIST, 2, spin = FALSE, diagonals_first = TRUE, callback = CALLBACK(src, .leap_end)) + +/mob/living/carbon/alien/humanoid/hunter/proc/leap_end() + leaping = FALSE + update_icons() + +/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A) + if(!leaping) + return ..() + + if(isliving(A)) + var/mob/living/L = A + L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") + if(issilicon(A)) + L.Weaken(1) //Only brief stun + else + L.Weaken(5) + sleep(2) // Runtime prevention (infinite bump() calls on hulks) + step_towards(src, L) + toggle_leap(FALSE) + pounce_cooldown = TRUE + addtimer(CALLBACK(src, .proc/refresh_pounce_cooldown), pounce_cooldown_time) + else if(A.density) + visible_message("[src] smashes into [A]!", "You smashes into [A]!") + weakened = 2 + + update_canmove() + +/mob/living/carbon/alien/humanoid/hunter/proc/refresh_pounce_cooldown() + pounce_cooldown = FALSE + +#undef MAX_ALIEN_LEAP_DIST + +/mob/living/carbon/alien/humanoid/hunter/movement_delay() + return(-1 + move_delay_add + config.alien_delay) 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 58d3b418c528..05e9d3b7df7d 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm @@ -1,44 +1,44 @@ -/mob/living/carbon/alien/humanoid/sentinel - name = "alien sentinel" - caste = "s" - maxHealth = 150 - health = 150 - storedPlasma = 100 - max_plasma = 250 - icon_state = "aliens_s" - plasma_rate = 10 - heal_rate = 2 - -/mob/living/carbon/alien/humanoid/sentinel/atom_init() - 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) - . = ..() - -/mob/living/carbon/alien/humanoid/sentinel/handle_hud_icons_health() - if (healths) - if (stat != DEAD) - switch(health) - if(125 to INFINITY) - healths.icon_state = "health0" - if(100 to 125) - healths.icon_state = "health1" - if(75 to 100) - healths.icon_state = "health2" - if(50 to 75) - healths.icon_state = "health3" - if(25 to 50) - healths.icon_state = "health4" - if(0 to 25) - healths.icon_state = "health5" - else - healths.icon_state = "health6" - else - healths.icon_state = "health7" - -/mob/living/carbon/alien/humanoid/sentinel/movement_delay() - return(1 + move_delay_add + config.alien_delay) +/mob/living/carbon/alien/humanoid/sentinel + name = "alien sentinel" + caste = "s" + maxHealth = 150 + health = 150 + storedPlasma = 100 + max_plasma = 250 + icon_state = "aliens_s" + plasma_rate = 10 + heal_rate = 2 + +/mob/living/carbon/alien/humanoid/sentinel/atom_init() + 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) + . = ..() + +/mob/living/carbon/alien/humanoid/sentinel/handle_hud_icons_health() + if (healths) + if (stat != DEAD) + switch(health) + if(125 to INFINITY) + healths.icon_state = "health0" + if(100 to 125) + healths.icon_state = "health1" + if(75 to 100) + healths.icon_state = "health2" + if(50 to 75) + healths.icon_state = "health3" + if(25 to 50) + healths.icon_state = "health4" + if(0 to 25) + healths.icon_state = "health5" + else + healths.icon_state = "health6" + else + healths.icon_state = "health7" + +/mob/living/carbon/alien/humanoid/sentinel/movement_delay() + return(1 + move_delay_add + config.alien_delay) diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm index 1360a52fc743..2eef6c482715 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm @@ -1,135 +1,135 @@ -/mob/living/carbon/alien/humanoid/emote(act,m_type=1,message = null) - - 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, "\red 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 alien signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) - m_type = 1 - if ("burp") - if (!muzzled) - message = "[src] burps." - m_type = 2 - if ("deathgasp") - message = "[src] lets out a waning guttural screech, green blood bubbling from its maw..." - m_type = 2 - if("scratch") - if (!src.restrained()) - message = "The [src.name] scratches." - m_type = 1 - if("whimper") - if (!muzzled) - message = "The [src.name] whimpers." - m_type = 2 - if("roar") - if (!muzzled) - message = "The [src.name] roars." - m_type = 2 - if("hiss") - if(!muzzled) - message = "The [src.name] hisses." - m_type = 2 - if("tail") - message = "The [src.name] waves its tail." - m_type = 1 - if("gasp") - message = "The [src.name] gasps." - m_type = 2 - if("shiver") - message = "The [src.name] shivers." - m_type = 2 - if("drool") - message = "The [src.name] drools." - m_type = 1 - if("scretch") - if (!muzzled) - message = "The [src.name] scretches." - m_type = 2 - if("choke") - message = "The [src.name] chokes." - m_type = 2 - if("moan") - message = "The [src.name] moans!" - m_type = 2 - if("nod") - message = "The [src.name] nods its head." - m_type = 1 - if("sit") - message = "The [src.name] sits down." - m_type = 1 - if("sway") - message = "The [src.name] sways around dizzily." - m_type = 1 - if("sulk") - message = "The [src.name] sulks down sadly." - m_type = 1 - if("twitch") - message = "The [src.name] twitches violently." - m_type = 1 - if("dance") - if (!src.restrained()) - message = "The [src.name] dances around happily." - m_type = 1 - if("roll") - if (!src.restrained()) - message = "The [src.name] rolls." - m_type = 1 - if("shake") - message = "The [src.name] shakes its head." - m_type = 1 - if("gnarl") - if (!muzzled) - message = "The [src.name] gnarls and shows its teeth.." - m_type = 2 - if("jump") - message = "The [src.name] jumps!" - m_type = 1 - if("collapse") - Paralyse(2) - message = text("[] collapses!", src) - m_type = 2 - if("help") - to_chat(src, "burp, deathgasp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper") - else - to_chat(src, text("Invalid Emote: []", act)) - if ((message && src.stat == CONSCIOUS)) - log_emote("[name]/[key] : [message]") - if (act == "roar") - playsound(src.loc, 'sound/voice/hiss5.ogg', 40, 1, 1) - if (act == "deathgasp") - playsound(src.loc, 'sound/voice/hiss6.ogg', 80, 1, 1) - 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 +/mob/living/carbon/alien/humanoid/emote(act,m_type=1,message = null) + + 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, "\red 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 alien signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) + m_type = 1 + if ("burp") + if (!muzzled) + message = "[src] burps." + m_type = 2 + if ("deathgasp") + message = "[src] lets out a waning guttural screech, green blood bubbling from its maw..." + m_type = 2 + if("scratch") + if (!src.restrained()) + message = "The [src.name] scratches." + m_type = 1 + if("whimper") + if (!muzzled) + message = "The [src.name] whimpers." + m_type = 2 + if("roar") + if (!muzzled) + message = "The [src.name] roars." + m_type = 2 + if("hiss") + if(!muzzled) + message = "The [src.name] hisses." + m_type = 2 + if("tail") + message = "The [src.name] waves its tail." + m_type = 1 + if("gasp") + message = "The [src.name] gasps." + m_type = 2 + if("shiver") + message = "The [src.name] shivers." + m_type = 2 + if("drool") + message = "The [src.name] drools." + m_type = 1 + if("scretch") + if (!muzzled) + message = "The [src.name] scretches." + m_type = 2 + if("choke") + message = "The [src.name] chokes." + m_type = 2 + if("moan") + message = "The [src.name] moans!" + m_type = 2 + if("nod") + message = "The [src.name] nods its head." + m_type = 1 + if("sit") + message = "The [src.name] sits down." + m_type = 1 + if("sway") + message = "The [src.name] sways around dizzily." + m_type = 1 + if("sulk") + message = "The [src.name] sulks down sadly." + m_type = 1 + if("twitch") + message = "The [src.name] twitches violently." + m_type = 1 + if("dance") + if (!src.restrained()) + message = "The [src.name] dances around happily." + m_type = 1 + if("roll") + if (!src.restrained()) + message = "The [src.name] rolls." + m_type = 1 + if("shake") + message = "The [src.name] shakes its head." + m_type = 1 + if("gnarl") + if (!muzzled) + message = "The [src.name] gnarls and shows its teeth.." + m_type = 2 + if("jump") + message = "The [src.name] jumps!" + m_type = 1 + if("collapse") + Paralyse(2) + message = text("[] collapses!", src) + m_type = 2 + if("help") + to_chat(src, "burp, deathgasp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper") + else + to_chat(src, text("Invalid Emote: []", act)) + if ((message && src.stat == CONSCIOUS)) + log_emote("[name]/[key] : [message]") + if (act == "roar") + playsound(src.loc, 'sound/voice/hiss5.ogg', 40, 1, 1) + if (act == "deathgasp") + playsound(src.loc, 'sound/voice/hiss6.ogg', 80, 1, 1) + 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 diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index 6dda1de77796..f68e1283664c 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -1,44 +1,44 @@ -/mob/living/carbon/alien/humanoid - name = "alien" - icon = 'icons/mob/xenomorph.dmi' - icon_state = "alien_s" - - pass_flags = PASSTABLE - var/obj/item/clothing/suit/wear_suit = null //TODO: necessary? Are they even used? ~Carn - var/obj/item/weapon/r_store = null - var/obj/item/weapon/l_store = null - var/caste = "" - //var/perception = 0 //0 - standart mode, 1 - SEE_TURF mode - var/praetorians = 2 - //update_icon = 1 - var/alt_icon = 'icons/mob/xenoleap.dmi' //used to switch between the two alien icon files. - var/leap_on_click = 0 - - var/pounce_cooldown = 0 - var/pounce_cooldown_time = 50 - - var/neurotoxin_on_click = 0 - var/neurotoxin_delay = 15 - var/neurotoxin_next_shot = 0 - var/last_neurotoxin = 0 - - var/last_screech = 0 - var/screech_delay = 900 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/xenomeat = 5) - - -//This is fine right now, if we're adding organ specific damage this needs to be updated -/mob/living/carbon/alien/humanoid/atom_init() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(name == "alien") - name = text("alien ([rand(1, 1000)])") - real_name = name - ..() - -/mob/living/carbon/alien/humanoid/movement_delay() - return (move_delay_add + config.alien_delay) - -///mob/living/carbon/alien/humanoid/bullet_act(obj/item/projectile/Proj) taken care of in living - +/mob/living/carbon/alien/humanoid + name = "alien" + icon = 'icons/mob/xenomorph.dmi' + icon_state = "alien_s" + + pass_flags = PASSTABLE + var/obj/item/clothing/suit/wear_suit = null //TODO: necessary? Are they even used? ~Carn + var/obj/item/weapon/r_store = null + var/obj/item/weapon/l_store = null + var/caste = "" + //var/perception = 0 //0 - standart mode, 1 - SEE_TURF mode + var/praetorians = 2 + //update_icon = 1 + var/alt_icon = 'icons/mob/xenoleap.dmi' //used to switch between the two alien icon files. + var/leap_on_click = 0 + + var/pounce_cooldown = 0 + var/pounce_cooldown_time = 50 + + var/neurotoxin_on_click = 0 + var/neurotoxin_delay = 15 + var/neurotoxin_next_shot = 0 + var/last_neurotoxin = 0 + + var/last_screech = 0 + var/screech_delay = 900 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/xenomeat = 5) + + +//This is fine right now, if we're adding organ specific damage this needs to be updated +/mob/living/carbon/alien/humanoid/atom_init() + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + if(name == "alien") + name = text("alien ([rand(1, 1000)])") + real_name = name + ..() + +/mob/living/carbon/alien/humanoid/movement_delay() + return (move_delay_add + config.alien_delay) + +///mob/living/carbon/alien/humanoid/bullet_act(obj/item/projectile/Proj) taken care of in living + diff --git a/code/modules/mob/living/carbon/alien/humanoid/inventory.dm b/code/modules/mob/living/carbon/alien/humanoid/inventory.dm index 41fafd6173f0..6a0682708cd3 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/inventory.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/inventory.dm @@ -1,54 +1,54 @@ -//unequip -/mob/living/carbon/alien/humanoid/u_equip(obj/item/W) - if (W == wear_suit) - wear_suit = null - update_inv_wear_suit(0) - else if (W == head) - head = null - update_inv_head(0) - else if (W == r_store) - r_store = null - update_inv_pockets(0) - else if (W == l_store) - l_store = null - update_inv_pockets(0) - else if (W == r_hand) - r_hand = null - update_inv_r_hand(0) - else if (W == l_hand) - l_hand = null - update_inv_l_hand(0) - -/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) - l_store = W - update_inv_pockets() - if(slot_r_store) - if(r_store) - return - if(W.w_class > 3) - return - u_equip(W) - 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) +//unequip +/mob/living/carbon/alien/humanoid/u_equip(obj/item/W) + if (W == wear_suit) + wear_suit = null + update_inv_wear_suit(0) + else if (W == head) + head = null + update_inv_head(0) + else if (W == r_store) + r_store = null + update_inv_pockets(0) + else if (W == l_store) + l_store = null + update_inv_pockets(0) + else if (W == r_hand) + r_hand = null + update_inv_r_hand(0) + else if (W == l_hand) + l_hand = null + update_inv_l_hand(0) + +/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) + l_store = W + update_inv_pockets() + if(slot_r_store) + if(r_store) + return + if(W.w_class > 3) + return + u_equip(W) + 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) diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm index 7ce5963f1a4a..d96c928e0095 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm @@ -1,108 +1,108 @@ -/mob/living/carbon/alien/humanoid/queen - name = "alien queen" - caste = "q" - maxHealth = 300 - health = 300 - icon = 'icons/mob/alienqueen.dmi' - icon_state = "queen_s" - pixel_x = -16 - status_flags = CANPARALYSE - heal_rate = 5 - plasma_rate = 20 - neurotoxin_delay = 10 - ventcrawler = 0 - - -/mob/living/carbon/alien/humanoid/queen/atom_init() - 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 queen_list) - 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,/mob/living/carbon/alien/humanoid/proc/screech) - . = ..() - queen_list += src - -/mob/living/carbon/alien/humanoid/queen/Destroy() - queen_list -= src - return ..() - -/mob/living/carbon/alien/humanoid/queen/handle_hud_icons_health() - if (src.healths) - if (src.stat != DEAD) - switch(health) - if(250 to INFINITY) - src.healths.icon_state = "health0" - if(200 to 250) - src.healths.icon_state = "health1" - if(150 to 200) - src.healths.icon_state = "health2" - if(100 to 150) - src.healths.icon_state = "health3" - if(50 to 100) - src.healths.icon_state = "health4" - if(0 to 50) - src.healths.icon_state = "health5" - else - src.healths.icon_state = "health6" - else - src.healths.icon_state = "health7" - - -//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) - for(var/mob/O in viewers(src, null)) - O.show_message(text("\green [src] has laid an egg!"), 1) - new /obj/effect/alien/egg(loc) - return - -/mob/living/carbon/alien/humanoid/queen/update_icons() - update_hud() //TODO: remove the need for this to be here - overlays.Cut() - if(stat == DEAD) - icon_state = "queen_dead" - else if(stat == UNCONSCIOUS || lying || resting) - icon_state = "queen_sleep" - else - icon_state = "queen_s" - for(var/image/I in overlays_standing) - overlays += I - -/mob/living/carbon/alien/humanoid/queen/movement_delay() - return(5 + move_delay_add + config.alien_delay) - -/mob/living/carbon/alien/humanoid/queen/large - icon = 'icons/mob/alienqueen.dmi' - icon_state = "queen_s-old" - pixel_x = -16 - -/mob/living/carbon/alien/humanoid/queen/large/update_icons() - update_hud() //TODO: remove the need for this to be here - overlays.Cut() - if(stat == DEAD) - icon_state = "queen_dead-old" - else if(stat == UNCONSCIOUS || lying || resting) - icon_state = "queen_sleep-old" - else - icon_state = "queen_s-old" - for(var/image/I in overlays_standing) - overlays += I +/mob/living/carbon/alien/humanoid/queen + name = "alien queen" + caste = "q" + maxHealth = 300 + health = 300 + icon = 'icons/mob/alienqueen.dmi' + icon_state = "queen_s" + pixel_x = -16 + status_flags = CANPARALYSE + heal_rate = 5 + plasma_rate = 20 + neurotoxin_delay = 10 + ventcrawler = 0 + + +/mob/living/carbon/alien/humanoid/queen/atom_init() + 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 queen_list) + 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,/mob/living/carbon/alien/humanoid/proc/screech) + . = ..() + queen_list += src + +/mob/living/carbon/alien/humanoid/queen/Destroy() + queen_list -= src + return ..() + +/mob/living/carbon/alien/humanoid/queen/handle_hud_icons_health() + if (src.healths) + if (src.stat != DEAD) + switch(health) + if(250 to INFINITY) + src.healths.icon_state = "health0" + if(200 to 250) + src.healths.icon_state = "health1" + if(150 to 200) + src.healths.icon_state = "health2" + if(100 to 150) + src.healths.icon_state = "health3" + if(50 to 100) + src.healths.icon_state = "health4" + if(0 to 50) + src.healths.icon_state = "health5" + else + src.healths.icon_state = "health6" + else + src.healths.icon_state = "health7" + + +//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) + for(var/mob/O in viewers(src, null)) + O.show_message(text("\green [src] has laid an egg!"), 1) + new /obj/effect/alien/egg(loc) + return + +/mob/living/carbon/alien/humanoid/queen/update_icons() + update_hud() //TODO: remove the need for this to be here + overlays.Cut() + if(stat == DEAD) + icon_state = "queen_dead" + else if(stat == UNCONSCIOUS || lying || resting) + icon_state = "queen_sleep" + else + icon_state = "queen_s" + for(var/image/I in overlays_standing) + overlays += I + +/mob/living/carbon/alien/humanoid/queen/movement_delay() + return(5 + move_delay_add + config.alien_delay) + +/mob/living/carbon/alien/humanoid/queen/large + icon = 'icons/mob/alienqueen.dmi' + icon_state = "queen_s-old" + pixel_x = -16 + +/mob/living/carbon/alien/humanoid/queen/large/update_icons() + update_hud() //TODO: remove the need for this to be here + overlays.Cut() + if(stat == DEAD) + icon_state = "queen_dead-old" + else if(stat == UNCONSCIOUS || lying || resting) + icon_state = "queen_sleep-old" + else + icon_state = "queen_s-old" + for(var/image/I in overlays_standing) + overlays += I 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 1e1ba2d31bc1..00a97172d2ee 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm @@ -1,173 +1,173 @@ -//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 TARGETED_LAYER 5 -#define X_FIRE_LAYER 6 -#define X_TOTAL_LAYERS 6 -///////////////////////////////// - -/mob/living/carbon/alien/humanoid - var/list/overlays_standing[X_TOTAL_LAYERS] - -/mob/living/carbon/alien/humanoid/update_icons() - update_hud() //TODO: remove the need for this to be here - overlays.Cut() - for(var/image/I in overlays_standing) - overlays += I - - if(stat == DEAD) - //If we mostly took damage from fire - if(fireloss > 125) - icon_state = "alien[caste]_husked" - else - icon_state = "alien[caste]_dead" - else if((stat == UNCONSCIOUS && !sleeping) || weakened) - icon_state = "alien[caste]_unconscious" - else if(leap_on_click) - icon_state = "alien[caste]_pounce" - else if(stat == UNCONSCIOUS || lying || resting) - icon_state = "alien[caste]_sleep" - else if(m_intent == "run") - icon_state = "alien[caste]_running" - else - icon_state = "alien[caste]_s" - - if(leaping) - if(alt_icon == initial(alt_icon)) - var/old_icon = icon - icon = alt_icon - alt_icon = old_icon - icon_state = "alien[caste]_leap" - pixel_x = -32 - pixel_y = -32 - else - if(alt_icon != initial(alt_icon)) - var/old_icon = icon - icon = alt_icon - alt_icon = old_icon - pixel_x = get_standard_pixel_x_offset(lying) - pixel_y = get_standard_pixel_y_offset(lying) - -/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() //Handled in update_transform(), leaving this here as a reminder - update_transform() - -/mob/living/carbon/alien/humanoid/update_transform() //The old method of updating lying/standing was update_icons(). Aliens still expect that. - if(lying > 0) - lying = 90 //Anything else looks retarded - update_icons() - ..() - - -/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/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") - - if(wear_suit.blood_DNA) - var/t_suit = "suit" - if( istype(wear_suit, /obj/item/clothing/suit/armor) ) - t_suit = "armor" - 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_r_hand() - drop_l_hand() - - overlays_standing[X_SUIT_LAYER] = standing - else - 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/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") - if(head.blood_DNA) - standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood") - head.screen_loc = ui_alien_head - overlays_standing[X_HEAD_LAYER] = standing - else - 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) - if(r_hand) - var/t_state = r_hand.item_state - if(!t_state) t_state = r_hand.icon_state - r_hand.screen_loc = ui_rhand - overlays_standing[X_R_HAND_LAYER] = image("icon" = r_hand.righthand_file, "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) - if(l_hand) - var/t_state = l_hand.item_state - if(!t_state) t_state = l_hand.icon_state - l_hand.screen_loc = ui_lhand - overlays_standing[X_L_HAND_LAYER] = image("icon" = l_hand.lefthand_file, "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_standing[TARGETED_LAYER] = target_locked - else if (!targeted_by && target_locked) - qdel(target_locked) - if (!targeted_by) - overlays_standing[TARGETED_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/alien/humanoid/update_fire() - overlays -= overlays_standing[X_FIRE_LAYER] - if(on_fire) - overlays_standing[X_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing") - overlays += overlays_standing[X_FIRE_LAYER] - return - else - 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 TARGETED_LAYER 5 +#define X_FIRE_LAYER 6 +#define X_TOTAL_LAYERS 6 +///////////////////////////////// + +/mob/living/carbon/alien/humanoid + var/list/overlays_standing[X_TOTAL_LAYERS] + +/mob/living/carbon/alien/humanoid/update_icons() + update_hud() //TODO: remove the need for this to be here + overlays.Cut() + for(var/image/I in overlays_standing) + overlays += I + + if(stat == DEAD) + //If we mostly took damage from fire + if(fireloss > 125) + icon_state = "alien[caste]_husked" + else + icon_state = "alien[caste]_dead" + else if((stat == UNCONSCIOUS && !sleeping) || weakened) + icon_state = "alien[caste]_unconscious" + else if(leap_on_click) + icon_state = "alien[caste]_pounce" + else if(stat == UNCONSCIOUS || lying || resting) + icon_state = "alien[caste]_sleep" + else if(m_intent == "run") + icon_state = "alien[caste]_running" + else + icon_state = "alien[caste]_s" + + if(leaping) + if(alt_icon == initial(alt_icon)) + var/old_icon = icon + icon = alt_icon + alt_icon = old_icon + icon_state = "alien[caste]_leap" + pixel_x = -32 + pixel_y = -32 + else + if(alt_icon != initial(alt_icon)) + var/old_icon = icon + icon = alt_icon + alt_icon = old_icon + pixel_x = get_standard_pixel_x_offset(lying) + pixel_y = get_standard_pixel_y_offset(lying) + +/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() //Handled in update_transform(), leaving this here as a reminder + update_transform() + +/mob/living/carbon/alien/humanoid/update_transform() //The old method of updating lying/standing was update_icons(). Aliens still expect that. + if(lying > 0) + lying = 90 //Anything else looks retarded + update_icons() + ..() + + +/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/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") + + if(wear_suit.blood_DNA) + var/t_suit = "suit" + if( istype(wear_suit, /obj/item/clothing/suit/armor) ) + t_suit = "armor" + 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_r_hand() + drop_l_hand() + + overlays_standing[X_SUIT_LAYER] = standing + else + 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/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") + if(head.blood_DNA) + standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood") + head.screen_loc = ui_alien_head + overlays_standing[X_HEAD_LAYER] = standing + else + 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) + if(r_hand) + var/t_state = r_hand.item_state + if(!t_state) t_state = r_hand.icon_state + r_hand.screen_loc = ui_rhand + overlays_standing[X_R_HAND_LAYER] = image("icon" = r_hand.righthand_file, "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) + if(l_hand) + var/t_state = l_hand.item_state + if(!t_state) t_state = l_hand.icon_state + l_hand.screen_loc = ui_lhand + overlays_standing[X_L_HAND_LAYER] = image("icon" = l_hand.lefthand_file, "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_standing[TARGETED_LAYER] = target_locked + else if (!targeted_by && target_locked) + qdel(target_locked) + if (!targeted_by) + overlays_standing[TARGETED_LAYER] = null + if(update_icons) update_icons() + +/mob/living/carbon/alien/humanoid/update_fire() + overlays -= overlays_standing[X_FIRE_LAYER] + if(on_fire) + overlays_standing[X_FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing") + overlays += overlays_standing[X_FIRE_LAYER] + return + else + 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/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm index c23c9b0becc7..9a04bd855c2e 100644 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ b/code/modules/mob/living/carbon/alien/larva/emote.dm @@ -1,127 +1,127 @@ -/mob/living/carbon/alien/larva/emote(act,m_type=1,message = null) - - 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, "\red 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 alien signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) - m_type = 1 - if ("burp") - if (!muzzled) - message = "[src] burps." - m_type = 2 - if("scratch") - if (!src.restrained()) - message = "The [src.name] scratches." - m_type = 1 - if("whimper") - if (!muzzled) - message = "The [src.name] whimpers." - m_type = 2 -// if("roar") -// if (!muzzled) -// message = "The [src.name] roars." Commenting out since larva shouldn't roar /N -// m_type = 2 - if("tail") - message = "The [src.name] waves its tail." - m_type = 1 - if("gasp") - message = "The [src.name] gasps." - m_type = 2 - if("shiver") - message = "The [src.name] shivers." - m_type = 2 - if("drool") - message = "The [src.name] drools." - m_type = 1 - if("scretch") - if (!muzzled) - message = "The [src.name] scretches." - m_type = 2 - if("choke") - message = "The [src.name] chokes." - m_type = 2 - if("moan") - message = "The [src.name] moans!" - m_type = 2 - if("nod") - message = "The [src.name] nods its head." - m_type = 1 -// if("sit") -// message = "The [src.name] sits down." //Larvan can't sit down, /N -// m_type = 1 - if("sway") - message = "The [src.name] sways around dizzily." - m_type = 1 - if("sulk") - message = "The [src.name] sulks down sadly." - m_type = 1 - if("twitch") - message = "The [src.name] twitches violently." - m_type = 1 - if("dance") - if (!src.restrained()) - message = "The [src.name] dances around happily." - m_type = 1 - if("roll") - if (!src.restrained()) - message = "The [src.name] rolls." - m_type = 1 - if("shake") - message = "The [src.name] shakes its head." - m_type = 1 - if("gnarl") - if (!muzzled) - message = "The [src.name] gnarls and shows its teeth.." - m_type = 2 - if("jump") - message = "The [src.name] jumps!" - m_type = 1 - if("hiss_") - message = "The [src.name] hisses softly." - m_type = 1 - if("collapse") - Paralyse(2) - message = text("[] collapses!", src) - m_type = 2 - 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 - to_chat(src, text("Invalid Emote: []", act)) - if ((message && src.stat == CONSCIOUS)) - log_emote("[name]/[key] : [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 +/mob/living/carbon/alien/larva/emote(act,m_type=1,message = null) + + 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, "\red 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 alien signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) + m_type = 1 + if ("burp") + if (!muzzled) + message = "[src] burps." + m_type = 2 + if("scratch") + if (!src.restrained()) + message = "The [src.name] scratches." + m_type = 1 + if("whimper") + if (!muzzled) + message = "The [src.name] whimpers." + m_type = 2 +// if("roar") +// if (!muzzled) +// message = "The [src.name] roars." Commenting out since larva shouldn't roar /N +// m_type = 2 + if("tail") + message = "The [src.name] waves its tail." + m_type = 1 + if("gasp") + message = "The [src.name] gasps." + m_type = 2 + if("shiver") + message = "The [src.name] shivers." + m_type = 2 + if("drool") + message = "The [src.name] drools." + m_type = 1 + if("scretch") + if (!muzzled) + message = "The [src.name] scretches." + m_type = 2 + if("choke") + message = "The [src.name] chokes." + m_type = 2 + if("moan") + message = "The [src.name] moans!" + m_type = 2 + if("nod") + message = "The [src.name] nods its head." + m_type = 1 +// if("sit") +// message = "The [src.name] sits down." //Larvan can't sit down, /N +// m_type = 1 + if("sway") + message = "The [src.name] sways around dizzily." + m_type = 1 + if("sulk") + message = "The [src.name] sulks down sadly." + m_type = 1 + if("twitch") + message = "The [src.name] twitches violently." + m_type = 1 + if("dance") + if (!src.restrained()) + message = "The [src.name] dances around happily." + m_type = 1 + if("roll") + if (!src.restrained()) + message = "The [src.name] rolls." + m_type = 1 + if("shake") + message = "The [src.name] shakes its head." + m_type = 1 + if("gnarl") + if (!muzzled) + message = "The [src.name] gnarls and shows its teeth.." + m_type = 2 + if("jump") + message = "The [src.name] jumps!" + m_type = 1 + if("hiss_") + message = "The [src.name] hisses softly." + m_type = 1 + if("collapse") + Paralyse(2) + message = text("[] collapses!", src) + m_type = 2 + 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 + to_chat(src, text("Invalid Emote: []", act)) + if ((message && src.stat == CONSCIOUS)) + log_emote("[name]/[key] : [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 diff --git a/code/modules/mob/living/carbon/alien/larva/inventory.dm b/code/modules/mob/living/carbon/alien/larva/inventory.dm index 07434fb0abcb..7aa8341b6449 100644 --- a/code/modules/mob/living/carbon/alien/larva/inventory.dm +++ b/code/modules/mob/living/carbon/alien/larva/inventory.dm @@ -1,7 +1,7 @@ -/mob/living/carbon/alien/larva/u_equip(obj/item/W) - if(W == r_hand) - r_hand = null - update_inv_r_hand(0) - -/mob/living/carbon/alien/larva/attack_ui(slot_id) - return +/mob/living/carbon/alien/larva/u_equip(obj/item/W) + if(W == r_hand) + r_hand = null + update_inv_r_hand(0) + +/mob/living/carbon/alien/larva/attack_ui(slot_id) + return diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 5ecb4bc89d4c..0b704d224da4 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -1,58 +1,58 @@ -/mob/living/carbon/alien/larva - name = "alien larva" - real_name = "alien larva" - icon_state = "larva0" - pass_flags = PASSTABLE | PASSMOB - - maxHealth = 25 - health = 25 - storedPlasma = 50 - max_plasma = 50 - - density = 0 - small = 1 - - var/amount_grown = 0 - var/max_grown = 200 - var/time_of_birth - - var/obj/item/clothing/suit/wear_suit = null //TODO: necessary? Are they even used? ~Carn - var/obj/item/weapon/r_store = null - var/obj/item/weapon/l_store = null - -//This is fine right now, if we're adding organ specific damage this needs to be updated -/mob/living/carbon/alien/larva/atom_init() - 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() - . = ..() - -//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/proc/update_progression() - if(stat != DEAD) - if(!iscarbon(loc) && !(istype(loc, /obj/item/alien_embryo))) - if(amount_grown < max_grown) - amount_grown++ - return - -/mob/living/carbon/alien/larva/start_pulling(atom/movable/AM)//Prevents mouse from pulling things - to_chat(src, "You are too small to pull anything.") - return - -/mob/living/carbon/alien/larva/swap_hand() - return - -/mob/living/carbon/alien/larva/movement_delay() - var/tally = 0 - if (istype(src, /mob/living/carbon/alien/larva/)) //just in case - tally = -1 - return (tally + move_delay_add + config.alien_delay) +/mob/living/carbon/alien/larva + name = "alien larva" + real_name = "alien larva" + icon_state = "larva0" + pass_flags = PASSTABLE | PASSMOB + + maxHealth = 25 + health = 25 + storedPlasma = 50 + max_plasma = 50 + + density = 0 + small = 1 + + var/amount_grown = 0 + var/max_grown = 200 + var/time_of_birth + + var/obj/item/clothing/suit/wear_suit = null //TODO: necessary? Are they even used? ~Carn + var/obj/item/weapon/r_store = null + var/obj/item/weapon/l_store = null + +//This is fine right now, if we're adding organ specific damage this needs to be updated +/mob/living/carbon/alien/larva/atom_init() + 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() + . = ..() + +//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/proc/update_progression() + if(stat != DEAD) + if(!iscarbon(loc) && !(istype(loc, /obj/item/alien_embryo))) + if(amount_grown < max_grown) + amount_grown++ + return + +/mob/living/carbon/alien/larva/start_pulling(atom/movable/AM)//Prevents mouse from pulling things + to_chat(src, "You are too small to pull anything.") + return + +/mob/living/carbon/alien/larva/swap_hand() + return + +/mob/living/carbon/alien/larva/movement_delay() + var/tally = 0 + if (istype(src, /mob/living/carbon/alien/larva/)) //just in case + tally = -1 + return (tally + move_delay_add + config.alien_delay) diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 467f810a94ec..119ad4d0f07d 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -1,38 +1,38 @@ -/mob/living/carbon/alien/larva/Life() - set invisibility = 0 - - for(var/obj/item/weapon/larva_bite/G in src) - G.process() - - if(istype(src.loc, /obj/item/alien_embryo)) - sleeping = 5 - - update_progression() - - ..() - -/mob/living/carbon/alien/larva - - proc/handle_random_events() - return - -/mob/living/carbon/alien/larva/handle_hud_icons_health() - if (healths) - if (stat != DEAD) - switch(health) - if(25 to INFINITY) - healths.icon_state = "health0" - if(20 to 25) - healths.icon_state = "health1" - if(15 to 20) - healths.icon_state = "health2" - if(10 to 15) - healths.icon_state = "health3" - if(5 to 10) - healths.icon_state = "health4" - if(0 to 5) - healths.icon_state = "health5" - else - healths.icon_state = "health6" - else - healths.icon_state = "health7" +/mob/living/carbon/alien/larva/Life() + set invisibility = 0 + + for(var/obj/item/weapon/larva_bite/G in src) + G.process() + + if(istype(src.loc, /obj/item/alien_embryo)) + sleeping = 5 + + update_progression() + + ..() + +/mob/living/carbon/alien/larva + + proc/handle_random_events() + return + +/mob/living/carbon/alien/larva/handle_hud_icons_health() + if (healths) + if (stat != DEAD) + switch(health) + if(25 to INFINITY) + healths.icon_state = "health0" + if(20 to 25) + healths.icon_state = "health1" + if(15 to 20) + healths.icon_state = "health2" + if(10 to 15) + healths.icon_state = "health3" + if(5 to 10) + healths.icon_state = "health4" + if(0 to 5) + healths.icon_state = "health5" + else + healths.icon_state = "health6" + else + healths.icon_state = "health7" diff --git a/code/modules/mob/living/carbon/alien/larva/powers.dm b/code/modules/mob/living/carbon/alien/larva/powers.dm index 55f4034808c3..2c346dc9b49c 100644 --- a/code/modules/mob/living/carbon/alien/larva/powers.dm +++ b/code/modules/mob/living/carbon/alien/larva/powers.dm @@ -1,64 +1,64 @@ - -/mob/living/carbon/alien/larva/verb/hide() - set name = "Hide" - set desc = "Allows to hide beneath tables or certain items. Toggled on or off." - set category = "Alien" - - if(stat != CONSCIOUS) - return - - if (layer != TURF_LAYER+0.2) - layer = TURF_LAYER+0.2 - to_chat(src, text("\green You are now hiding.")) - 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 - to_chat(src, text("\green You have stopped hiding.")) - for(var/mob/O in oviewers(src, null)) - if ((O.client && !( O.blinded ))) - to_chat(O, text("[] slowly peaks up from the ground...", src)) - -/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 - - if(!isturf(src.loc)) - to_chat(src, "\red You cannot evolve when you are inside something.")//Silly aliens! - return - - if(handcuffed || legcuffed) - to_chat(src, "\red You cannot evolve when you are cuffed.") - return - - 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, "\blue You are growing into a beautiful alien! It is time to choose a caste.") - to_chat(src, "\blue There are three to choose from:") - to_chat(src, "Hunters \blue 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.") - to_chat(src, "Sentinels \blue 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.") - to_chat(src, "Drones \blue 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/evolve_now = alert(src, "Are you sure?",,"Yes","No") - if(evolve_now == "No") - return - var/alien_caste = alert(src, "Please choose which alien caste you shall belong 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) - if(mind) mind.transfer_to(new_xeno) - qdel(src) - return - else - to_chat(src, "\red You are not fully grown.") - return + +/mob/living/carbon/alien/larva/verb/hide() + set name = "Hide" + set desc = "Allows to hide beneath tables or certain items. Toggled on or off." + set category = "Alien" + + if(stat != CONSCIOUS) + return + + if (layer != TURF_LAYER+0.2) + layer = TURF_LAYER+0.2 + to_chat(src, text("\green You are now hiding.")) + 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 + to_chat(src, text("\green You have stopped hiding.")) + for(var/mob/O in oviewers(src, null)) + if ((O.client && !( O.blinded ))) + to_chat(O, text("[] slowly peaks up from the ground...", src)) + +/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 + + if(!isturf(src.loc)) + to_chat(src, "\red You cannot evolve when you are inside something.")//Silly aliens! + return + + if(handcuffed || legcuffed) + to_chat(src, "\red You cannot evolve when you are cuffed.") + return + + 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, "\blue You are growing into a beautiful alien! It is time to choose a caste.") + to_chat(src, "\blue There are three to choose from:") + to_chat(src, "Hunters \blue 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.") + to_chat(src, "Sentinels \blue 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.") + to_chat(src, "Drones \blue 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/evolve_now = alert(src, "Are you sure?",,"Yes","No") + if(evolve_now == "No") + return + var/alien_caste = alert(src, "Please choose which alien caste you shall belong 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) + if(mind) mind.transfer_to(new_xeno) + qdel(src) + return + else + to_chat(src, "\red You are not fully grown.") + 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 39ffc16a12e3..1e07db027fdc 100644 --- a/code/modules/mob/living/carbon/alien/larva/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/larva/update_icons.dm @@ -1,35 +1,35 @@ -/mob/living/carbon/alien/larva/regenerate_icons() - overlays = list() - update_inv_r_hand(0) - update_hud() - update_icons() - -/mob/living/carbon/alien/larva/update_icons() - update_hud() //TODO: remove the need for this to be here - overlays.Cut() - 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) //This should be an overlay. Who made this an icon_state? - icon_state = "larva[state]_cuff" - else if(stat == UNCONSCIOUS || lying || resting) - icon_state = "larva[state]_sleep" - else if (stunned) - icon_state = "larva[state]_stun" - else - icon_state = "larva[state]" - -/mob/living/carbon/alien/larva/update_transform() //All this is handled in update_icons() - return update_icons() - -/mob/living/carbon/alien/larva/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/larva/regenerate_icons() + overlays = list() + update_inv_r_hand(0) + update_hud() + update_icons() + +/mob/living/carbon/alien/larva/update_icons() + update_hud() //TODO: remove the need for this to be here + overlays.Cut() + 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) //This should be an overlay. Who made this an icon_state? + icon_state = "larva[state]_cuff" + else if(stat == UNCONSCIOUS || lying || resting) + icon_state = "larva[state]_sleep" + else if (stunned) + icon_state = "larva[state]_stun" + else + icon_state = "larva[state]" + +/mob/living/carbon/alien/larva/update_transform() //All this is handled in update_icons() + return update_icons() + +/mob/living/carbon/alien/larva/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 diff --git a/code/modules/mob/living/carbon/alien/login.dm b/code/modules/mob/living/carbon/alien/login.dm index 117fe13b1c1f..6422f42e635d 100644 --- a/code/modules/mob/living/carbon/alien/login.dm +++ b/code/modules/mob/living/carbon/alien/login.dm @@ -1,8 +1,8 @@ -/mob/living/carbon/alien/Login() - ..() - AddInfectionImages() - update_hud() - if(!isturf(loc)) - client.eye = loc - client.perspective = EYE_PERSPECTIVE - return +/mob/living/carbon/alien/Login() + ..() + AddInfectionImages() + update_hud() + if(!isturf(loc)) + client.eye = loc + client.perspective = EYE_PERSPECTIVE + return diff --git a/code/modules/mob/living/carbon/alien/logout.dm b/code/modules/mob/living/carbon/alien/logout.dm index a4145581cb3c..f25b21f0cca9 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/Logout() - ..() - RemoveInfectionImages() - return +/mob/living/carbon/alien/Logout() + ..() + RemoveInfectionImages() + return diff --git a/code/modules/mob/living/carbon/alien/powers.dm b/code/modules/mob/living/carbon/alien/powers.dm index f33023b446cc..1206f2aea90f 100644 --- a/code/modules/mob/living/carbon/alien/powers.dm +++ b/code/modules/mob/living/carbon/alien/powers.dm @@ -1,19 +1,19 @@ -/mob/living/carbon/alien/proc/toggle_nvg(message = 1) - if(stat != CONSCIOUS) - return - - src.nightvision = !src.nightvision - - if(!src.nightvision) - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_MINIMUM - src.nightvisionicon.icon_state = "nightvision0" - else if(src.nightvision == 1) - src.see_in_dark = 4 - src.see_invisible = 45 - src.nightvisionicon.icon_state = "nightvision1" - - if(message) - to_chat(src, "You adapt your eyes for [nightvision ? "dark":"light"] !") - else - return +/mob/living/carbon/alien/proc/toggle_nvg(message = 1) + if(stat != CONSCIOUS) + return + + src.nightvision = !src.nightvision + + if(!src.nightvision) + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_MINIMUM + src.nightvisionicon.icon_state = "nightvision0" + else if(src.nightvision == 1) + src.see_in_dark = 4 + src.see_invisible = 45 + src.nightvisionicon.icon_state = "nightvision1" + + if(message) + to_chat(src, "You adapt your eyes for [nightvision ? "dark":"light"] !") + else + return diff --git a/code/modules/mob/living/carbon/alien/say.dm b/code/modules/mob/living/carbon/alien/say.dm index 00583b4e9332..f9356c5f5278 100644 --- a/code/modules/mob/living/carbon/alien/say.dm +++ b/code/modules/mob/living/carbon/alien/say.dm @@ -1,106 +1,106 @@ -/mob/living/carbon/alien/say(message) - - if (silent) - return - - message = sanitize(message) - - if (length(message) >= 2) - if (department_radio_keys[copytext(message, 1, 3)] == "alientalk") - message = copytext(message, 3) - message = trim(message) - if (stat == DEAD) - return say_dead(message) - else - alien_talk(message) - else - if (copytext(message, 1, 2) != "*" && !stat) - playsound(loc, "hiss", 25, 1, 1)//So aliens can hiss while they hiss yo/N - return ..(message, sanitize = 0) - -/mob/living/carbon/alien/facehugger/say(message) - - if (silent) - return - - message = sanitize(message) - - if (length(message) >= 2) - if (department_radio_keys[copytext(message, 1, 3)] == "alientalk") - message = copytext(message, 3) - message = trim(message) - if (stat == DEAD) - return say_dead(message) - else - alien_talk(message) - -/mob/living/carbon/alien/larva/say(message) - - if (silent) - return - - message = sanitize(message) - - if (length(message) >= 2) - if (department_radio_keys[copytext(message, 1, 3)] == "alientalk") - message = copytext(message, 3) - message = trim(message) - if (stat == DEAD) - return say_dead(message) - else - alien_talk(message) - -/mob/living/proc/alien_talk(message) - - log_say("[key_name(src)] : [message]") - message = trim(message) - - if (!message) - return - - //var/message_a = sanitize_chat(say_quote(message)) - // , . , - var/message_a = "hisses, \"[message]\"" - - var/rendered = "Hivemind, [name] [message_a]" - for (var/mob/living/S in player_list) - if(!S.stat) - if(S.alien_talk_understand) - if(S.alien_talk_understand == alien_talk_understand) - S.show_message(rendered, 2) - else if (S.hivecheck()) - S.show_message(rendered, 2) - - var/list/listening = hearers(1, src) - listening -= src - listening += src - - var/list/heard = list() - for (var/mob/M in listening) - if(!isalien(M) && !M.alien_talk_understand) - heard += M - - - if (length(heard)) - var/message_b - - //message_b = "hsssss" - //message_b = say_quote(message_b) - message_b = "hisses, \"hsssss\"" - - message_b = "[message_b]" - rendered = "[voice_name] [message_b]" - - for (var/mob/M in heard) - M.show_message(rendered, 2) - - //message = say_quote(message) - message = "hisses, \"[message]\"" - - rendered = "Hivemind, [name] [message_a]" - - for (var/mob/M in player_list) - if (isnewplayer(M)) - continue - if (M.stat > 1) - M.show_message(rendered, 2) +/mob/living/carbon/alien/say(message) + + if (silent) + return + + message = sanitize(message) + + if (length(message) >= 2) + if (department_radio_keys[copytext(message, 1, 3)] == "alientalk") + message = copytext(message, 3) + message = trim(message) + if (stat == DEAD) + return say_dead(message) + else + alien_talk(message) + else + if (copytext(message, 1, 2) != "*" && !stat) + playsound(loc, "hiss", 25, 1, 1)//So aliens can hiss while they hiss yo/N + return ..(message, sanitize = 0) + +/mob/living/carbon/alien/facehugger/say(message) + + if (silent) + return + + message = sanitize(message) + + if (length(message) >= 2) + if (department_radio_keys[copytext(message, 1, 3)] == "alientalk") + message = copytext(message, 3) + message = trim(message) + if (stat == DEAD) + return say_dead(message) + else + alien_talk(message) + +/mob/living/carbon/alien/larva/say(message) + + if (silent) + return + + message = sanitize(message) + + if (length(message) >= 2) + if (department_radio_keys[copytext(message, 1, 3)] == "alientalk") + message = copytext(message, 3) + message = trim(message) + if (stat == DEAD) + return say_dead(message) + else + alien_talk(message) + +/mob/living/proc/alien_talk(message) + + log_say("[key_name(src)] : [message]") + message = trim(message) + + if (!message) + return + + //var/message_a = sanitize_chat(say_quote(message)) + // , . , + var/message_a = "hisses, \"[message]\"" + + var/rendered = "Hivemind, [name] [message_a]" + for (var/mob/living/S in player_list) + if(!S.stat) + if(S.alien_talk_understand) + if(S.alien_talk_understand == alien_talk_understand) + S.show_message(rendered, 2) + else if (S.hivecheck()) + S.show_message(rendered, 2) + + var/list/listening = hearers(1, src) + listening -= src + listening += src + + var/list/heard = list() + for (var/mob/M in listening) + if(!isalien(M) && !M.alien_talk_understand) + heard += M + + + if (length(heard)) + var/message_b + + //message_b = "hsssss" + //message_b = say_quote(message_b) + message_b = "hisses, \"hsssss\"" + + message_b = "[message_b]" + rendered = "[voice_name] [message_b]" + + for (var/mob/M in heard) + M.show_message(rendered, 2) + + //message = say_quote(message) + message = "hisses, \"[message]\"" + + rendered = "Hivemind, [name] [message_a]" + + for (var/mob/M in player_list) + if (isnewplayer(M)) + continue + if (M.stat > 1) + M.show_message(rendered, 2) diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 05b6132e1639..f165011fec42 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -1,200 +1,200 @@ -//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" - - req_access = list(access_robotics) - - //Revised. Brainmob is now contained directly within object of transfer. MMI in this case. - - var/locked = FALSE - 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/attackby(obj/item/O, mob/user) - if(istype(O,/obj/item/brain) && !brainmob) //Time to stick a brain in it --NEO - var/obj/item/brain/B = O - if(!B.brainmob) - to_chat(user, "You aren't sure where this brain came from, but you're pretty sure it's a useless brain.") - return - visible_message("[user] sticks \a [O] into \the [src].") - - brainmob = B.brainmob - B.brainmob = null - brainmob.forceMove(src) - brainmob.container = src - brainmob.stat = CONSCIOUS - dead_mob_list -= brainmob//Update dem lists - alive_mob_list += brainmob - - name = "Man-Machine Interface: [brainmob.real_name]" - icon_state = "mmi_full" - - locked = TRUE - - feedback_inc("cyborg_mmis_filled", 1) - qdel(O) - return - - else if(istype(O, /obj/item/weapon/holder/diona) && !brainmob) - visible_message("[user] sticks \a [O] into \the [src].") - - var/mob/living/carbon/monkey/diona/D = locate(/mob/living/carbon/monkey/diona) in O - if(!D) - world.log << "This is seriously really wrong, and I would like to keep a message for this case." - if(!D.mind || !D.key) - to_chat(user, "It would appear [D] is void of consciousness, defeats MMI's purpose.") - return - transfer_nymph(D) - - feedback_inc("cyborg_mmis_filled",1) - qdel(O) - return - - else 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 brain holder.") - else - to_chat(user, "Access denied.") - return - - else if(brainmob) - O.attack(brainmob, user)//Oh noooeeeee - return - - ..() - -/obj/item/device/mmi/attack_self(mob/user) - if(!brainmob) - to_chat(user, "You upend the MMI, but there's nothing in it.") - return - else if(locked) - to_chat(user, "You upend the MMI, but the brain is clamped into place.") - return - var/mob/living/carbon/monkey/diona/D = locate(/mob/living/carbon/monkey/diona) in brainmob - icon_state = "mmi_empty" - name = "Man-Machine Interface" - if(D) - to_chat(user, "You uppend the MMI, dropping [brainmob.real_name] onto the floor.") - D.forceMove(user.loc) - if(brainmob.mind) - brainmob.mind.transfer_to(D) - brainmob = null - qdel(brainmob) - return - else - to_chat(user, "You upend the MMI, spilling the brain onto the floor.") - var/obj/item/brain/brain = new(user.loc) - brainmob.container = null//Reset brainmob mmi var. - brainmob.loc = brain//Throw mob into brain. - alive_mob_list -= brainmob//Get outta here - brain.brainmob = brainmob//Set the brain to use the brainmob - brainmob = null - qdel(brainmob) - -/obj/item/device/mmi/MouseDrop_T(mob/living/carbon/monkey/diona/target, mob/user) - if(user.incapacitated() || !istype(target)) - return - if(target.buckled || !in_range(user, src) || !in_range(user, target)) - return - if(target == user) - visible_message("[usr] starts climbing into the MMI.", 3) - else - if(target.anchored) - return - visible_message("[usr] starts stuffing [target.name] into the MMI.", 3) - if(user.is_busy() || !do_after(usr, 20, target = usr)) - return - if(target == user) - visible_message("[user.name] climbs into the MMI.","You climb into the MMI.") - else if(target != user) - visible_message("[user.name] stuffs [target.name] into the MMI!","You stuff [target.name] into the MMI!") - else - return - transfer_nymph(target) - - feedback_inc("cyborg_mmis_filled",1) - -/obj/item/device/mmi/proc/transfer_identity(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 - brainmob.dna = H.dna - brainmob.container = src - - name = "Man-Machine Interface: [brainmob.real_name]" - icon_state = "mmi_full" - locked = TRUE - -/obj/item/device/mmi/proc/transfer_nymph(mob/living/carbon/monkey/diona/D) - brainmob = new(src) - brainmob.name = D.real_name - brainmob.real_name = D.real_name - brainmob.dna = D.dna - brainmob.container = src - brainmob.stat = CONSCIOUS - if(D.mind) - D.mind.transfer_to(brainmob) - D.forceMove(brainmob) - - name = "Man-Machine Interface: [brainmob.real_name]" - icon_state = "mmi_fullnymph" - locked = TRUE - -/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/atom_init() - . = ..() - radio = new(src)//Spawns a radio inside the MMI. - radio.broadcasting = 1//So it's broadcasting from the start. - -/obj/item/device/mmi/radio_enabled/verb/Toggle_Broadcasting() //Allows the brain to toggle the radio functions. - 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, "\blue 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, "\blue Radio is [radio.listening==1 ? "now" : "no longer"] 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) - ..() +//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" + + req_access = list(access_robotics) + + //Revised. Brainmob is now contained directly within object of transfer. MMI in this case. + + var/locked = FALSE + 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/attackby(obj/item/O, mob/user) + if(istype(O,/obj/item/brain) && !brainmob) //Time to stick a brain in it --NEO + var/obj/item/brain/B = O + if(!B.brainmob) + to_chat(user, "You aren't sure where this brain came from, but you're pretty sure it's a useless brain.") + return + visible_message("[user] sticks \a [O] into \the [src].") + + brainmob = B.brainmob + B.brainmob = null + brainmob.forceMove(src) + brainmob.container = src + brainmob.stat = CONSCIOUS + dead_mob_list -= brainmob//Update dem lists + alive_mob_list += brainmob + + name = "Man-Machine Interface: [brainmob.real_name]" + icon_state = "mmi_full" + + locked = TRUE + + feedback_inc("cyborg_mmis_filled", 1) + qdel(O) + return + + else if(istype(O, /obj/item/weapon/holder/diona) && !brainmob) + visible_message("[user] sticks \a [O] into \the [src].") + + var/mob/living/carbon/monkey/diona/D = locate(/mob/living/carbon/monkey/diona) in O + if(!D) + world.log << "This is seriously really wrong, and I would like to keep a message for this case." + if(!D.mind || !D.key) + to_chat(user, "It would appear [D] is void of consciousness, defeats MMI's purpose.") + return + transfer_nymph(D) + + feedback_inc("cyborg_mmis_filled",1) + qdel(O) + return + + else 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 brain holder.") + else + to_chat(user, "Access denied.") + return + + else if(brainmob) + O.attack(brainmob, user)//Oh noooeeeee + return + + ..() + +/obj/item/device/mmi/attack_self(mob/user) + if(!brainmob) + to_chat(user, "You upend the MMI, but there's nothing in it.") + return + else if(locked) + to_chat(user, "You upend the MMI, but the brain is clamped into place.") + return + var/mob/living/carbon/monkey/diona/D = locate(/mob/living/carbon/monkey/diona) in brainmob + icon_state = "mmi_empty" + name = "Man-Machine Interface" + if(D) + to_chat(user, "You uppend the MMI, dropping [brainmob.real_name] onto the floor.") + D.forceMove(user.loc) + if(brainmob.mind) + brainmob.mind.transfer_to(D) + brainmob = null + qdel(brainmob) + return + else + to_chat(user, "You upend the MMI, spilling the brain onto the floor.") + var/obj/item/brain/brain = new(user.loc) + brainmob.container = null//Reset brainmob mmi var. + brainmob.loc = brain//Throw mob into brain. + alive_mob_list -= brainmob//Get outta here + brain.brainmob = brainmob//Set the brain to use the brainmob + brainmob = null + qdel(brainmob) + +/obj/item/device/mmi/MouseDrop_T(mob/living/carbon/monkey/diona/target, mob/user) + if(user.incapacitated() || !istype(target)) + return + if(target.buckled || !in_range(user, src) || !in_range(user, target)) + return + if(target == user) + visible_message("[usr] starts climbing into the MMI.", 3) + else + if(target.anchored) + return + visible_message("[usr] starts stuffing [target.name] into the MMI.", 3) + if(user.is_busy() || !do_after(usr, 20, target = usr)) + return + if(target == user) + visible_message("[user.name] climbs into the MMI.","You climb into the MMI.") + else if(target != user) + visible_message("[user.name] stuffs [target.name] into the MMI!","You stuff [target.name] into the MMI!") + else + return + transfer_nymph(target) + + feedback_inc("cyborg_mmis_filled",1) + +/obj/item/device/mmi/proc/transfer_identity(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 + brainmob.dna = H.dna + brainmob.container = src + + name = "Man-Machine Interface: [brainmob.real_name]" + icon_state = "mmi_full" + locked = TRUE + +/obj/item/device/mmi/proc/transfer_nymph(mob/living/carbon/monkey/diona/D) + brainmob = new(src) + brainmob.name = D.real_name + brainmob.real_name = D.real_name + brainmob.dna = D.dna + brainmob.container = src + brainmob.stat = CONSCIOUS + if(D.mind) + D.mind.transfer_to(brainmob) + D.forceMove(brainmob) + + name = "Man-Machine Interface: [brainmob.real_name]" + icon_state = "mmi_fullnymph" + locked = TRUE + +/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/atom_init() + . = ..() + radio = new(src)//Spawns a radio inside the MMI. + radio.broadcasting = 1//So it's broadcasting from the start. + +/obj/item/device/mmi/radio_enabled/verb/Toggle_Broadcasting() //Allows the brain to toggle the radio functions. + 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, "\blue 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, "\blue Radio is [radio.listening==1 ? "now" : "no longer"] 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) + ..() diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm index 503a465718ba..e2b46f78cc6c 100644 --- a/code/modules/mob/living/carbon/brain/brain.dm +++ b/code/modules/mob/living/carbon/brain/brain.dm @@ -1,58 +1,58 @@ -//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 - use_me = 0 //Can't use the me verb, it's a freaking immobile brain - icon = 'icons/obj/surgery.dmi' - icon_state = "brain1" - -/mob/living/carbon/brain/atom_init() - 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 - ghostize(bancheck = TRUE) //Ghostize checks for key so nothing else is necessary. - return ..() - -/mob/living/carbon/brain/say_understands(other)//Goddamn is this hackish, but this say code is so odd - 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/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 +//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 + use_me = 0 //Can't use the me verb, it's a freaking immobile brain + icon = 'icons/obj/surgery.dmi' + icon_state = "brain1" + +/mob/living/carbon/brain/atom_init() + 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 + ghostize(bancheck = TRUE) //Ghostize checks for key so nothing else is necessary. + return ..() + +/mob/living/carbon/brain/say_understands(other)//Goddamn is this hackish, but this say code is so odd + 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/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 diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index eb6848d29654..7d0924bea1fb 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -1,97 +1,97 @@ -/obj/item/brain - name = "brain" - desc = "A piece of juicy meat found in a persons head." - icon = 'icons/obj/surgery.dmi' - icon_state = "brain2" - force = 1.0 - w_class = 2.0 - throwforce = 1.0 - throw_speed = 3 - throw_range = 5 - origin_tech = "biotech=3" - attack_verb = list("attacked", "slapped", "whacked") - - var/mob/living/carbon/brain/brainmob = null - -/obj/item/brain/atom_init() - . = ..() - //Shifting the brain "mob" over to the brain object so it's easier to keep track of. --NEO - //WASSSSSUUUPPPP /N - spawn(5) - if(brainmob && brainmob.client) - brainmob.client.screen.len = null //clear the hud - -/obj/item/brain/proc/transfer_identity(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, "\blue You feel slightly disoriented. That's normal when you're just a brain.") - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if(mode) - mode.debrain_directive(src) - -/obj/item/brain/examine(mob/user) // -- TLE - ..() - if(brainmob && brainmob.client)//if thar be a brain inside... the brain. - 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/brain/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) - if(!ishuman(M)) - return ..() - - add_fingerprint(user) - - if(!(def_zone == BP_HEAD)) - return ..() - - if( !(locate(/obj/machinery/optable, M.loc) && M.resting) && ( !(locate(/obj/structure/table/, M.loc) && M.lying) && prob(50) ) ) - return ..() - - var/mob/living/carbon/human/H = M - if(ishuman(M) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) - // you can't stab someone in the eyes wearing a mask! - to_chat(user, "\blue You're going to need to remove their head cover first.") - return - -//since these people will be dead M != usr - - if(M:brain_op_stage == 4.0) - for(var/mob/O in viewers(M, null)) - if(O == (user || M)) - continue - if(M == user) - O.show_message(text("\red [user] inserts [src] into his head!"), 1) - else - O.show_message(text("\red [M] has [src] inserted into his head by [user]."), 1) - - if(M != user) - to_chat(M, "\red [user] inserts [src] into your head!") - to_chat(user, "\red You insert [src] into [M]'s head!") - else - to_chat(user, "\red You insert [src] into your head!") - - //this might actually be outdated since barring badminnery, a debrain'd body will have any client sucked out to the brain's internal mob. Leaving it anyway to be safe. --NEO - if(M.key)//Revised. /N - M.ghostize() - - if(brainmob.mind) - brainmob.mind.transfer_to(M) - else - M.key = brainmob.key - - M.dna = brainmob.dna - - M:brain_op_stage = 3.0 - - qdel(src) - else - ..() - return +/obj/item/brain + name = "brain" + desc = "A piece of juicy meat found in a persons head." + icon = 'icons/obj/surgery.dmi' + icon_state = "brain2" + force = 1.0 + w_class = 2.0 + throwforce = 1.0 + throw_speed = 3 + throw_range = 5 + origin_tech = "biotech=3" + attack_verb = list("attacked", "slapped", "whacked") + + var/mob/living/carbon/brain/brainmob = null + +/obj/item/brain/atom_init() + . = ..() + //Shifting the brain "mob" over to the brain object so it's easier to keep track of. --NEO + //WASSSSSUUUPPPP /N + spawn(5) + if(brainmob && brainmob.client) + brainmob.client.screen.len = null //clear the hud + +/obj/item/brain/proc/transfer_identity(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, "\blue You feel slightly disoriented. That's normal when you're just a brain.") + var/datum/game_mode/mutiny/mode = get_mutiny_mode() + if(mode) + mode.debrain_directive(src) + +/obj/item/brain/examine(mob/user) // -- TLE + ..() + if(brainmob && brainmob.client)//if thar be a brain inside... the brain. + 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/brain/attack(mob/living/carbon/M, mob/living/carbon/user, def_zone) + if(!ishuman(M)) + return ..() + + add_fingerprint(user) + + if(!(def_zone == BP_HEAD)) + return ..() + + if( !(locate(/obj/machinery/optable, M.loc) && M.resting) && ( !(locate(/obj/structure/table/, M.loc) && M.lying) && prob(50) ) ) + return ..() + + var/mob/living/carbon/human/H = M + if(ishuman(M) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) + // you can't stab someone in the eyes wearing a mask! + to_chat(user, "\blue You're going to need to remove their head cover first.") + return + +//since these people will be dead M != usr + + if(M:brain_op_stage == 4.0) + for(var/mob/O in viewers(M, null)) + if(O == (user || M)) + continue + if(M == user) + O.show_message(text("\red [user] inserts [src] into his head!"), 1) + else + O.show_message(text("\red [M] has [src] inserted into his head by [user]."), 1) + + if(M != user) + to_chat(M, "\red [user] inserts [src] into your head!") + to_chat(user, "\red You insert [src] into [M]'s head!") + else + to_chat(user, "\red You insert [src] into your head!") + + //this might actually be outdated since barring badminnery, a debrain'd body will have any client sucked out to the brain's internal mob. Leaving it anyway to be safe. --NEO + if(M.key)//Revised. /N + M.ghostize() + + if(brainmob.mind) + brainmob.mind.transfer_to(M) + else + M.key = brainmob.key + + M.dna = brainmob.dna + + M:brain_op_stage = 3.0 + + qdel(src) + else + ..() + return diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/carbon/brain/death.dm index 6e4b64571f9a..35273209f7f0 100644 --- a/code/modules/mob/living/carbon/brain/death.dm +++ b/code/modules/mob/living/carbon/brain/death.dm @@ -1,42 +1,42 @@ -/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. - for(var/mob/O in viewers(container, null)) - O.show_message(text("\red []'s MMI flatlines!", src), 1, "\red You hear something flatline.", 2) - container.icon_state = "mmi_dead" - stat = DEAD - - 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) - var/atom/movable/overlay/animation = null - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - animation = new(loc) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - -// flick("gibbed-m", animation) - gibs(loc, viruses, dna) - - dead_mob_list -= src - 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/brain)) - qdel(loc)//Gets rid of the brain item - spawn(15) - if(animation) qdel(animation) - if(src) qdel(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. + for(var/mob/O in viewers(container, null)) + O.show_message(text("\red []'s MMI flatlines!", src), 1, "\red You hear something flatline.", 2) + container.icon_state = "mmi_dead" + stat = DEAD + + 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) + var/atom/movable/overlay/animation = null + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + animation = new(loc) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + +// flick("gibbed-m", animation) + gibs(loc, viruses, dna) + + dead_mob_list -= src + 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/brain)) + qdel(loc)//Gets rid of the brain item + spawn(15) + if(animation) qdel(animation) + if(src) qdel(src) diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm index a5da1158ad37..241156b235f5 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(act,m_type=1,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, "\red 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") - to_chat(src, "You sound an alarm.") - message = "[src] sounds an alarm." - m_type = 2 - if ("alert") - to_chat(src, "You let out a distressed noise.") - message = "[src] lets out a distressed noise." - m_type = 2 - if ("notice") - to_chat(src, "You play a loud tone.") - message = "[src] plays a loud tone." - m_type = 2 - if ("flash") - message = "The lights on [src] flash quickly." - m_type = 1 - if ("blink") - message = "[src] blinks." - m_type = 1 - if ("whistle") - to_chat(src, "You whistle.") - message = "[src] whistles." - m_type = 2 - if ("beep") - to_chat(src, "You beep.") - message = "[src] beeps." - m_type = 2 - if ("boop") - to_chat(src, "You boop.") - message = "[src] boops." - m_type = 2 - if ("help") - to_chat(src, "alarm,alert,notice,flash,blink,whistle,beep,boop") - else - to_chat(src, "\blue Unusable emote '[act]'. Say *help for a list.") - - if (message) - log_emote("[name]/[key] : [message]") - - for(var/mob/M in observer_list) - if (!M.client) - continue //skip leavers - if((M.client.prefs.chat_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) +/mob/living/carbon/brain/emote(act,m_type=1,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, "\red 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") + to_chat(src, "You sound an alarm.") + message = "[src] sounds an alarm." + m_type = 2 + if ("alert") + to_chat(src, "You let out a distressed noise.") + message = "[src] lets out a distressed noise." + m_type = 2 + if ("notice") + to_chat(src, "You play a loud tone.") + message = "[src] plays a loud tone." + m_type = 2 + if ("flash") + message = "The lights on [src] flash quickly." + m_type = 1 + if ("blink") + message = "[src] blinks." + m_type = 1 + if ("whistle") + to_chat(src, "You whistle.") + message = "[src] whistles." + m_type = 2 + if ("beep") + to_chat(src, "You beep.") + message = "[src] beeps." + m_type = 2 + if ("boop") + to_chat(src, "You boop.") + message = "[src] boops." + m_type = 2 + if ("help") + to_chat(src, "alarm,alert,notice,flash,blink,whistle,beep,boop") + else + to_chat(src, "\blue Unusable emote '[act]'. Say *help for a list.") + + if (message) + log_emote("[name]/[key] : [message]") + + for(var/mob/M in observer_list) + if (!M.client) + continue //skip leavers + if((M.client.prefs.chat_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) diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm index 35dabc4c0cdf..4654c8b3d34b 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/carbon/brain/life.dm @@ -1,262 +1,262 @@ -/mob/living/carbon/brain/Life() - set invisibility = 0 - //set background = 1 - ..() - - 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 (radiation) - if (radiation > 100) - radiation = 100 - if(!container)//If it's not in an MMI - to_chat(src, "\red You feel weak.") - else//Fluff-wise, since the brain can't detect anything itself, the MMI handles thing like that - to_chat(src, "\red 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) - to_chat(src, "\red You feel weak.") - else - to_chat(src, "\red STATUS: DANGEROUS LEVELS OF RADIATION DETECTED.") - updatehealth() - - if(75 to 100) - radiation -= 3 - adjustToxLoss(3) - updatehealth() - - - handle_environment(datum/gas_mixture/environment) - if(!environment) - 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, "\red 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") - to_chat(src, "\red 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") - to_chat(src, "\red System reboot nearly complete.") - alert = 1 - if(prob(25)) - emp_damage -= 1 - if(1) - alert = 0 - to_chat(src, "\red 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 - - - handle_regular_hud_updates() - if(!client) - return 0 - - if (stat == DEAD || (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 != DEAD) - sight &= ~SEE_TURFS - sight &= ~SEE_MOBS - sight &= ~SEE_OBJS - see_in_dark = 2 - see_invisible = SEE_INVISIBLE_LIVING - - if (healths) - if (stat != DEAD) - 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]" - - ..() - - return 1 - - -/*/mob/living/carbon/brain/emp_act(severity) - 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) - ..()*/ +/mob/living/carbon/brain/Life() + set invisibility = 0 + //set background = 1 + ..() + + 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 (radiation) + if (radiation > 100) + radiation = 100 + if(!container)//If it's not in an MMI + to_chat(src, "\red You feel weak.") + else//Fluff-wise, since the brain can't detect anything itself, the MMI handles thing like that + to_chat(src, "\red 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) + to_chat(src, "\red You feel weak.") + else + to_chat(src, "\red STATUS: DANGEROUS LEVELS OF RADIATION DETECTED.") + updatehealth() + + if(75 to 100) + radiation -= 3 + adjustToxLoss(3) + updatehealth() + + + handle_environment(datum/gas_mixture/environment) + if(!environment) + 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, "\red 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") + to_chat(src, "\red 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") + to_chat(src, "\red System reboot nearly complete.") + alert = 1 + if(prob(25)) + emp_damage -= 1 + if(1) + alert = 0 + to_chat(src, "\red 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 + + + handle_regular_hud_updates() + if(!client) + return 0 + + if (stat == DEAD || (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 != DEAD) + sight &= ~SEE_TURFS + sight &= ~SEE_MOBS + sight &= ~SEE_OBJS + see_in_dark = 2 + see_invisible = SEE_INVISIBLE_LIVING + + if (healths) + if (stat != DEAD) + 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]" + + ..() + + return 1 + + +/*/mob/living/carbon/brain/emp_act(severity) + 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) + ..()*/ diff --git a/code/modules/mob/living/carbon/brain/login.dm b/code/modules/mob/living/carbon/brain/login.dm index c37080d0e170..46fd03d6043e 100644 --- a/code/modules/mob/living/carbon/brain/login.dm +++ b/code/modules/mob/living/carbon/brain/login.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/brain/Login() - ..() - update_hud() +/mob/living/carbon/brain/Login() + ..() + update_hud() 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 4e8a7548f354..ff9e6c86d075 100644 --- a/code/modules/mob/living/carbon/brain/say.dm +++ b/code/modules/mob/living/carbon/brain/say.dm @@ -1,28 +1,28 @@ - -/mob/living/carbon/brain/say(var/message) - if (silent) - return - if(container) - if(istype(container, /obj/item/device/mmi) || istype(container, /obj/item/device/mmi/posibrain)) - message = sanitize(message) - if ((department_radio_keys[copytext(message, 1, 3)] == "binary") && (container && istype(container, /obj/item/device/mmi/posibrain))) - message = copytext(message, 3) - message = trim(message) - robot_talk(message) - return - if(prob(emp_damage*4)) - if(prob(10))//10% chane to drop the message entirely - return - else - message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher - if(istype(container, /obj/item/device/mmi/radio_enabled)) - var/obj/item/device/mmi/radio_enabled/R = container - if(R.radio) - spawn(0) R.radio.hear_talk(src, message) - ..(message, sanitize = 0) - if(istype(container, /obj/item/device/biocan)) - var/obj/item/device/biocan/B = container - if(B.commutator_enabled) - ..(sanitize(message), sanitize = 0) - else + +/mob/living/carbon/brain/say(var/message) + if (silent) + return + if(container) + if(istype(container, /obj/item/device/mmi) || istype(container, /obj/item/device/mmi/posibrain)) + message = sanitize(message) + if ((department_radio_keys[copytext(message, 1, 3)] == "binary") && (container && istype(container, /obj/item/device/mmi/posibrain))) + message = copytext(message, 3) + message = trim(message) + robot_talk(message) + return + if(prob(emp_damage*4)) + if(prob(10))//10% chane to drop the message entirely + return + else + message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher + if(istype(container, /obj/item/device/mmi/radio_enabled)) + var/obj/item/device/mmi/radio_enabled/R = container + if(R.radio) + spawn(0) R.radio.hear_talk(src, message) + ..(message, sanitize = 0) + if(istype(container, /obj/item/device/biocan)) + var/obj/item/device/biocan/B = container + if(B.commutator_enabled) + ..(sanitize(message), sanitize = 0) + else return \ 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 dae13d8ecdb0..85fd9cb4dcdf 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1,686 +1,686 @@ -/mob/living/carbon/atom_init() - . = ..() - carbon_list += src - -/mob/living/carbon/Destroy() - carbon_list -= src - return ..() - -/mob/living/carbon/Life() - ..() - - // Increase germ_level regularly - if(germ_level < GERM_LEVEL_AMBIENT && prob(80)) //if you're just standing there, you shouldn't get more germs beyond an ambient level - germ_level++ - -/mob/living/carbon/Move(NewLoc, direct) - . = ..() - if(.) - handle_phantom_move(NewLoc, direct) - if(nutrition && stat != DEAD) - nutrition -= metabolism_factor/100 - if(m_intent == "run") - nutrition -= metabolism_factor/100 - if((FAT in mutations) && m_intent == "run" && bodytemperature <= 360) - bodytemperature += 2 - - // Moving around increases germ_level faster - if(germ_level < GERM_LEVEL_MOVE_CAP && prob(8)) - germ_level++ - -/mob/living/carbon/relaymove(mob/user, direction) - if(isessence(user)) - user.setMoveCooldown(1) - var/mob/living/parasite/essence/essence = user - if(!(essence.flags_allowed & ESSENCE_PHANTOM)) - to_chat(user, "Your host forbrade you to own phantom") - return - - if(!essence.phantom.showed) - essence.phantom.show_phantom() - return - var/tile = get_turf(get_step(essence.phantom, direction)) - if(get_dist(tile, essence.host) < 8) - essence.phantom.dir = direction - essence.phantom.loc = tile - return - 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/obj/item/organ/external/BP = H.bodyparts_by_name[BP_CHEST] - BP.take_damage(d, 0) - H.updatehealth() - else - src.take_bodypart_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/attack_animal(mob/living/simple_animal/M) - ..() - if(istype(M,/mob/living/simple_animal/headcrab)) - var/mob/living/simple_animal/headcrab/crab = M - crab.Infect(src) - return TRUE - return FALSE - -/mob/living/carbon/gib() - 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/MiddleClickOn(atom/A) - if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) - next_click = world.time + 5 - mind.changeling.chosen_sting.try_to_sting(src, A) - else - ..() - -/mob/living/carbon/AltClickOn(atom/A) - if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) - next_click = world.time + 5 - mind.changeling.chosen_sting.try_to_sting(src, A) - else - ..() - -/mob/living/carbon/attack_hand(mob/M) - if(!iscarbon(M)) - return - - 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_paw(mob/M) - if(!iscarbon(M)) - return - - 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/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, def_zone = null, tesla_shock = 0) - if(status_flags & GODMODE) return 0 //godmode - - var/turf/T = get_turf(src) - var/obj/effect/fluid/F = locate() in T - if(F) - attack_log += "\[[time_stamp()]\] [src] was shocked by the [source] and started chain-reaction with water!" - msg_admin_attack("[key_name(src)] was shocked by the [source] and started chain-reaction with water! [ADMIN_JMP(src)]") - F.electrocute_act(shock_damage) - - shock_damage *= siemens_coeff - if(shock_damage<1) - return 0 - apply_damage(shock_damage, BURN, def_zone, used_weapon="Electrocution") - playsound(loc, "sparks", 50, 1, -1) - if(shock_damage > 10) - visible_message( - "[src] was shocked by the [source]!", \ - "You feel a powerful shock course through your body!", \ - "You hear a heavy electrical crack." \ - ) - make_jittery(1000) - stuttering += 2 - if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) - Stun(2) - spawn(20) - jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less - if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) - Stun(8) - Weaken(8) - else - visible_message( - "[src] was mildly shocked by the [source].", \ - "You feel a mild shock course through your body.", \ - "You hear a light zapping." \ - ) - return shock_damage - - -/mob/living/carbon/proc/swap_hand() - var/obj/item/item_in_hand = src.get_active_hand() - if(item_in_hand) //this segment checks if the item in your hand is twohanded. - if(istype(item_in_hand, /obj/item/weapon/twohanded) || istype(item_in_hand, /obj/item/weapon/gun/projectile/automatic/l6_saw)) //OOP? Generics? Hue hue hue hue ... - if(item_in_hand:wielded) - to_chat(usr, "Your other hand is too busy holding the [item_in_hand.name]") - return - 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_l_active" - hud_used.r_hand_hud_object.icon_state = "hand_r_inactive" - else - hud_used.l_hand_hud_object.icon_state = "hand_l_inactive" - hud_used.r_hand_hud_object.icon_state = "hand_r_active" - /*if (!( src.hand )) - src.hands.dir = NORTH - else - src.hands.dir = SOUTH*/ - return - -/mob/living/carbon/proc/activate_hand(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/obj/item/organ/external/BP in H.bodyparts) - var/status = "" - var/brutedamage = BP.brute_dam - var/burndamage = BP.burn_dam - if(halloss > 0) - if(prob(30)) - brutedamage += halloss - if(prob(30)) - burndamage += halloss - - if(brutedamage > 40) - status = "mangled" - else if(brutedamage > 20) - status = "bleeding" - else if(brutedamage > 0) - status = "bruised" - - 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(BP.status & ORGAN_DESTROYED) - status = "MISSING!" - if(BP.status & ORGAN_MUTATED) - status = "weirdly shapen." - if(status == "") - status = "OK" - src.show_message(text("\t []My [] is [].", status == "OK" ? "\blue " : "\red ", BP.name,status), 1) - - if(roundstart_quirks.len) - to_chat(src, "You have these traits: [get_trait_string()].") - - if(H.species && (H.species.name == SKELETON) && !H.w_uniform && !H.wear_suit) - H.play_xylophone() - else - 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) - - if(lying) - src.sleeping = max(0,src.sleeping-5) - if (!M.lying) - if(!src.sleeping) - src.resting = 0 - if(src.crawling) - if(crawl_can_use() && src.pass_flags & PASSCRAWL) - src.pass_flags ^= PASSCRAWL - src.crawling = 0 - M.visible_message("[M] shakes [src] trying to wake [t_him] up!", \ - "You shake [src] trying to wake [t_him] up!") - else - if(!src.sleeping) - M.visible_message("[M] cuddles with [src] to make [t_him] feel better!", \ - "You cuddle with [src] to make [t_him] feel better!") - else - M.visible_message("[M] gently touches [src] trying to wake [t_him] up!", \ - "You gently touch [src] trying to wake [t_him] up!") - else - M.visible_message("[M] hugs [src] to make [t_him] feel better!", \ - "You hug [src] to make [t_him] feel better!") - - AdjustParalysis(-3) - AdjustStunned(-3) - AdjustWeakened(-3) - - playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - -/mob/living/carbon/proc/crawl_can_use() - var/turf/T = get_turf(src) - if( (locate(/obj/structure/table) in T) || (locate(/obj/structure/stool/bed) in T) || (locate(/obj/structure/plasticflaps) in T)) - return FALSE - return TRUE - -/mob/living/carbon/var/crawl_getup = FALSE -/mob/living/carbon/proc/crawl() - set name = "Crawl" - set category = "IC" - - if( stat || weakened || stunned || paralysis || resting || sleeping || (status_flags & FAKEDEATH) || buckled) - return - if(crawl_getup) - return - - if(crawling) - crawl_getup = TRUE - if(do_after(src, 10, target = src)) - crawl_getup = FALSE - if(!crawl_can_use()) - playsound(loc, 'sound/weapons/tablehit1.ogg', 50, 1) - if(ishuman(src)) - var/mob/living/carbon/human/H = src - var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] - BP.take_damage(5, used_weapon = "Facepalm") // what?.. that guy was insane anyway. - else - take_overall_damage(5, used_weapon = "Table") - Stun(1) - to_chat(src, "Ouch!") - return - layer = 4.0 - else - crawl_getup = FALSE - return - else - if(!crawl_can_use()) - to_chat(src, "You can't crawl here!") - return - layer = 3.9 - - pass_flags ^= PASSCRAWL - crawling = !crawling - - to_chat(src, "You are now [crawling ? "crawling" : "getting up"].") - update_canmove() - -/mob/living/carbon/proc/eyecheck() - return 0 - -/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash) - if(eyecheck() < intensity || override_blindness_check) - return ..() - -// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching. -// Stop! ... Hammertime! ~Carn - -/mob/living/carbon/proc/getDNA() - return dna - -/mob/living/carbon/proc/setDNA(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() - H.gloves.germ_level = 0 - else - if(H.bloody_hands) - H.bloody_hands = 0 - H.update_inv_gloves() - 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 - if(src.throw_icon) //in case we don't have the HUD and we use the hotkey - src.throw_icon.icon_state = "act_throw_off" - -/mob/living/carbon/proc/throw_mode_on() - src.in_throw_mode = 1 - if(src.throw_icon) - src.throw_icon.icon_state = "act_throw_on" - -/mob/proc/throw_item(atom/target) - return - -/mob/living/carbon/throw_item(atom/target) - src.throw_mode_off() - if(usr.stat || !target) - return - if(target.type == /obj/screen) return - - var/atom/movable/item = src.get_active_hand() - - if(!item || !item:canremove) return - - if (istype(item, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = item - item = G.throw_held() //throw the person instead of the grab - qdel(G) - 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]") - msg_admin_attack("[usr.name] ([usr.ckey]) has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor] (JMP)") - - if(!item) return //Grab processing has a chance of returning null - - src.remove_from_mob(item) - - //actually throw it! - if (item) - src.visible_message("[src] has thrown [item].") - - newtonian_move(get_dir(target, src)) - - item.throw_at(target, item.throw_range, item.throw_speed, src) - - if(ishuman(src)) - var/mob/living/carbon/human/H = src - if(H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/V = H.wear_suit - V.attack_reaction(H, REACTION_THROWITEM) - -/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(buckled && ! istype(buckled, /obj/structure/stool/bed/chair)) // buckling does not restrict hands - return 0 - return 1 - -/mob/living/carbon/restrained() - if (handcuffed) - return 1 - return - -/mob/living/carbon/u_equip(obj/item/W) - if(!W) return 0 - - else if (W == handcuffed) - handcuffed = null - update_inv_handcuffed() - if(buckled && buckled.buckle_require_restraints) - buckled.unbuckle_mob() - - else if (W == legcuffed) - legcuffed = null - update_inv_legcuffed() - else - ..() - - return - -/mob/living/carbon/show_inv(mob/living/carbon/user) - user.set_machine(src) - var/dat = {" -
                    [name]
                    -

                    -
                    Head(Mask):[(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"] -
                    Left Hand:[(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"] -
                    Right Hand:[(r_hand && !(r_hand.flags&ABSTRACT)) ? 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(entity_ja(dat), text("window=mob[];size=325x500", name)) - onclose(user, "mob[name]") - return - -//generates realistic-ish pulse output based on preset levels -/mob/living/carbon/proc/get_pulse(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(sleeping) - to_chat(src, "You are already sleeping") - return - if(alert(src, "You sure you want to sleep for a while?","Sleep","Yes","No") == "Yes") - sleeping = 20 //Short nap - -/mob/living/carbon/slip(slipped_on, stun_duration=4, weaken_duration=2) - if(buckled || sleeping || weakened || paralysis || stunned || resting || crawling) - return FALSE - stop_pulling() - to_chat(src, "You slipped on [slipped_on]!") - playsound(loc, 'sound/misc/slip.ogg', 50, 1, -3) - if (stun_duration > 0) - Stun(stun_duration) - if(weaken_duration > 0) - Weaken(weaken_duration) - return TRUE - -//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." - - var/mob/living/simple_animal/borer/B = has_brain_worms() - - if(!B) - return - - if(B.controlling) - 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 - verbs -= /mob/living/carbon/proc/spawn_larvae - -//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/proc/spawn_larvae() - set category = "Alien" - set name = "Reproduce" - set desc = "Spawn several young." - - var/mob/living/simple_animal/borer/B = has_brain_worms() - - if(!B) - return - - if(B.chemicals >= 100) - to_chat(src, "Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body.") - visible_message("[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") - B.chemicals -= 100 - - new /obj/effect/decal/cleanable/vomit(get_turf(src)) - playsound(loc, 'sound/effects/splat.ogg', 50, 1) - new /mob/living/simple_animal/borer(get_turf(src)) - - else - to_chat(src, "You do not have enough chemicals stored to reproduce.") - return - -/mob/living/carbon/proc/uncuff() - if(handcuffed) - var/obj/item/weapon/W = handcuffed - handcuffed = null - if(buckled && buckled.buckle_require_restraints) - buckled.unbuckle_mob() - update_inv_handcuffed() - if(client) - client.screen -= W - if(W) - W.loc = loc - W.dropped(src) - if(W) - W.layer = initial(W.layer) - W.plane = initial(W.plane) - if(legcuffed) - var/obj/item/weapon/W = legcuffed - legcuffed = null - update_inv_legcuffed() - if (client) - client.screen -= W - if (W) - W.loc = loc - W.dropped(src) - if(W) - W.layer = initial(W.layer) - W.plane = initial(W.plane) - -//-TG- port for smooth lying/standing animations -/mob/living/carbon/get_standard_pixel_y_offset(lying_current = 0) - if(lying) - if(buckled && istype(buckled, /obj/structure/stool/bed/roller)) - return 1 - else if(locate(/obj/structure/stool/bed/roller, src.loc)) - return -5 - else if(locate(/obj/machinery/optable, src.loc)||locate(/obj/structure/stool/bed, src.loc)) //we need special pixel shift for beds & optable to make mob lying centered - return -4 - else - return -6 - else - return initial(pixel_y) - -/mob/living/carbon/get_standard_pixel_x_offset(lying_current = 0) - if(lying) - if(locate(/obj/machinery/optable, src.loc)||locate(/obj/structure/stool/bed, src.loc)) //we need special pixel shift for beds & optable to make mob lying centered - switch(src.lying_current) - if(90) return 2 - if(270) return -2 - else - return initial(pixel_x) - -/mob/living/carbon/proc/bloody_hands(mob/living/source, amount = 2) - return - -/mob/living/carbon/proc/bloody_body(mob/living/source) - return - -/mob/living/carbon/proc/handle_phantom_move(NewLoc, direct) - if(!mind || !mind.changeling || length(mind.changeling.essences) < 1) - return - if(loc == NewLoc) - for(var/mob/living/parasite/essence/essence in mind.changeling.essences) - if(essence.phantom.showed) - essence.phantom.loc = get_turf(get_step(essence.phantom, direct)) - -/mob/living/carbon/proc/remove_passemotes_flag() - for(var/thing in src) - if(istype(thing, /obj/item/weapon/holder)) - return - if(istype(thing, /mob/living/carbon/monkey/diona)) - return - status_flags &= ~PASSEMOTES - -/mob/living/carbon/proc/can_eat(flags = 255) //I don't know how and why does it work - return TRUE - -/mob/living/carbon/proc/crawl_in_blood(obj/effect/decal/cleanable/blood/floor_blood) - return - -/mob/living/carbon/get_nutrition() - return nutrition + (reagents.get_reagent("nutriment") + reagents.get_reagent("plantmatter") + reagents.get_reagent("protein") + reagents.get_reagent("dairy")) * 2.5 // We multiply by this "magic" number, because all of these are equal to 2.5 nutrition. +/mob/living/carbon/atom_init() + . = ..() + carbon_list += src + +/mob/living/carbon/Destroy() + carbon_list -= src + return ..() + +/mob/living/carbon/Life() + ..() + + // Increase germ_level regularly + if(germ_level < GERM_LEVEL_AMBIENT && prob(80)) //if you're just standing there, you shouldn't get more germs beyond an ambient level + germ_level++ + +/mob/living/carbon/Move(NewLoc, direct) + . = ..() + if(.) + handle_phantom_move(NewLoc, direct) + if(nutrition && stat != DEAD) + nutrition -= metabolism_factor/100 + if(m_intent == "run") + nutrition -= metabolism_factor/100 + if((FAT in mutations) && m_intent == "run" && bodytemperature <= 360) + bodytemperature += 2 + + // Moving around increases germ_level faster + if(germ_level < GERM_LEVEL_MOVE_CAP && prob(8)) + germ_level++ + +/mob/living/carbon/relaymove(mob/user, direction) + if(isessence(user)) + user.setMoveCooldown(1) + var/mob/living/parasite/essence/essence = user + if(!(essence.flags_allowed & ESSENCE_PHANTOM)) + to_chat(user, "Your host forbrade you to own phantom") + return + + if(!essence.phantom.showed) + essence.phantom.show_phantom() + return + var/tile = get_turf(get_step(essence.phantom, direction)) + if(get_dist(tile, essence.host) < 8) + essence.phantom.dir = direction + essence.phantom.loc = tile + return + 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/obj/item/organ/external/BP = H.bodyparts_by_name[BP_CHEST] + BP.take_damage(d, 0) + H.updatehealth() + else + src.take_bodypart_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/attack_animal(mob/living/simple_animal/M) + ..() + if(istype(M,/mob/living/simple_animal/headcrab)) + var/mob/living/simple_animal/headcrab/crab = M + crab.Infect(src) + return TRUE + return FALSE + +/mob/living/carbon/gib() + 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/MiddleClickOn(atom/A) + if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) + next_click = world.time + 5 + mind.changeling.chosen_sting.try_to_sting(src, A) + else + ..() + +/mob/living/carbon/AltClickOn(atom/A) + if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) + next_click = world.time + 5 + mind.changeling.chosen_sting.try_to_sting(src, A) + else + ..() + +/mob/living/carbon/attack_hand(mob/M) + if(!iscarbon(M)) + return + + 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_paw(mob/M) + if(!iscarbon(M)) + return + + 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/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, def_zone = null, tesla_shock = 0) + if(status_flags & GODMODE) return 0 //godmode + + var/turf/T = get_turf(src) + var/obj/effect/fluid/F = locate() in T + if(F) + attack_log += "\[[time_stamp()]\] [src] was shocked by the [source] and started chain-reaction with water!" + msg_admin_attack("[key_name(src)] was shocked by the [source] and started chain-reaction with water! [ADMIN_JMP(src)]") + F.electrocute_act(shock_damage) + + shock_damage *= siemens_coeff + if(shock_damage<1) + return 0 + apply_damage(shock_damage, BURN, def_zone, used_weapon="Electrocution") + playsound(loc, "sparks", 50, 1, -1) + if(shock_damage > 10) + visible_message( + "[src] was shocked by the [source]!", \ + "You feel a powerful shock course through your body!", \ + "You hear a heavy electrical crack." \ + ) + make_jittery(1000) + stuttering += 2 + if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) + Stun(2) + spawn(20) + jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less + if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) + Stun(8) + Weaken(8) + else + visible_message( + "[src] was mildly shocked by the [source].", \ + "You feel a mild shock course through your body.", \ + "You hear a light zapping." \ + ) + return shock_damage + + +/mob/living/carbon/proc/swap_hand() + var/obj/item/item_in_hand = src.get_active_hand() + if(item_in_hand) //this segment checks if the item in your hand is twohanded. + if(istype(item_in_hand, /obj/item/weapon/twohanded) || istype(item_in_hand, /obj/item/weapon/gun/projectile/automatic/l6_saw)) //OOP? Generics? Hue hue hue hue ... + if(item_in_hand:wielded) + to_chat(usr, "Your other hand is too busy holding the [item_in_hand.name]") + return + 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_l_active" + hud_used.r_hand_hud_object.icon_state = "hand_r_inactive" + else + hud_used.l_hand_hud_object.icon_state = "hand_l_inactive" + hud_used.r_hand_hud_object.icon_state = "hand_r_active" + /*if (!( src.hand )) + src.hands.dir = NORTH + else + src.hands.dir = SOUTH*/ + return + +/mob/living/carbon/proc/activate_hand(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/obj/item/organ/external/BP in H.bodyparts) + var/status = "" + var/brutedamage = BP.brute_dam + var/burndamage = BP.burn_dam + if(halloss > 0) + if(prob(30)) + brutedamage += halloss + if(prob(30)) + burndamage += halloss + + if(brutedamage > 40) + status = "mangled" + else if(brutedamage > 20) + status = "bleeding" + else if(brutedamage > 0) + status = "bruised" + + 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(BP.status & ORGAN_DESTROYED) + status = "MISSING!" + if(BP.status & ORGAN_MUTATED) + status = "weirdly shapen." + if(status == "") + status = "OK" + src.show_message(text("\t []My [] is [].", status == "OK" ? "\blue " : "\red ", BP.name,status), 1) + + if(roundstart_quirks.len) + to_chat(src, "You have these traits: [get_trait_string()].") + + if(H.species && (H.species.name == SKELETON) && !H.w_uniform && !H.wear_suit) + H.play_xylophone() + else + 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) + + if(lying) + src.sleeping = max(0,src.sleeping-5) + if (!M.lying) + if(!src.sleeping) + src.resting = 0 + if(src.crawling) + if(crawl_can_use() && src.pass_flags & PASSCRAWL) + src.pass_flags ^= PASSCRAWL + src.crawling = 0 + M.visible_message("[M] shakes [src] trying to wake [t_him] up!", \ + "You shake [src] trying to wake [t_him] up!") + else + if(!src.sleeping) + M.visible_message("[M] cuddles with [src] to make [t_him] feel better!", \ + "You cuddle with [src] to make [t_him] feel better!") + else + M.visible_message("[M] gently touches [src] trying to wake [t_him] up!", \ + "You gently touch [src] trying to wake [t_him] up!") + else + M.visible_message("[M] hugs [src] to make [t_him] feel better!", \ + "You hug [src] to make [t_him] feel better!") + + AdjustParalysis(-3) + AdjustStunned(-3) + AdjustWeakened(-3) + + playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + +/mob/living/carbon/proc/crawl_can_use() + var/turf/T = get_turf(src) + if( (locate(/obj/structure/table) in T) || (locate(/obj/structure/stool/bed) in T) || (locate(/obj/structure/plasticflaps) in T)) + return FALSE + return TRUE + +/mob/living/carbon/var/crawl_getup = FALSE +/mob/living/carbon/proc/crawl() + set name = "Crawl" + set category = "IC" + + if( stat || weakened || stunned || paralysis || resting || sleeping || (status_flags & FAKEDEATH) || buckled) + return + if(crawl_getup) + return + + if(crawling) + crawl_getup = TRUE + if(do_after(src, 10, target = src)) + crawl_getup = FALSE + if(!crawl_can_use()) + playsound(loc, 'sound/weapons/tablehit1.ogg', 50, 1) + if(ishuman(src)) + var/mob/living/carbon/human/H = src + var/obj/item/organ/external/BP = H.bodyparts_by_name[BP_HEAD] + BP.take_damage(5, used_weapon = "Facepalm") // what?.. that guy was insane anyway. + else + take_overall_damage(5, used_weapon = "Table") + Stun(1) + to_chat(src, "Ouch!") + return + layer = 4.0 + else + crawl_getup = FALSE + return + else + if(!crawl_can_use()) + to_chat(src, "You can't crawl here!") + return + layer = 3.9 + + pass_flags ^= PASSCRAWL + crawling = !crawling + + to_chat(src, "You are now [crawling ? "crawling" : "getting up"].") + update_canmove() + +/mob/living/carbon/proc/eyecheck() + return 0 + +/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash) + if(eyecheck() < intensity || override_blindness_check) + return ..() + +// ++++ROCKDTBEN++++ MOB PROCS -- Ask me before touching. +// Stop! ... Hammertime! ~Carn + +/mob/living/carbon/proc/getDNA() + return dna + +/mob/living/carbon/proc/setDNA(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() + H.gloves.germ_level = 0 + else + if(H.bloody_hands) + H.bloody_hands = 0 + H.update_inv_gloves() + 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 + if(src.throw_icon) //in case we don't have the HUD and we use the hotkey + src.throw_icon.icon_state = "act_throw_off" + +/mob/living/carbon/proc/throw_mode_on() + src.in_throw_mode = 1 + if(src.throw_icon) + src.throw_icon.icon_state = "act_throw_on" + +/mob/proc/throw_item(atom/target) + return + +/mob/living/carbon/throw_item(atom/target) + src.throw_mode_off() + if(usr.stat || !target) + return + if(target.type == /obj/screen) return + + var/atom/movable/item = src.get_active_hand() + + if(!item || !item:canremove) return + + if (istype(item, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = item + item = G.throw_held() //throw the person instead of the grab + qdel(G) + 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]") + msg_admin_attack("[usr.name] ([usr.ckey]) has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor] (JMP)") + + if(!item) return //Grab processing has a chance of returning null + + src.remove_from_mob(item) + + //actually throw it! + if (item) + src.visible_message("[src] has thrown [item].") + + newtonian_move(get_dir(target, src)) + + item.throw_at(target, item.throw_range, item.throw_speed, src) + + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(H.wear_suit && istype(H.wear_suit, /obj/item/clothing/suit)) + var/obj/item/clothing/suit/V = H.wear_suit + V.attack_reaction(H, REACTION_THROWITEM) + +/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(buckled && ! istype(buckled, /obj/structure/stool/bed/chair)) // buckling does not restrict hands + return 0 + return 1 + +/mob/living/carbon/restrained() + if (handcuffed) + return 1 + return + +/mob/living/carbon/u_equip(obj/item/W) + if(!W) return 0 + + else if (W == handcuffed) + handcuffed = null + update_inv_handcuffed() + if(buckled && buckled.buckle_require_restraints) + buckled.unbuckle_mob() + + else if (W == legcuffed) + legcuffed = null + update_inv_legcuffed() + else + ..() + + return + +/mob/living/carbon/show_inv(mob/living/carbon/user) + user.set_machine(src) + var/dat = {" +
                    [name]
                    +

                    +
                    Head(Mask):[(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"] +
                    Left Hand:[(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"] +
                    Right Hand:[(r_hand && !(r_hand.flags&ABSTRACT)) ? 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(entity_ja(dat), text("window=mob[];size=325x500", name)) + onclose(user, "mob[name]") + return + +//generates realistic-ish pulse output based on preset levels +/mob/living/carbon/proc/get_pulse(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(sleeping) + to_chat(src, "You are already sleeping") + return + if(alert(src, "You sure you want to sleep for a while?","Sleep","Yes","No") == "Yes") + sleeping = 20 //Short nap + +/mob/living/carbon/slip(slipped_on, stun_duration=4, weaken_duration=2) + if(buckled || sleeping || weakened || paralysis || stunned || resting || crawling) + return FALSE + stop_pulling() + to_chat(src, "You slipped on [slipped_on]!") + playsound(loc, 'sound/misc/slip.ogg', 50, 1, -3) + if (stun_duration > 0) + Stun(stun_duration) + if(weaken_duration > 0) + Weaken(weaken_duration) + return TRUE + +//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." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.controlling) + 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 + verbs -= /mob/living/carbon/proc/spawn_larvae + +//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/proc/spawn_larvae() + set category = "Alien" + set name = "Reproduce" + set desc = "Spawn several young." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.chemicals >= 100) + to_chat(src, "Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body.") + visible_message("[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") + B.chemicals -= 100 + + new /obj/effect/decal/cleanable/vomit(get_turf(src)) + playsound(loc, 'sound/effects/splat.ogg', 50, 1) + new /mob/living/simple_animal/borer(get_turf(src)) + + else + to_chat(src, "You do not have enough chemicals stored to reproduce.") + return + +/mob/living/carbon/proc/uncuff() + if(handcuffed) + var/obj/item/weapon/W = handcuffed + handcuffed = null + if(buckled && buckled.buckle_require_restraints) + buckled.unbuckle_mob() + update_inv_handcuffed() + if(client) + client.screen -= W + if(W) + W.loc = loc + W.dropped(src) + if(W) + W.layer = initial(W.layer) + W.plane = initial(W.plane) + if(legcuffed) + var/obj/item/weapon/W = legcuffed + legcuffed = null + update_inv_legcuffed() + if (client) + client.screen -= W + if (W) + W.loc = loc + W.dropped(src) + if(W) + W.layer = initial(W.layer) + W.plane = initial(W.plane) + +//-TG- port for smooth lying/standing animations +/mob/living/carbon/get_standard_pixel_y_offset(lying_current = 0) + if(lying) + if(buckled && istype(buckled, /obj/structure/stool/bed/roller)) + return 1 + else if(locate(/obj/structure/stool/bed/roller, src.loc)) + return -5 + else if(locate(/obj/machinery/optable, src.loc)||locate(/obj/structure/stool/bed, src.loc)) //we need special pixel shift for beds & optable to make mob lying centered + return -4 + else + return -6 + else + return initial(pixel_y) + +/mob/living/carbon/get_standard_pixel_x_offset(lying_current = 0) + if(lying) + if(locate(/obj/machinery/optable, src.loc)||locate(/obj/structure/stool/bed, src.loc)) //we need special pixel shift for beds & optable to make mob lying centered + switch(src.lying_current) + if(90) return 2 + if(270) return -2 + else + return initial(pixel_x) + +/mob/living/carbon/proc/bloody_hands(mob/living/source, amount = 2) + return + +/mob/living/carbon/proc/bloody_body(mob/living/source) + return + +/mob/living/carbon/proc/handle_phantom_move(NewLoc, direct) + if(!mind || !mind.changeling || length(mind.changeling.essences) < 1) + return + if(loc == NewLoc) + for(var/mob/living/parasite/essence/essence in mind.changeling.essences) + if(essence.phantom.showed) + essence.phantom.loc = get_turf(get_step(essence.phantom, direct)) + +/mob/living/carbon/proc/remove_passemotes_flag() + for(var/thing in src) + if(istype(thing, /obj/item/weapon/holder)) + return + if(istype(thing, /mob/living/carbon/monkey/diona)) + return + status_flags &= ~PASSEMOTES + +/mob/living/carbon/proc/can_eat(flags = 255) //I don't know how and why does it work + return TRUE + +/mob/living/carbon/proc/crawl_in_blood(obj/effect/decal/cleanable/blood/floor_blood) + return + +/mob/living/carbon/get_nutrition() + return nutrition + (reagents.get_reagent("nutriment") + reagents.get_reagent("plantmatter") + reagents.get_reagent("protein") + reagents.get_reagent("dairy")) * 2.5 // We multiply by this "magic" number, because all of these are equal to 2.5 nutrition. diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 61d1921d9d4c..d770019e0ec4 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -1,39 +1,39 @@ -/mob/living/carbon/ - gender = MALE - var/list/stomach_contents = list() - var/brain_op_stage = 0.0 - var/chest_brain_op_stage = 0 - 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/oxygen_alert = 0 - var/phoron_alert = 0 - var/fire_alert = 0 - var/pressure_alert = 0 - var/temperature_alert = 0 - var/co2overloadtime = null - var/temperature_resistance = T0C+75 - - var/metabolism_factor = METABOLISM_FACTOR - - var/obj/item/head - var/obj/item/shoes - var/obj/item/neck - var/obj/item/mouth - - var/stamina = 100 //Ian uses this for now. +/mob/living/carbon/ + gender = MALE + var/list/stomach_contents = list() + var/brain_op_stage = 0.0 + var/chest_brain_op_stage = 0 + 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/oxygen_alert = 0 + var/phoron_alert = 0 + var/fire_alert = 0 + var/pressure_alert = 0 + var/temperature_alert = 0 + var/co2overloadtime = null + var/temperature_resistance = T0C+75 + + var/metabolism_factor = METABOLISM_FACTOR + + var/obj/item/head + var/obj/item/shoes + var/obj/item/neck + var/obj/item/mouth + + var/stamina = 100 //Ian uses this for now. diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 69845be92723..3dbc9941dbeb 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -1,148 +1,148 @@ -/mob/living/carbon/human/gib() - death(1) - var/atom/movable/overlay/animation = null - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - animation = new(loc) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - - for(var/obj/item/organ/external/BP in bodyparts) - // Only make the limb drop if it's not too damaged - if(prob(100 - BP.get_damage())) - // Override the current limb status and don't cause an explosion - BP.droplimb(TRUE, null, DROPLIMB_EDGE) - - flick("gibbed-h", animation) - if(species) - hgibs(loc, viruses, dna, species.flesh_color, species.blood_color) - else - hgibs(loc, viruses, dna) - - spawn(15) - if(animation) qdel(animation) - if(src) qdel(src) - -/mob/living/carbon/human/dust() - death(1) - var/atom/movable/overlay/animation = null - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - animation = new(loc) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - - flick("dust-h", animation) - new /obj/effect/decal/remains/human(loc) - - spawn(15) - if(animation) qdel(animation) - if(src) qdel(src) - - -/mob/living/carbon/human/death(gibbed) - if(stat == DEAD) return - if(healths) healths.icon_state = "health5" - - stat = DEAD - dizziness = 0 - jitteriness = 0 - dog_owner = null - - update_health_hud() - handle_hud_list() - - //Handle species-specific deaths. - if(species) species.handle_death(src) - - //Handle brain slugs. - var/obj/item/organ/external/BP = bodyparts_by_name[BP_HEAD] - var/mob/living/simple_animal/borer/B - - for(var/I in BP.implants) - if(istype(I,/mob/living/simple_animal/borer)) - B = I - if(B) - if(!B.ckey && ckey && B.controlling) - 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 - - var/datum/game_mode/mutiny/mode = get_mutiny_mode() - if(mode) - mode.infected_killed(src) - mode.body_count.Add(mind) - - //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. - //world << "Vox kills: [vox_kills]" - vox_kills++ //Bad vox. Shouldn't be killing humans. - - if(!gibbed) - emote("deathgasp") //let the world KNOW WE ARE DEAD - - update_canmove() - - if(is_infected_with_zombie_virus()) - handle_infected_death(src) - - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) - 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(!species || (species.name == SKELETON)) - return - if(f_style) - f_style = "Shaved" - if(h_style) - h_style = "Bald" - - set_species(SKELETON) - status_flags |= DISFIGURED - regenerate_icons() - return - -/mob/living/carbon/human/proc/ChangeToHusk() - if(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() - mutations.Add(HUSK) - status_flags |= DISFIGURED //makes them unknown without fucking up other stuff like admintools - update_body() - update_mutantrace() - return - -/mob/living/carbon/human/proc/Drain() - if(fake_death) - fake_death = 0 - ChangeToHusk() - mutations.Add(NOCLONE) - return +/mob/living/carbon/human/gib() + death(1) + var/atom/movable/overlay/animation = null + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + animation = new(loc) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + + for(var/obj/item/organ/external/BP in bodyparts) + // Only make the limb drop if it's not too damaged + if(prob(100 - BP.get_damage())) + // Override the current limb status and don't cause an explosion + BP.droplimb(TRUE, null, DROPLIMB_EDGE) + + flick("gibbed-h", animation) + if(species) + hgibs(loc, viruses, dna, species.flesh_color, species.blood_color) + else + hgibs(loc, viruses, dna) + + spawn(15) + if(animation) qdel(animation) + if(src) qdel(src) + +/mob/living/carbon/human/dust() + death(1) + var/atom/movable/overlay/animation = null + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + animation = new(loc) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + + flick("dust-h", animation) + new /obj/effect/decal/remains/human(loc) + + spawn(15) + if(animation) qdel(animation) + if(src) qdel(src) + + +/mob/living/carbon/human/death(gibbed) + if(stat == DEAD) return + if(healths) healths.icon_state = "health5" + + stat = DEAD + dizziness = 0 + jitteriness = 0 + dog_owner = null + + update_health_hud() + handle_hud_list() + + //Handle species-specific deaths. + if(species) species.handle_death(src) + + //Handle brain slugs. + var/obj/item/organ/external/BP = bodyparts_by_name[BP_HEAD] + var/mob/living/simple_animal/borer/B + + for(var/I in BP.implants) + if(istype(I,/mob/living/simple_animal/borer)) + B = I + if(B) + if(!B.ckey && ckey && B.controlling) + 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 + + var/datum/game_mode/mutiny/mode = get_mutiny_mode() + if(mode) + mode.infected_killed(src) + mode.body_count.Add(mind) + + //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. + //world << "Vox kills: [vox_kills]" + vox_kills++ //Bad vox. Shouldn't be killing humans. + + if(!gibbed) + emote("deathgasp") //let the world KNOW WE ARE DEAD + + update_canmove() + + if(is_infected_with_zombie_virus()) + handle_infected_death(src) + + tod = worldtime2text() //weasellos time of death patch + if(mind) mind.store_memory("Time of death: [tod]", 0) + 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(!species || (species.name == SKELETON)) + return + if(f_style) + f_style = "Shaved" + if(h_style) + h_style = "Bald" + + set_species(SKELETON) + status_flags |= DISFIGURED + regenerate_icons() + return + +/mob/living/carbon/human/proc/ChangeToHusk() + if(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() + mutations.Add(HUSK) + status_flags |= DISFIGURED //makes them unknown without fucking up other stuff like admintools + update_body() + update_mutantrace() + return + +/mob/living/carbon/human/proc/Drain() + if(fake_death) + fake_death = 0 + ChangeToHusk() + mutations.Add(NOCLONE) + return diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 6595cadfa867..de27b9ad5975 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -1,619 +1,619 @@ -/mob/living/carbon/human/emote(act,m_type=1,message = null, auto) - var/param = null - var/virus_scream = FALSE - - 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(wear_mask, /obj/item/clothing/mask/muzzle) - //var/m_type = 1 - - for (var/obj/item/weapon/implant/I in src) - if (I.implanted) - I.trigger(act, src) - - if(stat == DEAD && (act != "deathgasp")) - return - - var/cloud_emote = "" - - switch(act) - if ("airguitar") - if (!src.restrained()) - message = "[src] is strumming the air and headbanging like a safari chimp." - m_type = 1 - - if ("blink") - message = "[src] blinks." - m_type = 1 - - if ("blink_r") - message = "[src] blinks rapidly." - 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 ("custom") - var/input = sanitize(input("Choose an emote to display.") as text|null) - if (!input) - return - var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable") - if (input2 == "Visible") - m_type = 1 - else if (input2 == "Hearable") - if (src.miming) - return - m_type = 2 - else - alert("Unable to use this emote, must be either hearable or visible.") - return - return custom_emote(m_type, message) - - if ("me") - - //if(silent && silent > 0 && findtext(message,"\"",1, null) > 0) - // return //This check does not work and I have no idea why, I'm leaving it in for reference. - - if (src.client) - if (client.prefs.muted & MUTE_IC) - to_chat(src, "\red 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.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 ("choke") - if(miming) - message = "[src] clutches his throat desperately!" - m_type = 1 - else - if (!muzzled) - message = "[src] chokes!" - m_type = 2 - else - message = "[src] makes a strong noise." - m_type = 2 - - if ("clap") - if (!src.restrained()) - message = "[src] claps." - m_type = 2 - if(miming) - m_type = 1 - if ("flap") - if (!src.restrained()) - message = "[src] flaps his wings." - m_type = 2 - if(miming) - m_type = 1 - - if ("aflap") - if (!src.restrained()) - message = "[src] flaps his wings ANGRILY!" - m_type = 2 - if(miming) - m_type = 1 - - if ("drool") - message = "[src] drools." - m_type = 1 - - if ("eyebrow") - message = "[src] raises an eyebrow." - m_type = 1 - - if ("chuckle") - if(miming) - message = "[src] appears to chuckle." - m_type = 1 - else - if (!muzzled) - message = "[src] chuckles." - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - if ("twitch") - message = "[src] twitches violently." - m_type = 1 - - if ("twitch_s") - message = "[src] twitches." - m_type = 1 - - if ("faint") - message = "[src] faints." - if(src.sleeping) - return //Can't faint while asleep - src.sleeping += 10 //Short-short nap - m_type = 1 - - if ("cough") - if(miming) - message = "[src] appears to cough!" - m_type = 1 - else - if (!muzzled) - if (!(get_species() == DIONA)) - message = "[src] coughs!" - m_type = 2 - else - message = "[src] creaks!" - m_type = 2 - else - message = "[src] makes a strong noise." - m_type = 2 - - if ("frown") - message = "[src] frowns." - m_type = 1 - - if ("nod") - message = "[src] nods." - m_type = 1 - - if ("blush") - message = "[src] blushes." - m_type = 1 - - if ("wave") - message = "[src] waves." - m_type = 1 - - if ("gasp") - if(miming) - message = "[src] appears to be gasping!" - m_type = 1 - else - if (!muzzled) - message = "[src] [message ? message : "gasps!"]" - m_type = 2 - else - message = "[src] makes a weak noise." - m_type = 2 - - cloud_emote = "cloud-gasp" - - if ("deathgasp") - message = "[src] seizes up and falls limp, \his eyes dead and lifeless..." - m_type = 1 - - if ("giggle") - if(miming) - message = "[src] giggles silently!" - m_type = 1 - else - if (!muzzled) - message = "[src] giggles." - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - 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 - - if ("grin") - message = "[src] grins." - m_type = 1 - - if ("cry") - if(miming) - message = "[src] cries." - m_type = 1 - else - if (!muzzled) - message = "[src] cries." - m_type = 2 - else - message = "[src] makes a weak noise. \He frowns." - m_type = 2 - - if ("sigh") - if(miming) - message = "[src] sighs." - m_type = 1 - else - if (!muzzled) - message = "[src] sighs." - m_type = 2 - else - message = "[src] makes a weak noise." - m_type = 2 - - if ("laugh") - if(miming) - message = "[src] acts out a laugh." - m_type = 1 - else - if (!muzzled) - message = "[src] laughs." - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - if ("mumble") - message = "[src] mumbles!" - m_type = 2 - if(miming) - m_type = 1 - - if ("grumble") - if(miming) - message = "[src] grumbles!" - m_type = 1 - if (!muzzled) - message = "[src] grumbles!" - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - if ("groan") - if(miming) - message = "[src] appears to groan!" - m_type = 1 - else - if (!muzzled) - message = "[src] groans!" - m_type = 2 - else - message = "[src] makes a loud noise." - m_type = 2 - - if ("moan") - if(miming) - message = "[src] appears to moan!" - m_type = 1 - else - message = "[src] moans!" - m_type = 2 - - 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 = 1 - 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 = 2 - - if ("point") - if (!restrained()) - var/atom/target = null - if (param) - for (var/atom/A as mob|obj|turf in oview()) - if (param == A.name) - target = A - break - if (!target) - message = "[src] points." - else - pointed(target) - m_type = 1 - - if ("raise") - if (!src.restrained()) - message = "[src] raises a hand." - m_type = 1 - - if("shake") - message = "[src] shakes \his head." - m_type = 1 - - if ("shrug") - message = "[src] shrugs." - m_type = 1 - - 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 = 1 - - if ("smile") - message = "[src] smiles." - m_type = 1 - - if ("shiver") - message = "[src] shivers." - m_type = 2 - if(miming) - m_type = 1 - - if ("pale") - message = "[src] goes pale for a second." - m_type = 1 - - if ("tremble") - message = "[src] trembles in fear!" - m_type = 1 - - if ("sneeze") - if (miming) - message = "[src] sneezes." - m_type = 1 - else - if (!muzzled) - message = "[src] sneezes." - m_type = 2 - else - message = "[src] makes a strange noise." - m_type = 2 - - if ("sniff") - message = "[src] sniffs." - m_type = 2 - if(miming) - m_type = 1 - - if ("snore") - if (miming) - message = "[src] sleeps soundly." - m_type = 1 - else - if (!muzzled) - message = "[src] snores." - m_type = 2 - else - message = "[src] makes a noise." - m_type = 2 - - if ("whimper") - if (miming) - message = "[src] appears hurt." - m_type = 1 - else - if (!muzzled) - message = "[src] whimpers." - m_type = 2 - else - message = "[src] makes a weak noise." - m_type = 2 - - if ("wink") - message = "[src] winks." - m_type = 1 - - if ("yawn") - if (!muzzled) - message = "[src] yawns." - m_type = 2 - if(miming) - m_type = 1 - - if ("collapse") - Paralyse(2) - message = "[src] collapses!" - m_type = 2 - if(miming) - m_type = 1 - - if("hug") - m_type = 1 - 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 = 1 - 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 = 1 - 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("pain") - if(!message) - if(miming) - message = "[src] appears to be in pain!" - m_type = 1 // Can't we get defines for these? - else - message = "[src] twists in pain." - m_type = 1 - - cloud_emote = "cloud-pain" - - if ("scream") - if(miming) - message = "[src] acts out a scream!" - m_type = 1 - else - virus_scream = locate(/datum/disease2/effect/scream, src) in virus2 - if(virus_scream || !(species && species.flags[NO_PAIN])) - if (!muzzled) - if (auto) - 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 (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 = 2 - lastScream = world.time - else - if(!message) - message = "[src] screams!" - m_type = 2 - else - message = "[src] makes a very loud noise." - m_type = 2 - - cloud_emote = "cloud-scream" - - 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 - to_chat(src, "\blue Unusable emote '[act]'. Say *help for a list.") - - if(message) - log_emote("[name]/[key] : [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 observer_list) - if(!M.client) - continue //skip leavers - if((M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) - M.show_message(message) - - - if (m_type & 1) - for (var/mob/O in get_mobs_in_view(world.view,src)) - O.show_message(message, m_type) - else if (m_type & 2) - for (var/mob/O in (hearers(src.loc, null) | get_mobs_in_view(world.view,src))) - O.show_message(message, m_type) - - if(cloud_emote) - var/image/emote_bubble = image('icons/mob/emote.dmi', src, cloud_emote, MOB_LAYER + 1) - flick_overlay(emote_bubble, clients, 30) - QDEL_IN(emote_bubble, 3 SECONDS) - -/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 = sanitize(input(usr, "This is [src]. \He is...", "Pose", null) as text) - -/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" - - flavor_text = sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text) +/mob/living/carbon/human/emote(act,m_type=1,message = null, auto) + var/param = null + var/virus_scream = FALSE + + 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(wear_mask, /obj/item/clothing/mask/muzzle) + //var/m_type = 1 + + for (var/obj/item/weapon/implant/I in src) + if (I.implanted) + I.trigger(act, src) + + if(stat == DEAD && (act != "deathgasp")) + return + + var/cloud_emote = "" + + switch(act) + if ("airguitar") + if (!src.restrained()) + message = "[src] is strumming the air and headbanging like a safari chimp." + m_type = 1 + + if ("blink") + message = "[src] blinks." + m_type = 1 + + if ("blink_r") + message = "[src] blinks rapidly." + 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 ("custom") + var/input = sanitize(input("Choose an emote to display.") as text|null) + if (!input) + return + var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable") + if (input2 == "Visible") + m_type = 1 + else if (input2 == "Hearable") + if (src.miming) + return + m_type = 2 + else + alert("Unable to use this emote, must be either hearable or visible.") + return + return custom_emote(m_type, message) + + if ("me") + + //if(silent && silent > 0 && findtext(message,"\"",1, null) > 0) + // return //This check does not work and I have no idea why, I'm leaving it in for reference. + + if (src.client) + if (client.prefs.muted & MUTE_IC) + to_chat(src, "\red 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.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 ("choke") + if(miming) + message = "[src] clutches his throat desperately!" + m_type = 1 + else + if (!muzzled) + message = "[src] chokes!" + m_type = 2 + else + message = "[src] makes a strong noise." + m_type = 2 + + if ("clap") + if (!src.restrained()) + message = "[src] claps." + m_type = 2 + if(miming) + m_type = 1 + if ("flap") + if (!src.restrained()) + message = "[src] flaps his wings." + m_type = 2 + if(miming) + m_type = 1 + + if ("aflap") + if (!src.restrained()) + message = "[src] flaps his wings ANGRILY!" + m_type = 2 + if(miming) + m_type = 1 + + if ("drool") + message = "[src] drools." + m_type = 1 + + if ("eyebrow") + message = "[src] raises an eyebrow." + m_type = 1 + + if ("chuckle") + if(miming) + message = "[src] appears to chuckle." + m_type = 1 + else + if (!muzzled) + message = "[src] chuckles." + m_type = 2 + else + message = "[src] makes a noise." + m_type = 2 + + if ("twitch") + message = "[src] twitches violently." + m_type = 1 + + if ("twitch_s") + message = "[src] twitches." + m_type = 1 + + if ("faint") + message = "[src] faints." + if(src.sleeping) + return //Can't faint while asleep + src.sleeping += 10 //Short-short nap + m_type = 1 + + if ("cough") + if(miming) + message = "[src] appears to cough!" + m_type = 1 + else + if (!muzzled) + if (!(get_species() == DIONA)) + message = "[src] coughs!" + m_type = 2 + else + message = "[src] creaks!" + m_type = 2 + else + message = "[src] makes a strong noise." + m_type = 2 + + if ("frown") + message = "[src] frowns." + m_type = 1 + + if ("nod") + message = "[src] nods." + m_type = 1 + + if ("blush") + message = "[src] blushes." + m_type = 1 + + if ("wave") + message = "[src] waves." + m_type = 1 + + if ("gasp") + if(miming) + message = "[src] appears to be gasping!" + m_type = 1 + else + if (!muzzled) + message = "[src] [message ? message : "gasps!"]" + m_type = 2 + else + message = "[src] makes a weak noise." + m_type = 2 + + cloud_emote = "cloud-gasp" + + if ("deathgasp") + message = "[src] seizes up and falls limp, \his eyes dead and lifeless..." + m_type = 1 + + if ("giggle") + if(miming) + message = "[src] giggles silently!" + m_type = 1 + else + if (!muzzled) + message = "[src] giggles." + m_type = 2 + else + message = "[src] makes a noise." + m_type = 2 + + 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 + + if ("grin") + message = "[src] grins." + m_type = 1 + + if ("cry") + if(miming) + message = "[src] cries." + m_type = 1 + else + if (!muzzled) + message = "[src] cries." + m_type = 2 + else + message = "[src] makes a weak noise. \He frowns." + m_type = 2 + + if ("sigh") + if(miming) + message = "[src] sighs." + m_type = 1 + else + if (!muzzled) + message = "[src] sighs." + m_type = 2 + else + message = "[src] makes a weak noise." + m_type = 2 + + if ("laugh") + if(miming) + message = "[src] acts out a laugh." + m_type = 1 + else + if (!muzzled) + message = "[src] laughs." + m_type = 2 + else + message = "[src] makes a noise." + m_type = 2 + + if ("mumble") + message = "[src] mumbles!" + m_type = 2 + if(miming) + m_type = 1 + + if ("grumble") + if(miming) + message = "[src] grumbles!" + m_type = 1 + if (!muzzled) + message = "[src] grumbles!" + m_type = 2 + else + message = "[src] makes a noise." + m_type = 2 + + if ("groan") + if(miming) + message = "[src] appears to groan!" + m_type = 1 + else + if (!muzzled) + message = "[src] groans!" + m_type = 2 + else + message = "[src] makes a loud noise." + m_type = 2 + + if ("moan") + if(miming) + message = "[src] appears to moan!" + m_type = 1 + else + message = "[src] moans!" + m_type = 2 + + 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 = 1 + 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 = 2 + + if ("point") + if (!restrained()) + var/atom/target = null + if (param) + for (var/atom/A as mob|obj|turf in oview()) + if (param == A.name) + target = A + break + if (!target) + message = "[src] points." + else + pointed(target) + m_type = 1 + + if ("raise") + if (!src.restrained()) + message = "[src] raises a hand." + m_type = 1 + + if("shake") + message = "[src] shakes \his head." + m_type = 1 + + if ("shrug") + message = "[src] shrugs." + m_type = 1 + + 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 = 1 + + if ("smile") + message = "[src] smiles." + m_type = 1 + + if ("shiver") + message = "[src] shivers." + m_type = 2 + if(miming) + m_type = 1 + + if ("pale") + message = "[src] goes pale for a second." + m_type = 1 + + if ("tremble") + message = "[src] trembles in fear!" + m_type = 1 + + if ("sneeze") + if (miming) + message = "[src] sneezes." + m_type = 1 + else + if (!muzzled) + message = "[src] sneezes." + m_type = 2 + else + message = "[src] makes a strange noise." + m_type = 2 + + if ("sniff") + message = "[src] sniffs." + m_type = 2 + if(miming) + m_type = 1 + + if ("snore") + if (miming) + message = "[src] sleeps soundly." + m_type = 1 + else + if (!muzzled) + message = "[src] snores." + m_type = 2 + else + message = "[src] makes a noise." + m_type = 2 + + if ("whimper") + if (miming) + message = "[src] appears hurt." + m_type = 1 + else + if (!muzzled) + message = "[src] whimpers." + m_type = 2 + else + message = "[src] makes a weak noise." + m_type = 2 + + if ("wink") + message = "[src] winks." + m_type = 1 + + if ("yawn") + if (!muzzled) + message = "[src] yawns." + m_type = 2 + if(miming) + m_type = 1 + + if ("collapse") + Paralyse(2) + message = "[src] collapses!" + m_type = 2 + if(miming) + m_type = 1 + + if("hug") + m_type = 1 + 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 = 1 + 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 = 1 + 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("pain") + if(!message) + if(miming) + message = "[src] appears to be in pain!" + m_type = 1 // Can't we get defines for these? + else + message = "[src] twists in pain." + m_type = 1 + + cloud_emote = "cloud-pain" + + if ("scream") + if(miming) + message = "[src] acts out a scream!" + m_type = 1 + else + virus_scream = locate(/datum/disease2/effect/scream, src) in virus2 + if(virus_scream || !(species && species.flags[NO_PAIN])) + if (!muzzled) + if (auto) + 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 (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 = 2 + lastScream = world.time + else + if(!message) + message = "[src] screams!" + m_type = 2 + else + message = "[src] makes a very loud noise." + m_type = 2 + + cloud_emote = "cloud-scream" + + 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 + to_chat(src, "\blue Unusable emote '[act]'. Say *help for a list.") + + if(message) + log_emote("[name]/[key] : [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 observer_list) + if(!M.client) + continue //skip leavers + if((M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null))) + M.show_message(message) + + + if (m_type & 1) + for (var/mob/O in get_mobs_in_view(world.view,src)) + O.show_message(message, m_type) + else if (m_type & 2) + for (var/mob/O in (hearers(src.loc, null) | get_mobs_in_view(world.view,src))) + O.show_message(message, m_type) + + if(cloud_emote) + var/image/emote_bubble = image('icons/mob/emote.dmi', src, cloud_emote, MOB_LAYER + 1) + flick_overlay(emote_bubble, clients, 30) + QDEL_IN(emote_bubble, 3 SECONDS) + +/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 = sanitize(input(usr, "This is [src]. \He is...", "Pose", null) as text) + +/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" + + flavor_text = sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 47a528049276..1cf9562b2b13 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -1,514 +1,514 @@ -/mob/living/carbon/human/examine(mob/user) - var/skipgloves = 0 - var/skipsuitstorage = 0 - var/skipjumpsuit = 0 - var/skipshoes = 0 - var/skipmask = 0 - var/skipears = 0 - var/skipeyes = 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 |= wear_mask.flags_inv & 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( skipjumpsuit && skipface ) //big suits/masks/helmets make it hard to tell their gender - t_He = "They" - t_his = "their" - t_him = "them" - t_has = "have" - t_is = "are" - else - switch(gender) - if(MALE) - t_He = "He" - t_his = "his" - t_him = "him" - if(FEMALE) - t_He = "She" - t_his = "her" - t_him = "her" - - msg += "[src.name]" - if(!(skipface && skipjumpsuit)) - var/species_name = "\improper [get_species()]" - msg += ", \a [species_name]" - msg += "!\n" - - //uniform - if(w_uniform && !skipjumpsuit) - //Ties - var/list/ties = list() - if(istype(w_uniform,/obj/item/clothing/under)) - var/obj/item/clothing/under/U = w_uniform - for(var/accessory in U.accessories) - ties += "[bicon(accessory)] \a [accessory]" - var/tie_msg = ties.len ? ". Attached to it is [english_list(ties)]" : "" - - if(w_uniform.dirt_overlay) - msg += "[t_He] [t_is] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] [w_uniform.dirt_description()][tie_msg]!\n" - else if(w_uniform.wet) - msg += "[t_He] [t_is] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] wet [w_uniform.name][tie_msg]!\n" - else - msg += "[t_He] [t_is] wearing [bicon(w_uniform)] \a [w_uniform][tie_msg].\n" - - //head - if(head) - if(head.dirt_overlay) - msg += "[t_He] [t_is] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] [head.dirt_description()] on [t_his] head!\n" - else if(head.wet) - msg += "[t_He] [t_is] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] wet [head.name] on [t_his] head!\n" - else - msg += "[t_He] [t_is] wearing [bicon(head)] \a [head] on [t_his] head.\n" - - //suit/armour - if(wear_suit) - if(wear_suit.dirt_overlay) - msg += "[t_He] [t_is] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] [wear_suit.dirt_description()]!\n" - else if(wear_suit.wet) - msg += "[t_He] [t_is] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] wet [wear_suit.name]!\n" - else - msg += "[t_He] [t_is] wearing [bicon(wear_suit)] \a [wear_suit].\n" - - //suit/armour storage - if(s_store && !skipsuitstorage) - if(s_store.dirt_overlay) - msg += "[t_He] [t_is] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] [s_store.dirt_description()] on [t_his] [wear_suit.name]!\n" - else - msg += "[t_He] [t_is] carrying [bicon(s_store)] \a [s_store] on [t_his] [wear_suit.name].\n" - - //back - if(back) - if(back.dirt_overlay) - msg += "[t_He] [t_has] [bicon(back)] [back.gender==PLURAL?"some":"a"] [back.dirt_description()] on [t_his] back.\n" - else if(back.wet) - msg += "[t_He] [t_has] [bicon(back)] [back.gender==PLURAL?"some":"a"] wet [back] on [t_his] back.\n" - else - msg += "[t_He] [t_has] [bicon(back)] \a [back] on [t_his] back.\n" - - //left hand - if(l_hand && !(l_hand.flags&ABSTRACT)) - if(l_hand.dirt_overlay) - msg += "[t_He] [t_is] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] [l_hand.dirt_description()] in [t_his] left hand!\n" - else if(l_hand.wet) - msg += "[t_He] [t_is] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] wet [l_hand.name] in [t_his] left hand!\n" - else - msg += "[t_He] [t_is] holding [bicon(l_hand)] \a [l_hand] in [t_his] left hand.\n" - - //right hand - if(r_hand && !(r_hand.flags&ABSTRACT)) - if(r_hand.dirt_overlay) - msg += "[t_He] [t_is] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] [r_hand.dirt_description()] in [t_his] right hand!\n" - else if(r_hand.wet) - msg += "[t_He] [t_is] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] wet [r_hand.name] in [t_his] right hand!\n" - else - msg += "[t_He] [t_is] holding [bicon(r_hand)] \a [r_hand] in [t_his] right hand.\n" - - //gloves - if(gloves && !skipgloves) - if(gloves.dirt_overlay) - msg += "[t_He] [t_has] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] [gloves.dirt_description()] on [t_his] hands!\n" - else if(gloves.wet) - msg += "[t_He] [t_has] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] wet [gloves.name] on [t_his] hands!\n" - else - msg += "[t_He] [t_has] [bicon(gloves)] \a [gloves] on [t_his] hands.\n" - else if(hand_dirt_color) - msg += "[t_He] [t_has] [hand_dirt_color.name]-stained hands!\n" - - //handcuffed? - if(handcuffed) - if(istype(handcuffed, /obj/item/weapon/handcuffs/cable)) - msg += "[t_He] [t_is] [bicon(handcuffed)] restrained with cable!\n" - else - msg += "[t_He] [t_is] [bicon(handcuffed)] handcuffed!\n" - - //buckled - if(buckled) - msg += "[t_He] [t_is] [bicon(buckled)] buckled to [buckled]!\n" - - //belt - if(belt) - if(belt.dirt_overlay) - msg += "[t_He] [t_has] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] [belt.dirt_description()] about [t_his] waist!\n" - else if(belt.wet) - msg += "[t_He] [t_has] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] wet [belt.name] about [t_his] waist!\n" - else - msg += "[t_He] [t_has] [bicon(belt)] \a [belt] about [t_his] waist.\n" - - //shoes - if(shoes && !skipshoes) - if(shoes.dirt_overlay) - msg += "[t_He] [t_is] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] [shoes.dirt_description()] on [t_his] feet!\n" - else if(shoes.wet) - msg += "[t_He] [t_is] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] wet [shoes.name] on [t_his] feet!\n" - else - msg += "[t_He] [t_is] wearing [bicon(shoes)] \a [shoes] on [t_his] feet.\n" - else if(feet_dirt_color) - msg += "[t_He] [t_has] [feet_dirt_color.name]-stained feet!\n" - - //mask - if(wear_mask && !skipmask) - if(wear_mask.dirt_overlay) - msg += "[t_He] [t_has] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] [wear_mask.dirt_description()] on [t_his] face!\n" - else if(wear_mask.wet) - msg += "[t_He] [t_has] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] wet [wear_mask.name] on [t_his] face!\n" - else - msg += "[t_He] [t_has] [bicon(wear_mask)] \a [wear_mask] on [t_his] face.\n" - - //eyes - if(glasses && !skipeyes) - if(glasses.dirt_overlay) - msg += "[t_He] [t_has] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] [glasses.dirt_description()] covering [t_his] eyes!\n" - else if(glasses.wet) - msg += "[t_He] [t_has] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] wet [glasses] covering [t_his] eyes!\n" - else - msg += "[t_He] [t_has] [bicon(glasses)] \a [glasses] covering [t_his] eyes.\n" - - //left ear - if(l_ear && !skipears) - msg += "[t_He] [t_has] [bicon(l_ear)] \a [l_ear] on [t_his] left ear.\n" - - //right ear - if(r_ear && !skipears) - msg += "[t_He] [t_has] [bicon(r_ear)] \a [r_ear] on [t_his] right ear.\n" - - //ID - if(wear_id) - msg += "[t_He] [t_is] wearing [bicon(wear_id)] \a [wear_id].\n" - - //Jitters - if(is_jittery) - if(jitteriness >= 300) - msg += "[t_He] [t_is] convulsing violently!\n" - else if(jitteriness >= 200) - msg += "[t_He] [t_is] extremely jittery.\n" - else if(jitteriness >= 100) - msg += "[t_He] [t_is] twitching ever so slightly.\n" - - //splints - for(var/bodypart in list(BP_L_LEG , BP_R_LEG , BP_L_ARM , BP_R_ARM)) - var/obj/item/organ/external/BP = bodyparts_by_name[bodypart] - if(BP && BP.status & ORGAN_SPLINTED) - msg += "[t_He] [t_has] a splint on [t_his] [BP.name]!\n" - - if(suiciding) - msg += "[t_He] appears to have commited suicide... there is no hope of recovery.\n" - - if(SMALLSIZE in mutations) - msg += "[t_He] [t_is] small halfling!\n" - - var/distance = get_dist(user,src) - if(istype(user, /mob/dead/observer) || user.stat == DEAD) // ghosts can see anything - distance = 1 - if (src.stat || (iszombie(src) && (crawling || lying || resting))) - msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n" - if((stat == DEAD || src.losebreath || iszombie(src)) && distance <= 3) - msg += "[t_He] does not appear to be breathing.\n" - if(istype(user, /mob/living/carbon/human) && !user.stat && distance <= 1) - for(var/mob/O in viewers(user.loc, null)) - O.show_message("[user] checks [src]'s pulse.", 1) - spawn(15) - if(distance <= 1 && user && user.stat != UNCONSCIOUS) - if(pulse == PULSE_NONE) - 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) - msg += "[t_He] [t_is] severely malnourished.\n" - else if(nutrition >= 500) - msg += "[t_He] [t_is] quite chubby.\n" - - msg += "" - - if(stat == UNCONSCIOUS) - msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n" - else if(getBrainLoss() >= 60) - msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n" - - if(!key && brain_op_stage != 4 && stat != DEAD) - 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 && brain_op_stage != 4 && stat != DEAD) - msg += "[t_He] [t_has] suddenly fallen asleep.\n" - - var/list/wound_flavor_text = list() - var/list/is_destroyed = list() - var/list/is_bleeding = list() - var/applying_pressure = "" - - for(var/obj/item/organ/external/BP in bodyparts) - if(BP) - if(BP.status & ORGAN_DESTROYED) - is_destroyed["[BP.name]"] = 1 - wound_flavor_text["[BP.name]"] = "[t_He] is missing [t_his] [BP.name].\n" - continue - if(BP.applied_pressure) - if(BP.applied_pressure == src) - applying_pressure = "[t_He] is applying pressure to [t_his] [BP.name].
                    " - else - applying_pressure = "[BP.applied_pressure] is applying pressure to [t_his] [BP.name].
                    " - if(BP.status & ORGAN_ROBOT) - if(!(BP.brute_dam + BP.burn_dam)) - if(!species.flags[IS_SYNTHETIC]) - wound_flavor_text["[BP.name]"] = "[t_He] has a robot [BP.name]!\n" - continue - else - wound_flavor_text["[BP.name]"] = "[t_He] has a robot [BP.name], it has" - if(BP.brute_dam) - switch(BP.brute_dam) - if(0 to 20) - wound_flavor_text["[BP.name]"] += " some dents" - if(21 to INFINITY) - wound_flavor_text["[BP.name]"] += pick(" a lot of dents"," severe denting") - if(BP.brute_dam && BP.burn_dam) - wound_flavor_text["[BP.name]"] += " and" - if(BP.burn_dam) - switch(BP.burn_dam) - if(0 to 20) - wound_flavor_text["[BP.name]"] += " some burns" - if(21 to INFINITY) - wound_flavor_text["[BP.name]"] += pick(" a lot of burns"," severe melting") - if(wound_flavor_text["[BP.name]"]) - wound_flavor_text["[BP.name]"] += "!\n" - else if(BP.wounds.len > 0) - var/list/wound_descriptors = list() - for(var/datum/wound/W in BP.wounds) - var/this_wound_desc = W.desc - if(W.damage_type == BURN && W.salved) this_wound_desc = "salved [this_wound_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] [BP.name].
                    " - wound_flavor_text["[BP.name]"] = flavor_text_string - else - wound_flavor_text["[BP.name]"] = "" - if(BP.status & ORGAN_BLEEDING) - is_bleeding["[BP.name]"] = 1 - else - wound_flavor_text["[BP.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 their flesh!\n" - if(digitalcamo) - msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n" - if(mind && mind.changeling && mind.changeling.isabsorbing) - msg += "[t_He] sucking fluids from someone through a giant proboscis!\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"] - - msg += "Criminal status: \[[criminal]\]\n" - msg += "Security records: \[View\] \[Add comment\]\n" - - if(hasHUD(user,"medical")) - if(hasHUD(user,"security")) - msg += "---------\n" - 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"] - - msg += "Physical status: \[[medical]\]\n" - msg += "Medical records: \[View\] \[Add comment\]\n" - - - if(!skipface && print_flavor_text()) - msg += "[print_flavor_text()]\n" - - msg += "*---------*

                    " - if(applying_pressure) - msg += applying_pressure - else if(busy_with_action) - msg += "[t_He] is busy with something!
                    " - if (pose) - if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) - pose = addtext(pose,".") //Makes sure all emotes end with a period. - msg += "\n[t_He] is [pose]" - - //someone here, but who? - if(istype(user, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - if(H.species && H.species.name != ABDUCTOR) - for(var/obj/item/clothing/suit/armor/abductor/vest/V in list(wear_suit)) - if(V.stealth_active) - to_chat(H, "You can't focus your eyes on [src].") - return - - if(roundstart_quirks.len && isobserver(user)) - var/mob/dead/observer/O = user - if(O.started_as_observer) - msg += "[t_He] has these traits: [get_trait_string()]." - - 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, 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) || istype(H.glasses, /obj/item/clothing/glasses/sunglasses/hud/secmed) - if("medical") - return istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.glasses, /obj/item/clothing/glasses/sunglasses/hud/secmed) - else - return 0 - else if(istype(M, /mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = M - switch(hudtype) - if("security") - return istype(R.module_state_1, /obj/item/borg/sight/hud/sec) || istype(R.module_state_2, /obj/item/borg/sight/hud/sec) || istype(R.module_state_3, /obj/item/borg/sight/hud/sec) - if("medical") - return istype(R.module_state_1, /obj/item/borg/sight/hud/med) || istype(R.module_state_2, /obj/item/borg/sight/hud/med) || istype(R.module_state_3, /obj/item/borg/sight/hud/med) - else - return 0 - else - return 0 +/mob/living/carbon/human/examine(mob/user) + var/skipgloves = 0 + var/skipsuitstorage = 0 + var/skipjumpsuit = 0 + var/skipshoes = 0 + var/skipmask = 0 + var/skipears = 0 + var/skipeyes = 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 |= wear_mask.flags_inv & 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( skipjumpsuit && skipface ) //big suits/masks/helmets make it hard to tell their gender + t_He = "They" + t_his = "their" + t_him = "them" + t_has = "have" + t_is = "are" + else + switch(gender) + if(MALE) + t_He = "He" + t_his = "his" + t_him = "him" + if(FEMALE) + t_He = "She" + t_his = "her" + t_him = "her" + + msg += "[src.name]" + if(!(skipface && skipjumpsuit)) + var/species_name = "\improper [get_species()]" + msg += ", \a [species_name]" + msg += "!\n" + + //uniform + if(w_uniform && !skipjumpsuit) + //Ties + var/list/ties = list() + if(istype(w_uniform,/obj/item/clothing/under)) + var/obj/item/clothing/under/U = w_uniform + for(var/accessory in U.accessories) + ties += "[bicon(accessory)] \a [accessory]" + var/tie_msg = ties.len ? ". Attached to it is [english_list(ties)]" : "" + + if(w_uniform.dirt_overlay) + msg += "[t_He] [t_is] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] [w_uniform.dirt_description()][tie_msg]!\n" + else if(w_uniform.wet) + msg += "[t_He] [t_is] wearing [bicon(w_uniform)] [w_uniform.gender==PLURAL?"some":"a"] wet [w_uniform.name][tie_msg]!\n" + else + msg += "[t_He] [t_is] wearing [bicon(w_uniform)] \a [w_uniform][tie_msg].\n" + + //head + if(head) + if(head.dirt_overlay) + msg += "[t_He] [t_is] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] [head.dirt_description()] on [t_his] head!\n" + else if(head.wet) + msg += "[t_He] [t_is] wearing [bicon(head)] [head.gender==PLURAL?"some":"a"] wet [head.name] on [t_his] head!\n" + else + msg += "[t_He] [t_is] wearing [bicon(head)] \a [head] on [t_his] head.\n" + + //suit/armour + if(wear_suit) + if(wear_suit.dirt_overlay) + msg += "[t_He] [t_is] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] [wear_suit.dirt_description()]!\n" + else if(wear_suit.wet) + msg += "[t_He] [t_is] wearing [bicon(wear_suit)] [wear_suit.gender==PLURAL?"some":"a"] wet [wear_suit.name]!\n" + else + msg += "[t_He] [t_is] wearing [bicon(wear_suit)] \a [wear_suit].\n" + + //suit/armour storage + if(s_store && !skipsuitstorage) + if(s_store.dirt_overlay) + msg += "[t_He] [t_is] carrying [bicon(s_store)] [s_store.gender==PLURAL?"some":"a"] [s_store.dirt_description()] on [t_his] [wear_suit.name]!\n" + else + msg += "[t_He] [t_is] carrying [bicon(s_store)] \a [s_store] on [t_his] [wear_suit.name].\n" + + //back + if(back) + if(back.dirt_overlay) + msg += "[t_He] [t_has] [bicon(back)] [back.gender==PLURAL?"some":"a"] [back.dirt_description()] on [t_his] back.\n" + else if(back.wet) + msg += "[t_He] [t_has] [bicon(back)] [back.gender==PLURAL?"some":"a"] wet [back] on [t_his] back.\n" + else + msg += "[t_He] [t_has] [bicon(back)] \a [back] on [t_his] back.\n" + + //left hand + if(l_hand && !(l_hand.flags&ABSTRACT)) + if(l_hand.dirt_overlay) + msg += "[t_He] [t_is] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] [l_hand.dirt_description()] in [t_his] left hand!\n" + else if(l_hand.wet) + msg += "[t_He] [t_is] holding [bicon(l_hand)] [l_hand.gender==PLURAL?"some":"a"] wet [l_hand.name] in [t_his] left hand!\n" + else + msg += "[t_He] [t_is] holding [bicon(l_hand)] \a [l_hand] in [t_his] left hand.\n" + + //right hand + if(r_hand && !(r_hand.flags&ABSTRACT)) + if(r_hand.dirt_overlay) + msg += "[t_He] [t_is] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] [r_hand.dirt_description()] in [t_his] right hand!\n" + else if(r_hand.wet) + msg += "[t_He] [t_is] holding [bicon(r_hand)] [r_hand.gender==PLURAL?"some":"a"] wet [r_hand.name] in [t_his] right hand!\n" + else + msg += "[t_He] [t_is] holding [bicon(r_hand)] \a [r_hand] in [t_his] right hand.\n" + + //gloves + if(gloves && !skipgloves) + if(gloves.dirt_overlay) + msg += "[t_He] [t_has] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] [gloves.dirt_description()] on [t_his] hands!\n" + else if(gloves.wet) + msg += "[t_He] [t_has] [bicon(gloves)] [gloves.gender==PLURAL?"some":"a"] wet [gloves.name] on [t_his] hands!\n" + else + msg += "[t_He] [t_has] [bicon(gloves)] \a [gloves] on [t_his] hands.\n" + else if(hand_dirt_color) + msg += "[t_He] [t_has] [hand_dirt_color.name]-stained hands!\n" + + //handcuffed? + if(handcuffed) + if(istype(handcuffed, /obj/item/weapon/handcuffs/cable)) + msg += "[t_He] [t_is] [bicon(handcuffed)] restrained with cable!\n" + else + msg += "[t_He] [t_is] [bicon(handcuffed)] handcuffed!\n" + + //buckled + if(buckled) + msg += "[t_He] [t_is] [bicon(buckled)] buckled to [buckled]!\n" + + //belt + if(belt) + if(belt.dirt_overlay) + msg += "[t_He] [t_has] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] [belt.dirt_description()] about [t_his] waist!\n" + else if(belt.wet) + msg += "[t_He] [t_has] [bicon(belt)] [belt.gender==PLURAL?"some":"a"] wet [belt.name] about [t_his] waist!\n" + else + msg += "[t_He] [t_has] [bicon(belt)] \a [belt] about [t_his] waist.\n" + + //shoes + if(shoes && !skipshoes) + if(shoes.dirt_overlay) + msg += "[t_He] [t_is] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] [shoes.dirt_description()] on [t_his] feet!\n" + else if(shoes.wet) + msg += "[t_He] [t_is] wearing [bicon(shoes)] [shoes.gender==PLURAL?"some":"a"] wet [shoes.name] on [t_his] feet!\n" + else + msg += "[t_He] [t_is] wearing [bicon(shoes)] \a [shoes] on [t_his] feet.\n" + else if(feet_dirt_color) + msg += "[t_He] [t_has] [feet_dirt_color.name]-stained feet!\n" + + //mask + if(wear_mask && !skipmask) + if(wear_mask.dirt_overlay) + msg += "[t_He] [t_has] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] [wear_mask.dirt_description()] on [t_his] face!\n" + else if(wear_mask.wet) + msg += "[t_He] [t_has] [bicon(wear_mask)] [wear_mask.gender==PLURAL?"some":"a"] wet [wear_mask.name] on [t_his] face!\n" + else + msg += "[t_He] [t_has] [bicon(wear_mask)] \a [wear_mask] on [t_his] face.\n" + + //eyes + if(glasses && !skipeyes) + if(glasses.dirt_overlay) + msg += "[t_He] [t_has] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] [glasses.dirt_description()] covering [t_his] eyes!\n" + else if(glasses.wet) + msg += "[t_He] [t_has] [bicon(glasses)] [glasses.gender==PLURAL?"some":"a"] wet [glasses] covering [t_his] eyes!\n" + else + msg += "[t_He] [t_has] [bicon(glasses)] \a [glasses] covering [t_his] eyes.\n" + + //left ear + if(l_ear && !skipears) + msg += "[t_He] [t_has] [bicon(l_ear)] \a [l_ear] on [t_his] left ear.\n" + + //right ear + if(r_ear && !skipears) + msg += "[t_He] [t_has] [bicon(r_ear)] \a [r_ear] on [t_his] right ear.\n" + + //ID + if(wear_id) + msg += "[t_He] [t_is] wearing [bicon(wear_id)] \a [wear_id].\n" + + //Jitters + if(is_jittery) + if(jitteriness >= 300) + msg += "[t_He] [t_is] convulsing violently!\n" + else if(jitteriness >= 200) + msg += "[t_He] [t_is] extremely jittery.\n" + else if(jitteriness >= 100) + msg += "[t_He] [t_is] twitching ever so slightly.\n" + + //splints + for(var/bodypart in list(BP_L_LEG , BP_R_LEG , BP_L_ARM , BP_R_ARM)) + var/obj/item/organ/external/BP = bodyparts_by_name[bodypart] + if(BP && BP.status & ORGAN_SPLINTED) + msg += "[t_He] [t_has] a splint on [t_his] [BP.name]!\n" + + if(suiciding) + msg += "[t_He] appears to have commited suicide... there is no hope of recovery.\n" + + if(SMALLSIZE in mutations) + msg += "[t_He] [t_is] small halfling!\n" + + var/distance = get_dist(user,src) + if(istype(user, /mob/dead/observer) || user.stat == DEAD) // ghosts can see anything + distance = 1 + if (src.stat || (iszombie(src) && (crawling || lying || resting))) + msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n" + if((stat == DEAD || src.losebreath || iszombie(src)) && distance <= 3) + msg += "[t_He] does not appear to be breathing.\n" + if(istype(user, /mob/living/carbon/human) && !user.stat && distance <= 1) + for(var/mob/O in viewers(user.loc, null)) + O.show_message("[user] checks [src]'s pulse.", 1) + spawn(15) + if(distance <= 1 && user && user.stat != UNCONSCIOUS) + if(pulse == PULSE_NONE) + 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) + msg += "[t_He] [t_is] severely malnourished.\n" + else if(nutrition >= 500) + msg += "[t_He] [t_is] quite chubby.\n" + + msg += "" + + if(stat == UNCONSCIOUS) + msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n" + else if(getBrainLoss() >= 60) + msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n" + + if(!key && brain_op_stage != 4 && stat != DEAD) + 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 && brain_op_stage != 4 && stat != DEAD) + msg += "[t_He] [t_has] suddenly fallen asleep.\n" + + var/list/wound_flavor_text = list() + var/list/is_destroyed = list() + var/list/is_bleeding = list() + var/applying_pressure = "" + + for(var/obj/item/organ/external/BP in bodyparts) + if(BP) + if(BP.status & ORGAN_DESTROYED) + is_destroyed["[BP.name]"] = 1 + wound_flavor_text["[BP.name]"] = "[t_He] is missing [t_his] [BP.name].\n" + continue + if(BP.applied_pressure) + if(BP.applied_pressure == src) + applying_pressure = "[t_He] is applying pressure to [t_his] [BP.name].
                    " + else + applying_pressure = "[BP.applied_pressure] is applying pressure to [t_his] [BP.name].
                    " + if(BP.status & ORGAN_ROBOT) + if(!(BP.brute_dam + BP.burn_dam)) + if(!species.flags[IS_SYNTHETIC]) + wound_flavor_text["[BP.name]"] = "[t_He] has a robot [BP.name]!\n" + continue + else + wound_flavor_text["[BP.name]"] = "[t_He] has a robot [BP.name], it has" + if(BP.brute_dam) + switch(BP.brute_dam) + if(0 to 20) + wound_flavor_text["[BP.name]"] += " some dents" + if(21 to INFINITY) + wound_flavor_text["[BP.name]"] += pick(" a lot of dents"," severe denting") + if(BP.brute_dam && BP.burn_dam) + wound_flavor_text["[BP.name]"] += " and" + if(BP.burn_dam) + switch(BP.burn_dam) + if(0 to 20) + wound_flavor_text["[BP.name]"] += " some burns" + if(21 to INFINITY) + wound_flavor_text["[BP.name]"] += pick(" a lot of burns"," severe melting") + if(wound_flavor_text["[BP.name]"]) + wound_flavor_text["[BP.name]"] += "!\n" + else if(BP.wounds.len > 0) + var/list/wound_descriptors = list() + for(var/datum/wound/W in BP.wounds) + var/this_wound_desc = W.desc + if(W.damage_type == BURN && W.salved) this_wound_desc = "salved [this_wound_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] [BP.name].
                    " + wound_flavor_text["[BP.name]"] = flavor_text_string + else + wound_flavor_text["[BP.name]"] = "" + if(BP.status & ORGAN_BLEEDING) + is_bleeding["[BP.name]"] = 1 + else + wound_flavor_text["[BP.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 their flesh!\n" + if(digitalcamo) + msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n" + if(mind && mind.changeling && mind.changeling.isabsorbing) + msg += "[t_He] sucking fluids from someone through a giant proboscis!\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"] + + msg += "Criminal status: \[[criminal]\]\n" + msg += "Security records: \[View\] \[Add comment\]\n" + + if(hasHUD(user,"medical")) + if(hasHUD(user,"security")) + msg += "---------\n" + 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"] + + msg += "Physical status: \[[medical]\]\n" + msg += "Medical records: \[View\] \[Add comment\]\n" + + + if(!skipface && print_flavor_text()) + msg += "[print_flavor_text()]\n" + + msg += "*---------*

                    " + if(applying_pressure) + msg += applying_pressure + else if(busy_with_action) + msg += "[t_He] is busy with something!
                    " + if (pose) + if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) + pose = addtext(pose,".") //Makes sure all emotes end with a period. + msg += "\n[t_He] is [pose]" + + //someone here, but who? + if(istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + if(H.species && H.species.name != ABDUCTOR) + for(var/obj/item/clothing/suit/armor/abductor/vest/V in list(wear_suit)) + if(V.stealth_active) + to_chat(H, "You can't focus your eyes on [src].") + return + + if(roundstart_quirks.len && isobserver(user)) + var/mob/dead/observer/O = user + if(O.started_as_observer) + msg += "[t_He] has these traits: [get_trait_string()]." + + 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, 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) || istype(H.glasses, /obj/item/clothing/glasses/sunglasses/hud/secmed) + if("medical") + return istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.glasses, /obj/item/clothing/glasses/sunglasses/hud/secmed) + else + return 0 + else if(istype(M, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = M + switch(hudtype) + if("security") + return istype(R.module_state_1, /obj/item/borg/sight/hud/sec) || istype(R.module_state_2, /obj/item/borg/sight/hud/sec) || istype(R.module_state_3, /obj/item/borg/sight/hud/sec) + if("medical") + return istype(R.module_state_1, /obj/item/borg/sight/hud/med) || istype(R.module_state_2, /obj/item/borg/sight/hud/med) || istype(R.module_state_3, /obj/item/borg/sight/hud/med) + else + return 0 + else + return 0 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index a944e34918a8..36e2a6d9bd8a 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1,1772 +1,1772 @@ -/mob/living/carbon/human - name = "unknown" - real_name = "unknown" - voice_name = "unknown" - icon = 'icons/mob/human.dmi' - //icon_state = "body_m_s" - var/list/hud_list[9] - var/datum/species/species //Contains icon generation and language information, set during New(). - var/dog_owner - var/heart_beat = 0 - var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. - - var/scientist = 0 //Vars used in abductors checks and etc. Should be here because in species datums it changes globaly. - var/agent = 0 - var/team = 0 - var/metadata - var/seer = 0 // used in cult datum /cult/seer - - throw_range = 2 - -/mob/living/carbon/human/dummy - real_name = "Test Dummy" - status_flags = GODMODE|CANPUSH - -INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) - -/mob/living/carbon/human/skrell/atom_init(mapload) - h_style = "Skrell Male Tentacles" - . = ..(mapload, SKRELL) - -/mob/living/carbon/human/tajaran/atom_init(mapload) - h_style = "Tajaran Ears" - . = ..(mapload, TAJARAN) - -/mob/living/carbon/human/unathi/atom_init(mapload) - h_style = "Unathi Horns" - . = ..(mapload, UNATHI) - -/mob/living/carbon/human/vox/atom_init(mapload) - h_style = "Short Vox Quills" - . = ..(mapload, VOX) - -/mob/living/carbon/human/voxarmalis/atom_init(mapload) - h_style = "Bald" - . = ..(mapload, VOX_ARMALIS) - -/mob/living/carbon/human/diona/atom_init(mapload) - . = ..(mapload, DIONA) - -/mob/living/carbon/human/machine/atom_init(mapload) - h_style = "blue IPC screen" - . = ..(mapload, IPC) - -/mob/living/carbon/human/abductor/atom_init(mapload) - . = ..(mapload, ABDUCTOR) - -/mob/living/carbon/human/golem/atom_init(mapload) - . = ..(mapload, GOLEM) - -/mob/living/carbon/human/shadowling/atom_init(mapload) - . = ..(mapload, SHADOWLING) - var/newNameId = pick(possibleShadowlingNames) - possibleShadowlingNames.Remove(newNameId) - real_name = newNameId - name = real_name - - underwear = 0 - undershirt = 0 - faction = "faithless" - dna.mutantrace = "shadowling" - update_mutantrace() - regenerate_icons() - - spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind - spell_list += new /obj/effect/proc_holder/spell/targeted/enthrall - spell_list += new /obj/effect/proc_holder/spell/targeted/glare - spell_list += new /obj/effect/proc_holder/spell/aoe_turf/veil - spell_list += new /obj/effect/proc_holder/spell/targeted/shadow_walk - spell_list += new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze - spell_list += new /obj/effect/proc_holder/spell/targeted/collective_mind - spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor - -/mob/living/carbon/human/atom_init(mapload, new_species) - - dna = new - - if(!species) - if(new_species) - set_species(new_species, null, TRUE) - else - set_species() - - if(species) // Just to be sure. - metabolism_factor = species.metabolism_mod - butcher_results = species.butcher_drops - - dna.species = species.name - - var/datum/reagents/R = new/datum/reagents(1000) - reagents = R - R.my_atom = src - - hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudhealth100") - hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudhealthy") - hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudunknown") - hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[STATUS_HUD_OOC] = image('icons/mob/hud.dmi', src, "hudhealthy") - - . = ..() - - human_list += src - - if(dna) - dna.real_name = real_name - - handcrafting = new() - - verbs += /mob/living/carbon/proc/crawl - - prev_gender = gender // Debug for plural genders - make_blood() - regenerate_icons() - -/mob/living/carbon/human/Destroy() - human_list -= src - return ..() - -/mob/living/carbon/human/OpenCraftingMenu() - handcrafting.ui_interact(src) - -/mob/living/carbon/human/Stat() - ..() - - if(statpanel("Status")) - stat(null, "Intent: [a_intent]") - stat(null, "Move Mode: [m_intent]") - if(internal) - if(!internal.air_contents) - qdel(internal) - else - stat("Internal Atmosphere Info", internal.name) - stat("Tank Pressure", internal.air_contents.return_pressure()) - stat("Distribution Pressure", internal.distribute_pressure) - - CHANGELING_STATPANEL_STATS(null) - - if(istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)) - var/obj/item/clothing/suit/space/space_ninja/SN = wear_suit - stat("SpiderOS Status:","[SN.s_initialized ? "Initialized" : "Disabled"]") - stat("Current Time:", "[worldtime2text()]") - if(SN.s_initialized) - //Suit gear - stat("Energy Charge", "[round(SN.cell.charge/100)]%") - stat("Smoke Bombs:", "\Roman [SN.s_bombs]") - //Ninja status - stat("Fingerprints:", "[md5(dna.uni_identity)]") - stat("Unique Identity:", "[dna.unique_enzymes]") - stat("Overall Status:", "[stat > 1 ? "dead" : "[health]% healthy"]") - stat("Nutrition Status:", "[nutrition]") - stat("Oxygen Loss:", "[getOxyLoss()]") - stat("Toxin Levels:", "[getToxLoss()]") - stat("Burn Severity:", "[getFireLoss()]") - stat("Brute Trauma:", "[getBruteLoss()]") - stat("Radiation Levels:","[radiation] rad") - stat("Body Temperature:","[bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)") - - CHANGELING_STATPANEL_POWERS(null) - -/mob/living/carbon/human/ex_act(severity) - if(!blinded) - flash_eyes() - - var/shielded = 0 - var/b_loss = null - var/f_loss = null - switch (severity) - if (1.0) - b_loss += 500 - if (!prob(getarmor(null, "bomb"))) - gib() - return - else - var/atom/target = get_edge_target_turf(src, get_dir(src, get_step_away(src, src))) - throw_at(target, 200, 4) - //return -// var/atom/target = get_edge_target_turf(user, get_dir(src, get_step_away(user, src))) - //user.throw_at(target, 200, 4) - - if (2.0) - if (!shielded) - b_loss += 60 - - f_loss += 60 - - if (prob(getarmor(null, "bomb"))) - b_loss = b_loss/1.5 - f_loss = f_loss/1.5 - - if (!istype(l_ear, /obj/item/clothing/ears/earmuffs) && !istype(r_ear, /obj/item/clothing/ears/earmuffs)) - ear_damage += 30 - ear_deaf += 120 - if (prob(70) && !shielded) - Paralyse(10) - - if(3.0) - b_loss += 30 - if (prob(getarmor(null, "bomb"))) - b_loss = b_loss/2 - if (!istype(l_ear, /obj/item/clothing/ears/earmuffs) && !istype(r_ear, /obj/item/clothing/ears/earmuffs)) - ear_damage += 15 - ear_deaf += 60 - if (prob(50) && !shielded) - Paralyse(10) - - // focus most of the blast on one organ - var/obj/item/organ/external/BP = pick(bodyparts) - BP.take_damage(b_loss * 0.9, f_loss * 0.9, used_weapon = "Explosive blast") - - // distribute the remaining 10% on all limbs equally - b_loss *= 0.1 - f_loss *= 0.1 - - var/weapon_message = "Explosive Blast" - take_overall_damage(b_loss * 0.2, f_loss * 0.2, used_weapon = weapon_message) - -/mob/living/carbon/human/singularity_act() - var/gain = 20 - if(mind) - switch(mind.assigned_role) - if("Station Engineer","Chief Engineer") - gain = 100 - if("Clown") - gain = rand(-300, 300)//HONK - investigate_log(" has consumed [key_name(src)].","singulo") //Oh that's where the clown ended up! - gib() - return(gain) - -/mob/living/carbon/human/singularity_pull(S, current_size) - if(current_size >= STAGE_THREE) - var/list/handlist = list(l_hand, r_hand) - for(var/obj/item/hand in handlist) - if(prob(current_size * 5) && hand.w_class >= ((STAGE_FIVE-current_size)/2) && unEquip(hand)) - step_towards(hand, src) - to_chat(src, "\The [S] pulls \the [hand] from your grip!") - apply_effect(current_size * 3, IRRADIATE) - if(mob_negates_gravity())//Magboots protection - return - ..() - -/mob/living/carbon/human/blob_act() - if(stat == DEAD) return - to_chat(src, "\The blob attacks you!") - var/dam_zone = pick(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) - var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(dam_zone)] - apply_damage(rand(30, 40), BRUTE, BP, run_armor_check(BP, "melee")) - return - -/mob/living/carbon/human/meteorhit(O) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red [src] has been hit by [O]", 1) - if (health > 0) - var/obj/item/organ/external/BP = bodyparts_by_name[pick(BP_CHEST , BP_CHEST , BP_CHEST , BP_HEAD)] - if(!BP) - return - if (istype(O, /obj/effect/immovablerod)) - BP.take_damage(101, 0) - else - BP.take_damage((istype(O, /obj/effect/meteor/small) ? 10 : 25), 30) - updatehealth() - return - - -/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M) - if(..()) - 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) - visible_message("[M][M.attacktext] [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(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) - var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(dam_zone)] - var/armor = run_armor_check(BP, "melee") - apply_damage(damage, BRUTE, BP, armor) - if(armor >= 2) return - -/mob/living/carbon/human/attack_slime(mob/living/carbon/slime/M) - 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("\red The [M.name] glomps []!", src), 1) - - var/damage = rand(1, 3) - - if(istype(M, /mob/living/carbon/slime/adult)) - damage = rand(10, 35) - else - damage = rand(5, 25) - - - var/dam_zone = pick(BP_HEAD , BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG , BP_GROIN) - - var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(dam_zone)] - var/armor_block = run_armor_check(BP, "melee") - apply_damage(damage, BRUTE, BP, armor_block) - - - 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("\red 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/human/proc/can_use_two_hands(broken = TRUE) // Replace arms with hands in case of reverting Kurshan's PR. - var/obj/item/organ/external/l_arm/BPL = bodyparts_by_name[BP_L_ARM] - var/obj/item/organ/external/r_arm/BPR = bodyparts_by_name[BP_R_ARM] - if(broken && (BPL.is_broken() || BPR.is_broken())) - return FALSE - if(!BPL.is_usable() || !BPR.is_usable()) - return FALSE - return TRUE - -/mob/living/carbon/human/proc/wield(/obj/item/I, name, wieldsound = null) - if(!can_use_two_hands()) - to_chat(src, "You need both of your hands to be intact to do this.") - return FALSE - if(get_inactive_hand()) - to_chat(src, "You need your other hand to be empty to do this.") - return FALSE - to_chat(src, "You grab the [name] with both hands.") - if(wieldsound) - playsound(loc, wieldsound, 50, 1) - - if(hand) - update_inv_l_hand() - else - update_inv_r_hand() - - var/obj/item/weapon/twohanded/offhand/O = new(src) - O.name = "[name] - offhand" - O.desc = "Your second grip on the [name]" - put_in_inactive_hand(O) - return TRUE - -/mob/living/carbon/human/proc/is_type_organ(organ, o_type) - var/obj/item/organ/O - if(organ in organs_by_name) - O = organs_by_name[organ] - if(organ in bodyparts_by_name) - O = bodyparts_by_name[organ] - if(!O) - return FALSE - return istype(O, o_type) - -/mob/living/carbon/human/proc/is_bruised_organ(organ) - var/obj/item/organ/internal/IO = organs_by_name[organ] - if(!IO) - return TRUE - if(IO.is_bruised()) - return TRUE - return FALSE - -/mob/living/carbon/human/proc/find_damaged_bodypart() - for(var/obj/item/organ/external/BP in bodyparts) // find a broken/destroyed limb - if(BP.status & (ORGAN_DESTROYED | ORGAN_BROKEN | ORGAN_SPLINTED)) - if(BP.parent && (BP.parent.status & ORGAN_DESTROYED)) - continue - else - return BP - return FALSE // In case we didn't find anything. - -/mob/living/carbon/human/proc/regen_bodyparts(remove_blood_amount = 0, use_cost = FALSE) - if(vessel && regenerating_bodypart) // start fixing broken/destroyed limb - if(remove_blood_amount) - for(var/datum/reagent/blood/B in vessel.reagent_list) - B.volume -= remove_blood_amount - var/regenerating_capacity_penalty = 0 // Used as time till organ regeneration. - if(regenerating_bodypart.status & ORGAN_DESTROYED) - regenerating_capacity_penalty = regenerating_bodypart.regen_bodypart_penalty - else - regenerating_capacity_penalty = regenerating_bodypart.regen_bodypart_penalty/2 - regenerating_organ_time++ - switch(regenerating_organ_time) - if(1) - visible_message("You see odd movement in [src]'s [regenerating_bodypart.name]..."," You [species && species.flags[NO_PAIN] ? "notice" : "feel"] strange vibration on tips of your [regenerating_bodypart.name]... ") - if(10) - visible_message("You hear sickening crunch In [src]'s [regenerating_bodypart.name]...") - if(20) - visible_message("[src]'s [regenerating_bodypart.name] shortly bends...") - if(30) - if(regenerating_capacity_penalty == regenerating_bodypart.regen_bodypart_penalty/2) - visible_message("[src] stirs his [regenerating_bodypart.name]...","You [species && species.flags[NO_PAIN] ? "notice" : "feel"] freedom in moving your [regenerating_bodypart.name]") - else - visible_message("From [src]'s [regenerating_bodypart.parent.name] grows a small meaty sprout...") - if(50) - visible_message("You see something resembling [regenerating_bodypart.name] at [src]'s [regenerating_bodypart.parent.name]...") - if(65) - visible_message("A new [regenerating_bodypart.name] has grown from [src]'s [regenerating_bodypart.parent.name]!","You [species && species.flags[NO_PAIN] ? "notice" : "feel"] your [regenerating_bodypart.name] again!") - if(prob(50)) - emote("scream",1,null,1) - if(regenerating_organ_time >= regenerating_capacity_penalty) // recover organ - regenerating_bodypart.rejuvenate() - regenerating_organ_time = 0 - if(use_cost) - nutrition -= regenerating_capacity_penalty - regenerating_bodypart = null - update_body() - -/mob/living/carbon/human/restrained(check_type = ARMS) - if ((check_type & ARMS) && handcuffed) - return TRUE - if ((check_type & LEGS) && legcuffed) - return TRUE - if (istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) - return TRUE - if (istype(buckled, /obj/structure/stool/bed/nest)) - return TRUE - return 0 - -/mob/living/carbon/human/resist() - ..() - if(usr && !usr.incapacitated()) - var/mob/living/carbon/human/D = usr - if(D.get_species() == DIONA) - var/list/choices = list() - for(var/mob/living/carbon/monkey/diona/V in contents) - if(istype(V) && V.gestalt == src) - choices += V - var/mob/living/carbon/monkey/diona/V = input(D,"Who do wish you to expel from within?") in null|choices - if(V) - to_chat(D, "You wriggle [V] out of your insides.") - V.splitting(D) - -/mob/living/carbon/human/show_inv(mob/user) - var/obj/item/clothing/under/suit = null - if (istype(w_uniform, /obj/item/clothing/under)) - suit = w_uniform - - user.set_machine(src) - var/dat = {" -
                    [name]
                    -

                    -
                    Head(Mask): [(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"] -
                    Left Hand: [(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"] -
                    Right Hand: [(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "Nothing"] -
                    Gloves: [(gloves && !(gloves.flags&ABSTRACT)) ? gloves : "Nothing"] -
                    Eyes: [(glasses && !(glasses.flags&ABSTRACT)) ? glasses : "Nothing"] -
                    Left Ear: [(l_ear && !(l_ear.flags&ABSTRACT) ? l_ear : "Nothing")] -
                    Right Ear: [(r_ear && !(r_ear.flags&ABSTRACT) ? r_ear : "Nothing")] -
                    Head: [(head && !(head.flags&ABSTRACT)) ? head : "Nothing"] -
                    Shoes: [(shoes && !(shoes.flags&ABSTRACT)) ? shoes : "Nothing"] -
                    Belt: [(belt ? belt : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(belt, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] -
                    Uniform: [(w_uniform && !(w_uniform.flags&ABSTRACT)) ? w_uniform : "Nothing"] [(suit) ? ((suit.has_sensor == 1) ? text(" Sensors", src) : "") :] -
                    (Exo)Suit: [(wear_suit && !(wear_suit.flags&ABSTRACT)) ? wear_suit : "Nothing"] -
                    Back: [(back && !(back.flags&ABSTRACT)) ? back : "Nothing"] [((istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] -
                    ID: [(wear_id ? wear_id : "Nothing")] -
                    Suit Storage: [(s_store ? s_store : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(s_store, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] -
                    [(handcuffed ? text("Handcuffed") : text("Not Handcuffed"))] -
                    [(legcuffed ? text("Legcuffed") : text(""))] -
                    [(suit) ? ((suit.accessories.len) ? text(" Remove Accessory", src) : "") :] -
                    [(internal ? text("Remove Internal") : "")] -
                    Remove Bandages -
                    Remove Splints -
                    Empty Pockets -
                    Refresh -
                    Close -
                    "} - user << browse(entity_ja(dat), text("window=mob[name];size=340x540")) - onclose(user, "mob[name]") - return - -// called when something steps onto a human -// this could be made more general, but for now just handle mulebot -/mob/living/carbon/human/Crossed(var/atom/movable/AM) - var/obj/machinery/bot/mulebot/MB = AM - if(istype(MB)) - MB.RunOver(src) - -// Get rank from ID, ID inside PDA, PDA, ID in wallet, etc. -/mob/living/carbon/human/proc/get_authentification_rank(if_no_id = "No id", if_no_job = "No job") - var/obj/item/device/pda/pda = wear_id - if (istype(pda)) - if (pda.id) - return pda.id.rank - else - return pda.ownrank - else - var/obj/item/weapon/card/id/id = get_idcard() - if(id) - return id.rank ? id.rank : if_no_job - else - return if_no_id - -//gets assignment from ID or ID inside PDA or PDA itself -//Useful when player do something with computers -/mob/living/carbon/human/proc/get_assignment(if_no_id = "No id", if_no_job = "No job") - var/obj/item/device/pda/pda = wear_id - var/obj/item/weapon/card/id/id = wear_id - if (istype(pda)) - if (pda.id && istype(pda.id, /obj/item/weapon/card/id)) - . = pda.id.assignment - else - . = pda.ownjob - else if (istype(id)) - . = id.assignment - else - return if_no_id - if (!.) - . = if_no_job - return - -//gets name from ID or ID inside PDA or PDA itself -//Useful when player do something with computers -/mob/living/carbon/human/proc/get_authentification_name(if_no_id = "Unknown") - var/obj/item/device/pda/pda = wear_id - var/obj/item/weapon/card/id/id = wear_id - if (istype(pda)) - if (pda.id) - . = pda.id.registered_name - else - . = pda.owner - else if (istype(id)) - . = id.registered_name - else - return if_no_id - return - -//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere -/mob/living/carbon/human/proc/get_visible_name() - if( wear_mask && (wear_mask.flags_inv&HIDEFACE) ) //Wearing a mask which hides our face, use id-name if possible - return get_id_name("Unknown") - if( head && (head.flags_inv&HIDEFACE) ) - return get_id_name("Unknown") //Likewise for hats - if(name_override) - return name_override - var/face_name = get_face_name() - var/id_name = get_id_name("") - if(id_name && (id_name != face_name)) - return "[face_name] (as [id_name])" - return face_name - -//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable -/mob/living/carbon/human/proc/get_face_name() - var/obj/item/organ/external/head/BP = bodyparts_by_name[BP_HEAD] - if( !BP || BP.disfigured || (BP.status & ORGAN_DESTROYED) || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible - return "Unknown" - return real_name - -//gets name from ID or PDA itself, ID inside PDA doesn't matter -//Useful when player is being seen by other mobs -/mob/living/carbon/human/proc/get_id_name(if_no_id = "Unknown") - . = if_no_id - if(istype(wear_id,/obj/item/device/pda)) - var/obj/item/device/pda/P = wear_id - return P.owner - if(wear_id) - var/obj/item/weapon/card/id/I = wear_id.GetID() - if(I) - return I.registered_name - return - -//gets ID card object from special clothes slot or null. -/mob/living/carbon/human/proc/get_idcard() - if(wear_id) - return wear_id.GetID() - -//Removed the horrible safety parameter. It was only being used by ninja code anyways. -//Now checks siemens_coefficient of the affected area by default -/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, def_zone = null, tesla_shock = 0) - if(status_flags & GODMODE) - return 0 //godmode - if(NO_SHOCK in src.mutations) - return 0 //#Z2 no shock with that mutation. - - if(!def_zone) - def_zone = pick(BP_L_ARM , BP_R_ARM) - - var/obj/item/organ/external/BP = get_bodypart(check_zone(def_zone)) - - if(tesla_shock) - var/total_coeff = 1 - if(gloves) - var/obj/item/clothing/gloves/G = gloves - if(G.siemens_coefficient <= 0) - total_coeff -= 0.5 - if(wear_suit) - var/obj/item/clothing/suit/S = wear_suit - if(S.siemens_coefficient <= 0) - total_coeff -= 0.95 - siemens_coeff = total_coeff - else - siemens_coeff *= get_siemens_coefficient_organ(BP) - - if(species) - siemens_coeff *= species.siemens_coefficient - - . = ..(shock_damage, source, siemens_coeff, def_zone, tesla_shock) - if(.) - if(species && species.flags[IS_SYNTHETIC]) - nutrition += . // Electrocute act returns it's shock_damage value. - if(species.flags[NO_PAIN]) // Because for all intents and purposes, if the mob feels no pain, he was not shocked. - . = 0 - electrocution_animation(40) - -/mob/living/carbon/human/Topic(href, href_list) - if (href_list["refresh"]) - if((machine)&&(in_range(src, usr))) - show_inv(machine) - - 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.canmove && !( usr.restrained() ) && in_range(src, usr) && ticker)) //if game hasn't started, can't make an equip_e - var/obj/item/item = usr.get_active_hand() - if(item && (item.flags & (ABSTRACT | DROPDEL))) - return - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) - O.source = usr - O.target = src - O.item = item - O.s_loc = usr.loc - O.t_loc = loc - O.place = href_list["item"] - requests += O - spawn( 0 ) - O.process() - return - - if (href_list["criminal"]) - if(hasHUD(usr,"security")) - - var/modified = 0 - var/perpname = "wot" - 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"]) - - var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Paroled", "Released", "Cancel") - - if(hasHUD(usr, "security")) - if(setcriminal != "Cancel") - R.fields["criminal"] = setcriminal - modified = 1 - - spawn() - hud_updateflag |= 1 << WANTED_HUD - if(istype(usr,/mob/living/carbon/human)) - var/mob/living/carbon/human/U = usr - U.handle_regular_hud_updates() - if(istype(usr,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/U = usr - U.handle_regular_hud_updates() - - if(!modified) - to_chat(usr, "\red Unable to locate a data core entry for this person.") - - if (href_list["secrecord"]) - if(hasHUD(usr,"security")) - var/perpname = "wot" - var/read = 0 - - 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.security) - if (R.fields["id"] == E.fields["id"]) - if(hasHUD(usr,"security")) - to_chat(usr, "Name: [R.fields["name"]] Criminal Status: [R.fields["criminal"]]") - to_chat(usr, "Minor Crimes: [R.fields["mi_crim"]]") - to_chat(usr, "Details: [R.fields["mi_crim_d"]]") - to_chat(usr, "Major Crimes: [R.fields["ma_crim"]]") - to_chat(usr, "Details: [R.fields["ma_crim_d"]]") - to_chat(usr, "Notes: [R.fields["notes"]]") - to_chat(usr, "\[View Comment Log\]") - read = 1 - - if(!read) - to_chat(usr, "\red Unable to locate a data core entry for this person.") - - if (href_list["secrecordComment"]) - if(hasHUD(usr,"security")) - var/perpname = "wot" - var/read = 0 - - 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.security) - if (R.fields["id"] == E.fields["id"]) - if(hasHUD(usr,"security")) - read = 1 - var/counter = 1 - while(R.fields[text("com_[]", counter)]) - to_chat(usr, text("[]", R.fields[text("com_[]", counter)])) - counter++ - if (counter == 1) - to_chat(usr, "No comment found") - to_chat(usr, "\[Add comment\]") - - if(!read) - to_chat(usr, "\red Unable to locate a data core entry for this person.") - - if (href_list["secrecordadd"]) - if(hasHUD(usr,"security")) - var/perpname = "wot" - 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.security) - if (R.fields["id"] == E.fields["id"]) - if(hasHUD(usr,"security")) - var/t1 = sanitize(input("Add Comment:", "Sec. records", null, null) as message) - if ( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"security")) ) - return - var/counter = 1 - while(R.fields[text("com_[]", counter)]) - counter++ - if(istype(usr,/mob/living/carbon/human)) - var/mob/living/carbon/human/U = usr - R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
                    [t1]") - if(istype(usr,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/U = usr - R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
                    [t1]") - - if (href_list["medical"]) - if(hasHUD(usr,"medical")) - var/perpname = "wot" - var/modified = 0 - - 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"]) - - var/setmedical = input(usr, "Specify a new medical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("*SSD*", "*Deceased*", "Physically Unfit", "Active", "Disabled", "Cancel") - - if(hasHUD(usr,"medical")) - if(setmedical != "Cancel") - R.fields["p_stat"] = setmedical - modified = 1 - if(PDA_Manifest.len) - PDA_Manifest.Cut() - - spawn() - if(istype(usr,/mob/living/carbon/human)) - var/mob/living/carbon/human/U = usr - U.handle_regular_hud_updates() - if(istype(usr,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/U = usr - U.handle_regular_hud_updates() - - if(!modified) - to_chat(usr, "\red Unable to locate a data core entry for this person.") - - if (href_list["medrecord"]) - if(hasHUD(usr,"medical")) - var/perpname = "wot" - var/read = 0 - - 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.medical) - if (R.fields["id"] == E.fields["id"]) - if(hasHUD(usr,"medical")) - to_chat(usr, "Name: [R.fields["name"]] Blood Type: [R.fields["b_type"]]") - to_chat(usr, "DNA: [R.fields["b_dna"]]") - to_chat(usr, "Minor Disabilities: [R.fields["mi_dis"]]") - to_chat(usr, "Details: [R.fields["mi_dis_d"]]") - to_chat(usr, "Major Disabilities: [R.fields["ma_dis"]]") - to_chat(usr, "Details: [R.fields["ma_dis_d"]]") - to_chat(usr, "Notes: [R.fields["notes"]]") - to_chat(usr, "\[View Comment Log\]") - read = 1 - - if(!read) - to_chat(usr, "\red Unable to locate a data core entry for this person.") - - if (href_list["medrecordComment"]) - if(hasHUD(usr,"medical")) - var/perpname = "wot" - var/read = 0 - - 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.medical) - if (R.fields["id"] == E.fields["id"]) - if(hasHUD(usr,"medical")) - read = 1 - var/counter = 1 - while(R.fields[text("com_[]", counter)]) - to_chat(usr, text("[]", R.fields[text("com_[]", counter)])) - counter++ - if (counter == 1) - to_chat(usr, "No comment found") - to_chat(usr, "\[Add comment\]") - - if(!read) - to_chat(usr, "\red Unable to locate a data core entry for this person.") - - if (href_list["medrecordadd"]) - if(hasHUD(usr,"medical")) - var/perpname = "wot" - 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.medical) - if (R.fields["id"] == E.fields["id"]) - if(hasHUD(usr,"medical")) - var/t1 = sanitize(input("Add Comment:", "Med. records", null, null) as message) - if ( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"medical")) ) - return - var/counter = 1 - while(R.fields[text("com_[]", counter)]) - counter++ - if(istype(usr,/mob/living/carbon/human)) - var/mob/living/carbon/human/U = usr - R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
                    [t1]") - if(istype(usr,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/U = usr - R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
                    [t1]") - - if (href_list["lookitem"]) - var/obj/item/I = locate(href_list["lookitem"]) - usr.examinate(I) - - if (href_list["lookmob"]) - var/mob/M = locate(href_list["lookmob"]) - usr.examinate(M) - ..() - return - - -///eyecheck() -///Returns a number between -1 to 2 -/mob/living/carbon/human/eyecheck() - var/number = 0 - if(istype(src.head, /obj/item/clothing/head/welding)) - if(!src.head:up) - number += 2 - if(istype(src.head, /obj/item/clothing/head/helmet/space) && !istype(src.head, /obj/item/clothing/head/helmet/space/sk)) - number += 2 - if(istype(src.glasses, /obj/item/clothing/glasses/thermal)) - number -= 1 - if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses)) - number += 1 - if(istype(src.wear_mask, /obj/item/clothing/mask/gas/welding)) - var/obj/item/clothing/mask/gas/welding/W = src.wear_mask - if(!W.up) - number += 2 - if(istype(src.glasses, /obj/item/clothing/glasses/welding)) - var/obj/item/clothing/glasses/welding/W = src.glasses - if(!W.up) - number += 2 - if(istype(src.glasses, /obj/item/clothing/glasses/night/shadowling)) - number -= 1 - return number - - -/mob/living/carbon/human/IsAdvancedToolUser() - return 1//Humans can use guns and such - - -/mob/living/carbon/human/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 || src.head || src.shoes || src.w_uniform || src.wear_suit || src.glasses || src.l_ear || src.r_ear || src.gloves))) - return 1 - - if( (src.l_hand && !src.l_hand.abstract) || (src.r_hand && !src.r_hand.abstract) ) - return 1 - - return 0 - - -/mob/living/carbon/human/proc/check_dna() - dna.check_integrity(src) - return - -/mob/living/carbon/human/get_species() - - if(!species) - set_species() - - if(dna && dna.mutantrace == "golem") - return "Animated Construct" - - - - return species.name - -/mob/living/carbon/human/proc/play_xylophone() - if(!src.xylophone) - visible_message("\red [src] begins playing his ribcage like a xylophone. It's quite spooky.","\blue You begin to play a spooky refrain on your ribcage.","\red You hear a spooky xylophone melody.") - var/song = pick('sound/effects/xylophone1.ogg','sound/effects/xylophone2.ogg','sound/effects/xylophone3.ogg') - playsound(loc, song, 50, 1, -1) - xylophone = 1 - spawn(1200) - xylophone=0 - return - -/mob/living/carbon/human/proc/vomit() - - if(species.flags[IS_SYNTHETIC]) - return //Machines don't throw up. - - if(!lastpuke) - lastpuke = 1 - to_chat(src, "You feel nauseous...") - spawn(150) //15 seconds until second warning - to_chat(src, "You feel like you are about to throw up!") - spawn(100) //and you have 10 more for mad dash to the bucket - Stun(5) - - src.visible_message("[src] throws up!","You throw up!") - playsound(loc, 'sound/effects/splat.ogg', 50, 1) - - var/turf/location = loc - if (istype(location, /turf/simulated)) - location.add_vomit_floor(src, 1) - - nutrition -= 40 - adjustToxLoss(-3) - spawn(350) //wait 35 seconds before next volley - lastpuke = 0 - -/mob/living/carbon/human/proc/morph() - set name = "Morph" - set category = "Superpower" - - if(stat!=CONSCIOUS) - reset_view(0) - remoteview_target = null - return - - if(!(MORPH in mutations)) - src.verbs -= /mob/living/carbon/human/proc/morph - return - - var/new_facial = input("Please select facial hair color.", "Character Generation",rgb(r_facial,g_facial,b_facial)) as color - 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)) - - var/new_hair = input("Please select hair color.", "Character Generation",rgb(r_hair,g_hair,b_hair)) as color - if(new_facial) - r_hair = hex2num(copytext(new_hair, 2, 4)) - g_hair = hex2num(copytext(new_hair, 4, 6)) - b_hair = hex2num(copytext(new_hair, 6, 8)) - - var/new_eyes = input("Please select eye color.", "Character Generation",rgb(r_eyes,g_eyes,b_eyes)) as color - 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)) - - var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", "[35-s_tone]") as text - - if (!new_tone) - new_tone = 35 - s_tone = max(min(round(text2num(new_tone)), 220), 1) - s_tone = -s_tone + 35 - - // hair - var/list/all_hairs = typesof(/datum/sprite_accessory/hair) - /datum/sprite_accessory/hair - var/list/hairs = list() - - // loop through potential hairs - for(var/x in all_hairs) - var/datum/sprite_accessory/hair/H = new x // create new hair datum based on type x - hairs.Add(H.name) // add hair name to hairs - qdel(H) // delete the hair after it's all done - - var/new_style = input("Please select hair style", "Character Generation",h_style) as null|anything in hairs - - // if new style selected (not cancel) - if (new_style) - h_style = new_style - - // facial hair - var/list/all_fhairs = typesof(/datum/sprite_accessory/facial_hair) - /datum/sprite_accessory/facial_hair - var/list/fhairs = list() - - for(var/x in all_fhairs) - var/datum/sprite_accessory/facial_hair/H = new x - fhairs.Add(H.name) - qdel(H) - - new_style = input("Please select facial style", "Character Generation",f_style) as null|anything in fhairs - - if(new_style) - f_style = new_style - - var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") - if (new_gender) - if(new_gender == "Male") - gender = MALE - else - gender = FEMALE - regenerate_icons() - check_dna() - - visible_message("\blue \The [src] morphs and changes [get_visible_gender() == MALE ? "his" : get_visible_gender() == FEMALE ? "her" : "their"] appearance!", "\blue You change your appearance!", "\red Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!") - -/mob/living/carbon/human/proc/remotesay() //#Z2 - set name = "Project mind" - set category = "Superpower" - - if(stat!=CONSCIOUS) - reset_view(0) - remoteview_target = null - return - - if(!(REMOTE_TALK in src.mutations)) - src.verbs -= /mob/living/carbon/human/proc/remotesay - return - - var/list/names = list() - var/list/creatures = list() - var/list/namecounts = list() - - var/turf/src_turf = get_turf(src) - if(!src_turf) - return - - for(var/mob/living/carbon/M in carbon_list) - var/name = M.real_name - if(name in names) - namecounts[name]++ - name = "[name] ([namecounts[name]])" - else - names.Add(name) - namecounts[name] = 1 - var/turf/temp_turf = get_turf(M) - if(!temp_turf || temp_turf.z != src_turf.z) - continue - creatures[name] += M - - var/mob/target = input ("Who do you want to project your mind to ?") as null|anything in creatures - if(isnull(target)) - return - - var/say = input ("What do you wish to say") - if(!say) - return - else - say = sanitize(say) - var/mob/T = creatures[target] - if(REMOTE_TALK in T.mutations) - T.show_message("\blue You hear [src.real_name]'s voice: [say]") - else - T.show_message("\blue You hear a voice that seems to echo around the room: [say]") - usr.show_message("\blue You project your mind into [T.real_name]: [say]") - for(var/mob/dead/observer/G in observer_list) - G.show_message("Telepathic message from [src] to [T]: [say]") - log_say("Telepathic message from [key_name(src)] to [key_name(T)]: [say]") - -/mob/living/carbon/human/proc/remoteobserve() - set name = "Remote View" - set category = "Superpower" - - if(stat!=CONSCIOUS) - remoteview_target = null - reset_view(0) - return - - if(!(REMOTE_VIEW in src.mutations)) - remoteview_target = null - reset_view(0) - src.verbs -= /mob/living/carbon/human/proc/remoteobserve - return - - if(client.eye != client.mob) - remoteview_target = null - reset_view(0) - return - - if(src.getBrainLoss() >= 100) //#Z2 - to_chat(src, "Too hard to concentrate... Better stop trying!") - src.adjustBrainLoss(7) - if(src.getBrainLoss() >= 125) return - - var/list/names = list() - var/list/creatures = list() - var/list/namecounts = list() - var/target = null //Chosen target. - - for(var/mob/living/carbon/human/M in human_list) //#Z2 only carbon/human for now - var/name = M.real_name - if(!(REMOTE_TALK in src.mutations)) - namecounts++ - name = "([namecounts])" - else - if(name in names) - namecounts[name]++ - name = "[name] ([namecounts[name]])" - else - names.Add(name) - namecounts[name] = 1 - var/turf/temp_turf = get_turf(M) - if((temp_turf.z != ZLEVEL_STATION && temp_turf.z != ZLEVEL_ASTEROID || temp_turf.z != src.z) || M.stat!=CONSCIOUS) //Not on mining or the station. Or dead #Z2 + target on the same Z level as player - continue - creatures[name] += M - - target = input ("Who do you want to project your mind to ?") as null|anything in creatures - - if (!target)//Make sure we actually have a target - return - if(src.getBrainLoss() >= 100) - to_chat(src, "Too hard to concentrate...") - return - if (target && (creatures[target] != src)) - src.adjustBrainLoss(4) - remoteview_target = creatures[target] - reset_view(creatures[target]) - else - remoteview_target = null - reset_view(0) //##Z2 - -/mob/living/carbon/human/proc/get_visible_gender() - if(wear_suit && wear_suit.flags_inv & HIDEJUMPSUIT && ((head && head.flags_inv & HIDEMASK) || wear_mask)) - return NEUTER - return gender - -/mob/living/carbon/human/proc/increase_germ_level(n) - if(gloves) - gloves.germ_level += n - else - germ_level += n - -/mob/living/carbon/human/proc/is_lung_ruptured() - var/obj/item/organ/internal/lungs/IO = organs_by_name[O_LUNGS] - return IO.is_bruised() - -/mob/living/carbon/human/proc/rupture_lung() - var/obj/item/organ/internal/lungs/IO = organs_by_name[O_LUNGS] - - if(!IO.is_bruised()) - src.custom_pain("You feel a stabbing pain in your chest!", 1) - IO.damage = IO.min_bruised_damage - -/* -/mob/living/carbon/human/verb/simulate() - set name = "sim" - //set background = 1 - - var/damage = input("Wound damage","Wound damage") as num - - var/germs = 0 - var/tdamage = 0 - var/ticks = 0 - while (germs < 2501 && ticks < 100000 && round(damage/10)*20) - log_misc("VIRUS TESTING: [ticks] : germs [germs] tdamage [tdamage] prob [round(damage/10)*20]") - ticks++ - if (prob(round(damage/10)*20)) - germs++ - if (germs == 100) - to_chat(world, "Reached stage 1 in [ticks] ticks") - if (germs > 100) - if (prob(10)) - damage++ - germs++ - if (germs == 1000) - to_chat(world, "Reached stage 2 in [ticks] ticks") - if (germs > 1000) - damage++ - germs++ - if (germs == 2500) - to_chat(world, "Reached stage 3 in [ticks] ticks") - to_chat(world, "Mob took [tdamage] tox damage") -*/ -//returns 1 if made bloody, returns 0 otherwise - -/mob/living/carbon/human/add_blood(mob/living/carbon/human/M) - if (!..()) - return 0 - //if this blood isn't already in the list, add it - if(blood_DNA[M.dna.unique_enzymes]) - return 0 //already bloodied with this blood. Cannot add more. - blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - hand_dirt_color = new/datum/dirt_cover/(dirt_overlay) - - src.update_inv_gloves() //handles bloody hands overlays and updating - verbs += /mob/living/carbon/human/proc/bloody_doodle - return 1 //we applied blood to the item - -/mob/living/carbon/human/get_visible_implants(class = 0) - - var/list/visible_implants = list() - for(var/obj/item/organ/external/BP in bodyparts) - for(var/obj/item/weapon/O in BP.implants) - if(!istype(O,/obj/item/weapon/implant) && O.w_class > class) - visible_implants += O - - return(visible_implants) - -/mob/living/carbon/human/proc/handle_embedded_objects() - - for(var/obj/item/organ/external/BP in bodyparts) - if(BP.status & ORGAN_SPLINTED) //Splints prevent movement. - continue - for(var/obj/item/weapon/O in BP.implants) - if(!istype(O,/obj/item/weapon/implant) && prob(5)) //Moving with things stuck in you could be bad. - // All kinds of embedded objects cause bleeding. - var/msg = null - switch(rand(1,3)) - if(1) - msg ="A spike of pain jolts your [BP.name] as you bump [O] inside." - if(2) - msg ="Your movement jostles [O] in your [BP.name] painfully." - if(3) - msg ="[O] in your [BP.name] twists painfully as you move." - to_chat(src, msg) - - BP.take_damage(rand(1,3), 0, 0) - if(!(BP.status & ORGAN_ROBOT)) //There is no blood in protheses. - BP.status |= ORGAN_BLEEDING - src.adjustToxLoss(rand(1,3)) - -/mob/living/carbon/human/verb/check_pulse() - set category = "Object" - set name = "Check pulse" - set desc = "Approximately count somebody's pulse. Requires you to stand still at least 6 seconds." - set src in view(1) - var/self = 0 - - if(usr.stat == 1 || usr.restrained() || !isliving(usr)) return - - if(usr == src) - self = 1 - if(!self) - usr.visible_message("\blue [usr] kneels down, puts \his hand on [src]'s wrist and begins counting their pulse.",\ - "You begin counting [src]'s pulse") - else - usr.visible_message("\blue [usr] begins counting their pulse.",\ - "You begin counting your pulse.") - - if(src.pulse) - to_chat(usr, "\blue [self ? "You have a" : "[src] has a"] pulse! Counting...") - else - to_chat(usr, "\red [src] has no pulse!")//it is REALLY UNLIKELY that a dead person would check his own pulse - return - - to_chat(usr, "Don't move until counting is finished.") - var/time = world.time - sleep(60) - if(usr.l_move_time >= time) //checks if our mob has moved during the sleep() - to_chat(usr, "You moved while counting. Try again.") - else - to_chat(usr, "\blue [self ? "Your" : "[src]'s"] pulse is [src.get_pulse(GETPULSE_HAND)].") - -/mob/living/carbon/human/proc/set_species(new_species, force_organs, default_colour) - - if(!new_species) - if(dna.species) - new_species = dna.species - else - new_species = HUMAN - else - dna.species = new_species - - if(species) - if(species.name == new_species) - return - - if(species.language) - remove_language(species.language) - - species.on_loose(src) - - species = all_species[new_species] - maxHealth = species.total_health - - if(force_organs || !bodyparts.len) - species.create_organs(src) - - if(species.language) - add_language(species.language) - - if(species.additional_languages) - for(var/A in species.additional_languages) - add_language(A) - - if(species.base_color && default_colour) - //Apply colour. - r_skin = hex2num(copytext(species.base_color,2,4)) - g_skin = hex2num(copytext(species.base_color,4,6)) - b_skin = hex2num(copytext(species.base_color,6,8)) - else - r_skin = 0 - g_skin = 0 - b_skin = 0 - - species.handle_post_spawn(src) - species.on_gain(src) - - regenerate_icons() - full_prosthetic = null - - if(species) - return 1 - else - return 0 - -// Unlike set_species(), this proc simply changes owner's specie and thats it. -/mob/living/carbon/human/proc/set_species_soft(new_species) - if(species.name == new_species) - return - - species.on_loose(src) - - species = all_species[new_species] - maxHealth = species.total_health - - species.handle_post_spawn(src) - species.on_gain(src) - - regenerate_icons() - -/mob/living/carbon/human/proc/bloody_doodle() - set category = "IC" - set name = "Write in blood" - set desc = "Use blood on your hands to write a short message on the floor or a wall, murder mystery style." - - if (src.stat) - return - - if (usr != src) - return 0 //something is terribly wrong - - if (!bloody_hands) - verbs -= /mob/living/carbon/human/proc/bloody_doodle - - if (src.gloves) - to_chat(src, "Your [src.gloves] are getting in the way.") - return - - var/turf/simulated/T = src.loc - if (!istype(T)) //to prevent doodling out of mechs and lockers - to_chat(src, "You cannot reach the floor.") - return - - var/direction = input(src,"Which way?","Tile selection") as anything in list("Here","North","South","East","West") - if (direction != "Here") - T = get_step(T,text2dir(direction)) - if (!istype(T)) - to_chat(src, "You cannot doodle there.") - return - - var/num_doodles = 0 - for (var/obj/effect/decal/cleanable/blood/writing/W in T) - num_doodles++ - if (num_doodles > 4) - to_chat(src, "There is no space to write on!") - return - - var/max_length = bloody_hands * 30 //tweeter style - - var/message = sanitize(input(src,"Write a message. It cannot be longer than [max_length] characters.","Blood writing", ""), MAX_MESSAGE_LEN) - - if (message) - var/used_blood_amount = round(length(message) / 30, 1) - bloody_hands = max(0, bloody_hands - used_blood_amount) //use up some blood - - if (length(message) > max_length) - message += "-"//Should crop any letters? No? - to_chat(src, "You ran out of blood to write with!") - - var/obj/effect/decal/cleanable/blood/writing/W = new(T) - W.basedatum = new/datum/dirt_cover(hand_dirt_color) - W.update_icon() - W.message = message - W.add_fingerprint(src) - -/mob/living/carbon/human/verb/examine_ooc() - set name = "Examine OOC" - set category = "OOC" - set src in oview() - - if(!usr || !src) return - - to_chat(usr, "OOC-info: [src]") - if(metadata) - to_chat(usr, "[metadata]") - else - to_chat(usr, "Nothing of interest...") - -/mob/living/carbon/try_inject(mob/living/user, error_msg, instant, stealth, pierce_armor) - if(istype(user)) - if(user.is_busy()) - return - - if(!user.IsAdvancedToolUser()) - if(error_msg) - to_chat(user, "You have no idea, how to use this!") - return FALSE - - if (HULK in user.mutations) // TODO - meaty fingers or something like that. - if(error_msg) - to_chat(user, "You don't have the dexterity to do this!") - return FALSE - - var/hunt_injection_port = FALSE - - switch(check_thickmaterial(target_zone = user.zone_sel.selecting)) - if(NOLIMB) - if(error_msg) - to_chat(user, "[src] has no such body part, try to inject somewhere else.") - return FALSE - if(THICKMATERIAL) - if(!pierce_armor) - if(error_msg) - to_chat(user, "There is no exposed flesh or thin material [user.zone_sel.selecting == BP_HEAD ? "on their head" : "on their body"] to inject into.") - return FALSE - if(PHORONGUARD) - if(!pierce_armor) - if(user.a_intent == I_HURT) - if(error_msg) - to_chat(user, "There is no exposed flesh or thin material [user.zone_sel.selecting == BP_HEAD ? "on their head" : "on their body"] to inject into.") - return FALSE - hunt_injection_port = TRUE - - if(isSynthetic(user.zone_sel.selecting)) - if(error_msg) - to_chat(user, "You are trying to inject [src]'s synthetic body part!") - return FALSE - - if(!instant) - var/time_to_inject = HUMAN_STRIP_DELAY - if(hunt_injection_port) // takes additional time - if(!stealth) - user.visible_message("[user] begins hunting for an injection port on [src]'s suit!") - if(!do_mob(user, src, time_to_inject / 2, TRUE)) - return FALSE - - if(!stealth) - user.visible_message("[user] is trying to inject [src]!") - - if(!do_mob(user, src, time_to_inject, TRUE)) - return FALSE - - if(!stealth) - if(user != src) - user.visible_message("[user] injects [src] with the syringe!") - else - to_chat(user, "You inject [src] with the injector.") - to_chat(src, "You feel a tiny prick!") - - return TRUE - -/obj/screen/leap - name = "toggle leap" - icon = 'icons/mob/screen1_action.dmi' - icon_state = "action" - - var/on = FALSE - var/time_used = 0 - var/cooldown = 10 SECONDS - - -/obj/screen/leap/atom_init() - . = ..() - overlays += image(icon, "leap") - update_icon() - -/obj/screen/leap/update_icon() - icon_state = "[initial(icon_state)]_[on]" - -/obj/screen/leap/Click() - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - H.toggle_leap() - -/mob/living/carbon/human/proc/toggle_leap(message = 1) - leap_icon.on = !leap_icon.on - leap_icon.update_icon() - if(message) - to_chat(src, "You will [leap_icon.on ? "now" : "no longer"] leap at enemies!") - -/mob/living/carbon/human/ClickOn(atom/A, params) - if(leap_icon && leap_icon.on && A != src) - leap_at(A) - else - ..() - -#define MAX_LEAP_DIST 4 - -/mob/living/carbon/human/proc/leap_at(atom/A) - if(leap_icon.time_used > world.time) - to_chat(src, "You are too fatigued to leap right now!") - return - - if(status_flags & LEAPING) // Leap while you leap, so you can leap while you leap - return - - if(!has_gravity(src)) - to_chat(src, "It is unsafe to leap without gravity!") - return - - if(incapacitated(LEGS) || buckled || pinned.len || stance_damage >= 4) //because you need !restrained legs to leap - to_chat(src, "You cannot leap in your current state.") - return - - leap_icon.time_used = world.time + leap_icon.cooldown - status_flags |= LEAPING - stop_pulling() - - - var/prev_intent = a_intent - a_intent_change("hurt") - - if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/space/vox/stealth)) - for(var/obj/item/clothing/suit/space/vox/stealth/V in list(wear_suit)) - if(V.on) - V.overload() - - toggle_leap() - - throw_at(A, MAX_LEAP_DIST, 2, null, FALSE, TRUE, CALLBACK(src, .leap_end, prev_intent)) - -/mob/living/carbon/human/proc/leap_end(prev_intent) - status_flags &= ~LEAPING - a_intent_change(prev_intent) - -/mob/living/carbon/human/throw_impact(atom/A) - if(!(status_flags & LEAPING)) - return ..() - - if(isliving(A)) - var/mob/living/L = A - L.visible_message("\The [src] leaps at [L]!", "[src] leaps on you!") - if(issilicon(A)) - L.Weaken(1) //Only brief stun - step_towards(src, L) - else - L.Weaken(5) - sleep(2) // Runtime prevention (infinite bump() calls on hulks) - step_towards(src, L) - - if(restrained()) //You can leap when you hands are cuffed, but you can't grab - return - - var/use_hand = "left" - if(l_hand) - if(r_hand) - to_chat(src, "You need to have one hand free to grab someone.") - return - else - use_hand = "right" - - visible_message("\The [src] seizes [L] aggressively!") - - var/obj/item/weapon/grab/G = new(src, L) - if(use_hand == "left") - l_hand = G - else - r_hand = G - - G.state = GRAB_AGGRESSIVE - G.icon_state = "grabbed1" - G.synch() - L.grabbed_by += G - - else if(A.density) - visible_message("[src] smashes into [A]!", "You smashes into [A]!") - weakened = 2 - - update_canmove() - -#undef MAX_LEAP_DIST - -/mob/living/carbon/human/proc/gut() - set category = "IC" - set name = "Gut" - set desc = "While grabbing someone aggressively, rip their guts out or tear them apart." - - if(last_special > world.time) - return - - if(stat || paralysis || stunned || weakened || lying) - to_chat(src, "\red You cannot do that in your current state.") - return - - var/obj/item/weapon/grab/G = locate() in src - if(!G || !istype(G)) - to_chat(src, "\red You are not grabbing anyone.") - return - - if(G.state < GRAB_AGGRESSIVE) - to_chat(src, "\red You must have an aggressive grab to gut your prey!") - return - - last_special = world.time + 50 - - visible_message("\The [src] rips viciously at \the [G.affecting]'s body with its claws!") - - if(istype(G.affecting,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = G.affecting - H.apply_damage(50,BRUTE) - if(H.stat == DEAD) - H.gib() - else - var/mob/living/M = G.affecting - if(!istype(M)) return //wut - M.apply_damage(50,BRUTE) - if(M.stat == DEAD) - M.gib() - -/mob/living/carbon/human/has_eyes() - if(organs_by_name[O_EYES]) - var/obj/item/organ/internal/IO = organs_by_name[O_EYES] - if(istype(IO)) - return 1 - return 0 - -/mob/living/carbon/human/slip(slipped_on, stun_duration=4, weaken_duration=2) - if(shoes && (shoes.flags & NOSLIP)) - return FALSE - return ..(slipped_on,stun_duration, weaken_duration) - -//Turns a mob black, flashes a skeleton overlay -//Just like a cartoon! -/mob/living/carbon/human/proc/electrocution_animation(anim_duration) - //TG... - //Handle mutant parts if possible - //if(species) - // species.handle_mutant_bodyparts(src,"black") - // species.handle_hair(src,"black") - // species.update_color(src,"black") - // overlays += "electrocuted_base" - // spawn(anim_duration) - // if(src) - // if(dna && dna.species) - // dna.species.handle_mutant_bodyparts(src) - // dna.species.handle_hair(src) - // dna.species.update_color(src) - // overlays -= "electrocuted_base" - //else //or just do a generic animation - var/list/viewing = list() - for(var/mob/M in viewers(src)) - if(M.client) - viewing += M.client - flick_overlay(image(icon,src,"electrocuted_generic",MOB_LAYER+1), viewing, anim_duration) - -/mob/living/carbon/human/proc/should_have_organ(organ_check) - - var/obj/item/organ/external/BP - if(organ_check in list(O_HEART, O_LUNGS)) - BP = bodyparts_by_name[BP_CHEST] - else if(organ_check in list(O_LIVER, O_KIDNEYS)) - BP = bodyparts_by_name[BP_GROIN] - - if(BP && (BP.status & ORGAN_ROBOT)) - return FALSE - return species.has_organ[organ_check] - -/mob/living/carbon/human/can_eat(flags = DIET_ALL) - return species && (species.dietflags & flags) - -/mob/living/carbon/human/get_taste_sensitivity() - if(species) - return species.taste_sensitivity - else - return 1 +/mob/living/carbon/human + name = "unknown" + real_name = "unknown" + voice_name = "unknown" + icon = 'icons/mob/human.dmi' + //icon_state = "body_m_s" + var/list/hud_list[9] + var/datum/species/species //Contains icon generation and language information, set during New(). + var/dog_owner + var/heart_beat = 0 + var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. + + var/scientist = 0 //Vars used in abductors checks and etc. Should be here because in species datums it changes globaly. + var/agent = 0 + var/team = 0 + var/metadata + var/seer = 0 // used in cult datum /cult/seer + + throw_range = 2 + +/mob/living/carbon/human/dummy + real_name = "Test Dummy" + status_flags = GODMODE|CANPUSH + +INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) + +/mob/living/carbon/human/skrell/atom_init(mapload) + h_style = "Skrell Male Tentacles" + . = ..(mapload, SKRELL) + +/mob/living/carbon/human/tajaran/atom_init(mapload) + h_style = "Tajaran Ears" + . = ..(mapload, TAJARAN) + +/mob/living/carbon/human/unathi/atom_init(mapload) + h_style = "Unathi Horns" + . = ..(mapload, UNATHI) + +/mob/living/carbon/human/vox/atom_init(mapload) + h_style = "Short Vox Quills" + . = ..(mapload, VOX) + +/mob/living/carbon/human/voxarmalis/atom_init(mapload) + h_style = "Bald" + . = ..(mapload, VOX_ARMALIS) + +/mob/living/carbon/human/diona/atom_init(mapload) + . = ..(mapload, DIONA) + +/mob/living/carbon/human/machine/atom_init(mapload) + h_style = "blue IPC screen" + . = ..(mapload, IPC) + +/mob/living/carbon/human/abductor/atom_init(mapload) + . = ..(mapload, ABDUCTOR) + +/mob/living/carbon/human/golem/atom_init(mapload) + . = ..(mapload, GOLEM) + +/mob/living/carbon/human/shadowling/atom_init(mapload) + . = ..(mapload, SHADOWLING) + var/newNameId = pick(possibleShadowlingNames) + possibleShadowlingNames.Remove(newNameId) + real_name = newNameId + name = real_name + + underwear = 0 + undershirt = 0 + faction = "faithless" + dna.mutantrace = "shadowling" + update_mutantrace() + regenerate_icons() + + spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind + spell_list += new /obj/effect/proc_holder/spell/targeted/enthrall + spell_list += new /obj/effect/proc_holder/spell/targeted/glare + spell_list += new /obj/effect/proc_holder/spell/aoe_turf/veil + spell_list += new /obj/effect/proc_holder/spell/targeted/shadow_walk + spell_list += new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze + spell_list += new /obj/effect/proc_holder/spell/targeted/collective_mind + spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor + +/mob/living/carbon/human/atom_init(mapload, new_species) + + dna = new + + if(!species) + if(new_species) + set_species(new_species, null, TRUE) + else + set_species() + + if(species) // Just to be sure. + metabolism_factor = species.metabolism_mod + butcher_results = species.butcher_drops + + dna.species = species.name + + var/datum/reagents/R = new/datum/reagents(1000) + reagents = R + R.my_atom = src + + hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudhealth100") + hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudhealthy") + hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudunknown") + hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[STATUS_HUD_OOC] = image('icons/mob/hud.dmi', src, "hudhealthy") + + . = ..() + + human_list += src + + if(dna) + dna.real_name = real_name + + handcrafting = new() + + verbs += /mob/living/carbon/proc/crawl + + prev_gender = gender // Debug for plural genders + make_blood() + regenerate_icons() + +/mob/living/carbon/human/Destroy() + human_list -= src + return ..() + +/mob/living/carbon/human/OpenCraftingMenu() + handcrafting.ui_interact(src) + +/mob/living/carbon/human/Stat() + ..() + + if(statpanel("Status")) + stat(null, "Intent: [a_intent]") + stat(null, "Move Mode: [m_intent]") + if(internal) + if(!internal.air_contents) + qdel(internal) + else + stat("Internal Atmosphere Info", internal.name) + stat("Tank Pressure", internal.air_contents.return_pressure()) + stat("Distribution Pressure", internal.distribute_pressure) + + CHANGELING_STATPANEL_STATS(null) + + if(istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)) + var/obj/item/clothing/suit/space/space_ninja/SN = wear_suit + stat("SpiderOS Status:","[SN.s_initialized ? "Initialized" : "Disabled"]") + stat("Current Time:", "[worldtime2text()]") + if(SN.s_initialized) + //Suit gear + stat("Energy Charge", "[round(SN.cell.charge/100)]%") + stat("Smoke Bombs:", "\Roman [SN.s_bombs]") + //Ninja status + stat("Fingerprints:", "[md5(dna.uni_identity)]") + stat("Unique Identity:", "[dna.unique_enzymes]") + stat("Overall Status:", "[stat > 1 ? "dead" : "[health]% healthy"]") + stat("Nutrition Status:", "[nutrition]") + stat("Oxygen Loss:", "[getOxyLoss()]") + stat("Toxin Levels:", "[getToxLoss()]") + stat("Burn Severity:", "[getFireLoss()]") + stat("Brute Trauma:", "[getBruteLoss()]") + stat("Radiation Levels:","[radiation] rad") + stat("Body Temperature:","[bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)") + + CHANGELING_STATPANEL_POWERS(null) + +/mob/living/carbon/human/ex_act(severity) + if(!blinded) + flash_eyes() + + var/shielded = 0 + var/b_loss = null + var/f_loss = null + switch (severity) + if (1.0) + b_loss += 500 + if (!prob(getarmor(null, "bomb"))) + gib() + return + else + var/atom/target = get_edge_target_turf(src, get_dir(src, get_step_away(src, src))) + throw_at(target, 200, 4) + //return +// var/atom/target = get_edge_target_turf(user, get_dir(src, get_step_away(user, src))) + //user.throw_at(target, 200, 4) + + if (2.0) + if (!shielded) + b_loss += 60 + + f_loss += 60 + + if (prob(getarmor(null, "bomb"))) + b_loss = b_loss/1.5 + f_loss = f_loss/1.5 + + if (!istype(l_ear, /obj/item/clothing/ears/earmuffs) && !istype(r_ear, /obj/item/clothing/ears/earmuffs)) + ear_damage += 30 + ear_deaf += 120 + if (prob(70) && !shielded) + Paralyse(10) + + if(3.0) + b_loss += 30 + if (prob(getarmor(null, "bomb"))) + b_loss = b_loss/2 + if (!istype(l_ear, /obj/item/clothing/ears/earmuffs) && !istype(r_ear, /obj/item/clothing/ears/earmuffs)) + ear_damage += 15 + ear_deaf += 60 + if (prob(50) && !shielded) + Paralyse(10) + + // focus most of the blast on one organ + var/obj/item/organ/external/BP = pick(bodyparts) + BP.take_damage(b_loss * 0.9, f_loss * 0.9, used_weapon = "Explosive blast") + + // distribute the remaining 10% on all limbs equally + b_loss *= 0.1 + f_loss *= 0.1 + + var/weapon_message = "Explosive Blast" + take_overall_damage(b_loss * 0.2, f_loss * 0.2, used_weapon = weapon_message) + +/mob/living/carbon/human/singularity_act() + var/gain = 20 + if(mind) + switch(mind.assigned_role) + if("Station Engineer","Chief Engineer") + gain = 100 + if("Clown") + gain = rand(-300, 300)//HONK + investigate_log(" has consumed [key_name(src)].","singulo") //Oh that's where the clown ended up! + gib() + return(gain) + +/mob/living/carbon/human/singularity_pull(S, current_size) + if(current_size >= STAGE_THREE) + var/list/handlist = list(l_hand, r_hand) + for(var/obj/item/hand in handlist) + if(prob(current_size * 5) && hand.w_class >= ((STAGE_FIVE-current_size)/2) && unEquip(hand)) + step_towards(hand, src) + to_chat(src, "\The [S] pulls \the [hand] from your grip!") + apply_effect(current_size * 3, IRRADIATE) + if(mob_negates_gravity())//Magboots protection + return + ..() + +/mob/living/carbon/human/blob_act() + if(stat == DEAD) return + to_chat(src, "\The blob attacks you!") + var/dam_zone = pick(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) + var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(dam_zone)] + apply_damage(rand(30, 40), BRUTE, BP, run_armor_check(BP, "melee")) + return + +/mob/living/carbon/human/meteorhit(O) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red [src] has been hit by [O]", 1) + if (health > 0) + var/obj/item/organ/external/BP = bodyparts_by_name[pick(BP_CHEST , BP_CHEST , BP_CHEST , BP_HEAD)] + if(!BP) + return + if (istype(O, /obj/effect/immovablerod)) + BP.take_damage(101, 0) + else + BP.take_damage((istype(O, /obj/effect/meteor/small) ? 10 : 25), 30) + updatehealth() + return + + +/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M) + if(..()) + 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) + visible_message("[M][M.attacktext] [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(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) + var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(dam_zone)] + var/armor = run_armor_check(BP, "melee") + apply_damage(damage, BRUTE, BP, armor) + if(armor >= 2) return + +/mob/living/carbon/human/attack_slime(mob/living/carbon/slime/M) + 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("\red The [M.name] glomps []!", src), 1) + + var/damage = rand(1, 3) + + if(istype(M, /mob/living/carbon/slime/adult)) + damage = rand(10, 35) + else + damage = rand(5, 25) + + + var/dam_zone = pick(BP_HEAD , BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG , BP_GROIN) + + var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(dam_zone)] + var/armor_block = run_armor_check(BP, "melee") + apply_damage(damage, BRUTE, BP, armor_block) + + + 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("\red 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/human/proc/can_use_two_hands(broken = TRUE) // Replace arms with hands in case of reverting Kurshan's PR. + var/obj/item/organ/external/l_arm/BPL = bodyparts_by_name[BP_L_ARM] + var/obj/item/organ/external/r_arm/BPR = bodyparts_by_name[BP_R_ARM] + if(broken && (BPL.is_broken() || BPR.is_broken())) + return FALSE + if(!BPL.is_usable() || !BPR.is_usable()) + return FALSE + return TRUE + +/mob/living/carbon/human/proc/wield(/obj/item/I, name, wieldsound = null) + if(!can_use_two_hands()) + to_chat(src, "You need both of your hands to be intact to do this.") + return FALSE + if(get_inactive_hand()) + to_chat(src, "You need your other hand to be empty to do this.") + return FALSE + to_chat(src, "You grab the [name] with both hands.") + if(wieldsound) + playsound(loc, wieldsound, 50, 1) + + if(hand) + update_inv_l_hand() + else + update_inv_r_hand() + + var/obj/item/weapon/twohanded/offhand/O = new(src) + O.name = "[name] - offhand" + O.desc = "Your second grip on the [name]" + put_in_inactive_hand(O) + return TRUE + +/mob/living/carbon/human/proc/is_type_organ(organ, o_type) + var/obj/item/organ/O + if(organ in organs_by_name) + O = organs_by_name[organ] + if(organ in bodyparts_by_name) + O = bodyparts_by_name[organ] + if(!O) + return FALSE + return istype(O, o_type) + +/mob/living/carbon/human/proc/is_bruised_organ(organ) + var/obj/item/organ/internal/IO = organs_by_name[organ] + if(!IO) + return TRUE + if(IO.is_bruised()) + return TRUE + return FALSE + +/mob/living/carbon/human/proc/find_damaged_bodypart() + for(var/obj/item/organ/external/BP in bodyparts) // find a broken/destroyed limb + if(BP.status & (ORGAN_DESTROYED | ORGAN_BROKEN | ORGAN_SPLINTED)) + if(BP.parent && (BP.parent.status & ORGAN_DESTROYED)) + continue + else + return BP + return FALSE // In case we didn't find anything. + +/mob/living/carbon/human/proc/regen_bodyparts(remove_blood_amount = 0, use_cost = FALSE) + if(vessel && regenerating_bodypart) // start fixing broken/destroyed limb + if(remove_blood_amount) + for(var/datum/reagent/blood/B in vessel.reagent_list) + B.volume -= remove_blood_amount + var/regenerating_capacity_penalty = 0 // Used as time till organ regeneration. + if(regenerating_bodypart.status & ORGAN_DESTROYED) + regenerating_capacity_penalty = regenerating_bodypart.regen_bodypart_penalty + else + regenerating_capacity_penalty = regenerating_bodypart.regen_bodypart_penalty/2 + regenerating_organ_time++ + switch(regenerating_organ_time) + if(1) + visible_message("You see odd movement in [src]'s [regenerating_bodypart.name]..."," You [species && species.flags[NO_PAIN] ? "notice" : "feel"] strange vibration on tips of your [regenerating_bodypart.name]... ") + if(10) + visible_message("You hear sickening crunch In [src]'s [regenerating_bodypart.name]...") + if(20) + visible_message("[src]'s [regenerating_bodypart.name] shortly bends...") + if(30) + if(regenerating_capacity_penalty == regenerating_bodypart.regen_bodypart_penalty/2) + visible_message("[src] stirs his [regenerating_bodypart.name]...","You [species && species.flags[NO_PAIN] ? "notice" : "feel"] freedom in moving your [regenerating_bodypart.name]") + else + visible_message("From [src]'s [regenerating_bodypart.parent.name] grows a small meaty sprout...") + if(50) + visible_message("You see something resembling [regenerating_bodypart.name] at [src]'s [regenerating_bodypart.parent.name]...") + if(65) + visible_message("A new [regenerating_bodypart.name] has grown from [src]'s [regenerating_bodypart.parent.name]!","You [species && species.flags[NO_PAIN] ? "notice" : "feel"] your [regenerating_bodypart.name] again!") + if(prob(50)) + emote("scream",1,null,1) + if(regenerating_organ_time >= regenerating_capacity_penalty) // recover organ + regenerating_bodypart.rejuvenate() + regenerating_organ_time = 0 + if(use_cost) + nutrition -= regenerating_capacity_penalty + regenerating_bodypart = null + update_body() + +/mob/living/carbon/human/restrained(check_type = ARMS) + if ((check_type & ARMS) && handcuffed) + return TRUE + if ((check_type & LEGS) && legcuffed) + return TRUE + if (istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) + return TRUE + if (istype(buckled, /obj/structure/stool/bed/nest)) + return TRUE + return 0 + +/mob/living/carbon/human/resist() + ..() + if(usr && !usr.incapacitated()) + var/mob/living/carbon/human/D = usr + if(D.get_species() == DIONA) + var/list/choices = list() + for(var/mob/living/carbon/monkey/diona/V in contents) + if(istype(V) && V.gestalt == src) + choices += V + var/mob/living/carbon/monkey/diona/V = input(D,"Who do wish you to expel from within?") in null|choices + if(V) + to_chat(D, "You wriggle [V] out of your insides.") + V.splitting(D) + +/mob/living/carbon/human/show_inv(mob/user) + var/obj/item/clothing/under/suit = null + if (istype(w_uniform, /obj/item/clothing/under)) + suit = w_uniform + + user.set_machine(src) + var/dat = {" +
                    [name]
                    +

                    +
                    Head(Mask): [(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"] +
                    Left Hand: [(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"] +
                    Right Hand: [(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "Nothing"] +
                    Gloves: [(gloves && !(gloves.flags&ABSTRACT)) ? gloves : "Nothing"] +
                    Eyes: [(glasses && !(glasses.flags&ABSTRACT)) ? glasses : "Nothing"] +
                    Left Ear: [(l_ear && !(l_ear.flags&ABSTRACT) ? l_ear : "Nothing")] +
                    Right Ear: [(r_ear && !(r_ear.flags&ABSTRACT) ? r_ear : "Nothing")] +
                    Head: [(head && !(head.flags&ABSTRACT)) ? head : "Nothing"] +
                    Shoes: [(shoes && !(shoes.flags&ABSTRACT)) ? shoes : "Nothing"] +
                    Belt: [(belt ? belt : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(belt, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] +
                    Uniform: [(w_uniform && !(w_uniform.flags&ABSTRACT)) ? w_uniform : "Nothing"] [(suit) ? ((suit.has_sensor == 1) ? text(" Sensors", src) : "") :] +
                    (Exo)Suit: [(wear_suit && !(wear_suit.flags&ABSTRACT)) ? wear_suit : "Nothing"] +
                    Back: [(back && !(back.flags&ABSTRACT)) ? back : "Nothing"] [((istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] +
                    ID: [(wear_id ? wear_id : "Nothing")] +
                    Suit Storage: [(s_store ? s_store : "Nothing")] [((istype(wear_mask, /obj/item/clothing/mask) && istype(s_store, /obj/item/weapon/tank) && !( internal )) ? text(" Set Internal", src) : "")] +
                    [(handcuffed ? text("Handcuffed") : text("Not Handcuffed"))] +
                    [(legcuffed ? text("Legcuffed") : text(""))] +
                    [(suit) ? ((suit.accessories.len) ? text(" Remove Accessory", src) : "") :] +
                    [(internal ? text("Remove Internal") : "")] +
                    Remove Bandages +
                    Remove Splints +
                    Empty Pockets +
                    Refresh +
                    Close +
                    "} + user << browse(entity_ja(dat), text("window=mob[name];size=340x540")) + onclose(user, "mob[name]") + return + +// called when something steps onto a human +// this could be made more general, but for now just handle mulebot +/mob/living/carbon/human/Crossed(var/atom/movable/AM) + var/obj/machinery/bot/mulebot/MB = AM + if(istype(MB)) + MB.RunOver(src) + +// Get rank from ID, ID inside PDA, PDA, ID in wallet, etc. +/mob/living/carbon/human/proc/get_authentification_rank(if_no_id = "No id", if_no_job = "No job") + var/obj/item/device/pda/pda = wear_id + if (istype(pda)) + if (pda.id) + return pda.id.rank + else + return pda.ownrank + else + var/obj/item/weapon/card/id/id = get_idcard() + if(id) + return id.rank ? id.rank : if_no_job + else + return if_no_id + +//gets assignment from ID or ID inside PDA or PDA itself +//Useful when player do something with computers +/mob/living/carbon/human/proc/get_assignment(if_no_id = "No id", if_no_job = "No job") + var/obj/item/device/pda/pda = wear_id + var/obj/item/weapon/card/id/id = wear_id + if (istype(pda)) + if (pda.id && istype(pda.id, /obj/item/weapon/card/id)) + . = pda.id.assignment + else + . = pda.ownjob + else if (istype(id)) + . = id.assignment + else + return if_no_id + if (!.) + . = if_no_job + return + +//gets name from ID or ID inside PDA or PDA itself +//Useful when player do something with computers +/mob/living/carbon/human/proc/get_authentification_name(if_no_id = "Unknown") + var/obj/item/device/pda/pda = wear_id + var/obj/item/weapon/card/id/id = wear_id + if (istype(pda)) + if (pda.id) + . = pda.id.registered_name + else + . = pda.owner + else if (istype(id)) + . = id.registered_name + else + return if_no_id + return + +//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere +/mob/living/carbon/human/proc/get_visible_name() + if( wear_mask && (wear_mask.flags_inv&HIDEFACE) ) //Wearing a mask which hides our face, use id-name if possible + return get_id_name("Unknown") + if( head && (head.flags_inv&HIDEFACE) ) + return get_id_name("Unknown") //Likewise for hats + if(name_override) + return name_override + var/face_name = get_face_name() + var/id_name = get_id_name("") + if(id_name && (id_name != face_name)) + return "[face_name] (as [id_name])" + return face_name + +//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable +/mob/living/carbon/human/proc/get_face_name() + var/obj/item/organ/external/head/BP = bodyparts_by_name[BP_HEAD] + if( !BP || BP.disfigured || (BP.status & ORGAN_DESTROYED) || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible + return "Unknown" + return real_name + +//gets name from ID or PDA itself, ID inside PDA doesn't matter +//Useful when player is being seen by other mobs +/mob/living/carbon/human/proc/get_id_name(if_no_id = "Unknown") + . = if_no_id + if(istype(wear_id,/obj/item/device/pda)) + var/obj/item/device/pda/P = wear_id + return P.owner + if(wear_id) + var/obj/item/weapon/card/id/I = wear_id.GetID() + if(I) + return I.registered_name + return + +//gets ID card object from special clothes slot or null. +/mob/living/carbon/human/proc/get_idcard() + if(wear_id) + return wear_id.GetID() + +//Removed the horrible safety parameter. It was only being used by ninja code anyways. +//Now checks siemens_coefficient of the affected area by default +/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, def_zone = null, tesla_shock = 0) + if(status_flags & GODMODE) + return 0 //godmode + if(NO_SHOCK in src.mutations) + return 0 //#Z2 no shock with that mutation. + + if(!def_zone) + def_zone = pick(BP_L_ARM , BP_R_ARM) + + var/obj/item/organ/external/BP = get_bodypart(check_zone(def_zone)) + + if(tesla_shock) + var/total_coeff = 1 + if(gloves) + var/obj/item/clothing/gloves/G = gloves + if(G.siemens_coefficient <= 0) + total_coeff -= 0.5 + if(wear_suit) + var/obj/item/clothing/suit/S = wear_suit + if(S.siemens_coefficient <= 0) + total_coeff -= 0.95 + siemens_coeff = total_coeff + else + siemens_coeff *= get_siemens_coefficient_organ(BP) + + if(species) + siemens_coeff *= species.siemens_coefficient + + . = ..(shock_damage, source, siemens_coeff, def_zone, tesla_shock) + if(.) + if(species && species.flags[IS_SYNTHETIC]) + nutrition += . // Electrocute act returns it's shock_damage value. + if(species.flags[NO_PAIN]) // Because for all intents and purposes, if the mob feels no pain, he was not shocked. + . = 0 + electrocution_animation(40) + +/mob/living/carbon/human/Topic(href, href_list) + if (href_list["refresh"]) + if((machine)&&(in_range(src, usr))) + show_inv(machine) + + 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.canmove && !( usr.restrained() ) && in_range(src, usr) && ticker)) //if game hasn't started, can't make an equip_e + var/obj/item/item = usr.get_active_hand() + if(item && (item.flags & (ABSTRACT | DROPDEL))) + return + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) + O.source = usr + O.target = src + O.item = item + O.s_loc = usr.loc + O.t_loc = loc + O.place = href_list["item"] + requests += O + spawn( 0 ) + O.process() + return + + if (href_list["criminal"]) + if(hasHUD(usr,"security")) + + var/modified = 0 + var/perpname = "wot" + 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"]) + + var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Paroled", "Released", "Cancel") + + if(hasHUD(usr, "security")) + if(setcriminal != "Cancel") + R.fields["criminal"] = setcriminal + modified = 1 + + spawn() + hud_updateflag |= 1 << WANTED_HUD + if(istype(usr,/mob/living/carbon/human)) + var/mob/living/carbon/human/U = usr + U.handle_regular_hud_updates() + if(istype(usr,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/U = usr + U.handle_regular_hud_updates() + + if(!modified) + to_chat(usr, "\red Unable to locate a data core entry for this person.") + + if (href_list["secrecord"]) + if(hasHUD(usr,"security")) + var/perpname = "wot" + var/read = 0 + + 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.security) + if (R.fields["id"] == E.fields["id"]) + if(hasHUD(usr,"security")) + to_chat(usr, "Name: [R.fields["name"]] Criminal Status: [R.fields["criminal"]]") + to_chat(usr, "Minor Crimes: [R.fields["mi_crim"]]") + to_chat(usr, "Details: [R.fields["mi_crim_d"]]") + to_chat(usr, "Major Crimes: [R.fields["ma_crim"]]") + to_chat(usr, "Details: [R.fields["ma_crim_d"]]") + to_chat(usr, "Notes: [R.fields["notes"]]") + to_chat(usr, "\[View Comment Log\]") + read = 1 + + if(!read) + to_chat(usr, "\red Unable to locate a data core entry for this person.") + + if (href_list["secrecordComment"]) + if(hasHUD(usr,"security")) + var/perpname = "wot" + var/read = 0 + + 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.security) + if (R.fields["id"] == E.fields["id"]) + if(hasHUD(usr,"security")) + read = 1 + var/counter = 1 + while(R.fields[text("com_[]", counter)]) + to_chat(usr, text("[]", R.fields[text("com_[]", counter)])) + counter++ + if (counter == 1) + to_chat(usr, "No comment found") + to_chat(usr, "\[Add comment\]") + + if(!read) + to_chat(usr, "\red Unable to locate a data core entry for this person.") + + if (href_list["secrecordadd"]) + if(hasHUD(usr,"security")) + var/perpname = "wot" + 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.security) + if (R.fields["id"] == E.fields["id"]) + if(hasHUD(usr,"security")) + var/t1 = sanitize(input("Add Comment:", "Sec. records", null, null) as message) + if ( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"security")) ) + return + var/counter = 1 + while(R.fields[text("com_[]", counter)]) + counter++ + if(istype(usr,/mob/living/carbon/human)) + var/mob/living/carbon/human/U = usr + R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
                    [t1]") + if(istype(usr,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/U = usr + R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
                    [t1]") + + if (href_list["medical"]) + if(hasHUD(usr,"medical")) + var/perpname = "wot" + var/modified = 0 + + 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"]) + + var/setmedical = input(usr, "Specify a new medical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("*SSD*", "*Deceased*", "Physically Unfit", "Active", "Disabled", "Cancel") + + if(hasHUD(usr,"medical")) + if(setmedical != "Cancel") + R.fields["p_stat"] = setmedical + modified = 1 + if(PDA_Manifest.len) + PDA_Manifest.Cut() + + spawn() + if(istype(usr,/mob/living/carbon/human)) + var/mob/living/carbon/human/U = usr + U.handle_regular_hud_updates() + if(istype(usr,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/U = usr + U.handle_regular_hud_updates() + + if(!modified) + to_chat(usr, "\red Unable to locate a data core entry for this person.") + + if (href_list["medrecord"]) + if(hasHUD(usr,"medical")) + var/perpname = "wot" + var/read = 0 + + 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.medical) + if (R.fields["id"] == E.fields["id"]) + if(hasHUD(usr,"medical")) + to_chat(usr, "Name: [R.fields["name"]] Blood Type: [R.fields["b_type"]]") + to_chat(usr, "DNA: [R.fields["b_dna"]]") + to_chat(usr, "Minor Disabilities: [R.fields["mi_dis"]]") + to_chat(usr, "Details: [R.fields["mi_dis_d"]]") + to_chat(usr, "Major Disabilities: [R.fields["ma_dis"]]") + to_chat(usr, "Details: [R.fields["ma_dis_d"]]") + to_chat(usr, "Notes: [R.fields["notes"]]") + to_chat(usr, "\[View Comment Log\]") + read = 1 + + if(!read) + to_chat(usr, "\red Unable to locate a data core entry for this person.") + + if (href_list["medrecordComment"]) + if(hasHUD(usr,"medical")) + var/perpname = "wot" + var/read = 0 + + 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.medical) + if (R.fields["id"] == E.fields["id"]) + if(hasHUD(usr,"medical")) + read = 1 + var/counter = 1 + while(R.fields[text("com_[]", counter)]) + to_chat(usr, text("[]", R.fields[text("com_[]", counter)])) + counter++ + if (counter == 1) + to_chat(usr, "No comment found") + to_chat(usr, "\[Add comment\]") + + if(!read) + to_chat(usr, "\red Unable to locate a data core entry for this person.") + + if (href_list["medrecordadd"]) + if(hasHUD(usr,"medical")) + var/perpname = "wot" + 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.medical) + if (R.fields["id"] == E.fields["id"]) + if(hasHUD(usr,"medical")) + var/t1 = sanitize(input("Add Comment:", "Med. records", null, null) as message) + if ( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"medical")) ) + return + var/counter = 1 + while(R.fields[text("com_[]", counter)]) + counter++ + if(istype(usr,/mob/living/carbon/human)) + var/mob/living/carbon/human/U = usr + R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
                    [t1]") + if(istype(usr,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/U = usr + R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [worldtime2text()], [time2text(world.realtime, "DD/MM")]/[game_year]
                    [t1]") + + if (href_list["lookitem"]) + var/obj/item/I = locate(href_list["lookitem"]) + usr.examinate(I) + + if (href_list["lookmob"]) + var/mob/M = locate(href_list["lookmob"]) + usr.examinate(M) + ..() + return + + +///eyecheck() +///Returns a number between -1 to 2 +/mob/living/carbon/human/eyecheck() + var/number = 0 + if(istype(src.head, /obj/item/clothing/head/welding)) + if(!src.head:up) + number += 2 + if(istype(src.head, /obj/item/clothing/head/helmet/space) && !istype(src.head, /obj/item/clothing/head/helmet/space/sk)) + number += 2 + if(istype(src.glasses, /obj/item/clothing/glasses/thermal)) + number -= 1 + if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses)) + number += 1 + if(istype(src.wear_mask, /obj/item/clothing/mask/gas/welding)) + var/obj/item/clothing/mask/gas/welding/W = src.wear_mask + if(!W.up) + number += 2 + if(istype(src.glasses, /obj/item/clothing/glasses/welding)) + var/obj/item/clothing/glasses/welding/W = src.glasses + if(!W.up) + number += 2 + if(istype(src.glasses, /obj/item/clothing/glasses/night/shadowling)) + number -= 1 + return number + + +/mob/living/carbon/human/IsAdvancedToolUser() + return 1//Humans can use guns and such + + +/mob/living/carbon/human/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 || src.head || src.shoes || src.w_uniform || src.wear_suit || src.glasses || src.l_ear || src.r_ear || src.gloves))) + return 1 + + if( (src.l_hand && !src.l_hand.abstract) || (src.r_hand && !src.r_hand.abstract) ) + return 1 + + return 0 + + +/mob/living/carbon/human/proc/check_dna() + dna.check_integrity(src) + return + +/mob/living/carbon/human/get_species() + + if(!species) + set_species() + + if(dna && dna.mutantrace == "golem") + return "Animated Construct" + + + + return species.name + +/mob/living/carbon/human/proc/play_xylophone() + if(!src.xylophone) + visible_message("\red [src] begins playing his ribcage like a xylophone. It's quite spooky.","\blue You begin to play a spooky refrain on your ribcage.","\red You hear a spooky xylophone melody.") + var/song = pick('sound/effects/xylophone1.ogg','sound/effects/xylophone2.ogg','sound/effects/xylophone3.ogg') + playsound(loc, song, 50, 1, -1) + xylophone = 1 + spawn(1200) + xylophone=0 + return + +/mob/living/carbon/human/proc/vomit() + + if(species.flags[IS_SYNTHETIC]) + return //Machines don't throw up. + + if(!lastpuke) + lastpuke = 1 + to_chat(src, "You feel nauseous...") + spawn(150) //15 seconds until second warning + to_chat(src, "You feel like you are about to throw up!") + spawn(100) //and you have 10 more for mad dash to the bucket + Stun(5) + + src.visible_message("[src] throws up!","You throw up!") + playsound(loc, 'sound/effects/splat.ogg', 50, 1) + + var/turf/location = loc + if (istype(location, /turf/simulated)) + location.add_vomit_floor(src, 1) + + nutrition -= 40 + adjustToxLoss(-3) + spawn(350) //wait 35 seconds before next volley + lastpuke = 0 + +/mob/living/carbon/human/proc/morph() + set name = "Morph" + set category = "Superpower" + + if(stat!=CONSCIOUS) + reset_view(0) + remoteview_target = null + return + + if(!(MORPH in mutations)) + src.verbs -= /mob/living/carbon/human/proc/morph + return + + var/new_facial = input("Please select facial hair color.", "Character Generation",rgb(r_facial,g_facial,b_facial)) as color + 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)) + + var/new_hair = input("Please select hair color.", "Character Generation",rgb(r_hair,g_hair,b_hair)) as color + if(new_facial) + r_hair = hex2num(copytext(new_hair, 2, 4)) + g_hair = hex2num(copytext(new_hair, 4, 6)) + b_hair = hex2num(copytext(new_hair, 6, 8)) + + var/new_eyes = input("Please select eye color.", "Character Generation",rgb(r_eyes,g_eyes,b_eyes)) as color + 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)) + + var/new_tone = input("Please select skin tone level: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation", "[35-s_tone]") as text + + if (!new_tone) + new_tone = 35 + s_tone = max(min(round(text2num(new_tone)), 220), 1) + s_tone = -s_tone + 35 + + // hair + var/list/all_hairs = typesof(/datum/sprite_accessory/hair) - /datum/sprite_accessory/hair + var/list/hairs = list() + + // loop through potential hairs + for(var/x in all_hairs) + var/datum/sprite_accessory/hair/H = new x // create new hair datum based on type x + hairs.Add(H.name) // add hair name to hairs + qdel(H) // delete the hair after it's all done + + var/new_style = input("Please select hair style", "Character Generation",h_style) as null|anything in hairs + + // if new style selected (not cancel) + if (new_style) + h_style = new_style + + // facial hair + var/list/all_fhairs = typesof(/datum/sprite_accessory/facial_hair) - /datum/sprite_accessory/facial_hair + var/list/fhairs = list() + + for(var/x in all_fhairs) + var/datum/sprite_accessory/facial_hair/H = new x + fhairs.Add(H.name) + qdel(H) + + new_style = input("Please select facial style", "Character Generation",f_style) as null|anything in fhairs + + if(new_style) + f_style = new_style + + var/new_gender = alert(usr, "Please select gender.", "Character Generation", "Male", "Female") + if (new_gender) + if(new_gender == "Male") + gender = MALE + else + gender = FEMALE + regenerate_icons() + check_dna() + + visible_message("\blue \The [src] morphs and changes [get_visible_gender() == MALE ? "his" : get_visible_gender() == FEMALE ? "her" : "their"] appearance!", "\blue You change your appearance!", "\red Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!") + +/mob/living/carbon/human/proc/remotesay() //#Z2 + set name = "Project mind" + set category = "Superpower" + + if(stat!=CONSCIOUS) + reset_view(0) + remoteview_target = null + return + + if(!(REMOTE_TALK in src.mutations)) + src.verbs -= /mob/living/carbon/human/proc/remotesay + return + + var/list/names = list() + var/list/creatures = list() + var/list/namecounts = list() + + var/turf/src_turf = get_turf(src) + if(!src_turf) + return + + for(var/mob/living/carbon/M in carbon_list) + var/name = M.real_name + if(name in names) + namecounts[name]++ + name = "[name] ([namecounts[name]])" + else + names.Add(name) + namecounts[name] = 1 + var/turf/temp_turf = get_turf(M) + if(!temp_turf || temp_turf.z != src_turf.z) + continue + creatures[name] += M + + var/mob/target = input ("Who do you want to project your mind to ?") as null|anything in creatures + if(isnull(target)) + return + + var/say = input ("What do you wish to say") + if(!say) + return + else + say = sanitize(say) + var/mob/T = creatures[target] + if(REMOTE_TALK in T.mutations) + T.show_message("\blue You hear [src.real_name]'s voice: [say]") + else + T.show_message("\blue You hear a voice that seems to echo around the room: [say]") + usr.show_message("\blue You project your mind into [T.real_name]: [say]") + for(var/mob/dead/observer/G in observer_list) + G.show_message("Telepathic message from [src] to [T]: [say]") + log_say("Telepathic message from [key_name(src)] to [key_name(T)]: [say]") + +/mob/living/carbon/human/proc/remoteobserve() + set name = "Remote View" + set category = "Superpower" + + if(stat!=CONSCIOUS) + remoteview_target = null + reset_view(0) + return + + if(!(REMOTE_VIEW in src.mutations)) + remoteview_target = null + reset_view(0) + src.verbs -= /mob/living/carbon/human/proc/remoteobserve + return + + if(client.eye != client.mob) + remoteview_target = null + reset_view(0) + return + + if(src.getBrainLoss() >= 100) //#Z2 + to_chat(src, "Too hard to concentrate... Better stop trying!") + src.adjustBrainLoss(7) + if(src.getBrainLoss() >= 125) return + + var/list/names = list() + var/list/creatures = list() + var/list/namecounts = list() + var/target = null //Chosen target. + + for(var/mob/living/carbon/human/M in human_list) //#Z2 only carbon/human for now + var/name = M.real_name + if(!(REMOTE_TALK in src.mutations)) + namecounts++ + name = "([namecounts])" + else + if(name in names) + namecounts[name]++ + name = "[name] ([namecounts[name]])" + else + names.Add(name) + namecounts[name] = 1 + var/turf/temp_turf = get_turf(M) + if((temp_turf.z != ZLEVEL_STATION && temp_turf.z != ZLEVEL_ASTEROID || temp_turf.z != src.z) || M.stat!=CONSCIOUS) //Not on mining or the station. Or dead #Z2 + target on the same Z level as player + continue + creatures[name] += M + + target = input ("Who do you want to project your mind to ?") as null|anything in creatures + + if (!target)//Make sure we actually have a target + return + if(src.getBrainLoss() >= 100) + to_chat(src, "Too hard to concentrate...") + return + if (target && (creatures[target] != src)) + src.adjustBrainLoss(4) + remoteview_target = creatures[target] + reset_view(creatures[target]) + else + remoteview_target = null + reset_view(0) //##Z2 + +/mob/living/carbon/human/proc/get_visible_gender() + if(wear_suit && wear_suit.flags_inv & HIDEJUMPSUIT && ((head && head.flags_inv & HIDEMASK) || wear_mask)) + return NEUTER + return gender + +/mob/living/carbon/human/proc/increase_germ_level(n) + if(gloves) + gloves.germ_level += n + else + germ_level += n + +/mob/living/carbon/human/proc/is_lung_ruptured() + var/obj/item/organ/internal/lungs/IO = organs_by_name[O_LUNGS] + return IO.is_bruised() + +/mob/living/carbon/human/proc/rupture_lung() + var/obj/item/organ/internal/lungs/IO = organs_by_name[O_LUNGS] + + if(!IO.is_bruised()) + src.custom_pain("You feel a stabbing pain in your chest!", 1) + IO.damage = IO.min_bruised_damage + +/* +/mob/living/carbon/human/verb/simulate() + set name = "sim" + //set background = 1 + + var/damage = input("Wound damage","Wound damage") as num + + var/germs = 0 + var/tdamage = 0 + var/ticks = 0 + while (germs < 2501 && ticks < 100000 && round(damage/10)*20) + log_misc("VIRUS TESTING: [ticks] : germs [germs] tdamage [tdamage] prob [round(damage/10)*20]") + ticks++ + if (prob(round(damage/10)*20)) + germs++ + if (germs == 100) + to_chat(world, "Reached stage 1 in [ticks] ticks") + if (germs > 100) + if (prob(10)) + damage++ + germs++ + if (germs == 1000) + to_chat(world, "Reached stage 2 in [ticks] ticks") + if (germs > 1000) + damage++ + germs++ + if (germs == 2500) + to_chat(world, "Reached stage 3 in [ticks] ticks") + to_chat(world, "Mob took [tdamage] tox damage") +*/ +//returns 1 if made bloody, returns 0 otherwise + +/mob/living/carbon/human/add_blood(mob/living/carbon/human/M) + if (!..()) + return 0 + //if this blood isn't already in the list, add it + if(blood_DNA[M.dna.unique_enzymes]) + return 0 //already bloodied with this blood. Cannot add more. + blood_DNA[M.dna.unique_enzymes] = M.dna.b_type + hand_dirt_color = new/datum/dirt_cover/(dirt_overlay) + + src.update_inv_gloves() //handles bloody hands overlays and updating + verbs += /mob/living/carbon/human/proc/bloody_doodle + return 1 //we applied blood to the item + +/mob/living/carbon/human/get_visible_implants(class = 0) + + var/list/visible_implants = list() + for(var/obj/item/organ/external/BP in bodyparts) + for(var/obj/item/weapon/O in BP.implants) + if(!istype(O,/obj/item/weapon/implant) && O.w_class > class) + visible_implants += O + + return(visible_implants) + +/mob/living/carbon/human/proc/handle_embedded_objects() + + for(var/obj/item/organ/external/BP in bodyparts) + if(BP.status & ORGAN_SPLINTED) //Splints prevent movement. + continue + for(var/obj/item/weapon/O in BP.implants) + if(!istype(O,/obj/item/weapon/implant) && prob(5)) //Moving with things stuck in you could be bad. + // All kinds of embedded objects cause bleeding. + var/msg = null + switch(rand(1,3)) + if(1) + msg ="A spike of pain jolts your [BP.name] as you bump [O] inside." + if(2) + msg ="Your movement jostles [O] in your [BP.name] painfully." + if(3) + msg ="[O] in your [BP.name] twists painfully as you move." + to_chat(src, msg) + + BP.take_damage(rand(1,3), 0, 0) + if(!(BP.status & ORGAN_ROBOT)) //There is no blood in protheses. + BP.status |= ORGAN_BLEEDING + src.adjustToxLoss(rand(1,3)) + +/mob/living/carbon/human/verb/check_pulse() + set category = "Object" + set name = "Check pulse" + set desc = "Approximately count somebody's pulse. Requires you to stand still at least 6 seconds." + set src in view(1) + var/self = 0 + + if(usr.stat == 1 || usr.restrained() || !isliving(usr)) return + + if(usr == src) + self = 1 + if(!self) + usr.visible_message("\blue [usr] kneels down, puts \his hand on [src]'s wrist and begins counting their pulse.",\ + "You begin counting [src]'s pulse") + else + usr.visible_message("\blue [usr] begins counting their pulse.",\ + "You begin counting your pulse.") + + if(src.pulse) + to_chat(usr, "\blue [self ? "You have a" : "[src] has a"] pulse! Counting...") + else + to_chat(usr, "\red [src] has no pulse!")//it is REALLY UNLIKELY that a dead person would check his own pulse + return + + to_chat(usr, "Don't move until counting is finished.") + var/time = world.time + sleep(60) + if(usr.l_move_time >= time) //checks if our mob has moved during the sleep() + to_chat(usr, "You moved while counting. Try again.") + else + to_chat(usr, "\blue [self ? "Your" : "[src]'s"] pulse is [src.get_pulse(GETPULSE_HAND)].") + +/mob/living/carbon/human/proc/set_species(new_species, force_organs, default_colour) + + if(!new_species) + if(dna.species) + new_species = dna.species + else + new_species = HUMAN + else + dna.species = new_species + + if(species) + if(species.name == new_species) + return + + if(species.language) + remove_language(species.language) + + species.on_loose(src) + + species = all_species[new_species] + maxHealth = species.total_health + + if(force_organs || !bodyparts.len) + species.create_organs(src) + + if(species.language) + add_language(species.language) + + if(species.additional_languages) + for(var/A in species.additional_languages) + add_language(A) + + if(species.base_color && default_colour) + //Apply colour. + r_skin = hex2num(copytext(species.base_color,2,4)) + g_skin = hex2num(copytext(species.base_color,4,6)) + b_skin = hex2num(copytext(species.base_color,6,8)) + else + r_skin = 0 + g_skin = 0 + b_skin = 0 + + species.handle_post_spawn(src) + species.on_gain(src) + + regenerate_icons() + full_prosthetic = null + + if(species) + return 1 + else + return 0 + +// Unlike set_species(), this proc simply changes owner's specie and thats it. +/mob/living/carbon/human/proc/set_species_soft(new_species) + if(species.name == new_species) + return + + species.on_loose(src) + + species = all_species[new_species] + maxHealth = species.total_health + + species.handle_post_spawn(src) + species.on_gain(src) + + regenerate_icons() + +/mob/living/carbon/human/proc/bloody_doodle() + set category = "IC" + set name = "Write in blood" + set desc = "Use blood on your hands to write a short message on the floor or a wall, murder mystery style." + + if (src.stat) + return + + if (usr != src) + return 0 //something is terribly wrong + + if (!bloody_hands) + verbs -= /mob/living/carbon/human/proc/bloody_doodle + + if (src.gloves) + to_chat(src, "Your [src.gloves] are getting in the way.") + return + + var/turf/simulated/T = src.loc + if (!istype(T)) //to prevent doodling out of mechs and lockers + to_chat(src, "You cannot reach the floor.") + return + + var/direction = input(src,"Which way?","Tile selection") as anything in list("Here","North","South","East","West") + if (direction != "Here") + T = get_step(T,text2dir(direction)) + if (!istype(T)) + to_chat(src, "You cannot doodle there.") + return + + var/num_doodles = 0 + for (var/obj/effect/decal/cleanable/blood/writing/W in T) + num_doodles++ + if (num_doodles > 4) + to_chat(src, "There is no space to write on!") + return + + var/max_length = bloody_hands * 30 //tweeter style + + var/message = sanitize(input(src,"Write a message. It cannot be longer than [max_length] characters.","Blood writing", ""), MAX_MESSAGE_LEN) + + if (message) + var/used_blood_amount = round(length(message) / 30, 1) + bloody_hands = max(0, bloody_hands - used_blood_amount) //use up some blood + + if (length(message) > max_length) + message += "-"//Should crop any letters? No? + to_chat(src, "You ran out of blood to write with!") + + var/obj/effect/decal/cleanable/blood/writing/W = new(T) + W.basedatum = new/datum/dirt_cover(hand_dirt_color) + W.update_icon() + W.message = message + W.add_fingerprint(src) + +/mob/living/carbon/human/verb/examine_ooc() + set name = "Examine OOC" + set category = "OOC" + set src in oview() + + if(!usr || !src) return + + to_chat(usr, "OOC-info: [src]") + if(metadata) + to_chat(usr, "[metadata]") + else + to_chat(usr, "Nothing of interest...") + +/mob/living/carbon/try_inject(mob/living/user, error_msg, instant, stealth, pierce_armor) + if(istype(user)) + if(user.is_busy()) + return + + if(!user.IsAdvancedToolUser()) + if(error_msg) + to_chat(user, "You have no idea, how to use this!") + return FALSE + + if (HULK in user.mutations) // TODO - meaty fingers or something like that. + if(error_msg) + to_chat(user, "You don't have the dexterity to do this!") + return FALSE + + var/hunt_injection_port = FALSE + + switch(check_thickmaterial(target_zone = user.zone_sel.selecting)) + if(NOLIMB) + if(error_msg) + to_chat(user, "[src] has no such body part, try to inject somewhere else.") + return FALSE + if(THICKMATERIAL) + if(!pierce_armor) + if(error_msg) + to_chat(user, "There is no exposed flesh or thin material [user.zone_sel.selecting == BP_HEAD ? "on their head" : "on their body"] to inject into.") + return FALSE + if(PHORONGUARD) + if(!pierce_armor) + if(user.a_intent == I_HURT) + if(error_msg) + to_chat(user, "There is no exposed flesh or thin material [user.zone_sel.selecting == BP_HEAD ? "on their head" : "on their body"] to inject into.") + return FALSE + hunt_injection_port = TRUE + + if(isSynthetic(user.zone_sel.selecting)) + if(error_msg) + to_chat(user, "You are trying to inject [src]'s synthetic body part!") + return FALSE + + if(!instant) + var/time_to_inject = HUMAN_STRIP_DELAY + if(hunt_injection_port) // takes additional time + if(!stealth) + user.visible_message("[user] begins hunting for an injection port on [src]'s suit!") + if(!do_mob(user, src, time_to_inject / 2, TRUE)) + return FALSE + + if(!stealth) + user.visible_message("[user] is trying to inject [src]!") + + if(!do_mob(user, src, time_to_inject, TRUE)) + return FALSE + + if(!stealth) + if(user != src) + user.visible_message("[user] injects [src] with the syringe!") + else + to_chat(user, "You inject [src] with the injector.") + to_chat(src, "You feel a tiny prick!") + + return TRUE + +/obj/screen/leap + name = "toggle leap" + icon = 'icons/mob/screen1_action.dmi' + icon_state = "action" + + var/on = FALSE + var/time_used = 0 + var/cooldown = 10 SECONDS + + +/obj/screen/leap/atom_init() + . = ..() + overlays += image(icon, "leap") + update_icon() + +/obj/screen/leap/update_icon() + icon_state = "[initial(icon_state)]_[on]" + +/obj/screen/leap/Click() + if(ishuman(usr)) + var/mob/living/carbon/human/H = usr + H.toggle_leap() + +/mob/living/carbon/human/proc/toggle_leap(message = 1) + leap_icon.on = !leap_icon.on + leap_icon.update_icon() + if(message) + to_chat(src, "You will [leap_icon.on ? "now" : "no longer"] leap at enemies!") + +/mob/living/carbon/human/ClickOn(atom/A, params) + if(leap_icon && leap_icon.on && A != src) + leap_at(A) + else + ..() + +#define MAX_LEAP_DIST 4 + +/mob/living/carbon/human/proc/leap_at(atom/A) + if(leap_icon.time_used > world.time) + to_chat(src, "You are too fatigued to leap right now!") + return + + if(status_flags & LEAPING) // Leap while you leap, so you can leap while you leap + return + + if(!has_gravity(src)) + to_chat(src, "It is unsafe to leap without gravity!") + return + + if(incapacitated(LEGS) || buckled || pinned.len || stance_damage >= 4) //because you need !restrained legs to leap + to_chat(src, "You cannot leap in your current state.") + return + + leap_icon.time_used = world.time + leap_icon.cooldown + status_flags |= LEAPING + stop_pulling() + + + var/prev_intent = a_intent + a_intent_change("hurt") + + if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/space/vox/stealth)) + for(var/obj/item/clothing/suit/space/vox/stealth/V in list(wear_suit)) + if(V.on) + V.overload() + + toggle_leap() + + throw_at(A, MAX_LEAP_DIST, 2, null, FALSE, TRUE, CALLBACK(src, .leap_end, prev_intent)) + +/mob/living/carbon/human/proc/leap_end(prev_intent) + status_flags &= ~LEAPING + a_intent_change(prev_intent) + +/mob/living/carbon/human/throw_impact(atom/A) + if(!(status_flags & LEAPING)) + return ..() + + if(isliving(A)) + var/mob/living/L = A + L.visible_message("\The [src] leaps at [L]!", "[src] leaps on you!") + if(issilicon(A)) + L.Weaken(1) //Only brief stun + step_towards(src, L) + else + L.Weaken(5) + sleep(2) // Runtime prevention (infinite bump() calls on hulks) + step_towards(src, L) + + if(restrained()) //You can leap when you hands are cuffed, but you can't grab + return + + var/use_hand = "left" + if(l_hand) + if(r_hand) + to_chat(src, "You need to have one hand free to grab someone.") + return + else + use_hand = "right" + + visible_message("\The [src] seizes [L] aggressively!") + + var/obj/item/weapon/grab/G = new(src, L) + if(use_hand == "left") + l_hand = G + else + r_hand = G + + G.state = GRAB_AGGRESSIVE + G.icon_state = "grabbed1" + G.synch() + L.grabbed_by += G + + else if(A.density) + visible_message("[src] smashes into [A]!", "You smashes into [A]!") + weakened = 2 + + update_canmove() + +#undef MAX_LEAP_DIST + +/mob/living/carbon/human/proc/gut() + set category = "IC" + set name = "Gut" + set desc = "While grabbing someone aggressively, rip their guts out or tear them apart." + + if(last_special > world.time) + return + + if(stat || paralysis || stunned || weakened || lying) + to_chat(src, "\red You cannot do that in your current state.") + return + + var/obj/item/weapon/grab/G = locate() in src + if(!G || !istype(G)) + to_chat(src, "\red You are not grabbing anyone.") + return + + if(G.state < GRAB_AGGRESSIVE) + to_chat(src, "\red You must have an aggressive grab to gut your prey!") + return + + last_special = world.time + 50 + + visible_message("\The [src] rips viciously at \the [G.affecting]'s body with its claws!") + + if(istype(G.affecting,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = G.affecting + H.apply_damage(50,BRUTE) + if(H.stat == DEAD) + H.gib() + else + var/mob/living/M = G.affecting + if(!istype(M)) return //wut + M.apply_damage(50,BRUTE) + if(M.stat == DEAD) + M.gib() + +/mob/living/carbon/human/has_eyes() + if(organs_by_name[O_EYES]) + var/obj/item/organ/internal/IO = organs_by_name[O_EYES] + if(istype(IO)) + return 1 + return 0 + +/mob/living/carbon/human/slip(slipped_on, stun_duration=4, weaken_duration=2) + if(shoes && (shoes.flags & NOSLIP)) + return FALSE + return ..(slipped_on,stun_duration, weaken_duration) + +//Turns a mob black, flashes a skeleton overlay +//Just like a cartoon! +/mob/living/carbon/human/proc/electrocution_animation(anim_duration) + //TG... + //Handle mutant parts if possible + //if(species) + // species.handle_mutant_bodyparts(src,"black") + // species.handle_hair(src,"black") + // species.update_color(src,"black") + // overlays += "electrocuted_base" + // spawn(anim_duration) + // if(src) + // if(dna && dna.species) + // dna.species.handle_mutant_bodyparts(src) + // dna.species.handle_hair(src) + // dna.species.update_color(src) + // overlays -= "electrocuted_base" + //else //or just do a generic animation + var/list/viewing = list() + for(var/mob/M in viewers(src)) + if(M.client) + viewing += M.client + flick_overlay(image(icon,src,"electrocuted_generic",MOB_LAYER+1), viewing, anim_duration) + +/mob/living/carbon/human/proc/should_have_organ(organ_check) + + var/obj/item/organ/external/BP + if(organ_check in list(O_HEART, O_LUNGS)) + BP = bodyparts_by_name[BP_CHEST] + else if(organ_check in list(O_LIVER, O_KIDNEYS)) + BP = bodyparts_by_name[BP_GROIN] + + if(BP && (BP.status & ORGAN_ROBOT)) + return FALSE + return species.has_organ[organ_check] + +/mob/living/carbon/human/can_eat(flags = DIET_ALL) + return species && (species.dietflags & flags) + +/mob/living/carbon/human/get_taste_sensitivity() + if(species) + return species.taste_sensitivity + else + return 1 diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index a11ffcef7806..20a56c76b48e 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -1,297 +1,297 @@ -/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M) - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - to_chat(M, "No attacking people at spawn, you jackass.") - return - ..() - - if((M != src) && check_shields(0, M.name, get_dir(M,src))) - visible_message("\red [M] attempted to touch [src]!") - return 0 - - if(M.wear_suit && istype(M.wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/V = M.wear_suit - V.attack_reaction(M, REACTION_INTERACT_UNARMED, src) - - if(src.wear_suit && istype(src.wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/V = src.wear_suit - V.attack_reaction(src, REACTION_ATACKED, M) - - if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) - M.do_attack_animation(src) - var/obj/item/clothing/gloves/G = M.gloves - if(G.cell) - if(M.a_intent == "hurt")//Stungloves. Any contact will stun the alien. - if(G.cell.charge >= 2500) - G.cell.use(2500) - G.update_icon() - var/mob/living/carbon/human/target = src - var/obj/item/organ/external/BP = get_bodypart(M.zone_sel.selecting) // We're checking the outside, buddy! - var/calc_power - if((prob(25) && !istype(G, /obj/item/clothing/gloves/yellow)) && (target != M)) - visible_message("\red [M] accidentally touched \himself with the stun gloves!") - M.attack_log += text("\[[time_stamp()]\] Attempted to touch [src.name] ([src.ckey]) with stungloves") - src.attack_log += text("\[[time_stamp()]\] Has been unsuccessfully touched with stungloves by [M.name] ([M.ckey])") - msg_admin_attack("[M.name] ([M.ckey]) failed to stun [src.name] ([src.ckey]) with stungloves (JMP)") - target = M - calc_power = 150 * get_siemens_coefficient_organ(BP) - else - visible_message("\red [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])") - msg_admin_attack("[M.name] ([M.ckey]) stungloved [src.name] ([src.ckey]) (JMP)") - calc_power = 100 * get_siemens_coefficient_organ(BP) - target.apply_effects(0,0,0,0,2,0,0,calc_power) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() - s.set_up(3, 1, target) - s.start() - return 1 - else - to_chat(M, "\red Not enough charge! ") - visible_message("\red [src] has been touched with the stun gloves by [M]!") - return - - if(istype(M.gloves , /obj/item/clothing/gloves/boxing)) - - var/damage = rand(0, 9) - if(!damage) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("\red [M] has attempted to punch [src]!") - return 0 - var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(M.zone_sel.selecting)] - var/armor_block = run_armor_check(BP, "melee") - - if(HULK in M.mutations) damage += 5 - if(dna && dna.mutantrace == "adamantine") - damage += 5 - - playsound(loc, "punch", 25, 1, -1) - - visible_message("\red [M] has punched [src]!") - - apply_damage(damage, HALLOSS, BP, armor_block) - if(damage >= 9) - visible_message("\red [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("help") - if(health < config.health_threshold_crit && health > config.health_threshold_dead) - if(M.species && M.species.flags[NO_BREATHE]) - to_chat(M, "Your species can not perform CPR!") - return FALSE - if(species && species.flags[NO_BREATHE]) - to_chat(M, "You can not perform CPR on these species!") - return FALSE - if((M.head && (M.head.flags & HEADCOVERSMOUTH)) || (M.wear_mask && (M.wear_mask.flags & MASKCOVERSMOUTH))) - to_chat(M, "Remove your mask!") - return FALSE - if((head && (head.flags & HEADCOVERSMOUTH)) || (wear_mask && (wear_mask.flags & MASKCOVERSMOUTH))) - to_chat(M, "Remove his mask!") - return FALSE - - 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 - else if(!(M == src && apply_pressure(M, M.zone_sel.selecting))) - help_shake_act(M) - return 1 - - if("grab") - if(M == src || anchored || M.lying) - return 0 - for(var/obj/item/weapon/grab/G in src.grabbed_by) - if(G.assailant == M) - to_chat(M, "You already grabbed [src].") - return - if(w_uniform) - w_uniform.add_fingerprint(M) - - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) - if(buckled) - 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("hurt") - M.do_attack_animation(src) - var/datum/unarmed_attack/attack = M.species.unarmed - - M.attack_log += text("\[[time_stamp()]\] [pick(attack.attack_verb)]ed [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been [pick(attack.attack_verb)]ed by [M.name] ([M.ckey])") - msg_admin_attack("[key_name(M)] [pick(attack.attack_verb)]ed [key_name(src)]") - - var/damage = rand(0, 5)//BS12 EDIT - if(!damage) - playsound(loc, attack.miss_sound, 25, 1, -1) - visible_message("\red [M] tried to [pick(attack.attack_verb)] [src]!") - return 0 - - - - var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(M.zone_sel.selecting)] - var/armor_block = run_armor_check(BP, "melee") - - if(HULK in M.mutations) damage += 5 - - - playsound(loc, attack.attack_sound, 25, 1, -1) - - visible_message("\red [M] [pick(attack.attack_verb)]ed [src]!") - //Rearranged, so claws don't increase weaken chance. - if(damage >= 5 && prob(50)) - visible_message("\red [M] has weakened [src]!") - apply_effect(2, WEAKEN, armor_block) - - damage += attack.damage - apply_damage(damage, BRUTE, BP, armor_block, attack.damage_flags()) - - - if("disarm") - M.do_attack_animation(src) - 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])") - - msg_admin_attack("[key_name(M)] disarmed [src.name] ([src.ckey])") - - if(w_uniform) - w_uniform.add_fingerprint(M) - var/obj/item/organ/external/BP = bodyparts_by_name[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("[src]'s [W] 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) - - var/randn = rand(1, 100) - if (randn <= 25) - var/armor_check = run_armor_check(BP, "melee") - apply_effect(3, WEAKEN, armor_check) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - if(armor_check < 2) - visible_message("[M] has pushed [src]!") - else - visible_message("[M] attempted to push [src]!") - return - - var/talked = 0 // BubbleWrap - - if(randn <= 60) - //BubbleWrap: Disarming breaks a pull - if(pulling) - visible_message("\red [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("\red [M] has broken [src]'s grip on [lgrab.affecting]!") - talked = 1 - spawn(1) - qdel(lgrab) - if(istype(r_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/rgrab = r_hand - if(rgrab.affecting) - visible_message("\red [M] has broken [src]'s grip on [rgrab.affecting]!") - talked = 1 - spawn(1) - qdel(rgrab) - //End BubbleWrap - - if(!talked) //BubbleWrap - if( (l_hand && l_hand.flags & ABSTRACT) || (r_hand && r_hand.flags & ABSTRACT) ) - return - else - drop_item() - visible_message("\red [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("\red [M] attempted to disarm [src]!") - return - -/* - We want to ensure that a mob may only apply pressure to one bodypart of one mob at any given time. Currently this is done mostly implicitly through - the behaviour of do_after() and the fact that applying pressure to someone else requires a grab: - - If you are applying pressure to yourself and attempt to grab someone else, you'll change what you are holding in your active hand which will stop do_mob() - If you are applying pressure to another and attempt to apply pressure to yourself, you'll have to switch to an empty hand which will also stop do_mob() - Changing targeted zones should also stop do_mob(), preventing you from applying pressure to more than one body part at once. -*/ -/mob/living/carbon/human/proc/apply_pressure(mob/living/user, target_zone) - var/obj/item/organ/external/BP = get_bodypart(target_zone) - if(!BP || !(BP.status & ORGAN_BLEEDING) || (BP.status & ORGAN_ROBOT)) - return FALSE - - if(user.is_busy()) - return FALSE - - if(BP.applied_pressure) - var/message = "[ismob(BP.applied_pressure)? "Someone" : "\A [BP.applied_pressure]"] is already applying pressure to [user == src? "your [BP.name]" : "[src]'s [BP.name]"]." - to_chat(user, message) - return FALSE - - if(user == src) - user.visible_message("\The [user] starts applying pressure to \his [BP.name]!", "You start applying pressure to your [BP.name]!") - else - user.visible_message("\The [user] starts applying pressure to [src]'s [BP.name]!", "You start applying pressure to [src]'s [BP.name]!") - - INVOKE_ASYNC(src, .proc/do_apply_pressure, user, target_zone, BP) - - return TRUE - -/mob/living/carbon/human/proc/do_apply_pressure(mob/living/user, target_zone, obj/item/organ/external/BP) - BP.applied_pressure = user - - //apply pressure as long as they stay still and keep grabbing - do_mob(user, src, INFINITY, target_zone, progress = 0) - - BP.applied_pressure = null - - if(user == src) - user.visible_message("\The [user] stops applying pressure to \his [BP.name]!", "You stop applying pressure to your [BP.name]!") - else - user.visible_message("\The [user] stops applying pressure to [src]'s [BP.name]!", "You stop applying pressure to [src]'s [BP.name]!") - -/mob/living/carbon/human/proc/afterattack(atom/target, mob/living/user, inrange, params) - return +/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M) + if (istype(loc, /turf) && istype(loc.loc, /area/start)) + to_chat(M, "No attacking people at spawn, you jackass.") + return + ..() + + if((M != src) && check_shields(0, M.name, get_dir(M,src))) + visible_message("\red [M] attempted to touch [src]!") + return 0 + + if(M.wear_suit && istype(M.wear_suit, /obj/item/clothing/suit)) + var/obj/item/clothing/suit/V = M.wear_suit + V.attack_reaction(M, REACTION_INTERACT_UNARMED, src) + + if(src.wear_suit && istype(src.wear_suit, /obj/item/clothing/suit)) + var/obj/item/clothing/suit/V = src.wear_suit + V.attack_reaction(src, REACTION_ATACKED, M) + + if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) + M.do_attack_animation(src) + var/obj/item/clothing/gloves/G = M.gloves + if(G.cell) + if(M.a_intent == "hurt")//Stungloves. Any contact will stun the alien. + if(G.cell.charge >= 2500) + G.cell.use(2500) + G.update_icon() + var/mob/living/carbon/human/target = src + var/obj/item/organ/external/BP = get_bodypart(M.zone_sel.selecting) // We're checking the outside, buddy! + var/calc_power + if((prob(25) && !istype(G, /obj/item/clothing/gloves/yellow)) && (target != M)) + visible_message("\red [M] accidentally touched \himself with the stun gloves!") + M.attack_log += text("\[[time_stamp()]\] Attempted to touch [src.name] ([src.ckey]) with stungloves") + src.attack_log += text("\[[time_stamp()]\] Has been unsuccessfully touched with stungloves by [M.name] ([M.ckey])") + msg_admin_attack("[M.name] ([M.ckey]) failed to stun [src.name] ([src.ckey]) with stungloves (JMP)") + target = M + calc_power = 150 * get_siemens_coefficient_organ(BP) + else + visible_message("\red [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])") + msg_admin_attack("[M.name] ([M.ckey]) stungloved [src.name] ([src.ckey]) (JMP)") + calc_power = 100 * get_siemens_coefficient_organ(BP) + target.apply_effects(0,0,0,0,2,0,0,calc_power) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + s.set_up(3, 1, target) + s.start() + return 1 + else + to_chat(M, "\red Not enough charge! ") + visible_message("\red [src] has been touched with the stun gloves by [M]!") + return + + if(istype(M.gloves , /obj/item/clothing/gloves/boxing)) + + var/damage = rand(0, 9) + if(!damage) + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("\red [M] has attempted to punch [src]!") + return 0 + var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(M.zone_sel.selecting)] + var/armor_block = run_armor_check(BP, "melee") + + if(HULK in M.mutations) damage += 5 + if(dna && dna.mutantrace == "adamantine") + damage += 5 + + playsound(loc, "punch", 25, 1, -1) + + visible_message("\red [M] has punched [src]!") + + apply_damage(damage, HALLOSS, BP, armor_block) + if(damage >= 9) + visible_message("\red [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("help") + if(health < config.health_threshold_crit && health > config.health_threshold_dead) + if(M.species && M.species.flags[NO_BREATHE]) + to_chat(M, "Your species can not perform CPR!") + return FALSE + if(species && species.flags[NO_BREATHE]) + to_chat(M, "You can not perform CPR on these species!") + return FALSE + if((M.head && (M.head.flags & HEADCOVERSMOUTH)) || (M.wear_mask && (M.wear_mask.flags & MASKCOVERSMOUTH))) + to_chat(M, "Remove your mask!") + return FALSE + if((head && (head.flags & HEADCOVERSMOUTH)) || (wear_mask && (wear_mask.flags & MASKCOVERSMOUTH))) + to_chat(M, "Remove his mask!") + return FALSE + + 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 + else if(!(M == src && apply_pressure(M, M.zone_sel.selecting))) + help_shake_act(M) + return 1 + + if("grab") + if(M == src || anchored || M.lying) + return 0 + for(var/obj/item/weapon/grab/G in src.grabbed_by) + if(G.assailant == M) + to_chat(M, "You already grabbed [src].") + return + if(w_uniform) + w_uniform.add_fingerprint(M) + + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) + if(buckled) + 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("hurt") + M.do_attack_animation(src) + var/datum/unarmed_attack/attack = M.species.unarmed + + M.attack_log += text("\[[time_stamp()]\] [pick(attack.attack_verb)]ed [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] Has been [pick(attack.attack_verb)]ed by [M.name] ([M.ckey])") + msg_admin_attack("[key_name(M)] [pick(attack.attack_verb)]ed [key_name(src)]") + + var/damage = rand(0, 5)//BS12 EDIT + if(!damage) + playsound(loc, attack.miss_sound, 25, 1, -1) + visible_message("\red [M] tried to [pick(attack.attack_verb)] [src]!") + return 0 + + + + var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(M.zone_sel.selecting)] + var/armor_block = run_armor_check(BP, "melee") + + if(HULK in M.mutations) damage += 5 + + + playsound(loc, attack.attack_sound, 25, 1, -1) + + visible_message("\red [M] [pick(attack.attack_verb)]ed [src]!") + //Rearranged, so claws don't increase weaken chance. + if(damage >= 5 && prob(50)) + visible_message("\red [M] has weakened [src]!") + apply_effect(2, WEAKEN, armor_block) + + damage += attack.damage + apply_damage(damage, BRUTE, BP, armor_block, attack.damage_flags()) + + + if("disarm") + M.do_attack_animation(src) + 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])") + + msg_admin_attack("[key_name(M)] disarmed [src.name] ([src.ckey])") + + if(w_uniform) + w_uniform.add_fingerprint(M) + var/obj/item/organ/external/BP = bodyparts_by_name[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("[src]'s [W] 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) + + var/randn = rand(1, 100) + if (randn <= 25) + var/armor_check = run_armor_check(BP, "melee") + apply_effect(3, WEAKEN, armor_check) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + if(armor_check < 2) + visible_message("[M] has pushed [src]!") + else + visible_message("[M] attempted to push [src]!") + return + + var/talked = 0 // BubbleWrap + + if(randn <= 60) + //BubbleWrap: Disarming breaks a pull + if(pulling) + visible_message("\red [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("\red [M] has broken [src]'s grip on [lgrab.affecting]!") + talked = 1 + spawn(1) + qdel(lgrab) + if(istype(r_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/rgrab = r_hand + if(rgrab.affecting) + visible_message("\red [M] has broken [src]'s grip on [rgrab.affecting]!") + talked = 1 + spawn(1) + qdel(rgrab) + //End BubbleWrap + + if(!talked) //BubbleWrap + if( (l_hand && l_hand.flags & ABSTRACT) || (r_hand && r_hand.flags & ABSTRACT) ) + return + else + drop_item() + visible_message("\red [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("\red [M] attempted to disarm [src]!") + return + +/* + We want to ensure that a mob may only apply pressure to one bodypart of one mob at any given time. Currently this is done mostly implicitly through + the behaviour of do_after() and the fact that applying pressure to someone else requires a grab: + + If you are applying pressure to yourself and attempt to grab someone else, you'll change what you are holding in your active hand which will stop do_mob() + If you are applying pressure to another and attempt to apply pressure to yourself, you'll have to switch to an empty hand which will also stop do_mob() + Changing targeted zones should also stop do_mob(), preventing you from applying pressure to more than one body part at once. +*/ +/mob/living/carbon/human/proc/apply_pressure(mob/living/user, target_zone) + var/obj/item/organ/external/BP = get_bodypart(target_zone) + if(!BP || !(BP.status & ORGAN_BLEEDING) || (BP.status & ORGAN_ROBOT)) + return FALSE + + if(user.is_busy()) + return FALSE + + if(BP.applied_pressure) + var/message = "[ismob(BP.applied_pressure)? "Someone" : "\A [BP.applied_pressure]"] is already applying pressure to [user == src? "your [BP.name]" : "[src]'s [BP.name]"]." + to_chat(user, message) + return FALSE + + if(user == src) + user.visible_message("\The [user] starts applying pressure to \his [BP.name]!", "You start applying pressure to your [BP.name]!") + else + user.visible_message("\The [user] starts applying pressure to [src]'s [BP.name]!", "You start applying pressure to [src]'s [BP.name]!") + + INVOKE_ASYNC(src, .proc/do_apply_pressure, user, target_zone, BP) + + return TRUE + +/mob/living/carbon/human/proc/do_apply_pressure(mob/living/user, target_zone, obj/item/organ/external/BP) + BP.applied_pressure = user + + //apply pressure as long as they stay still and keep grabbing + do_mob(user, src, INFINITY, target_zone, progress = 0) + + BP.applied_pressure = null + + if(user == src) + user.visible_message("\The [user] stops applying pressure to \his [BP.name]!", "You stop applying pressure to your [BP.name]!") + else + user.visible_message("\The [user] stops applying pressure to [src]'s [BP.name]!", "You stop applying pressure to [src]'s [BP.name]!") + +/mob/living/carbon/human/proc/afterattack(atom/target, mob/living/user, 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 6eaa02f4715c..dfcbe5eca291 100644 --- a/code/modules/mob/living/carbon/human/human_attackpaw.dm +++ b/code/modules/mob/living/carbon/human/human_attackpaw.dm @@ -1,23 +1,23 @@ -/mob/living/carbon/human/attack_paw(mob/M) - ..() - if (M.a_intent == "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("\red [M.name] has bit []!", src), 1) - - var/damage = rand(1, 3) - var/dam_zone = pick(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) - var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(dam_zone)] - apply_damage(damage, BRUTE, BP, run_armor_check(BP, "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) + ..() + if (M.a_intent == "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("\red [M.name] has bit []!", src), 1) + + var/damage = rand(1, 3) + var/dam_zone = pick(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) + var/obj/item/organ/external/BP = bodyparts_by_name[ran_zone(dam_zone)] + apply_damage(damage, BRUTE, BP, run_armor_check(BP, "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 a9bc02b960b7..1299b3a7259d 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -1,359 +1,359 @@ -//Updates the mob's health from bodyparts 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/obj/item/organ/external/BP in bodyparts) // hardcoded to streamline things a bit - if((BP.status & ORGAN_ROBOT) && !BP.vital) - continue // *non-vital* robot limbs don't count towards shock and crit - total_brute += BP.brute_dam - total_burn += BP.burn_dam - - health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute - - //TODO: fix husking - if( ((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD) - ChangeToHusk() - return - -/mob/living/carbon/human/apply_effect(effect = 0, effecttype = STUN, blocked = 0) - if((effecttype == AGONY || effecttype == STUTTER) && species && species.flags[NO_PAIN]) - return FALSE - ..() - -// ============================================= - -/mob/living/carbon/human/getBrainLoss() - if(status_flags & GODMODE) - return 0 - - if(species.brain_mod == 0 || !should_have_organ(O_BRAIN)) - return 0 - - var/res = brainloss - var/obj/item/organ/internal/brain/IO = organs_by_name[O_BRAIN] - - if(!IO) - return maxHealth * 2 - if(IO.is_bruised()) - res += 20 - if(IO.is_broken()) - res += 50 - - res = min(res, maxHealth * 2) - - return res - -/mob/living/carbon/human/adjustBrainLoss(amount) - if(species.brain_mod == 0 || !should_have_organ(O_BRAIN)) - brainloss = 0 - else - amount = amount * species.brain_mod - ..(amount) - -/mob/living/carbon/human/setBrainLoss(amount) - if(species.brain_mod == 0 || !should_have_organ(O_BRAIN)) - brainloss = 0 - else - ..() - -// ============================================= - -//These procs fetch a cumulative total damage from all bodyparts -/mob/living/carbon/human/getBruteLoss() - var/amount = 0 - for(var/obj/item/organ/external/BP in bodyparts) - if((BP.status & ORGAN_ROBOT) && !BP.vital) - continue // robot limbs don't count towards shock and crit - amount += BP.brute_dam - return amount - -/mob/living/carbon/human/adjustBruteLoss(amount) - if(amount > 0) - take_overall_damage(amount, 0) - else - heal_overall_damage(-amount, 0) - -// ============================================= - -/mob/living/carbon/human/getFireLoss() - var/amount = 0 - for(var/obj/item/organ/external/BP in bodyparts) - if((BP.status & ORGAN_ROBOT) && !BP.vital) - continue // robot limbs don't count towards shock and crit - amount += BP.burn_dam - return amount - -/mob/living/carbon/human/adjustFireLoss(amount) - if(amount > 0) - if(RESIST_HEAT in mutations) - return - take_overall_damage(0, amount) - else - heal_overall_damage(0, -amount) - -// ============================================= - -/mob/living/carbon/human/getToxLoss() - if(species.tox_mod == 0 || species.flags[NO_BLOOD]) - toxloss = 0 - return ..() - -/mob/living/carbon/human/adjustToxLoss(amount) - if(species.tox_mod == 0 || species.flags[NO_BLOOD]) - toxloss = 0 - else - amount = amount * species.tox_mod - ..(amount) - -/mob/living/carbon/human/setToxLoss(amount) - if(species.tox_mod == 0 || species.flags[NO_BLOOD]) - toxloss = 0 - else - ..() - -// ============================================= - -/mob/living/carbon/human/getOxyLoss() - if(species.oxy_mod == 0 || !should_have_organ(O_LUNGS)) - oxyloss = 0 - return ..() - -/mob/living/carbon/human/adjustOxyLoss(amount) - if(species.oxy_mod == 0 || !should_have_organ(O_LUNGS)) - oxyloss = 0 - else - amount = amount * species.oxy_mod - ..(amount) - -/mob/living/carbon/human/setOxyLoss(amount) - if(species.oxy_mod == 0 || !should_have_organ(O_LUNGS)) - oxyloss = 0 - else - ..() - -// ============================================= - -/mob/living/carbon/human/adjustCloneLoss(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/candidates = list() - for (var/obj/item/organ/external/BP in bodyparts) - if(!(BP.status & ORGAN_MUTATED)) - candidates += BP - if (candidates.len) - var/obj/item/organ/external/BP = pick(candidates) - BP.mutate() - to_chat(src, "Something is not right with your [BP.name]...") - return - else - if (prob(heal_prob)) - for (var/obj/item/organ/external/BP in bodyparts) - if (BP.status & ORGAN_MUTATED) - BP.unmutate() - to_chat(src, "Your [BP.name] is shaped normally again.") - return - - if (getCloneLoss() < 1) - for (var/obj/item/organ/external/BP in bodyparts) - if (BP.status & ORGAN_MUTATED) - BP.unmutate() - to_chat(src, "Your [BP.name] is shaped normally again.") - hud_updateflag |= 1 << HEALTH_HUD - -// ============================================= - -/mob/living/carbon/human/Stun(amount) - if(HULK in mutations) - stunned = 0 - else - ..() - -/mob/living/carbon/human/Weaken(amount) - if(HULK in mutations) - weakened = 0 - else - ..() - -/mob/living/carbon/human/Paralyse(amount) - if(HULK in mutations) - paralysis = 0 - else - ..() - -//////////////////////////////////////////// - -//Returns a list of damaged bodyparts -/mob/living/carbon/human/proc/get_damaged_bodyparts(brute, burn) - var/list/parts = list() - for(var/obj/item/organ/external/BP in bodyparts) - if((brute && BP.brute_dam) || (burn && BP.burn_dam)) - parts += BP - return parts - -//Returns a list of damageable bodyparts -/mob/living/carbon/human/proc/get_damageable_bodyparts() - var/list/parts = list() - for(var/obj/item/organ/external/BP in bodyparts) - if(BP.is_damageable()) - parts += BP - 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_bodypart_damage(brute, burn) - var/list/parts = get_damaged_bodyparts(brute, burn) - if(!parts.len) - return - var/obj/item/organ/external/BP = pick(parts) - if(BP.heal_damage(brute, burn)) - hud_updateflag |= 1 << HEALTH_HUD - updatehealth() - -//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_bodypart_damage(brute, burn, sharp = 0, edge = 0) - var/list/parts = get_damageable_bodyparts() - if(!parts.len) - return - - var/obj/item/organ/external/BP = pick(parts) - var/damage_flags = (sharp ? DAM_SHARP : 0) | (edge ? DAM_EDGE : 0) - - if(BP.take_damage(brute, burn, damage_flags)) - hud_updateflag |= 1 << HEALTH_HUD - updatehealth() - speech_problem_flag = 1 - - -//Heal MANY external bodyparts, in random order -/mob/living/carbon/human/heal_overall_damage(brute, burn) - var/list/parts = get_damaged_bodyparts(brute, burn) - while(parts.len && (brute > 0 || burn > 0)) - var/obj/item/organ/external/BP = pick(parts) - var/brute_was = BP.brute_dam - var/burn_was = BP.burn_dam - BP.heal_damage(brute, burn) - brute -= (brute_was - BP.brute_dam) - burn -= (burn_was - BP.burn_dam) - parts -= BP - updatehealth() - hud_updateflag |= 1 << HEALTH_HUD - speech_problem_flag = 1 - - -// damage MANY external bodyparts, in random order -/mob/living/carbon/human/take_overall_damage(brute, burn, sharp = 0, edge = 0, used_weapon = null) - if(status_flags & GODMODE) - return // godmode - - var/list/parts = get_damageable_bodyparts() - if(!parts.len) - return - - var/damage_flags = (sharp ? DAM_SHARP : 0) | (edge ? DAM_EDGE : 0) - - while(parts.len && (brute > 0 || burn > 0) ) - var/obj/item/organ/external/BP = pick(parts) - - var/brute_was = BP.brute_dam - var/burn_was = BP.burn_dam - - BP.take_damage(brute, burn, damage_flags, used_weapon) - brute -= (BP.brute_dam - brute_was) - burn -= (BP.burn_dam - burn_was) - - parts -= BP - - updatehealth() - hud_updateflag |= 1 << HEALTH_HUD - - -//////////////////////////////////////////// - -/* -This function restores the subjects blood to max. -*/ -/mob/living/carbon/human/proc/restore_blood() - if(!species.flags[NO_BLOOD]) - vessel.add_reagent("blood", 560 - vessel.total_volume) - fixblood() - - -/* -This function restores all bodyparts. -*/ -/mob/living/carbon/human/restore_all_bodyparts() - for(var/obj/item/organ/external/BP in bodyparts) - BP.rejuvenate() - -/mob/living/carbon/human/proc/HealDamage(zone, brute, burn) - var/obj/item/organ/external/BP = get_bodypart(zone) - if(istype(BP, /obj/item/organ/external)) - if(BP.heal_damage(brute, burn)) - hud_updateflag |= 1 << HEALTH_HUD - else - return 0 - -/mob/living/carbon/human/proc/get_bodypart(zone) - if(!zone) - zone = BP_CHEST - if(zone in list(O_EYES , O_MOUTH)) - zone = BP_HEAD - return bodyparts_by_name[zone] - -/mob/living/carbon/human/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, damage_flags = 0, obj/used_weapon = null) - - if(damagetype == HALLOSS && species && species.flags[NO_PAIN]) - return FALSE - - //Handle other types of damage or healing - if(damage < 0 || !(damagetype in list(BRUTE, BURN))) - ..(damage, damagetype, def_zone, blocked) - return TRUE - - handle_suit_punctures(damagetype, damage) - - if(blocked >= 100) - return FALSE - - var/obj/item/organ/external/BP = null - if(isbodypart(def_zone)) - BP = def_zone - else - if(!def_zone) - def_zone = ran_zone(def_zone) - BP = get_bodypart(check_zone(def_zone)) - - if(!BP) - return FALSE - - if(blocked) - damage *= blocked_mult(blocked) - - var/datum/wound/created_wound - damageoverlaytemp = 20 - switch(damagetype) - if(BRUTE) - created_wound = BP.take_damage(damage, 0, damage_flags, used_weapon) - if(BURN) - created_wound = BP.take_damage(0, damage, damage_flags, used_weapon) - - // 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 - - return created_wound +//Updates the mob's health from bodyparts 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/obj/item/organ/external/BP in bodyparts) // hardcoded to streamline things a bit + if((BP.status & ORGAN_ROBOT) && !BP.vital) + continue // *non-vital* robot limbs don't count towards shock and crit + total_brute += BP.brute_dam + total_burn += BP.burn_dam + + health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute + + //TODO: fix husking + if( ((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD) + ChangeToHusk() + return + +/mob/living/carbon/human/apply_effect(effect = 0, effecttype = STUN, blocked = 0) + if((effecttype == AGONY || effecttype == STUTTER) && species && species.flags[NO_PAIN]) + return FALSE + ..() + +// ============================================= + +/mob/living/carbon/human/getBrainLoss() + if(status_flags & GODMODE) + return 0 + + if(species.brain_mod == 0 || !should_have_organ(O_BRAIN)) + return 0 + + var/res = brainloss + var/obj/item/organ/internal/brain/IO = organs_by_name[O_BRAIN] + + if(!IO) + return maxHealth * 2 + if(IO.is_bruised()) + res += 20 + if(IO.is_broken()) + res += 50 + + res = min(res, maxHealth * 2) + + return res + +/mob/living/carbon/human/adjustBrainLoss(amount) + if(species.brain_mod == 0 || !should_have_organ(O_BRAIN)) + brainloss = 0 + else + amount = amount * species.brain_mod + ..(amount) + +/mob/living/carbon/human/setBrainLoss(amount) + if(species.brain_mod == 0 || !should_have_organ(O_BRAIN)) + brainloss = 0 + else + ..() + +// ============================================= + +//These procs fetch a cumulative total damage from all bodyparts +/mob/living/carbon/human/getBruteLoss() + var/amount = 0 + for(var/obj/item/organ/external/BP in bodyparts) + if((BP.status & ORGAN_ROBOT) && !BP.vital) + continue // robot limbs don't count towards shock and crit + amount += BP.brute_dam + return amount + +/mob/living/carbon/human/adjustBruteLoss(amount) + if(amount > 0) + take_overall_damage(amount, 0) + else + heal_overall_damage(-amount, 0) + +// ============================================= + +/mob/living/carbon/human/getFireLoss() + var/amount = 0 + for(var/obj/item/organ/external/BP in bodyparts) + if((BP.status & ORGAN_ROBOT) && !BP.vital) + continue // robot limbs don't count towards shock and crit + amount += BP.burn_dam + return amount + +/mob/living/carbon/human/adjustFireLoss(amount) + if(amount > 0) + if(RESIST_HEAT in mutations) + return + take_overall_damage(0, amount) + else + heal_overall_damage(0, -amount) + +// ============================================= + +/mob/living/carbon/human/getToxLoss() + if(species.tox_mod == 0 || species.flags[NO_BLOOD]) + toxloss = 0 + return ..() + +/mob/living/carbon/human/adjustToxLoss(amount) + if(species.tox_mod == 0 || species.flags[NO_BLOOD]) + toxloss = 0 + else + amount = amount * species.tox_mod + ..(amount) + +/mob/living/carbon/human/setToxLoss(amount) + if(species.tox_mod == 0 || species.flags[NO_BLOOD]) + toxloss = 0 + else + ..() + +// ============================================= + +/mob/living/carbon/human/getOxyLoss() + if(species.oxy_mod == 0 || !should_have_organ(O_LUNGS)) + oxyloss = 0 + return ..() + +/mob/living/carbon/human/adjustOxyLoss(amount) + if(species.oxy_mod == 0 || !should_have_organ(O_LUNGS)) + oxyloss = 0 + else + amount = amount * species.oxy_mod + ..(amount) + +/mob/living/carbon/human/setOxyLoss(amount) + if(species.oxy_mod == 0 || !should_have_organ(O_LUNGS)) + oxyloss = 0 + else + ..() + +// ============================================= + +/mob/living/carbon/human/adjustCloneLoss(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/candidates = list() + for (var/obj/item/organ/external/BP in bodyparts) + if(!(BP.status & ORGAN_MUTATED)) + candidates += BP + if (candidates.len) + var/obj/item/organ/external/BP = pick(candidates) + BP.mutate() + to_chat(src, "Something is not right with your [BP.name]...") + return + else + if (prob(heal_prob)) + for (var/obj/item/organ/external/BP in bodyparts) + if (BP.status & ORGAN_MUTATED) + BP.unmutate() + to_chat(src, "Your [BP.name] is shaped normally again.") + return + + if (getCloneLoss() < 1) + for (var/obj/item/organ/external/BP in bodyparts) + if (BP.status & ORGAN_MUTATED) + BP.unmutate() + to_chat(src, "Your [BP.name] is shaped normally again.") + hud_updateflag |= 1 << HEALTH_HUD + +// ============================================= + +/mob/living/carbon/human/Stun(amount) + if(HULK in mutations) + stunned = 0 + else + ..() + +/mob/living/carbon/human/Weaken(amount) + if(HULK in mutations) + weakened = 0 + else + ..() + +/mob/living/carbon/human/Paralyse(amount) + if(HULK in mutations) + paralysis = 0 + else + ..() + +//////////////////////////////////////////// + +//Returns a list of damaged bodyparts +/mob/living/carbon/human/proc/get_damaged_bodyparts(brute, burn) + var/list/parts = list() + for(var/obj/item/organ/external/BP in bodyparts) + if((brute && BP.brute_dam) || (burn && BP.burn_dam)) + parts += BP + return parts + +//Returns a list of damageable bodyparts +/mob/living/carbon/human/proc/get_damageable_bodyparts() + var/list/parts = list() + for(var/obj/item/organ/external/BP in bodyparts) + if(BP.is_damageable()) + parts += BP + 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_bodypart_damage(brute, burn) + var/list/parts = get_damaged_bodyparts(brute, burn) + if(!parts.len) + return + var/obj/item/organ/external/BP = pick(parts) + if(BP.heal_damage(brute, burn)) + hud_updateflag |= 1 << HEALTH_HUD + updatehealth() + +//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_bodypart_damage(brute, burn, sharp = 0, edge = 0) + var/list/parts = get_damageable_bodyparts() + if(!parts.len) + return + + var/obj/item/organ/external/BP = pick(parts) + var/damage_flags = (sharp ? DAM_SHARP : 0) | (edge ? DAM_EDGE : 0) + + if(BP.take_damage(brute, burn, damage_flags)) + hud_updateflag |= 1 << HEALTH_HUD + updatehealth() + speech_problem_flag = 1 + + +//Heal MANY external bodyparts, in random order +/mob/living/carbon/human/heal_overall_damage(brute, burn) + var/list/parts = get_damaged_bodyparts(brute, burn) + while(parts.len && (brute > 0 || burn > 0)) + var/obj/item/organ/external/BP = pick(parts) + var/brute_was = BP.brute_dam + var/burn_was = BP.burn_dam + BP.heal_damage(brute, burn) + brute -= (brute_was - BP.brute_dam) + burn -= (burn_was - BP.burn_dam) + parts -= BP + updatehealth() + hud_updateflag |= 1 << HEALTH_HUD + speech_problem_flag = 1 + + +// damage MANY external bodyparts, in random order +/mob/living/carbon/human/take_overall_damage(brute, burn, sharp = 0, edge = 0, used_weapon = null) + if(status_flags & GODMODE) + return // godmode + + var/list/parts = get_damageable_bodyparts() + if(!parts.len) + return + + var/damage_flags = (sharp ? DAM_SHARP : 0) | (edge ? DAM_EDGE : 0) + + while(parts.len && (brute > 0 || burn > 0) ) + var/obj/item/organ/external/BP = pick(parts) + + var/brute_was = BP.brute_dam + var/burn_was = BP.burn_dam + + BP.take_damage(brute, burn, damage_flags, used_weapon) + brute -= (BP.brute_dam - brute_was) + burn -= (BP.burn_dam - burn_was) + + parts -= BP + + updatehealth() + hud_updateflag |= 1 << HEALTH_HUD + + +//////////////////////////////////////////// + +/* +This function restores the subjects blood to max. +*/ +/mob/living/carbon/human/proc/restore_blood() + if(!species.flags[NO_BLOOD]) + vessel.add_reagent("blood", 560 - vessel.total_volume) + fixblood() + + +/* +This function restores all bodyparts. +*/ +/mob/living/carbon/human/restore_all_bodyparts() + for(var/obj/item/organ/external/BP in bodyparts) + BP.rejuvenate() + +/mob/living/carbon/human/proc/HealDamage(zone, brute, burn) + var/obj/item/organ/external/BP = get_bodypart(zone) + if(istype(BP, /obj/item/organ/external)) + if(BP.heal_damage(brute, burn)) + hud_updateflag |= 1 << HEALTH_HUD + else + return 0 + +/mob/living/carbon/human/proc/get_bodypart(zone) + if(!zone) + zone = BP_CHEST + if(zone in list(O_EYES , O_MOUTH)) + zone = BP_HEAD + return bodyparts_by_name[zone] + +/mob/living/carbon/human/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, damage_flags = 0, obj/used_weapon = null) + + if(damagetype == HALLOSS && species && species.flags[NO_PAIN]) + return FALSE + + //Handle other types of damage or healing + if(damage < 0 || !(damagetype in list(BRUTE, BURN))) + ..(damage, damagetype, def_zone, blocked) + return TRUE + + handle_suit_punctures(damagetype, damage) + + if(blocked >= 100) + return FALSE + + var/obj/item/organ/external/BP = null + if(isbodypart(def_zone)) + BP = def_zone + else + if(!def_zone) + def_zone = ran_zone(def_zone) + BP = get_bodypart(check_zone(def_zone)) + + if(!BP) + return FALSE + + if(blocked) + damage *= blocked_mult(blocked) + + var/datum/wound/created_wound + damageoverlaytemp = 20 + switch(damagetype) + if(BRUTE) + created_wound = BP.take_damage(damage, 0, damage_flags, used_weapon) + if(BURN) + created_wound = BP.take_damage(0, damage, damage_flags, used_weapon) + + // 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 + + return created_wound diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index e2563e847e05..cab09ac1a197 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -1,457 +1,457 @@ -/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone) - - def_zone = check_zone(def_zone) - if(!has_bodypart(def_zone)) - return PROJECTILE_FORCE_MISS //if they don't have the body part in question then the projectile just passes by. - - if(P.impact_force) - for(var/i=1, i<=P.impact_force, i++) - step_to(src, get_step(loc, P.dir)) - if(istype(src.loc, /turf/simulated)) - src.loc.add_blood(src) - - if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself - if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) - if(check_reflect(def_zone, dir, P.dir)) // Checks if you've passed a reflection% check - visible_message("The [P.name] gets reflected by [src]!", \ - "The [P.name] gets reflected by [src]!") - // Find a turf near or on the original location to bounce to - if(P.starting) - var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/turf/curloc = get_turf(src) - - // redirect the projectile - P.redirect(new_x, new_y, curloc, src) - - return -1 // complete projectile permutation - - if(check_shields(P.damage, "the [P.name]", P.dir)) - P.on_hit(src, 100, def_zone) - return 2 - - if(istype(P, /obj/item/projectile/bullet/weakbullet)) - var/obj/item/organ/external/BP = get_bodypart(def_zone) // We're checking the outside, buddy! - if(check_thickmaterial(BP)) - visible_message("The [P.name] hits [src]'s armor!") - P.agony /= 2 - apply_effect(P.agony,AGONY,0) - qdel(P) - if(istype(wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/V = wear_suit - V.attack_reaction(src, REACTION_HIT_BY_BULLET) - return - - if(istype(P, /obj/item/projectile/energy/electrode) || istype(P, /obj/item/projectile/beam/stun) || istype(P, /obj/item/projectile/bullet/stunslug)) - var/obj/item/organ/external/BP = get_bodypart(def_zone) // We're checking the outside, buddy! - P.agony *= get_siemens_coefficient_organ(BP) - P.stun *= get_siemens_coefficient_organ(BP) - P.weaken *= get_siemens_coefficient_organ(BP) - P.stutter *= get_siemens_coefficient_organ(BP) - - if(P.agony) // No effect against full protection. - if(prob(max(P.agony, 20))) - var/obj/item/hand = get_active_hand() - if(hand && !(hand.flags & ABSTRACT)) - drop_item() - P.on_hit(src) - flash_pain() - to_chat(src, "You have been shot!") - qdel(P) - if(istype(wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/V = wear_suit - V.attack_reaction(src, REACTION_HIT_BY_BULLET) - return - - if(istype(P, /obj/item/projectile/energy/bolt)) - var/obj/item/organ/external/BP = get_bodypart(def_zone) // We're checking the outside, buddy! - var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking? - for(var/bp in body_parts) //Make an unregulated var to pass around. - if(!bp) - continue //Does this thing we're shooting even exist? - if(bp && istype(bp ,/obj/item/clothing)) // If it exists, and it's clothed - var/obj/item/clothing/C = bp // Then call an argument C to be that clothing! - if(C.body_parts_covered & BP.body_part) // Is that body part being targeted covered? - if(C.flags & THICKMATERIAL ) - visible_message(" The [P.name] gets absorbed by [src]'s [C.name]!") - qdel(P) - return - - BP = bodyparts_by_name[check_zone(def_zone)] - var/armorblock = run_armor_check(BP, "energy") - apply_damage(P.damage, P.damage_type, BP, armorblock, P.damage_flags(), P) - apply_effects(P.stun,P.weaken,0,0,P.stutter,0,0,armorblock) - flash_pain() - to_chat(src, "You have been shot!") - qdel(P) - if(istype(wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/V = wear_suit - V.attack_reaction(src, REACTION_HIT_BY_BULLET) - return - - if(istype(P, /obj/item/projectile/bullet)) - var/obj/item/projectile/bullet/B = P - - var/obj/item/organ/external/BP = bodyparts_by_name[check_zone(def_zone)] - var/armor = getarmor_organ(BP, "bullet") - - var/delta = max(0, P.damage - (P.damage * (armor/100))) - if(delta) - apply_effect(delta,AGONY,armor) - P.on_hit(src, armor, def_zone) - //return Nope! ~Zve - if(delta < 10) - P.sharp = 0 - P.embed = 0 - - if(B.stoping_power) - var/force = (armor/P.damage)*100 - if (force <= 60 && force > 40) - apply_effects(B.stoping_power/2,B.stoping_power/2,0,0,B.stoping_power/2,0,0,armor) - else if(force <= 40) - apply_effects(B.stoping_power,B.stoping_power,0,0,B.stoping_power,0,0,armor) - - if(!species.flags[NO_EMBED] && P.embed && prob(20 + max(P.damage - armor, -20)) && P.damage_type == BRUTE) - var/obj/item/weapon/shard/shrapnel/SP = new() - SP.name = "[P.name] shrapnel" - SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]." - SP.loc = BP - BP.embed(SP) - - if(istype(P, /obj/item/projectile/neurotoxin)) - var/obj/item/projectile/neurotoxin/B = P - - var/obj/item/organ/external/BP = bodyparts_by_name[check_zone(def_zone)] - var/armor = getarmor_organ(BP, "bio") - if (armor < 100) - apply_effects(B.stun,B.stun,B.stun,0,0,0,0,armor) - to_chat(src, "You feel that yor muscles can`t move!") - - if(istype(wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/V = wear_suit - V.attack_reaction(src, REACTION_HIT_BY_BULLET) - - return (..(P , def_zone)) - -/mob/living/carbon/human/proc/check_reflect(def_zone, hol_dir, hit_dir) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object - if(head && head.IsReflect(def_zone, hol_dir, hit_dir)) - return TRUE - if(wear_suit && wear_suit.IsReflect(def_zone, hol_dir, hit_dir)) - return TRUE - if(l_hand && l_hand.IsReflect(def_zone, hol_dir, hit_dir)) - return TRUE - if(r_hand && r_hand.IsReflect(def_zone, hol_dir, hit_dir)) - return TRUE - return FALSE - -/mob/living/carbon/human/proc/is_in_space_suit(only_helmet = FALSE) //Wearing human full space suit (or only space helmet)? - if(!head || !(only_helmet || wear_suit)) - return FALSE - if(istype(head, /obj/item/clothing/head/helmet/space) && (only_helmet || istype(wear_suit, /obj/item/clothing/suit/space))) - return TRUE - return FALSE - -/mob/living/carbon/human/getarmor(def_zone, type) - var/armorval = 0 - var/organnum = 0 - - if(def_zone) - if(isbodypart(def_zone)) - return getarmor_organ(def_zone, type) - var/obj/item/organ/external/BP = get_bodypart(def_zone) - return getarmor_organ(BP, type) - //If a specific bodypart is targetted, check how that bodypart is protected and return the value. - - //If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values - for(var/obj/item/organ/external/BP in bodyparts) - armorval += getarmor_organ(BP, type) - organnum++ - return (armorval/max(organnum, 1)) - -//this proc returns the Siemens coefficient of electrical resistivity for a particular external organ. -/mob/living/carbon/human/proc/get_siemens_coefficient_organ(obj/item/organ/external/BP) - if (!BP) - return 1.0 - - var/siemens_coefficient = 1.0 - - var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking? - for(var/obj/item/clothing/C in clothing_items) - if(!istype(C)) //is this necessary? - continue - else if(C.body_parts_covered & BP.body_part) // Is that body part being targeted covered? - if(C.wet) - siemens_coefficient = 3.0 - var/turf/T = get_turf(src) - var/obj/effect/fluid/F = locate() in T - if(F) - F.electrocute_act(60) - siemens_coefficient *= C.siemens_coefficient - - return siemens_coefficient - -//this proc returns the armour value for a particular external organ. -/mob/living/carbon/human/proc/getarmor_organ(obj/item/organ/external/BP, type) - if(!type || !BP) - return 0 - var/protection = 0 - var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) - for(var/gear in protective_gear) - if(gear && istype(gear ,/obj/item/clothing)) - var/obj/item/clothing/C = gear - if(istype(C) && (C.body_parts_covered & BP.body_part)) - protection += C.armor[type] - return protection - -/mob/living/carbon/human/proc/check_head_coverage() - - var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform) - for(var/bp in body_parts) - if(!bp) continue - if(bp && istype(bp ,/obj/item/clothing)) - var/obj/item/clothing/C = bp - if(C.body_parts_covered & HEAD) - return 1 - return 0 - -/mob/living/carbon/human/check_shields(damage = 0, attack_text = "the attack", hit_dir = 0) - if(l_hand && istype(l_hand, /obj/item/weapon))//Current base is the prob(50-d/3) - var/obj/item/weapon/I = l_hand - if( (!hit_dir || is_the_opposite_dir(dir, hit_dir)) && prob(I.Get_shield_chance() - round(damage / 3) )) - visible_message("[src] blocks [attack_text] with the [l_hand.name]!") - return 1 - if(r_hand && istype(r_hand, /obj/item/weapon)) - var/obj/item/weapon/I = r_hand - if( (!hit_dir || is_the_opposite_dir(dir, hit_dir)) && prob(I.Get_shield_chance() - round(damage / 3) )) - visible_message("[src] blocks [attack_text] with the [r_hand.name]!") - return 1 - if(wear_suit && istype(wear_suit, /obj/item/)) - var/obj/item/I = wear_suit - if(prob(I.Get_shield_chance() - round(damage / 3) )) - visible_message("The reactive teleport system flings [src] clear of [attack_text]!") - var/list/turfs = new/list() - for(var/turf/T in orange(6)) - if(istype(T,/turf/space)) continue - if(T.density) continue - if(T.x>world.maxx-6 || T.x<6) continue - if(T.y>world.maxy-6 || T.y<6) continue - turfs += T - if(!turfs.len) turfs += pick(/turf in orange(6)) - var/turf/picked = pick(turfs) - if(!isturf(picked)) return - src.loc = picked - return 1 - return 0 - -/mob/living/carbon/human/emp_act(severity) - for(var/obj/O in src) - if(!O) - continue - O.emp_act(severity) - for(var/obj/item/organ/external/BP in bodyparts) - if(BP.status & ORGAN_DESTROYED) - continue - BP.emp_act(severity) - for(var/obj/item/organ/internal/IO in BP.bodypart_organs) - if(IO.robotic == 0) - continue - IO.emp_act(severity) - ..() - - -/mob/living/carbon/human/proc/attacked_by(obj/item/I, mob/living/user, def_zone) - if(!I || !user) - return FALSE - - var/target_zone = def_zone? check_zone(def_zone) : get_zone_with_miss_chance(user.zone_sel.selecting, src) - - if(user == src) // Attacking yourself can't miss - target_zone = user.zone_sel.selecting - if(!target_zone) - visible_message("[user] misses [src] with \the [I]!") - return FALSE - - var/obj/item/organ/external/BP = get_bodypart(target_zone) - if (!BP) - return FALSE - if(BP.status & ORGAN_DESTROYED) - to_chat(user, "What [BP.name]?") - return FALSE - var/hit_area = BP.name - - if(user != src) - user.do_attack_animation(src) - if(check_shields(I.force, "the [I.name]", get_dir(user,src) )) - return 0 - - if(istype(I,/obj/item/weapon/card/emag)) - if(!(BP.status & ORGAN_ROBOT)) - to_chat(user, "That limb isn't robotic.") - return - if(BP.sabotaged) - to_chat(user, "[src]'s [BP.name] is already sabotaged!") - else - to_chat(user, "You sneakily slide [I] into the dataport on [src]'s [BP.name] and short out the safeties.") - var/obj/item/weapon/card/emag/emag = I - emag.uses-- - BP.sabotaged = 1 - return TRUE - - if(I.attack_verb.len) - visible_message("[src] has been [pick(I.attack_verb)] in the [hit_area] with [I.name] by [user]!") - else - visible_message("[src] has been attacked in the [hit_area] with [I.name] by [user]!") - - var/armor = run_armor_check(BP, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") - if(armor >= 100 || !I.force) - return FALSE - - //Apply weapon damage - var/damage_flags = I.damage_flags() - if(prob(armor)) - damage_flags &= ~(DAM_SHARP | DAM_EDGE) - - var/datum/wound/created_wound = apply_damage(I.force, I.damtype, BP, armor, damage_flags, I) - - //Melee weapon embedded object code. - if(I.damtype == BRUTE && !I.anchored && I.can_embed && !I.is_robot_module()) - var/weapon_sharp = (damage_flags & DAM_SHARP) - var/damage = I.force // just the effective damage used for sorting out embedding, no further damage is applied here - if (armor) - damage *= blocked_mult(armor) - - //blunt objects should really not be embedding in things unless a huge amount of force is involved - var/embed_chance = weapon_sharp ? (damage / (I.w_class / 2)) : (damage / (I.w_class * 3)) - var/embed_threshold = weapon_sharp ? (5 * I.w_class) : (15 * I.w_class) - - //Sharp objects will always embed if they do enough damage. - if((weapon_sharp && damage > (10 * I.w_class)) || (damage > embed_threshold && prob(embed_chance))) - BP.embed(I, null, null, created_wound) - - var/bloody = 0 - if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (I.force * 2))) - I.add_blood(src) //Make the weapon bloody, not the person. -// if(user.hand) user.update_inv_l_hand() //updates the attacker's overlay for the (now bloodied) weapon -// else user.update_inv_r_hand() //removed because weapons don't have on-mob blood overlays - if(prob(33)) - bloody = 1 - var/turf/location = loc - if(istype(location, /turf/simulated)) - location.add_blood(src) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood - H.bloody_body(src) - H.bloody_hands(src) - - switch(hit_area) - if(BP_HEAD)//Harder to score a stun but if you do it lasts a bit longer - if(prob(I.force)) - apply_effect(20, PARALYZE, armor) - visible_message("[src] has been knocked unconscious!") - if(prob(I.force + min(100,100 - src.health)) && src != user && I.damtype == BRUTE) - if(src != user && I.damtype == BRUTE) - ticker.mode.remove_revolutionary(mind) - ticker.mode.remove_gangster(mind, exclude_bosses=1) - - if(bloody)//Apply blood - if(wear_mask) - wear_mask.add_blood(src) - update_inv_wear_mask() - if(head) - head.add_blood(src) - update_inv_head() - if(glasses && prob(33)) - glasses.add_blood(src) - update_inv_glasses() - - if(BP_CHEST)//Easier to score a stun but lasts less time - if(prob((I.force + 10))) - apply_effect(5, WEAKEN, armor) - visible_message("[src] has been knocked down!") - - if(bloody) - bloody_body(src) - return TRUE - -//this proc handles being hit by a thrown atom -/mob/living/carbon/human/resolve_thrown_attack(obj/O, throw_damage, dtype, zone) - - var/hit_area = parse_zone(zone) - visible_message("[src] has been hit in the [hit_area] by [O].") - - var/armor = run_armor_check(zone, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here - ..(O, throw_damage, dtype, zone, armor) - -/mob/living/carbon/human/embed(obj/item/I, zone, created_wound) - if(!zone) - return ..() - - var/obj/item/organ/external/BP = get_bodypart(zone) - - BP.embed(I, null, null, created_wound) - -/mob/living/carbon/human/bloody_hands(mob/living/carbon/human/source, amount = 2) - if (gloves) - if(istype(gloves, /obj/item/clothing/gloves/)) - var/obj/item/clothing/gloves/GL = gloves - GL.add_blood(source) - GL.transfer_blood = amount - GL.bloody_hands_mob = source - else - add_blood(source) - bloody_hands = amount - bloody_hands_mob = source - update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves - -/mob/living/carbon/human/bloody_body(mob/living/carbon/human/source) - if(wear_suit) - wear_suit.add_blood(source) - update_inv_wear_suit() - if(w_uniform) - w_uniform.add_blood(source) - update_inv_w_uniform() - -/mob/living/carbon/human/crawl_in_blood(obj/effect/decal/cleanable/blood/floor_blood) - if(wear_suit) - wear_suit.add_dirt_cover(floor_blood.basedatum) - update_inv_wear_suit() - if(w_uniform) - w_uniform.add_dirt_cover(floor_blood.basedatum) - update_inv_w_uniform() - if (gloves) - gloves.add_dirt_cover(floor_blood.basedatum) - else - add_dirt_cover(floor_blood.basedatum) - update_inv_gloves() - -/mob/living/carbon/proc/check_thickmaterial(obj/item/organ/external/BP, target_zone) - return 0 - -/mob/living/carbon/human/check_thickmaterial(obj/item/organ/external/BP, target_zone) - if(target_zone) - BP = get_bodypart(target_zone) - - if(!BP || (BP.status & ORGAN_DESTROYED)) - return NOLIMB - - var/list/items = get_equipped_items() - for(var/obj/item/clothing/C in items) - if((C.flags & THICKMATERIAL) && (C.body_parts_covered & BP.body_part)) - if(C.flags & PHORONGUARD) // this means, clothes has injection port or smthing like that. - return PHORONGUARD // space suits and so on. (well, PHORONGUARD does not provide good readability, but i don't want to implement whole new define as this one is good, or maybe rename?) - else - return THICKMATERIAL // armors and so on. - return 0 // could be NOTHICKMATERIAL or smth, but zero is OK too. - -/mob/living/carbon/human/proc/handle_suit_punctures(damtype, damage) - - if(!wear_suit) return - if(!istype(wear_suit,/obj/item/clothing/suit/space)) return - if(damtype != BURN && damtype != BRUTE) return - - var/obj/item/clothing/suit/space/SS = wear_suit - var/reduction_dam = (100 - SS.breach_threshold) / 100 - var/penetrated_dam = max(0, min(50, (damage * reduction_dam) / 1.5)) // - SS.damage)) - Consider uncommenting this if suits seem too hardy on dev. - - if(penetrated_dam) SS.create_breaches(damtype, penetrated_dam) +/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone) + + def_zone = check_zone(def_zone) + if(!has_bodypart(def_zone)) + return PROJECTILE_FORCE_MISS //if they don't have the body part in question then the projectile just passes by. + + if(P.impact_force) + for(var/i=1, i<=P.impact_force, i++) + step_to(src, get_step(loc, P.dir)) + if(istype(src.loc, /turf/simulated)) + src.loc.add_blood(src) + + if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself + if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) + if(check_reflect(def_zone, dir, P.dir)) // Checks if you've passed a reflection% check + visible_message("The [P.name] gets reflected by [src]!", \ + "The [P.name] gets reflected by [src]!") + // Find a turf near or on the original location to bounce to + if(P.starting) + var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/turf/curloc = get_turf(src) + + // redirect the projectile + P.redirect(new_x, new_y, curloc, src) + + return -1 // complete projectile permutation + + if(check_shields(P.damage, "the [P.name]", P.dir)) + P.on_hit(src, 100, def_zone) + return 2 + + if(istype(P, /obj/item/projectile/bullet/weakbullet)) + var/obj/item/organ/external/BP = get_bodypart(def_zone) // We're checking the outside, buddy! + if(check_thickmaterial(BP)) + visible_message("The [P.name] hits [src]'s armor!") + P.agony /= 2 + apply_effect(P.agony,AGONY,0) + qdel(P) + if(istype(wear_suit, /obj/item/clothing/suit)) + var/obj/item/clothing/suit/V = wear_suit + V.attack_reaction(src, REACTION_HIT_BY_BULLET) + return + + if(istype(P, /obj/item/projectile/energy/electrode) || istype(P, /obj/item/projectile/beam/stun) || istype(P, /obj/item/projectile/bullet/stunslug)) + var/obj/item/organ/external/BP = get_bodypart(def_zone) // We're checking the outside, buddy! + P.agony *= get_siemens_coefficient_organ(BP) + P.stun *= get_siemens_coefficient_organ(BP) + P.weaken *= get_siemens_coefficient_organ(BP) + P.stutter *= get_siemens_coefficient_organ(BP) + + if(P.agony) // No effect against full protection. + if(prob(max(P.agony, 20))) + var/obj/item/hand = get_active_hand() + if(hand && !(hand.flags & ABSTRACT)) + drop_item() + P.on_hit(src) + flash_pain() + to_chat(src, "You have been shot!") + qdel(P) + if(istype(wear_suit, /obj/item/clothing/suit)) + var/obj/item/clothing/suit/V = wear_suit + V.attack_reaction(src, REACTION_HIT_BY_BULLET) + return + + if(istype(P, /obj/item/projectile/energy/bolt)) + var/obj/item/organ/external/BP = get_bodypart(def_zone) // We're checking the outside, buddy! + var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking? + for(var/bp in body_parts) //Make an unregulated var to pass around. + if(!bp) + continue //Does this thing we're shooting even exist? + if(bp && istype(bp ,/obj/item/clothing)) // If it exists, and it's clothed + var/obj/item/clothing/C = bp // Then call an argument C to be that clothing! + if(C.body_parts_covered & BP.body_part) // Is that body part being targeted covered? + if(C.flags & THICKMATERIAL ) + visible_message(" The [P.name] gets absorbed by [src]'s [C.name]!") + qdel(P) + return + + BP = bodyparts_by_name[check_zone(def_zone)] + var/armorblock = run_armor_check(BP, "energy") + apply_damage(P.damage, P.damage_type, BP, armorblock, P.damage_flags(), P) + apply_effects(P.stun,P.weaken,0,0,P.stutter,0,0,armorblock) + flash_pain() + to_chat(src, "You have been shot!") + qdel(P) + if(istype(wear_suit, /obj/item/clothing/suit)) + var/obj/item/clothing/suit/V = wear_suit + V.attack_reaction(src, REACTION_HIT_BY_BULLET) + return + + if(istype(P, /obj/item/projectile/bullet)) + var/obj/item/projectile/bullet/B = P + + var/obj/item/organ/external/BP = bodyparts_by_name[check_zone(def_zone)] + var/armor = getarmor_organ(BP, "bullet") + + var/delta = max(0, P.damage - (P.damage * (armor/100))) + if(delta) + apply_effect(delta,AGONY,armor) + P.on_hit(src, armor, def_zone) + //return Nope! ~Zve + if(delta < 10) + P.sharp = 0 + P.embed = 0 + + if(B.stoping_power) + var/force = (armor/P.damage)*100 + if (force <= 60 && force > 40) + apply_effects(B.stoping_power/2,B.stoping_power/2,0,0,B.stoping_power/2,0,0,armor) + else if(force <= 40) + apply_effects(B.stoping_power,B.stoping_power,0,0,B.stoping_power,0,0,armor) + + if(!species.flags[NO_EMBED] && P.embed && prob(20 + max(P.damage - armor, -20)) && P.damage_type == BRUTE) + var/obj/item/weapon/shard/shrapnel/SP = new() + SP.name = "[P.name] shrapnel" + SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]." + SP.loc = BP + BP.embed(SP) + + if(istype(P, /obj/item/projectile/neurotoxin)) + var/obj/item/projectile/neurotoxin/B = P + + var/obj/item/organ/external/BP = bodyparts_by_name[check_zone(def_zone)] + var/armor = getarmor_organ(BP, "bio") + if (armor < 100) + apply_effects(B.stun,B.stun,B.stun,0,0,0,0,armor) + to_chat(src, "You feel that yor muscles can`t move!") + + if(istype(wear_suit, /obj/item/clothing/suit)) + var/obj/item/clothing/suit/V = wear_suit + V.attack_reaction(src, REACTION_HIT_BY_BULLET) + + return (..(P , def_zone)) + +/mob/living/carbon/human/proc/check_reflect(def_zone, hol_dir, hit_dir) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object + if(head && head.IsReflect(def_zone, hol_dir, hit_dir)) + return TRUE + if(wear_suit && wear_suit.IsReflect(def_zone, hol_dir, hit_dir)) + return TRUE + if(l_hand && l_hand.IsReflect(def_zone, hol_dir, hit_dir)) + return TRUE + if(r_hand && r_hand.IsReflect(def_zone, hol_dir, hit_dir)) + return TRUE + return FALSE + +/mob/living/carbon/human/proc/is_in_space_suit(only_helmet = FALSE) //Wearing human full space suit (or only space helmet)? + if(!head || !(only_helmet || wear_suit)) + return FALSE + if(istype(head, /obj/item/clothing/head/helmet/space) && (only_helmet || istype(wear_suit, /obj/item/clothing/suit/space))) + return TRUE + return FALSE + +/mob/living/carbon/human/getarmor(def_zone, type) + var/armorval = 0 + var/organnum = 0 + + if(def_zone) + if(isbodypart(def_zone)) + return getarmor_organ(def_zone, type) + var/obj/item/organ/external/BP = get_bodypart(def_zone) + return getarmor_organ(BP, type) + //If a specific bodypart is targetted, check how that bodypart is protected and return the value. + + //If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values + for(var/obj/item/organ/external/BP in bodyparts) + armorval += getarmor_organ(BP, type) + organnum++ + return (armorval/max(organnum, 1)) + +//this proc returns the Siemens coefficient of electrical resistivity for a particular external organ. +/mob/living/carbon/human/proc/get_siemens_coefficient_organ(obj/item/organ/external/BP) + if (!BP) + return 1.0 + + var/siemens_coefficient = 1.0 + + var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking? + for(var/obj/item/clothing/C in clothing_items) + if(!istype(C)) //is this necessary? + continue + else if(C.body_parts_covered & BP.body_part) // Is that body part being targeted covered? + if(C.wet) + siemens_coefficient = 3.0 + var/turf/T = get_turf(src) + var/obj/effect/fluid/F = locate() in T + if(F) + F.electrocute_act(60) + siemens_coefficient *= C.siemens_coefficient + + return siemens_coefficient + +//this proc returns the armour value for a particular external organ. +/mob/living/carbon/human/proc/getarmor_organ(obj/item/organ/external/BP, type) + if(!type || !BP) + return 0 + var/protection = 0 + var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) + for(var/gear in protective_gear) + if(gear && istype(gear ,/obj/item/clothing)) + var/obj/item/clothing/C = gear + if(istype(C) && (C.body_parts_covered & BP.body_part)) + protection += C.armor[type] + return protection + +/mob/living/carbon/human/proc/check_head_coverage() + + var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform) + for(var/bp in body_parts) + if(!bp) continue + if(bp && istype(bp ,/obj/item/clothing)) + var/obj/item/clothing/C = bp + if(C.body_parts_covered & HEAD) + return 1 + return 0 + +/mob/living/carbon/human/check_shields(damage = 0, attack_text = "the attack", hit_dir = 0) + if(l_hand && istype(l_hand, /obj/item/weapon))//Current base is the prob(50-d/3) + var/obj/item/weapon/I = l_hand + if( (!hit_dir || is_the_opposite_dir(dir, hit_dir)) && prob(I.Get_shield_chance() - round(damage / 3) )) + visible_message("[src] blocks [attack_text] with the [l_hand.name]!") + return 1 + if(r_hand && istype(r_hand, /obj/item/weapon)) + var/obj/item/weapon/I = r_hand + if( (!hit_dir || is_the_opposite_dir(dir, hit_dir)) && prob(I.Get_shield_chance() - round(damage / 3) )) + visible_message("[src] blocks [attack_text] with the [r_hand.name]!") + return 1 + if(wear_suit && istype(wear_suit, /obj/item/)) + var/obj/item/I = wear_suit + if(prob(I.Get_shield_chance() - round(damage / 3) )) + visible_message("The reactive teleport system flings [src] clear of [attack_text]!") + var/list/turfs = new/list() + for(var/turf/T in orange(6)) + if(istype(T,/turf/space)) continue + if(T.density) continue + if(T.x>world.maxx-6 || T.x<6) continue + if(T.y>world.maxy-6 || T.y<6) continue + turfs += T + if(!turfs.len) turfs += pick(/turf in orange(6)) + var/turf/picked = pick(turfs) + if(!isturf(picked)) return + src.loc = picked + return 1 + return 0 + +/mob/living/carbon/human/emp_act(severity) + for(var/obj/O in src) + if(!O) + continue + O.emp_act(severity) + for(var/obj/item/organ/external/BP in bodyparts) + if(BP.status & ORGAN_DESTROYED) + continue + BP.emp_act(severity) + for(var/obj/item/organ/internal/IO in BP.bodypart_organs) + if(IO.robotic == 0) + continue + IO.emp_act(severity) + ..() + + +/mob/living/carbon/human/proc/attacked_by(obj/item/I, mob/living/user, def_zone) + if(!I || !user) + return FALSE + + var/target_zone = def_zone? check_zone(def_zone) : get_zone_with_miss_chance(user.zone_sel.selecting, src) + + if(user == src) // Attacking yourself can't miss + target_zone = user.zone_sel.selecting + if(!target_zone) + visible_message("[user] misses [src] with \the [I]!") + return FALSE + + var/obj/item/organ/external/BP = get_bodypart(target_zone) + if (!BP) + return FALSE + if(BP.status & ORGAN_DESTROYED) + to_chat(user, "What [BP.name]?") + return FALSE + var/hit_area = BP.name + + if(user != src) + user.do_attack_animation(src) + if(check_shields(I.force, "the [I.name]", get_dir(user,src) )) + return 0 + + if(istype(I,/obj/item/weapon/card/emag)) + if(!(BP.status & ORGAN_ROBOT)) + to_chat(user, "That limb isn't robotic.") + return + if(BP.sabotaged) + to_chat(user, "[src]'s [BP.name] is already sabotaged!") + else + to_chat(user, "You sneakily slide [I] into the dataport on [src]'s [BP.name] and short out the safeties.") + var/obj/item/weapon/card/emag/emag = I + emag.uses-- + BP.sabotaged = 1 + return TRUE + + if(I.attack_verb.len) + visible_message("[src] has been [pick(I.attack_verb)] in the [hit_area] with [I.name] by [user]!") + else + visible_message("[src] has been attacked in the [hit_area] with [I.name] by [user]!") + + var/armor = run_armor_check(BP, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") + if(armor >= 100 || !I.force) + return FALSE + + //Apply weapon damage + var/damage_flags = I.damage_flags() + if(prob(armor)) + damage_flags &= ~(DAM_SHARP | DAM_EDGE) + + var/datum/wound/created_wound = apply_damage(I.force, I.damtype, BP, armor, damage_flags, I) + + //Melee weapon embedded object code. + if(I.damtype == BRUTE && !I.anchored && I.can_embed && !I.is_robot_module()) + var/weapon_sharp = (damage_flags & DAM_SHARP) + var/damage = I.force // just the effective damage used for sorting out embedding, no further damage is applied here + if (armor) + damage *= blocked_mult(armor) + + //blunt objects should really not be embedding in things unless a huge amount of force is involved + var/embed_chance = weapon_sharp ? (damage / (I.w_class / 2)) : (damage / (I.w_class * 3)) + var/embed_threshold = weapon_sharp ? (5 * I.w_class) : (15 * I.w_class) + + //Sharp objects will always embed if they do enough damage. + if((weapon_sharp && damage > (10 * I.w_class)) || (damage > embed_threshold && prob(embed_chance))) + BP.embed(I, null, null, created_wound) + + var/bloody = 0 + if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (I.force * 2))) + I.add_blood(src) //Make the weapon bloody, not the person. +// if(user.hand) user.update_inv_l_hand() //updates the attacker's overlay for the (now bloodied) weapon +// else user.update_inv_r_hand() //removed because weapons don't have on-mob blood overlays + if(prob(33)) + bloody = 1 + var/turf/location = loc + if(istype(location, /turf/simulated)) + location.add_blood(src) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood + H.bloody_body(src) + H.bloody_hands(src) + + switch(hit_area) + if(BP_HEAD)//Harder to score a stun but if you do it lasts a bit longer + if(prob(I.force)) + apply_effect(20, PARALYZE, armor) + visible_message("[src] has been knocked unconscious!") + if(prob(I.force + min(100,100 - src.health)) && src != user && I.damtype == BRUTE) + if(src != user && I.damtype == BRUTE) + ticker.mode.remove_revolutionary(mind) + ticker.mode.remove_gangster(mind, exclude_bosses=1) + + if(bloody)//Apply blood + if(wear_mask) + wear_mask.add_blood(src) + update_inv_wear_mask() + if(head) + head.add_blood(src) + update_inv_head() + if(glasses && prob(33)) + glasses.add_blood(src) + update_inv_glasses() + + if(BP_CHEST)//Easier to score a stun but lasts less time + if(prob((I.force + 10))) + apply_effect(5, WEAKEN, armor) + visible_message("[src] has been knocked down!") + + if(bloody) + bloody_body(src) + return TRUE + +//this proc handles being hit by a thrown atom +/mob/living/carbon/human/resolve_thrown_attack(obj/O, throw_damage, dtype, zone) + + var/hit_area = parse_zone(zone) + visible_message("[src] has been hit in the [hit_area] by [O].") + + var/armor = run_armor_check(zone, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here + ..(O, throw_damage, dtype, zone, armor) + +/mob/living/carbon/human/embed(obj/item/I, zone, created_wound) + if(!zone) + return ..() + + var/obj/item/organ/external/BP = get_bodypart(zone) + + BP.embed(I, null, null, created_wound) + +/mob/living/carbon/human/bloody_hands(mob/living/carbon/human/source, amount = 2) + if (gloves) + if(istype(gloves, /obj/item/clothing/gloves/)) + var/obj/item/clothing/gloves/GL = gloves + GL.add_blood(source) + GL.transfer_blood = amount + GL.bloody_hands_mob = source + else + add_blood(source) + bloody_hands = amount + bloody_hands_mob = source + update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves + +/mob/living/carbon/human/bloody_body(mob/living/carbon/human/source) + if(wear_suit) + wear_suit.add_blood(source) + update_inv_wear_suit() + if(w_uniform) + w_uniform.add_blood(source) + update_inv_w_uniform() + +/mob/living/carbon/human/crawl_in_blood(obj/effect/decal/cleanable/blood/floor_blood) + if(wear_suit) + wear_suit.add_dirt_cover(floor_blood.basedatum) + update_inv_wear_suit() + if(w_uniform) + w_uniform.add_dirt_cover(floor_blood.basedatum) + update_inv_w_uniform() + if (gloves) + gloves.add_dirt_cover(floor_blood.basedatum) + else + add_dirt_cover(floor_blood.basedatum) + update_inv_gloves() + +/mob/living/carbon/proc/check_thickmaterial(obj/item/organ/external/BP, target_zone) + return 0 + +/mob/living/carbon/human/check_thickmaterial(obj/item/organ/external/BP, target_zone) + if(target_zone) + BP = get_bodypart(target_zone) + + if(!BP || (BP.status & ORGAN_DESTROYED)) + return NOLIMB + + var/list/items = get_equipped_items() + for(var/obj/item/clothing/C in items) + if((C.flags & THICKMATERIAL) && (C.body_parts_covered & BP.body_part)) + if(C.flags & PHORONGUARD) // this means, clothes has injection port or smthing like that. + return PHORONGUARD // space suits and so on. (well, PHORONGUARD does not provide good readability, but i don't want to implement whole new define as this one is good, or maybe rename?) + else + return THICKMATERIAL // armors and so on. + return 0 // could be NOTHICKMATERIAL or smth, but zero is OK too. + +/mob/living/carbon/human/proc/handle_suit_punctures(damtype, damage) + + if(!wear_suit) return + if(!istype(wear_suit,/obj/item/clothing/suit/space)) return + if(damtype != BURN && damtype != BRUTE) return + + var/obj/item/clothing/suit/space/SS = wear_suit + var/reduction_dam = (100 - SS.breach_threshold) / 100 + var/penetrated_dam = max(0, min(50, (damage * reduction_dam) / 1.5)) // - SS.damage)) - Consider uncommenting this if suits seem too hardy on dev. + + if(penetrated_dam) SS.create_breaches(damtype, penetrated_dam) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index a37ad64b574d..ceb0876ac107 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -1,101 +1,101 @@ -/mob/living/carbon/human - //Hair colour and style - var/r_hair = 0 - var/g_hair = 0 - var/b_hair = 0 - var/h_style = "Bald" - - var/dyed_r_hair = 0 - var/dyed_g_hair = 0 - var/dyed_b_hair = 0 - var/hair_painted = FALSE - - //Facial hair colour and style - var/r_facial = 0 - var/g_facial = 0 - var/b_facial = 0 - var/f_style = "Shaved" - - var/dyed_r_facial = 0 - var/dyed_g_facial = 0 - var/dyed_b_facial = 0 - var/facial_painted = FALSE - - //Eye colour - var/r_eyes = 0 - var/g_eyes = 0 - var/b_eyes = 0 - - var/s_tone = 0 //Skin tone - - //Skin colour - var/r_skin = 0 - var/g_skin = 0 - var/b_skin = 0 - - var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup - var/lip_color = "white" - - var/age = 30 //Player's age (pure fluff) - var/b_type = "A+" //Player's bloodtype - - var/underwear = 1 //Which underwear the player wants - var/undershirt = 0 //Which undershirt the player wants. - var/socks = 0 //Which socks the player wants. - var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack. - - // General information - var/home_system = "" - var/citizenship = "" - var/personal_faction = "" - var/religion = "" - - //Equipment slots - var/obj/item/wear_suit = null - var/obj/item/w_uniform = null - var/obj/item/belt = null - var/obj/item/gloves = null - var/obj/item/glasses = null - var/obj/item/l_ear = null - var/obj/item/r_ear = 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/used_skillpoints = 0 - var/skill_specialization = null - var/list/skills = null - - var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life() - - var/speech_problem_flag = 0 - - var/miming = null //Toggle for the mime's abilities. - var/special_voice = "" // For changing our voice. Used by a symptom. - - 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 bodyparts or just some or even none. - var/list/bad_bodyparts = list()// bodyparts we check until they are good. - - var/xylophone = 0 //For the spoooooooky xylophone cooldown - - var/mob/remoteview_target = null - var/datum/dirt_cover/hand_dirt_color - - // Organs regenerating variables. - var/regenerating_organ_time = 0 - var/obj/item/organ/external/regenerating_bodypart // A bodypart that is currently regenerating, so we don't have a random one picked each time. - - //Golem stuff - var/my_master = 0 - var/my_golems = list() - - var/lastScream = 0 // Prevent scream spam in some situations - var/name_override //For temporary visible name changes - - var/full_prosthetic // We are a robutt. - var/robolimb_count = 0 // Number of robot limbs. - var/sightglassesmod = null - var/datum/personal_crafting/handcrafting +/mob/living/carbon/human + //Hair colour and style + var/r_hair = 0 + var/g_hair = 0 + var/b_hair = 0 + var/h_style = "Bald" + + var/dyed_r_hair = 0 + var/dyed_g_hair = 0 + var/dyed_b_hair = 0 + var/hair_painted = FALSE + + //Facial hair colour and style + var/r_facial = 0 + var/g_facial = 0 + var/b_facial = 0 + var/f_style = "Shaved" + + var/dyed_r_facial = 0 + var/dyed_g_facial = 0 + var/dyed_b_facial = 0 + var/facial_painted = FALSE + + //Eye colour + var/r_eyes = 0 + var/g_eyes = 0 + var/b_eyes = 0 + + var/s_tone = 0 //Skin tone + + //Skin colour + var/r_skin = 0 + var/g_skin = 0 + var/b_skin = 0 + + var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup + var/lip_color = "white" + + var/age = 30 //Player's age (pure fluff) + var/b_type = "A+" //Player's bloodtype + + var/underwear = 1 //Which underwear the player wants + var/undershirt = 0 //Which undershirt the player wants. + var/socks = 0 //Which socks the player wants. + var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack. + + // General information + var/home_system = "" + var/citizenship = "" + var/personal_faction = "" + var/religion = "" + + //Equipment slots + var/obj/item/wear_suit = null + var/obj/item/w_uniform = null + var/obj/item/belt = null + var/obj/item/gloves = null + var/obj/item/glasses = null + var/obj/item/l_ear = null + var/obj/item/r_ear = 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/used_skillpoints = 0 + var/skill_specialization = null + var/list/skills = null + + var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life() + + var/speech_problem_flag = 0 + + var/miming = null //Toggle for the mime's abilities. + var/special_voice = "" // For changing our voice. Used by a symptom. + + 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 bodyparts or just some or even none. + var/list/bad_bodyparts = list()// bodyparts we check until they are good. + + var/xylophone = 0 //For the spoooooooky xylophone cooldown + + var/mob/remoteview_target = null + var/datum/dirt_cover/hand_dirt_color + + // Organs regenerating variables. + var/regenerating_organ_time = 0 + var/obj/item/organ/external/regenerating_bodypart // A bodypart that is currently regenerating, so we don't have a random one picked each time. + + //Golem stuff + var/my_master = 0 + var/my_golems = list() + + var/lastScream = 0 // Prevent scream spam in some situations + var/name_override //For temporary visible name changes + + var/full_prosthetic // We are a robutt. + var/robolimb_count = 0 // Number of robot limbs. + var/sightglassesmod = null + var/datum/personal_crafting/handcrafting diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 11eedcc046a6..8c5f3d8e7fcb 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -1,115 +1,115 @@ -/mob/living/carbon/human/movement_delay() - if(iszombie(src)) - return src.zombie_movement_delay() - if(mind && mind.changeling && mind.changeling.strained_muscles) - if(!has_gravity(src)) - return -3 // speed boost in space. - else - return -2.5 // changeling ability also nulify any speed modifications and gives boost. - - if(!has_gravity(src)) - return -1 // It's hard to be slowed down in space by... anything - - var/tally = species.speed_mod - - if(is_type_organ(O_HEART, /obj/item/organ/internal/heart/ipc)) // IPC's heart is a servomotor, damaging it influences speed. - var/obj/item/organ/internal/IO = organs_by_name[O_HEART] - if(!IO) // If it's servomotor somehow is missing, it's absence should be treated as 100 damage to it. - tally += 20 - else - tally += IO.damage/5 - - if(RUN in mutations) - tally -= 0.5 - - if(crawling) - tally += 7 - - if(embedded_flag) - handle_embedded_objects() // Moving with objects stuck in you can cause bad times. - - var/health_deficiency = (100 - health + halloss) - if(health_deficiency >= 40) - tally += (health_deficiency / 25) - - var/hungry = (500 - get_nutrition()) / 5 // So overeat would be 100 and default level would be 80 - if(hungry >= 70) - tally += hungry / 50 - - if(istype(buckled, /obj/structure/stool/bed/chair/wheelchair)) - for(var/bodypart_name in list(BP_L_ARM , BP_R_ARM)) - var/obj/item/organ/external/BP = bodyparts_by_name[bodypart_name] - if(!BP || (BP.status & ORGAN_DESTROYED)) - tally += 6 - else if(BP.status & ORGAN_SPLINTED) - tally += 0.8 - else if(BP.status & ORGAN_BROKEN) - tally += 3 - else - var/chem_nullify_debuff = FALSE - if(!species.flags[NO_BLOOD] && ( reagents.has_reagent("hyperzine") || reagents.has_reagent("nuka_cola") )) // hyperzine removes equipment slowdowns (no blood = no chemical effects). - chem_nullify_debuff = TRUE - - if(wear_suit && wear_suit.slowdown && !(wear_suit.slowdown > 0 && chem_nullify_debuff)) - tally += wear_suit.slowdown - - if(back && back.slowdown && !(back.slowdown > 0 && chem_nullify_debuff)) - tally += back.slowdown - - if(shoes && shoes.slowdown && !(shoes.slowdown > 0 && chem_nullify_debuff)) - tally += shoes.slowdown - - if(!chem_nullify_debuff) - for(var/x in list(l_hand, r_hand)) - var/obj/item/O = x - if(O && !(O.flags & ABSTRACT) && O.w_class >= ITEM_SIZE_NORMAL) - tally += 0.5 * (O.w_class - 2) // (3 = 0.5) || (4 = 1) || (5 = 1.5) - - if(buckled) // so, if we buckled we have large debuff - tally += 5.5 - - for(var/bodypart_name in list(BP_L_LEG , BP_R_LEG)) - var/obj/item/organ/external/BP = bodyparts_by_name[bodypart_name] - if(!BP || (BP.status & ORGAN_DESTROYED)) - tally += 6 - else if(BP.status & ORGAN_SPLINTED) - tally += 0.8 - else if(BP.status & ORGAN_BROKEN) - tally += 3 - - if(shock_stage >= 10) - tally += round(log(3.5, shock_stage), 0.1) // (40 = ~3.0) and (starts at ~1.83) - - if(pull_debuff) - tally += pull_debuff - - if(FAT in mutations) - tally += 1.5 - - if(bodytemperature < 283.222) - tally += (283.222 - bodytemperature) / 10 * 1.75 - - tally += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow - - return (tally + config.human_delay) - -/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) - - if(..()) - return 1 - - //Do we have a working jetpack - if(istype(back, /obj/item/weapon/tank/jetpack) && isturf(loc)) //Second check is so you can't use a jetpack in a mech - var/obj/item/weapon/tank/jetpack/J = back - if((movement_dir || J.stabilization_on) && J.allow_thrust(0.01, src)) - return 1 - return 0 - -/mob/living/carbon/human/mob_has_gravity() - . = ..() - if(!.) - if(mob_negates_gravity()) - . = 1 - -/mob/living/carbon/human/mob_negates_gravity() - return shoes && shoes.negates_gravity() +/mob/living/carbon/human/movement_delay() + if(iszombie(src)) + return src.zombie_movement_delay() + if(mind && mind.changeling && mind.changeling.strained_muscles) + if(!has_gravity(src)) + return -3 // speed boost in space. + else + return -2.5 // changeling ability also nulify any speed modifications and gives boost. + + if(!has_gravity(src)) + return -1 // It's hard to be slowed down in space by... anything + + var/tally = species.speed_mod + + if(is_type_organ(O_HEART, /obj/item/organ/internal/heart/ipc)) // IPC's heart is a servomotor, damaging it influences speed. + var/obj/item/organ/internal/IO = organs_by_name[O_HEART] + if(!IO) // If it's servomotor somehow is missing, it's absence should be treated as 100 damage to it. + tally += 20 + else + tally += IO.damage/5 + + if(RUN in mutations) + tally -= 0.5 + + if(crawling) + tally += 7 + + if(embedded_flag) + handle_embedded_objects() // Moving with objects stuck in you can cause bad times. + + var/health_deficiency = (100 - health + halloss) + if(health_deficiency >= 40) + tally += (health_deficiency / 25) + + var/hungry = (500 - get_nutrition()) / 5 // So overeat would be 100 and default level would be 80 + if(hungry >= 70) + tally += hungry / 50 + + if(istype(buckled, /obj/structure/stool/bed/chair/wheelchair)) + for(var/bodypart_name in list(BP_L_ARM , BP_R_ARM)) + var/obj/item/organ/external/BP = bodyparts_by_name[bodypart_name] + if(!BP || (BP.status & ORGAN_DESTROYED)) + tally += 6 + else if(BP.status & ORGAN_SPLINTED) + tally += 0.8 + else if(BP.status & ORGAN_BROKEN) + tally += 3 + else + var/chem_nullify_debuff = FALSE + if(!species.flags[NO_BLOOD] && ( reagents.has_reagent("hyperzine") || reagents.has_reagent("nuka_cola") )) // hyperzine removes equipment slowdowns (no blood = no chemical effects). + chem_nullify_debuff = TRUE + + if(wear_suit && wear_suit.slowdown && !(wear_suit.slowdown > 0 && chem_nullify_debuff)) + tally += wear_suit.slowdown + + if(back && back.slowdown && !(back.slowdown > 0 && chem_nullify_debuff)) + tally += back.slowdown + + if(shoes && shoes.slowdown && !(shoes.slowdown > 0 && chem_nullify_debuff)) + tally += shoes.slowdown + + if(!chem_nullify_debuff) + for(var/x in list(l_hand, r_hand)) + var/obj/item/O = x + if(O && !(O.flags & ABSTRACT) && O.w_class >= ITEM_SIZE_NORMAL) + tally += 0.5 * (O.w_class - 2) // (3 = 0.5) || (4 = 1) || (5 = 1.5) + + if(buckled) // so, if we buckled we have large debuff + tally += 5.5 + + for(var/bodypart_name in list(BP_L_LEG , BP_R_LEG)) + var/obj/item/organ/external/BP = bodyparts_by_name[bodypart_name] + if(!BP || (BP.status & ORGAN_DESTROYED)) + tally += 6 + else if(BP.status & ORGAN_SPLINTED) + tally += 0.8 + else if(BP.status & ORGAN_BROKEN) + tally += 3 + + if(shock_stage >= 10) + tally += round(log(3.5, shock_stage), 0.1) // (40 = ~3.0) and (starts at ~1.83) + + if(pull_debuff) + tally += pull_debuff + + if(FAT in mutations) + tally += 1.5 + + if(bodytemperature < 283.222) + tally += (283.222 - bodytemperature) / 10 * 1.75 + + tally += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow + + return (tally + config.human_delay) + +/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) + + if(..()) + return 1 + + //Do we have a working jetpack + if(istype(back, /obj/item/weapon/tank/jetpack) && isturf(loc)) //Second check is so you can't use a jetpack in a mech + var/obj/item/weapon/tank/jetpack/J = back + if((movement_dir || J.stabilization_on) && J.allow_thrust(0.01, src)) + return 1 + return 0 + +/mob/living/carbon/human/mob_has_gravity() + . = ..() + if(!.) + if(mob_negates_gravity()) + . = 1 + +/mob/living/carbon/human/mob_negates_gravity() + return shoes && shoes.negates_gravity() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index dde6647c3a33..aa1f17e137fe 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -1,873 +1,873 @@ -/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() - var/obj/item/weapon/storage/S = H.get_inactive_hand() - if(!I) - to_chat(H, "You are not holding anything to equip.") - return - - // if(istype(I, /obj/item/clothing/head/helmet/space/rig)) // If the item to be equipped is a rigid suit helmet - // src << "\red You must fasten the helmet to a hardsuit first. (Target the head)" // Stop eva helms equipping. - // return 0 - - if(istype(I, /obj/item/clothing/suit/space)) // If the item to be equipped is a space suit - if(H.wear_suit) - to_chat(H, "You need to take off [H.wear_suit.name] first.") - return - else - var/obj/item/clothing/suit/space/rig/J = I - if(J.equip_time > 0) - delay_clothing_equip_to_slot_if_possible(J, 13) // 13 = suit slot - return 0 - - if(H.equip_to_appropriate_slot(I)) - if(hand) - update_inv_l_hand() - else - update_inv_r_hand() - - else if(s_active && s_active.can_be_inserted(I,1)) //if storage active insert there - s_active.handle_item_insertion(I) - else if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) //see if we have box in other hand - S.handle_item_insertion(I) - - else - S = H.get_item_by_slot(slot_belt) - if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) //else we put in belt - S.handle_item_insertion(I) - else - S = H.get_item_by_slot(slot_back) //else we put in backpack - if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) - S.handle_item_insertion(I) - else - to_chat(H, "You are unable to equip that.") - - - -/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/W, list/slots, del_on_fail = 1) - for (var/slot in slots) - if (equip_to_slot_if_possible(W, slots[slot], del_on_fail = 0)) - return slot - if (del_on_fail) - qdel(W) - return null - - -/mob/living/carbon/human/proc/has_bodypart(name) - var/obj/item/organ/external/BP = bodyparts_by_name[name] - - return (BP && !(BP.status & ORGAN_DESTROYED) ) - -/mob/living/carbon/human/proc/specie_has_slot(slot) - if(species && slot in species.restricted_inventory_slots) - return FALSE - return TRUE - -/mob/living/carbon/human/proc/has_bodypart_for_slot(slot) - switch(slot) - if(slot_back) - return has_bodypart(BP_CHEST) - if(slot_wear_mask) - return has_bodypart(BP_HEAD) - if(slot_handcuffed) - return has_bodypart(BP_L_ARM) && has_bodypart(BP_R_ARM) - if(slot_legcuffed) - return has_bodypart(BP_L_LEG) && has_bodypart(BP_R_LEG) - if(slot_l_hand) - return has_bodypart(BP_L_ARM) - if(slot_r_hand) - return has_bodypart(BP_R_ARM) - if(slot_belt) - return has_bodypart(BP_CHEST) - if(slot_wear_id) - // the only relevant check for this is the uniform check - return TRUE - if(slot_l_ear) - return has_bodypart(BP_HEAD) - if(slot_r_ear) - return has_bodypart(BP_HEAD) - if(slot_glasses) - return has_bodypart(BP_HEAD) - if(slot_gloves) - return has_bodypart(BP_L_ARM) && has_bodypart(BP_R_ARM) - if(slot_head) - return has_bodypart(BP_HEAD) - if(slot_shoes) - return has_bodypart(BP_R_LEG) && has_bodypart(BP_L_LEG) - if(slot_wear_suit) - return has_bodypart(BP_CHEST) - if(slot_w_uniform) - return has_bodypart(BP_CHEST) - if(slot_l_store) - return has_bodypart(BP_CHEST) - if(slot_r_store) - return has_bodypart(BP_CHEST) - if(slot_s_store) - return has_bodypart(BP_CHEST) - if(slot_in_backpack) - return TRUE - if(slot_tie) - return TRUE - -/mob/living/carbon/human/u_equip(obj/W) - if(!W) return 0 - - if (W == wear_suit) - if(s_store) - drop_from_inventory(s_store) - wear_suit = null - var/update_hair = 0 - if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) - update_hair = 1 - else if(istype(W, /obj/item)) - var/obj/item/I = W - if(I.flags_inv & HIDEMASK) - update_hair = 1 - if(update_hair) - update_hair() - update_inv_ears() - update_inv_wear_mask() - update_inv_wear_suit() - else if (W == w_uniform) - if (r_store) - drop_from_inventory(r_store) - if (l_store) - drop_from_inventory(l_store) - if (wear_id) - drop_from_inventory(wear_id) - if (belt) - drop_from_inventory(belt) - w_uniform = null - update_inv_w_uniform() - else if (W == gloves) - gloves = null - update_inv_gloves() - else if (W == glasses) - glasses = null - update_inv_glasses() - else if (W == head) - head = null - - var/update_hair = 0 - if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) - update_hair = 1 - else if(istype(W, /obj/item)) - var/obj/item/I = W - if(I.flags_inv & HIDEMASK) - update_hair = 1 - if(update_hair) - update_hair() - update_inv_ears() - update_inv_wear_mask() - - update_inv_head() - else if (W == l_ear) - l_ear = null - update_inv_ears() - else if (W == r_ear) - r_ear = null - update_inv_ears() - else if (W == shoes) - shoes = null - update_inv_shoes() - else if (W == belt) - belt = null - update_inv_belt() - else if (W == wear_mask) - wear_mask = null - if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) - update_hair() //rebuild hair - if(internal) - if(internals) - internals.icon_state = "internal0" - internal = null - update_inv_wear_mask() - else if (W == wear_id) - wear_id = null - update_inv_wear_id() - else if (W == r_store) - r_store = null - update_inv_pockets() - else if (W == l_store) - l_store = null - update_inv_pockets() - else if (W == s_store) - s_store = null - update_inv_s_store() - else if (W == back) - back = null - update_inv_back() - else if (W == handcuffed) - handcuffed = null - update_inv_handcuffed() - if(buckled && buckled.buckle_require_restraints) - buckled.unbuckle_mob() - else if (W == legcuffed) - legcuffed = null - update_inv_legcuffed() - else if (W == r_hand) - r_hand = null - update_inv_r_hand() - else if (W == l_hand) - l_hand = null - update_inv_l_hand() - else - return 0 - - 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, slot, redraw_mob = 1) - if(!slot) - return - if(!istype(W)) - return - if(!has_bodypart_for_slot(slot)) - return - if(!specie_has_slot(slot)) - return - - W.screen_loc = null // will get moved if inventory is visible - - W.loc = src - switch(slot) - if(slot_back) - src.back = W - W.equipped(src, slot) - update_inv_back() - if(slot_wear_mask) - src.wear_mask = W - if((wear_mask.flags & BLOCKHAIR) || (wear_mask.flags & BLOCKHEADHAIR)) - update_hair() - W.equipped(src, slot) - update_inv_wear_mask() - if(slot_handcuffed) - src.handcuffed = W - update_inv_handcuffed() - if(slot_legcuffed) - src.legcuffed = W - W.equipped(src, slot) - update_inv_legcuffed() - if(slot_l_hand) - src.l_hand = W - W.equipped(src, slot) - update_inv_l_hand() - if(slot_r_hand) - src.r_hand = W - W.equipped(src, slot) - update_inv_r_hand() - if(slot_belt) - src.belt = W - W.equipped(src, slot) - update_inv_belt() - if(slot_wear_id) - src.wear_id = W - W.equipped(src, slot) - update_inv_wear_id() - if(slot_l_ear) - src.l_ear = W - if(l_ear.slot_flags & SLOT_TWOEARS) - var/obj/item/clothing/ears/offear/O = new(W) - O.loc = src - src.r_ear = O - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_LAYER - O.appearance_flags = APPEARANCE_UI - W.equipped(src, slot) - update_inv_ears() - if(slot_r_ear) - src.r_ear = W - if(r_ear.slot_flags & SLOT_TWOEARS) - var/obj/item/clothing/ears/offear/O = new(W) - O.loc = src - src.l_ear = O - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_LAYER - O.appearance_flags = APPEARANCE_UI - W.equipped(src, slot) - update_inv_ears() - if(slot_glasses) - src.glasses = W - W.equipped(src, slot) - update_inv_glasses() - if(slot_gloves) - src.gloves = W - W.equipped(src, slot) - update_inv_gloves() - if(slot_head) - src.head = W - if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) - update_hair() //rebuild hair - if(istype(W,/obj/item/clothing/head/kitty)) - W.update_icon(src) - W.equipped(src, slot) - update_inv_head() - if(slot_shoes) - src.shoes = W - W.equipped(src, slot) - update_inv_shoes() - if(slot_wear_suit) - src.wear_suit = W - if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) - update_hair() //rebuild hair - W.equipped(src, slot) - update_inv_wear_suit() - if(slot_w_uniform) - src.w_uniform = W - W.equipped(src, slot) - update_inv_w_uniform() - if(slot_l_store) - src.l_store = W - W.equipped(src, slot) - update_inv_pockets() - if(slot_r_store) - src.r_store = W - W.equipped(src, slot) - update_inv_pockets() - if(slot_s_store) - src.s_store = W - W.equipped(src, slot) - update_inv_s_store() - if(slot_in_backpack) - if(src.get_active_hand() == W) - src.remove_from_mob(W) - W.loc = src.back - if(slot_tie) - var/obj/item/clothing/under/uniform = w_uniform - uniform.attackby(W, src) - else - to_chat(src, "You are trying to eqip this item to an unsupported inventory slot. How the heck did you manage that? Stop it...") - return - - if(W == l_hand && slot != slot_l_hand) - l_hand = null - update_inv_l_hand() // So items actually disappear from hands. - else if(W == r_hand && slot != slot_r_hand) - r_hand = null - update_inv_r_hand() - - W.layer = ABOVE_HUD_LAYER - W.plane = ABOVE_HUD_PLANE - W.appearance_flags = APPEARANCE_UI - -/* - MouseDrop human inventory menu -*/ - -/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/obj/item/clothing/holder - -/obj/effect/equip_e/human - name = "human" - var/mob/living/carbon/human/target = null - -/obj/effect/equip_e/monkey - name = "monkey" - var/mob/living/carbon/monkey/target = null - -/obj/effect/equip_e/process() - return - -/obj/effect/equip_e/proc/done() - return - -/obj/effect/equip_e/atom_init() - ..() - if (!ticker) - return INITIALIZE_HINT_QDEL - return INITIALIZE_HINT_LATELOAD - -/obj/effect/equip_e/atom_init_late() - QDEL_IN(src, 100) - -/obj/effect/equip_e/Destroy() - source = null - s_loc = null - t_loc = null - item = null - return ..() - -/obj/effect/equip_e/human/process() - if(ismouse(source)) - return - 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/bodypart_name in list(BP_L_LEG , BP_R_LEG , BP_L_ARM , BP_R_ARM)) - var/obj/item/organ/external/BP = target.bodyparts_by_name[bodypart_name] - if(BP.status & ORGAN_SPLINTED) - count = 1 - break - if(count == 0) - qdel(src) - return - if("sensor") - if (! target.w_uniform ) - qdel(src) - if("internal") - if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && (istype(target.back, /obj/item/weapon/tank) || istype(target.belt, /obj/item/weapon/tank) || istype(target.s_store, /obj/item/weapon/tank)) && !( target.internal )) ) && !( target.internal ))) - qdel(src) - - var/list/L = list( "syringe", "pill", "drink", "dnainjector", "fuel", "sensor", "internal", "tie") - if ((item && !( L.Find(place) ))) - if(isrobot(source)) //#Z2 - if(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 - if((place == "handcuff") | (istype(item, /obj/item/weapon/handcuffs))) - for(var/mob/O in viewers(target, null)) - O.show_message("[source] is trying to put \a [item] on [target]", 1) - else - if((HULK in target.mutations) && !(HULK in source.mutations))//#Z2 - Hulk is too faking~ scary, so we cant put anything on him using inventory. - source.show_message("[target] is too scary! You dont want to risk your health.", 1) - return - else - for(var/mob/O in viewers(target, null)) - O.show_message("[source] is trying to put \a [item] on [target]", 1) //##Z2 - 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])") - if(target.l_hand && !target.l_hand.canremove) - message = "[source] fails to take off \a [target.l_hand] from [target]'s left hand!" - return - else - 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])") - if(target.r_hand && !target.r_hand.canremove) - message = "[source] fails to take off \a [target.r_hand] from [target]'s right hand!" - return - else - 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("l_ear") - target.attack_log += text("\[[time_stamp()]\] Has had their left ear item ([target.l_ear]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) left ear item ([target.l_ear])") - if(target.l_ear && !target.l_ear.canremove) - message = "[source] fails to take off \a [target.l_ear] from [target]'s left ear!" - return - else - message = "[source] is trying to take off the [target.l_ear] from [target]'s left ear!" - if("r_ear") - target.attack_log += text("\[[time_stamp()]\] Has had their right ear item ([target.r_ear]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) right ear item ([target.r_ear])") - if(target.r_ear && !target.r_ear.canremove) - message = "[source] fails to take off \a [target.r_ear] from [target]'s right ear!" - return - else - message = "[source] is trying to take off the [target.r_ear] from [target]'s right ear!" - 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])") - message = "[source] is trying 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("tie") - var/obj/item/clothing/under/suit = target.w_uniform - if(suit.accessories.len) - var/obj/item/clothing/accessory/A = suit.accessories[1] - target.attack_log += "\[[time_stamp()]\] Has had their accessory ([A]) removed by [source.name] ([source.ckey])" - source.attack_log += "\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) accessory ([A])" - if(istype(A, /obj/item/clothing/accessory/holobadge) || istype(A, /obj/item/clothing/accessory/medal)) - for(var/mob/M in viewers(target, null)) - M.show_message("\red [source] tears off \the [A] from [target]'s [suit]!" , 1) - done() - return - else - message = "[source] is trying to take off \a [A] from [target]'s [suit]!" - if("s_store") - target.attack_log += text("\[[time_stamp()]\] Has had their suit storage item ([target.s_store]) removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) suit storage item ([target.s_store])") - 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])") - message = "[source] is trying 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("splints") - message = text("[] is trying to remove []'s splints!", source, target) - if("bandages") - message = text("[] is trying to remove []'s bandages!", source, target) - target.attack_log += text("\[[time_stamp()]\] Has had their bandages removed by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) bandages") - if("sensor") - target.attack_log += text("\[[time_stamp()]\] Has had their sensors toggled by [source.name] ([source.ckey])") - source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) sensors") - var/obj/item/clothing/under/suit = target.w_uniform - if (suit.has_sensor >= 2) - to_chat(source, "The controls are locked.") - return - message = "[source] is trying to set [target]'s suit sensors!" - var/obj/item/clothing/gloves/Strip = null - if(ishuman(source)) - var/mob/living/carbon/human/Striper = source - Strip = Striper.gloves - if(istype(Strip, /obj/item/clothing/gloves/black/strip)) - to_chat(source, message) - else - source.visible_message(message) - 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, except Ian, hes a cat, cats no no animal! - 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(!in_range(s_loc, t_loc)) return //Use a proxi! - if(item && source.get_active_hand() != item) return //Swapped hands / removed item from the active one - 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("l_ear") - slot_to_process = slot_l_ear - if (target.l_ear) - strip_item = target.l_ear - if("r_ear") - slot_to_process = slot_r_ear - if (target.r_ear) - strip_item = target.r_ear - 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("tie") - var/obj/item/clothing/under/suit = target.w_uniform - if(suit && suit.accessories.len) - var/obj/item/clothing/accessory/A = suit.accessories[1] - A.on_removed(usr) - suit.accessories -= A - target.update_inv_w_uniform() - 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 - else if (source != target && ishuman(source)) - //check that we are still grabbing them - var/grabbing = 0 - for (var/obj/item/weapon/grab/G in target.grabbed_by) - if (G.loc == source && G.state >= GRAB_AGGRESSIVE) - grabbing = 1 - if (!grabbing) - slot_to_process = null - to_chat(source, "Your grasp was broken before you could restrain [target]!") - - if("legcuff") - slot_to_process = slot_legcuffed - if (target.legcuffed) - strip_item = target.legcuffed - if("splints") - for(var/bodypart_name in list(BP_L_LEG , BP_R_LEG , BP_L_ARM , BP_R_ARM)) - var/obj/item/organ/external/BP = target.bodyparts_by_name[bodypart_name] - if (BP && (BP.status & ORGAN_SPLINTED)) - var/obj/item/W = new /obj/item/stack/medical/splint(target.loc, 1) - BP.status &= ~ORGAN_SPLINTED - W.add_fingerprint(source) - if("bandages") - for(var/obj/item/organ/external/BP in target.bodyparts) - for(var/datum/wound/W in BP.wounds) - if(W.bandaged) - W.bandaged = 0 - target.update_bandage() - if("CPR") - if ((target.health > config.health_threshold_dead && target.health < config.health_threshold_crit)) - var/suff = min(target.getOxyLoss(), 5) //Pre-merge level, less healing, more prevention of dieing. - 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 - if (target.l_store) - strip_item = target.l_store - else if (target.r_store) - strip_item = target.r_store - if("sensor") - var/obj/item/clothing/under/suit = target.w_uniform - if (suit) - if(suit.has_sensor >= 2) - to_chat(source, "The controls are locked.") - else - suit.set_sensors(source) - 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(slot_to_process) - if(strip_item) //Stripping an item from the mob - var/obj/item/W = strip_item - var/obj/item/clothing/gloves/Strip = null - target.remove_from_mob(W) - if(ishuman(source)) - var/mob/living/carbon/human/Striper = source - Strip = Striper.gloves - if(istype(Strip, /obj/item/clothing/gloves/black/strip) && (!source.l_hand || !source.r_hand)) - source.put_in_hands(W) - else - 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.remove_from_mob(target.r_store) //At this stage l_store is already processed by the code above, we only need to process r_store. - W.add_fingerprint(source) - else - if(item && target.has_bodypart_for_slot(slot_to_process)) //Placing an item on the mob - if(item.mob_can_equip(target, slot_to_process, 0)) - source.remove_from_mob(item) - target.equip_to_slot_if_possible(item, slot_to_process, 0, 1, 1) - - if(source && target) - if(source.machine == target) - target.show_inv(source) - qdel(src) +/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() + var/obj/item/weapon/storage/S = H.get_inactive_hand() + if(!I) + to_chat(H, "You are not holding anything to equip.") + return + + // if(istype(I, /obj/item/clothing/head/helmet/space/rig)) // If the item to be equipped is a rigid suit helmet + // src << "\red You must fasten the helmet to a hardsuit first. (Target the head)" // Stop eva helms equipping. + // return 0 + + if(istype(I, /obj/item/clothing/suit/space)) // If the item to be equipped is a space suit + if(H.wear_suit) + to_chat(H, "You need to take off [H.wear_suit.name] first.") + return + else + var/obj/item/clothing/suit/space/rig/J = I + if(J.equip_time > 0) + delay_clothing_equip_to_slot_if_possible(J, 13) // 13 = suit slot + return 0 + + if(H.equip_to_appropriate_slot(I)) + if(hand) + update_inv_l_hand() + else + update_inv_r_hand() + + else if(s_active && s_active.can_be_inserted(I,1)) //if storage active insert there + s_active.handle_item_insertion(I) + else if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) //see if we have box in other hand + S.handle_item_insertion(I) + + else + S = H.get_item_by_slot(slot_belt) + if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) //else we put in belt + S.handle_item_insertion(I) + else + S = H.get_item_by_slot(slot_back) //else we put in backpack + if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) + S.handle_item_insertion(I) + else + to_chat(H, "You are unable to equip that.") + + + +/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/W, list/slots, del_on_fail = 1) + for (var/slot in slots) + if (equip_to_slot_if_possible(W, slots[slot], del_on_fail = 0)) + return slot + if (del_on_fail) + qdel(W) + return null + + +/mob/living/carbon/human/proc/has_bodypart(name) + var/obj/item/organ/external/BP = bodyparts_by_name[name] + + return (BP && !(BP.status & ORGAN_DESTROYED) ) + +/mob/living/carbon/human/proc/specie_has_slot(slot) + if(species && slot in species.restricted_inventory_slots) + return FALSE + return TRUE + +/mob/living/carbon/human/proc/has_bodypart_for_slot(slot) + switch(slot) + if(slot_back) + return has_bodypart(BP_CHEST) + if(slot_wear_mask) + return has_bodypart(BP_HEAD) + if(slot_handcuffed) + return has_bodypart(BP_L_ARM) && has_bodypart(BP_R_ARM) + if(slot_legcuffed) + return has_bodypart(BP_L_LEG) && has_bodypart(BP_R_LEG) + if(slot_l_hand) + return has_bodypart(BP_L_ARM) + if(slot_r_hand) + return has_bodypart(BP_R_ARM) + if(slot_belt) + return has_bodypart(BP_CHEST) + if(slot_wear_id) + // the only relevant check for this is the uniform check + return TRUE + if(slot_l_ear) + return has_bodypart(BP_HEAD) + if(slot_r_ear) + return has_bodypart(BP_HEAD) + if(slot_glasses) + return has_bodypart(BP_HEAD) + if(slot_gloves) + return has_bodypart(BP_L_ARM) && has_bodypart(BP_R_ARM) + if(slot_head) + return has_bodypart(BP_HEAD) + if(slot_shoes) + return has_bodypart(BP_R_LEG) && has_bodypart(BP_L_LEG) + if(slot_wear_suit) + return has_bodypart(BP_CHEST) + if(slot_w_uniform) + return has_bodypart(BP_CHEST) + if(slot_l_store) + return has_bodypart(BP_CHEST) + if(slot_r_store) + return has_bodypart(BP_CHEST) + if(slot_s_store) + return has_bodypart(BP_CHEST) + if(slot_in_backpack) + return TRUE + if(slot_tie) + return TRUE + +/mob/living/carbon/human/u_equip(obj/W) + if(!W) return 0 + + if (W == wear_suit) + if(s_store) + drop_from_inventory(s_store) + wear_suit = null + var/update_hair = 0 + if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) + update_hair = 1 + else if(istype(W, /obj/item)) + var/obj/item/I = W + if(I.flags_inv & HIDEMASK) + update_hair = 1 + if(update_hair) + update_hair() + update_inv_ears() + update_inv_wear_mask() + update_inv_wear_suit() + else if (W == w_uniform) + if (r_store) + drop_from_inventory(r_store) + if (l_store) + drop_from_inventory(l_store) + if (wear_id) + drop_from_inventory(wear_id) + if (belt) + drop_from_inventory(belt) + w_uniform = null + update_inv_w_uniform() + else if (W == gloves) + gloves = null + update_inv_gloves() + else if (W == glasses) + glasses = null + update_inv_glasses() + else if (W == head) + head = null + + var/update_hair = 0 + if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) + update_hair = 1 + else if(istype(W, /obj/item)) + var/obj/item/I = W + if(I.flags_inv & HIDEMASK) + update_hair = 1 + if(update_hair) + update_hair() + update_inv_ears() + update_inv_wear_mask() + + update_inv_head() + else if (W == l_ear) + l_ear = null + update_inv_ears() + else if (W == r_ear) + r_ear = null + update_inv_ears() + else if (W == shoes) + shoes = null + update_inv_shoes() + else if (W == belt) + belt = null + update_inv_belt() + else if (W == wear_mask) + wear_mask = null + if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) + update_hair() //rebuild hair + if(internal) + if(internals) + internals.icon_state = "internal0" + internal = null + update_inv_wear_mask() + else if (W == wear_id) + wear_id = null + update_inv_wear_id() + else if (W == r_store) + r_store = null + update_inv_pockets() + else if (W == l_store) + l_store = null + update_inv_pockets() + else if (W == s_store) + s_store = null + update_inv_s_store() + else if (W == back) + back = null + update_inv_back() + else if (W == handcuffed) + handcuffed = null + update_inv_handcuffed() + if(buckled && buckled.buckle_require_restraints) + buckled.unbuckle_mob() + else if (W == legcuffed) + legcuffed = null + update_inv_legcuffed() + else if (W == r_hand) + r_hand = null + update_inv_r_hand() + else if (W == l_hand) + l_hand = null + update_inv_l_hand() + else + return 0 + + 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, slot, redraw_mob = 1) + if(!slot) + return + if(!istype(W)) + return + if(!has_bodypart_for_slot(slot)) + return + if(!specie_has_slot(slot)) + return + + W.screen_loc = null // will get moved if inventory is visible + + W.loc = src + switch(slot) + if(slot_back) + src.back = W + W.equipped(src, slot) + update_inv_back() + if(slot_wear_mask) + src.wear_mask = W + if((wear_mask.flags & BLOCKHAIR) || (wear_mask.flags & BLOCKHEADHAIR)) + update_hair() + W.equipped(src, slot) + update_inv_wear_mask() + if(slot_handcuffed) + src.handcuffed = W + update_inv_handcuffed() + if(slot_legcuffed) + src.legcuffed = W + W.equipped(src, slot) + update_inv_legcuffed() + if(slot_l_hand) + src.l_hand = W + W.equipped(src, slot) + update_inv_l_hand() + if(slot_r_hand) + src.r_hand = W + W.equipped(src, slot) + update_inv_r_hand() + if(slot_belt) + src.belt = W + W.equipped(src, slot) + update_inv_belt() + if(slot_wear_id) + src.wear_id = W + W.equipped(src, slot) + update_inv_wear_id() + if(slot_l_ear) + src.l_ear = W + if(l_ear.slot_flags & SLOT_TWOEARS) + var/obj/item/clothing/ears/offear/O = new(W) + O.loc = src + src.r_ear = O + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_LAYER + O.appearance_flags = APPEARANCE_UI + W.equipped(src, slot) + update_inv_ears() + if(slot_r_ear) + src.r_ear = W + if(r_ear.slot_flags & SLOT_TWOEARS) + var/obj/item/clothing/ears/offear/O = new(W) + O.loc = src + src.l_ear = O + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_LAYER + O.appearance_flags = APPEARANCE_UI + W.equipped(src, slot) + update_inv_ears() + if(slot_glasses) + src.glasses = W + W.equipped(src, slot) + update_inv_glasses() + if(slot_gloves) + src.gloves = W + W.equipped(src, slot) + update_inv_gloves() + if(slot_head) + src.head = W + if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) + update_hair() //rebuild hair + if(istype(W,/obj/item/clothing/head/kitty)) + W.update_icon(src) + W.equipped(src, slot) + update_inv_head() + if(slot_shoes) + src.shoes = W + W.equipped(src, slot) + update_inv_shoes() + if(slot_wear_suit) + src.wear_suit = W + if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR)) + update_hair() //rebuild hair + W.equipped(src, slot) + update_inv_wear_suit() + if(slot_w_uniform) + src.w_uniform = W + W.equipped(src, slot) + update_inv_w_uniform() + if(slot_l_store) + src.l_store = W + W.equipped(src, slot) + update_inv_pockets() + if(slot_r_store) + src.r_store = W + W.equipped(src, slot) + update_inv_pockets() + if(slot_s_store) + src.s_store = W + W.equipped(src, slot) + update_inv_s_store() + if(slot_in_backpack) + if(src.get_active_hand() == W) + src.remove_from_mob(W) + W.loc = src.back + if(slot_tie) + var/obj/item/clothing/under/uniform = w_uniform + uniform.attackby(W, src) + else + to_chat(src, "You are trying to eqip this item to an unsupported inventory slot. How the heck did you manage that? Stop it...") + return + + if(W == l_hand && slot != slot_l_hand) + l_hand = null + update_inv_l_hand() // So items actually disappear from hands. + else if(W == r_hand && slot != slot_r_hand) + r_hand = null + update_inv_r_hand() + + W.layer = ABOVE_HUD_LAYER + W.plane = ABOVE_HUD_PLANE + W.appearance_flags = APPEARANCE_UI + +/* + MouseDrop human inventory menu +*/ + +/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/obj/item/clothing/holder + +/obj/effect/equip_e/human + name = "human" + var/mob/living/carbon/human/target = null + +/obj/effect/equip_e/monkey + name = "monkey" + var/mob/living/carbon/monkey/target = null + +/obj/effect/equip_e/process() + return + +/obj/effect/equip_e/proc/done() + return + +/obj/effect/equip_e/atom_init() + ..() + if (!ticker) + return INITIALIZE_HINT_QDEL + return INITIALIZE_HINT_LATELOAD + +/obj/effect/equip_e/atom_init_late() + QDEL_IN(src, 100) + +/obj/effect/equip_e/Destroy() + source = null + s_loc = null + t_loc = null + item = null + return ..() + +/obj/effect/equip_e/human/process() + if(ismouse(source)) + return + 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/bodypart_name in list(BP_L_LEG , BP_R_LEG , BP_L_ARM , BP_R_ARM)) + var/obj/item/organ/external/BP = target.bodyparts_by_name[bodypart_name] + if(BP.status & ORGAN_SPLINTED) + count = 1 + break + if(count == 0) + qdel(src) + return + if("sensor") + if (! target.w_uniform ) + qdel(src) + if("internal") + if ((!( (istype(target.wear_mask, /obj/item/clothing/mask) && (istype(target.back, /obj/item/weapon/tank) || istype(target.belt, /obj/item/weapon/tank) || istype(target.s_store, /obj/item/weapon/tank)) && !( target.internal )) ) && !( target.internal ))) + qdel(src) + + var/list/L = list( "syringe", "pill", "drink", "dnainjector", "fuel", "sensor", "internal", "tie") + if ((item && !( L.Find(place) ))) + if(isrobot(source)) //#Z2 + if(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 + if((place == "handcuff") | (istype(item, /obj/item/weapon/handcuffs))) + for(var/mob/O in viewers(target, null)) + O.show_message("[source] is trying to put \a [item] on [target]", 1) + else + if((HULK in target.mutations) && !(HULK in source.mutations))//#Z2 - Hulk is too faking~ scary, so we cant put anything on him using inventory. + source.show_message("[target] is too scary! You dont want to risk your health.", 1) + return + else + for(var/mob/O in viewers(target, null)) + O.show_message("[source] is trying to put \a [item] on [target]", 1) //##Z2 + 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])") + if(target.l_hand && !target.l_hand.canremove) + message = "[source] fails to take off \a [target.l_hand] from [target]'s left hand!" + return + else + 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])") + if(target.r_hand && !target.r_hand.canremove) + message = "[source] fails to take off \a [target.r_hand] from [target]'s right hand!" + return + else + 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("l_ear") + target.attack_log += text("\[[time_stamp()]\] Has had their left ear item ([target.l_ear]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) left ear item ([target.l_ear])") + if(target.l_ear && !target.l_ear.canremove) + message = "[source] fails to take off \a [target.l_ear] from [target]'s left ear!" + return + else + message = "[source] is trying to take off the [target.l_ear] from [target]'s left ear!" + if("r_ear") + target.attack_log += text("\[[time_stamp()]\] Has had their right ear item ([target.r_ear]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) right ear item ([target.r_ear])") + if(target.r_ear && !target.r_ear.canremove) + message = "[source] fails to take off \a [target.r_ear] from [target]'s right ear!" + return + else + message = "[source] is trying to take off the [target.r_ear] from [target]'s right ear!" + 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])") + message = "[source] is trying 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("tie") + var/obj/item/clothing/under/suit = target.w_uniform + if(suit.accessories.len) + var/obj/item/clothing/accessory/A = suit.accessories[1] + target.attack_log += "\[[time_stamp()]\] Has had their accessory ([A]) removed by [source.name] ([source.ckey])" + source.attack_log += "\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) accessory ([A])" + if(istype(A, /obj/item/clothing/accessory/holobadge) || istype(A, /obj/item/clothing/accessory/medal)) + for(var/mob/M in viewers(target, null)) + M.show_message("\red [source] tears off \the [A] from [target]'s [suit]!" , 1) + done() + return + else + message = "[source] is trying to take off \a [A] from [target]'s [suit]!" + if("s_store") + target.attack_log += text("\[[time_stamp()]\] Has had their suit storage item ([target.s_store]) removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) suit storage item ([target.s_store])") + 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])") + message = "[source] is trying 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("splints") + message = text("[] is trying to remove []'s splints!", source, target) + if("bandages") + message = text("[] is trying to remove []'s bandages!", source, target) + target.attack_log += text("\[[time_stamp()]\] Has had their bandages removed by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) bandages") + if("sensor") + target.attack_log += text("\[[time_stamp()]\] Has had their sensors toggled by [source.name] ([source.ckey])") + source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) sensors") + var/obj/item/clothing/under/suit = target.w_uniform + if (suit.has_sensor >= 2) + to_chat(source, "The controls are locked.") + return + message = "[source] is trying to set [target]'s suit sensors!" + var/obj/item/clothing/gloves/Strip = null + if(ishuman(source)) + var/mob/living/carbon/human/Striper = source + Strip = Striper.gloves + if(istype(Strip, /obj/item/clothing/gloves/black/strip)) + to_chat(source, message) + else + source.visible_message(message) + 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, except Ian, hes a cat, cats no no animal! + 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(!in_range(s_loc, t_loc)) return //Use a proxi! + if(item && source.get_active_hand() != item) return //Swapped hands / removed item from the active one + 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("l_ear") + slot_to_process = slot_l_ear + if (target.l_ear) + strip_item = target.l_ear + if("r_ear") + slot_to_process = slot_r_ear + if (target.r_ear) + strip_item = target.r_ear + 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("tie") + var/obj/item/clothing/under/suit = target.w_uniform + if(suit && suit.accessories.len) + var/obj/item/clothing/accessory/A = suit.accessories[1] + A.on_removed(usr) + suit.accessories -= A + target.update_inv_w_uniform() + 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 + else if (source != target && ishuman(source)) + //check that we are still grabbing them + var/grabbing = 0 + for (var/obj/item/weapon/grab/G in target.grabbed_by) + if (G.loc == source && G.state >= GRAB_AGGRESSIVE) + grabbing = 1 + if (!grabbing) + slot_to_process = null + to_chat(source, "Your grasp was broken before you could restrain [target]!") + + if("legcuff") + slot_to_process = slot_legcuffed + if (target.legcuffed) + strip_item = target.legcuffed + if("splints") + for(var/bodypart_name in list(BP_L_LEG , BP_R_LEG , BP_L_ARM , BP_R_ARM)) + var/obj/item/organ/external/BP = target.bodyparts_by_name[bodypart_name] + if (BP && (BP.status & ORGAN_SPLINTED)) + var/obj/item/W = new /obj/item/stack/medical/splint(target.loc, 1) + BP.status &= ~ORGAN_SPLINTED + W.add_fingerprint(source) + if("bandages") + for(var/obj/item/organ/external/BP in target.bodyparts) + for(var/datum/wound/W in BP.wounds) + if(W.bandaged) + W.bandaged = 0 + target.update_bandage() + if("CPR") + if ((target.health > config.health_threshold_dead && target.health < config.health_threshold_crit)) + var/suff = min(target.getOxyLoss(), 5) //Pre-merge level, less healing, more prevention of dieing. + 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 + if (target.l_store) + strip_item = target.l_store + else if (target.r_store) + strip_item = target.r_store + if("sensor") + var/obj/item/clothing/under/suit = target.w_uniform + if (suit) + if(suit.has_sensor >= 2) + to_chat(source, "The controls are locked.") + else + suit.set_sensors(source) + 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(slot_to_process) + if(strip_item) //Stripping an item from the mob + var/obj/item/W = strip_item + var/obj/item/clothing/gloves/Strip = null + target.remove_from_mob(W) + if(ishuman(source)) + var/mob/living/carbon/human/Striper = source + Strip = Striper.gloves + if(istype(Strip, /obj/item/clothing/gloves/black/strip) && (!source.l_hand || !source.r_hand)) + source.put_in_hands(W) + else + 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.remove_from_mob(target.r_store) //At this stage l_store is already processed by the code above, we only need to process r_store. + W.add_fingerprint(source) + else + if(item && target.has_bodypart_for_slot(slot_to_process)) //Placing an item on the mob + if(item.mob_can_equip(target, slot_to_process, 0)) + source.remove_from_mob(item) + target.equip_to_slot_if_possible(item, slot_to_process, 0, 1, 1) + + if(source && target) + if(source.machine == target) + target.show_inv(source) + qdel(src) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 7c37564ad53b..373fe16018fa 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1,1917 +1,1917 @@ -//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick! -#define HUMAN_MAX_OXYLOSS 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it. -#define HUMAN_CRIT_MAX_OXYLOSS (SSmob.wait/30) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks. - -#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 1000K point - -#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point -#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point -#define COLD_DAMAGE_LEVEL_3 3 //Amount of damage applied when your body temperature passes the 120K point - -//Note that gas heat damage is only applied once every FOUR ticks. -#define HEAT_GAS_DAMAGE_LEVEL_1 2 //Amount of damage applied when the current breath's temperature just passes the 360.15k safety point -#define HEAT_GAS_DAMAGE_LEVEL_2 4 //Amount of damage applied when the current breath's temperature passes the 400K point -#define HEAT_GAS_DAMAGE_LEVEL_3 8 //Amount of damage applied when the current breath's temperature passes the 1000K point - -#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point -#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point -#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point - -/mob/living/carbon/human - var/prev_gender = null // Debug for plural genders - var/in_stasis = 0 - - -/mob/living/carbon/human/Life() - set invisibility = 0 - set background = 1 - - if (monkeyizing) return - if(!loc) return // Fixing a null error that occurs when the mob isn't found in the world -- TLE - - ..() - - /* - //This code is here to try to determine what causes the gender switch to plural error. Once the error is tracked down and fixed, this code should be deleted - //Also delete var/prev_gender once this is removed. - if(prev_gender != gender) - prev_gender = gender - if(gender in list(PLURAL, NEUTER)) - message_admins("[src] ([ckey]) gender has been changed to plural or neuter. Please record what has happened recently to the person and then notify coders. (?) (VV) (PM) (JMP)") - */ - //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() - - in_stasis = istype(loc, /obj/structure/closet/body_bag/cryobag) && loc:opened == 0 - if(in_stasis) loc:used++ - - if(life_tick%30==15) - hud_updateflag = 1022 - - voice = GetVoice() - - //No need to update all of these procs if the guy is dead. - if(stat != DEAD && !in_stasis) - if(SSmob.times_fired%4==2 || failed_last_breath || (health < config.health_threshold_crit)) //First, resolve location and get a breath - breathe() //Only try to take a breath every 4 ticks, unless suffocating - - 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() - - //Random events (vomiting etc) - handle_random_events() - - handle_virus_updates() - - //stuff in the stomach - handle_stomach() - - handle_shock() - - handle_pain() - - handle_medical_side_effects() - - handle_heart_beat() - - handle_stasis_bag() - - 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 - return //We go ahead and process them 5 times for HUD images and other stuff though. - - //Handle temperature/pressure differences between body and environment - handle_environment(environment) //Optimized a good bit. - - //Check if we're on fire - handle_fire() - if(on_fire && fire_stacks > 0) - fire_stacks -= 0.5 - - //Status updates, death etc. - handle_regular_status_updates() //Optimized a bit - update_canmove() - - //Update our name based on whether our face is obscured/disfigured - name = get_visible_name() - - handle_regular_hud_updates() - - //Updates the number of stored chemicals for powers and essentials - handle_changeling() - - //Species-specific update. - if(species) - species.on_life(src) - - pulse = handle_pulse() - - // Grabbing - for(var/obj/item/weapon/grab/G in src) - G.process() - - -//Much like get_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. -/mob/living/carbon/human/proc/get_pressure_protection(pressure_check = STOPS_PRESSUREDMAGE) - var/pressure_adjustment_coefficient = 1 //Determins how much the clothing you are wearing protects you in percent. - - if((head && (head.flags_pressure & pressure_check))&&(wear_suit && (wear_suit.flags_pressure & pressure_check))) - pressure_adjustment_coefficient = 0 - - //Handles breaches in your space suit. 10 suit damage equals a 100% loss of pressure reduction. - if(istype(wear_suit,/obj/item/clothing/suit/space)) - var/obj/item/clothing/suit/space/S = wear_suit - if(S.can_breach && S.damage) - var/pressure_loss = S.damage * 0.1 - pressure_adjustment_coefficient = pressure_loss - - pressure_adjustment_coefficient = CLAMP01(pressure_adjustment_coefficient) //So it isn't less than 0 or larger than 1. - - return 1 - pressure_adjustment_coefficient //want 0 to be bad protection, 1 to be good protection - -/mob/living/carbon/human/calculate_affecting_pressure(var/pressure) - ..() - var/pressure_difference = abs( pressure - ONE_ATMOSPHERE ) - - if(pressure > ONE_ATMOSPHERE) - pressure_difference = pressure_difference * (1 - get_pressure_protection(STOPS_HIGHPRESSUREDMAGE)) - return ONE_ATMOSPHERE + pressure_difference - else - pressure_difference = pressure_difference * (1 - get_pressure_protection(STOPS_LOWPRESSUREDMAGE)) - return ONE_ATMOSPHERE - pressure_difference - -/mob/living/carbon/human/proc/handle_disabilities() - if (disabilities & EPILEPSY || has_trait(TRAIT_EPILEPSY)) - if ((prob(1) && paralysis < 1)) - to_chat(src, "\red You have a seizure!") - for(var/mob/O in viewers(src, null)) - if(O == src) - continue - O.show_message(text("\red [src] starts having a seizure!"), 1) - Paralyse(10) - make_jittery(1000) - if (disabilities & COUGHING || has_trait(TRAIT_COUGH)) - if ((prob(5) && paralysis <= 1)) - drop_item() - spawn( 0 ) - emote("cough") - return - if (disabilities & TOURETTES || has_trait(TRAIT_TOURETTE)) - speech_problem_flag = 1 - if ((prob(10) && paralysis <= 1)) - Stun(10) - spawn( 0 ) - switch(rand(1, 3)) - if(1) - emote("twitch") - if(2 to 3) - say("[pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]") - var/old_x = pixel_x - var/old_y = pixel_y - pixel_x += rand(-2,2) - pixel_y += rand(-1,1) - sleep(2) - pixel_x = old_x - pixel_y = old_y - return - if (disabilities & NERVOUS || has_trait(TRAIT_NERVOUS)) - speech_problem_flag = 1 - if (prob(10)) - stuttering = max(10, stuttering) - // No. -- cib - //Oh, really? - if (getBrainLoss() >= 60 && stat != DEAD) - if(prob(3)) - if(config.rus_language)//TODO:CYRILLIC dictionary? - switch(pick(1,2,3)) - if(1) - say(pick("!", " !", " !", "[pick("", " ")] [pick("", "", "", "")] [pick("", "", "")] ;!!!", " [pick("","","")]?", " !", " !", " !", " !!!!", "!")) - if(2) - say(pick(" [JA_PLACEHOLDER] ?"," !", "", "[JA_PLACEHOLDER] !", "!", "!!!", " !", "!", "!", "!!!!", " !", "", " ", " !")) - if(3) - emote("drool") - else - switch(pick(1,2,3)) - if(1) - say(pick("IM A PONY NEEEEEEIIIIIIIIIGH", "without oxigen blob don't evoluate?", "CAPTAINS A COMDOM", "[pick("", "that faggot traitor")] [pick("joerge", "george", "gorge", "gdoruge")] [pick("mellens", "melons", "mwrlins")] is grifing me HAL;P!!!", "can u give me [pick("telikesis","halk","eppilapse")]?", "THe saiyans screwed", "Bi is THE BEST OF BOTH WORLDS>", "I WANNA PET TEH monkeyS", "stop grifing me!!!!", "SOTP IT#")) - if(2) - say(pick("FUS RO DAH","fucking 4rries!", "stat me", ">my face", "roll it easy!", "waaaaaagh!!!", "red wonz go fasta", "FOR TEH EMPRAH", "lol2cat", "dem dwarfs man, dem dwarfs", "SPESS MAHREENS", "hwee did eet fhor khayosss", "lifelike texture ;_;", "luv can bloooom", "PACKETS!!!")) - if(3) - emote("drool") - - if(stat != DEAD) - var/rn = rand(0, 200) - if(getBrainLoss() >= 5) - if(0 <= rn && rn <= 3) - custom_pain("Your head feels numb and painful.") - if(getBrainLoss() >= 15) - if(4 <= rn && rn <= 6) if(eye_blurry <= 0) - to_chat(src, "\red It becomes hard to see for some reason.") - eye_blurry = 10 - if(getBrainLoss() >= 35) - if(7 <= rn && rn <= 9) if(get_active_hand()) - to_chat(src, "\red Your hand won't respond properly, you drop what you're holding.") - drop_item() - if(getBrainLoss() >= 50) - if(10 <= rn && rn <= 12) if(!lying) - to_chat(src, "\red Your legs won't respond properly, you fall down.") - resting = 1 - -/mob/living/carbon/human/proc/handle_stasis_bag() - // Handle side effects from stasis bag - if(in_stasis) - // First off, there's no oxygen supply, so the mob will slowly take brain damage - adjustBrainLoss(0.1) - - // Next, the method to induce stasis has some adverse side-effects, manifesting - // as cloneloss - adjustCloneLoss(0.1) - -/mob/living/carbon/human/proc/handle_mutations_and_radiation() - - if(species.flags[IS_SYNTHETIC]) //Robots don't suffer from mutations or radloss. - return - - // DNA2 - Gene processing. - // The HULK stuff that was here is now in the hulk gene. - for(var/datum/dna/gene/gene in dna_genes) - if(!gene.block) - continue - if(gene.is_active(src)) - speech_problem_flag = 1 - gene.OnMobLife(src) - - if(dna_inject_count > 0 && prob(2)) - dna_inject_count-- - - if(radiation) - if(species.flags[RAD_IMMUNE]) - return - - if (radiation > 100) - radiation = 100 - if(!species.flags[RAD_ABSORB]) - Weaken(10) - if(!lying) - to_chat(src, "\red You feel weak.") - emote("collapse") - - if (radiation < 0) - radiation = 0 - - else - - if(species.flags[RAD_ABSORB]) - var/rads = radiation/25 - radiation -= rads - nutrition += rads - adjustBruteLoss(-(rads)) - adjustOxyLoss(-(rads)) - adjustToxLoss(-(rads)) - updatehealth() - return - - var/damage = 0 - radiation-- - if(prob(25)) - damage = 1 - - if(radiation > 50) - radiation-- - damage = 1 - if(prob(5) && prob(radiation) && (h_style != "Bald" || f_style != "Shaved")) - h_style = "Bald" - f_style = "Shaved" - update_hair() - to_chat(src, "Suddenly you lost your hair!") - if(prob(5)) - radiation -= 5 - Weaken(3) - if(!lying) - to_chat(src, "\red You feel weak.") - emote("collapse") - if(radiation > 75) - radiation-- - damage = 3 - if(prob(1)) - to_chat(src, "\red You mutate!") - randmutb(src) - domutcheck(src,null) - emote("gasp") - - if(damage) - adjustToxLoss(damage) - updatehealth() - if (bodyparts.len) - var/obj/item/organ/external/BP = pick(bodyparts) - if(istype(BP)) - BP.add_autopsy_data("Radiation Poisoning", damage) - -/mob/living/carbon/human/proc/breathe() - if(NO_BREATH in src.mutations) - return //#Z2 We need no breath with this mutation - if(reagents.has_reagent("lexorin")) - return - if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) - return - if(species && (species.flags[NO_BREATHE] || species.flags[IS_SYNTHETIC])) - return - if(dna && dna.mutantrace == "adamantine") - return - if(ismob(loc)) - return - - var/datum/gas_mixture/environment = loc.return_air() - var/datum/gas_mixture/breath - - //First, check if we can breathe at all - if(handle_drowning() || health < config.health_threshold_crit && !reagents.has_reagent("inaprovaline")) - losebreath = max(2, losebreath + 1) - - if(losebreath>0) //Suffocating so do not take a breath - losebreath-- - if (prob(10)) //Gasp per 10 ticks? Sounds about right. - 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) // Super hacky -- TLE - //breath = get_breath_from_internal(0.5) // Manually setting to old BREATH_VOLUME amount -- TLE - - //No breath from internal atmosphere so get breath from location - if(!breath) - if(isobj(loc)) - var/obj/location_as_object = loc - breath = location_as_object.handle_internal_lifeform(src, BREATH_MOLES) - else if(isturf(loc)) - 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) - - if(istype(wear_mask, /obj/item/clothing/mask/gas) && breath) - var/obj/item/clothing/mask/gas/G = wear_mask - var/datum/gas_mixture/filtered = new - - for(var/g in list("phoron", "sleeping_agent")) - if(breath.gas[g]) - filtered.gas[g] = breath.gas[g] * G.gas_filter_strength - breath.gas[g] -= filtered.gas[g] - - breath.update_values() - filtered.update_values() - - if(!is_lung_ruptured()) - if(!breath || breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5) - if(prob(5)) - rupture_lung() - - // Handle filtering - var/block = 0 - if(wear_mask) - if(wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT) - block = 1 - if(glasses) - if(glasses.flags & BLOCK_GAS_SMOKE_EFFECT) - block = 1 - if(head) - if(head.flags & BLOCK_GAS_SMOKE_EFFECT) - 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) - - //spread some viruses while we are at it - if (virus2.len > 0) - if (prob(10) && get_infection_chance(src)) -// log_debug("[src] : Exhaling some viruses") - for(var/mob/living/carbon/M in view(1,src)) - src.spread_disease_to(M) - - -/mob/living/carbon/human/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) - return internal.remove_air_volume(volume_needed) - else if(internals) - internals.icon_state = "internal0" - return null - -/mob/living/carbon/human/proc/handle_breath(datum/gas_mixture/breath) - if(status_flags & GODMODE) - return - - if(!breath || (breath.total_moles == 0) || suiciding) - if(suiciding) - adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster - failed_last_breath = 1 - throw_alert("oxy") - return 0 - if(health > config.health_threshold_crit) - adjustOxyLoss(HUMAN_MAX_OXYLOSS) - failed_last_breath = 1 - else - adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) - failed_last_breath = 1 - - throw_alert("oxy") - - return 0 - - var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa - //var/safe_pressure_max = 140 // Maximum safe partial pressure of breathable gas in kPa (Not used for now) - var/safe_exhaled_max = 10 // Yes it's an arbitrary value who cares? - var/safe_toxins_max = 0.005 - var/SA_para_min = 1 - var/SA_sleep_min = 5 - var/inhaled_gas_used = 0 - - var/breath_pressure = (breath.total_moles * R_IDEAL_GAS_EQUATION * breath.temperature) / BREATH_VOLUME - - var/inhaling = breath.gas[species.breath_type] - var/poison = breath.gas[species.poison_type] - var/exhaling = species.exhale_type ? breath.gas[species.exhale_type] : 0 - - var/inhale_pp = (inhaling / breath.total_moles) * breath_pressure - var/toxins_pp = (poison / breath.total_moles) * breath_pressure - var/exhaled_pp = (exhaling / breath.total_moles) * breath_pressure - - if(inhale_pp < safe_pressure_min) - if(prob(20)) - emote("gasp") - if(inhale_pp > 0) - var/ratio = inhale_pp/safe_pressure_min - - // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) - adjustOxyLoss(min(5*(1 - ratio), HUMAN_MAX_OXYLOSS)) - failed_last_breath = 1 - inhaled_gas_used = inhaling*ratio/6 - - else - - adjustOxyLoss(HUMAN_MAX_OXYLOSS) - failed_last_breath = 1 - - throw_alert("oxy") - - else - // We're in safe limits - failed_last_breath = 0 - adjustOxyLoss(-5) - inhaled_gas_used = inhaling/6 - clear_alert("oxy") - - breath.adjust_gas(species.breath_type, -inhaled_gas_used, update = FALSE) //update afterwards - - if(species.exhale_type) - breath.adjust_gas_temp(species.exhale_type, inhaled_gas_used, bodytemperature, update = FALSE) //update afterwards - - // CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2, - // this will hurt you, but only once per 4 ticks, instead of once per tick. - - if(exhaled_pp > safe_exhaled_max) - - // If it's the first breath with too much CO2 in it, lets start a counter, - // then have them pass out after 12s or so. - if(!co2overloadtime) - co2overloadtime = world.time - - else if(world.time - co2overloadtime > 120) - - // Lets hurt em a little, let them know we mean business - Paralyse(3) - adjustOxyLoss(3) - - // They've been in here 30s now, lets start to kill them for their own good! - if(world.time - co2overloadtime > 300) - adjustOxyLoss(8) - - // Lets give them some chance to know somethings not right though I guess. - if(prob(20)) - spawn(0) emote("cough") - else - co2overloadtime = 0 - - // Too much poison in the air. - if(toxins_pp > safe_toxins_max) - var/ratio = (poison/safe_toxins_max) * 10 - if(reagents) - reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) - breath.adjust_gas(species.poison_type, -poison / 6, update = FALSE) //update after - throw_alert("tox_in_air") - else - clear_alert("tox_in_air") - - // If there's some other shit in the air lets deal with it here. - if(breath.gas["sleeping_agent"]) - var/SA_pp = (breath.gas["sleeping_agent"] / breath.total_moles) * breath_pressure - - // Enough to make us paralysed for a bit - if(SA_pp > SA_para_min) - - // 3 gives them one second to wake up and run away a bit! - Paralyse(3) - - // Enough to make us sleep as well - if(SA_pp > SA_sleep_min) - Sleeping(5) - - // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning - else if(SA_pp > 0.15) - if(prob(20)) - emote(pick("giggle", "laugh")) - - breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"] / 6, update = FALSE) //update after - - //handle_temperature_effects(breath) - - // Hot air hurts :( - if( (breath.temperature < species.cold_level_1 || breath.temperature > species.heat_level_1)) - // #Z2 Cold_resistance wont save us anymore, we have no_breath genetics power now @ZVe - - if(status_flags & GODMODE) - return 1 - - switch(breath.temperature) - if(-INFINITY to species.cold_level_3) - apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Cold") - if(species.cold_level_3 to species.cold_level_2) - apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Cold") - if(species.cold_level_2 to species.cold_level_1) - apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Cold") - if(species.heat_level_1 to species.heat_level_2) - apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Heat") - if(species.heat_level_2 to species.heat_level_3) - apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Heat") - if(species.heat_level_3 to INFINITY) - apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Heat") - - //breathing in hot/cold air also heats/cools you a bit - var/temp_adj = breath.temperature - bodytemperature - if (temp_adj < 0) - temp_adj /= (BODYTEMP_COLD_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed - else - temp_adj /= (BODYTEMP_HEAT_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed - - var/relative_density = breath.total_moles / (MOLES_CELLSTANDARD * BREATH_PERCENTAGE) - temp_adj *= relative_density - - if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX - if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX - //world << "Breath: [breath.temperature], [src]: [bodytemperature], Adjusting: [temp_adj]" - bodytemperature += temp_adj - - breath.update_values() - - return 1 - -/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment) - if(!environment) - return - - //Moved pressure calculations here for use in skip-processing check. - var/pressure = environment.return_pressure() - var/adjusted_pressure = calculate_affecting_pressure(pressure) - var/is_in_space = istype(get_turf(src), /turf/space) - - if(!is_in_space) //space is not meant to change your body temperature. - var/loc_temp = get_temperature(environment) - - if(adjusted_pressure < species.warning_high_pressure && adjusted_pressure > species.warning_low_pressure && abs(loc_temp - bodytemperature) < 20 && bodytemperature < species.heat_level_1 && bodytemperature > species.cold_level_1) - clear_alert("pressure") - clear_alert("temp") - return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp - - //Body temperature adjusts depending on surrounding atmosphere based on your thermal protection - var/temp_adj = 0 - if(!on_fire && !(is_type_organ(O_LUNGS, /obj/item/organ/internal/lungs/ipc) && is_bruised_organ(O_LUNGS))) //If you're on fire, you do not heat up or cool down based on surrounding gases. IPC's lungs are the cooling element. If it's broken, IPCs should cool down. - if(loc_temp < bodytemperature) //Place is colder than we are - var/thermal_protection = get_cold_protection(loc_temp) //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) - temp_adj = (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR) //this will be negative - else if (loc_temp > bodytemperature) //Place is hotter than we are - var/thermal_protection = get_heat_protection(loc_temp) //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) - temp_adj = (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR) - - //Use heat transfer as proportional to the gas density. However, we only care about the relative density vs standard 101 kPa/20 C air. Therefore we can use mole ratios - var/relative_density = (environment.total_moles / environment.volume) / (MOLES_CELLSTANDARD / CELL_VOLUME) - temp_adj *= relative_density - - if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX - if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX - //world << "Environment: [loc_temp], [src]: [bodytemperature], Adjusting: [temp_adj]" - bodytemperature += temp_adj - - else if(!species.flags[IS_SYNTHETIC] && !species.flags[IS_PLANT]) - if(istype(loc, /obj/mecha)) - return - if(istype(loc, /obj/structure/transit_tube_pod)) - return - var/protected = 0 - if( (head && istype(head, /obj/item/clothing/head/helmet/space)) && (wear_suit && istype(wear_suit, /obj/item/clothing/suit/space))) - protected = 1 - if(!protected && radiation < 100) - apply_effect(5, IRRADIATE) - - if(status_flags & GODMODE) - return 1 //godmode - - // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. - if(bodytemperature > species.heat_level_1) - //Body temperature is too hot. - if(bodytemperature > species.heat_level_3) - throw_alert("temp","hot",3) - take_overall_damage(burn=HEAT_DAMAGE_LEVEL_3, used_weapon = "High Body Temperature") - else if(bodytemperature > species.heat_level_2) - if(on_fire) - throw_alert("temp","hot",3) - take_overall_damage(burn=HEAT_DAMAGE_LEVEL_3, used_weapon = "High Body Temperature") - else - throw_alert("temp","hot",2) - take_overall_damage(burn=HEAT_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature") - else - throw_alert("temp","hot",1) - take_overall_damage(burn=HEAT_DAMAGE_LEVEL_1, used_weapon = "High Body Temperature") - else if(bodytemperature < species.cold_level_1) - if(!istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) - if(bodytemperature < species.cold_level_3) - throw_alert("temp","cold",3) - take_overall_damage(burn=COLD_DAMAGE_LEVEL_3, used_weapon = "Low Body Temperature") - else if(bodytemperature < species.cold_level_2) - throw_alert("temp","cold",2) - take_overall_damage(burn=COLD_DAMAGE_LEVEL_2, used_weapon = "Low Body Temperature") - else - throw_alert("temp","cold",1) - take_overall_damage(burn=COLD_DAMAGE_LEVEL_1, used_weapon = "Low Body Temperature") - else - clear_alert("temp") - else - clear_alert("temp") - - // Account for massive pressure differences. Done by Polymorph - // Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense! - - if(adjusted_pressure >= species.hazard_high_pressure) - var/pressure_damage = min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) - take_overall_damage(brute=pressure_damage, used_weapon = "High Pressure") - throw_alert("pressure","highpressure",2) - else if(adjusted_pressure >= species.warning_high_pressure) - throw_alert("pressure","highpressure",1) - else if(adjusted_pressure >= species.warning_low_pressure) - clear_alert("pressure") - else if(adjusted_pressure >= species.hazard_low_pressure) - throw_alert("pressure","lowpressure",1) - else - throw_alert("pressure","lowpressure",2) - apply_effect(is_in_space ? 15 : 7, AGONY, 0) - take_overall_damage(burn=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure") - - -//#Z2 - No more low pressure resistance with Cold Resistance genetic power, for now - /*if( !(COLD_RESISTANCE in mutations)) - take_overall_damage(brute=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure") - pressure_alert = -2 - else - pressure_alert = -1*/ -//##Z2 - //Check for contaminants before anything else because we don't want to skip it. - for(var/g in environment.gas) - if(gas_data.flags[g] & XGM_GAS_CONTAMINANT && environment.gas[g] > gas_data.overlay_limit[g] + 1) - pl_effects() - break - -///FIRE CODE -/mob/living/carbon/human/handle_fire() - if(..()) - return - var/thermal_protection = get_heat_protection(30000) //If you don't have fire suit level protection, you get a temperature increase - if((1 - thermal_protection) > 0.0001) - bodytemperature += BODYTEMP_HEATING_MAX - return -//END FIRE CODE - - -/* -/mob/living/carbon/human/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 -*/ - -/mob/living/carbon/human/proc/stabilize_body_temperature() - if (species.flags[IS_SYNTHETIC]) - bodytemperature += species.synth_temp_gain //just keep putting out heat. - return - - var/body_temperature_difference = species.body_temperature - bodytemperature - - if (abs(body_temperature_difference) < 0.5) - return //fuck this precision - - if(bodytemperature < species.cold_level_1) //260.15 is 310.15 - 50, the temperature where you start to feel effects. - if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up. - nutrition -= 2 - var/recovery_amt = max((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM) - //world << "Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]" -// log_debug("Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]") - bodytemperature += recovery_amt - else if(species.cold_level_1 <= bodytemperature && bodytemperature <= species.heat_level_1) - var/recovery_amt = body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR - //world << "Norm. Difference = [body_temperature_difference]. Recovering [recovery_amt]" -// log_debug("Norm. Difference = [body_temperature_difference]. Recovering [recovery_amt]") - bodytemperature += recovery_amt - else if(bodytemperature > species.heat_level_1) //360.15 is 310.15 + 50, the temperature where you start to feel effects. - //We totally need a sweat system cause it totally makes sense...~ - var/recovery_amt = min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers - //world << "Hot. Difference = [body_temperature_difference]. Recovering [recovery_amt]" -// log_debug("Hot. Difference = [body_temperature_difference]. Recovering [recovery_amt]") - bodytemperature += recovery_amt - -//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, UPPER_TORSO, LOWER_TORSO, etc. See setup.dm for the full list) -/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to. - var/thermal_protection_flags = 0 - //Handle normal clothing - if(head) - if(head.max_heat_protection_temperature && head.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= head.heat_protection - if(wear_suit) - if(wear_suit.max_heat_protection_temperature && wear_suit.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= wear_suit.heat_protection - if(w_uniform) - if(w_uniform.max_heat_protection_temperature && w_uniform.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= w_uniform.heat_protection - if(shoes) - if(shoes.max_heat_protection_temperature && shoes.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= shoes.heat_protection - if(gloves) - if(gloves.max_heat_protection_temperature && gloves.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= gloves.heat_protection - if(wear_mask) - if(wear_mask.max_heat_protection_temperature && wear_mask.max_heat_protection_temperature >= temperature) - thermal_protection_flags |= wear_mask.heat_protection - - return thermal_protection_flags - -/mob/living/carbon/human/proc/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to. - if(RESIST_HEAT in mutations) //#Z2 - return 1 //Fully protected from the fire. //##Z2 - - var/thermal_protection_flags = get_heat_protection_flags(temperature) - - var/thermal_protection = 0.0 - if(thermal_protection_flags) - if(thermal_protection_flags & HEAD) - thermal_protection += THERMAL_PROTECTION_HEAD - if(thermal_protection_flags & UPPER_TORSO) - thermal_protection += THERMAL_PROTECTION_UPPER_TORSO - if(thermal_protection_flags & LOWER_TORSO) - thermal_protection += THERMAL_PROTECTION_LOWER_TORSO - if(thermal_protection_flags & LEG_LEFT) - thermal_protection += THERMAL_PROTECTION_LEG_LEFT - if(thermal_protection_flags & LEG_RIGHT) - thermal_protection += THERMAL_PROTECTION_LEG_RIGHT - if(thermal_protection_flags & ARM_LEFT) - thermal_protection += THERMAL_PROTECTION_ARM_LEFT - if(thermal_protection_flags & ARM_RIGHT) - thermal_protection += THERMAL_PROTECTION_ARM_RIGHT - - return min(1,thermal_protection) - -//See proc/get_heat_protection_flags(temperature) for the description of this proc. -/mob/living/carbon/human/proc/get_cold_protection_flags(temperature) - var/thermal_protection_flags = 0 - //Handle normal clothing - - if(head) - if(head.min_cold_protection_temperature && head.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= head.cold_protection - if(wear_suit) - if(wear_suit.min_cold_protection_temperature && wear_suit.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= wear_suit.cold_protection - if(w_uniform) - if(w_uniform.min_cold_protection_temperature && w_uniform.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= w_uniform.cold_protection - if(shoes) - if(shoes.min_cold_protection_temperature && shoes.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= shoes.cold_protection - if(gloves) - if(gloves.min_cold_protection_temperature && gloves.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= gloves.cold_protection - if(wear_mask) - if(wear_mask.min_cold_protection_temperature && wear_mask.min_cold_protection_temperature <= temperature) - thermal_protection_flags |= wear_mask.cold_protection - - return thermal_protection_flags - -/mob/living/carbon/human/proc/get_cold_protection(temperature) - - if(COLD_RESISTANCE in mutations) - return 1 //Fully protected from the cold. - - temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K. - var/thermal_protection_flags = get_cold_protection_flags(temperature) - - var/thermal_protection = 0.0 - if(thermal_protection_flags) - if(thermal_protection_flags & HEAD) - thermal_protection += THERMAL_PROTECTION_HEAD - if(thermal_protection_flags & UPPER_TORSO) - thermal_protection += THERMAL_PROTECTION_UPPER_TORSO - if(thermal_protection_flags & LOWER_TORSO) - thermal_protection += THERMAL_PROTECTION_LOWER_TORSO - if(thermal_protection_flags & LEG_LEFT) - thermal_protection += THERMAL_PROTECTION_LEG_LEFT - if(thermal_protection_flags & LEG_RIGHT) - thermal_protection += THERMAL_PROTECTION_LEG_RIGHT - if(thermal_protection_flags & ARM_LEFT) - thermal_protection += THERMAL_PROTECTION_ARM_LEFT - if(thermal_protection_flags & ARM_RIGHT) - thermal_protection += THERMAL_PROTECTION_ARM_RIGHT - - return min(1,thermal_protection) - -/* -/mob/living/carbon/human/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(glasses) - if(glasses.protective_temperature > temp) - fire_prot += (glasses.protective_temperature/10) - if(ears) - if(ears.protective_temperature > temp) - fire_prot += (ears.protective_temperature/10) - if(wear_suit) - if(wear_suit.protective_temperature > temp) - fire_prot += (wear_suit.protective_temperature/10) - if(w_uniform) - if(w_uniform.protective_temperature > temp) - fire_prot += (w_uniform.protective_temperature/10) - if(gloves) - if(gloves.protective_temperature > temp) - fire_prot += (gloves.protective_temperature/10) - if(shoes) - if(shoes.protective_temperature > temp) - fire_prot += (shoes.protective_temperature/10) - - return fire_prot - -/mob/living/carbon/human/proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity) - if(nodamage) - return - //world <<"body_part = [body_part], exposed_temperature = [exposed_temperature], exposed_intensity = [exposed_intensity]" - var/discomfort = min(abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0) - - if(exposed_temperature > bodytemperature) - discomfort *= 4 - - if(mutantrace == "plant") - discomfort *= TEMPERATURE_DAMAGE_COEFFICIENT * 2 //I don't like magic numbers. I'll make mutantraces a datum with vars sometime later. -- Urist - else - discomfort *= TEMPERATURE_DAMAGE_COEFFICIENT //Dangercon 2011 - now with less magic numbers! - //world <<"[discomfort]" - - switch(body_part) - if(HEAD) - apply_damage(2.5*discomfort, BURN, BP_HEAD) - if(UPPER_TORSO) - apply_damage(2.5*discomfort, BURN, BP_CHEST) - if(LEGS) - apply_damage(0.6*discomfort, BURN, BP_L_LEG) - apply_damage(0.6*discomfort, BURN, BP_R_LEG) - if(ARMS) - apply_damage(0.4*discomfort, BURN, BP_L_ARM) - apply_damage(0.4*discomfort, BURN, BP_R_ARM) -*/ - -/mob/living/carbon/human/proc/handle_chemicals_in_body() - - if(reagents && !species.flags[IS_SYNTHETIC]) //Synths don't process reagents. - var/alien = null - if(species) - alien = species.name - reagents.metabolize(src,alien) - - var/total_phoronloss = 0 - for(var/obj/item/I in src) - if(I.contaminated) - total_phoronloss += vsc.plc.CONTAMINATION_LOSS - if(!(status_flags & GODMODE)) adjustToxLoss(total_phoronloss) - - if(status_flags & GODMODE) return 0 //godmode - - if(species.flags[REQUIRE_LIGHT]) - 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 - light_amount = round((T.get_lumcount()*10)-5) - - if(is_type_organ(O_LIVER, /obj/item/organ/internal/liver/diona) && !is_bruised_organ(O_LIVER)) // Specie may require light, but only plants, with chlorophyllic plasts can produce nutrition out of light! - nutrition += light_amount - - if(species.flags[IS_PLANT]) - if(is_type_organ(O_KIDNEYS, /obj/item/organ/internal/kidneys/diona)) // Diona's kidneys contain all the nutritious elements. Damaging them means they aren't held. - var/obj/item/organ/internal/kidneys/KS = organs_by_name[O_KIDNEYS] - if(!KS) - nutrition = 0 - else if(nutrition > (500 - KS.damage*5)) - nutrition = 500 - KS.damage*5 - species.regen(src, light_amount) - - if(dna && dna.mutantrace == "shadow") - var/light_amount = 0 - if(isturf(loc)) - var/turf/T = loc - light_amount = round(T.get_lumcount()*10) - - if(light_amount > 2) //if there's enough light, start dying - take_overall_damage(1,1) - else if (light_amount < 2) //heal in the dark - heal_overall_damage(1,1) - - if(dna && dna.mutantrace == "shadowling") - var/light_amount = 0 - nutrition = 450 //i aint never get hongry - if(isturf(loc)) - var/turf/T = loc - light_amount = round(T.get_lumcount()*10) - - if(light_amount > LIGHT_DAM_THRESHOLD) - take_overall_damage(0,LIGHT_DAMAGE_TAKEN) - to_chat(src, "The light burns you!") - src << 'sound/weapons/sear.ogg' - else if (light_amount < LIGHT_HEAL_THRESHOLD) //heal in the dark - heal_overall_damage(5,5) - adjustToxLoss(-3) - adjustBrainLoss(-25) //gibbering shadowlings are hilarious but also bad to have - adjustCloneLoss(-1) - adjustOxyLoss(-10) - SetWeakened(0) - SetStunned(0) - - //The fucking FAT mutation is the dumbest shit ever. It makes the code so difficult to work with - if(FAT in mutations) - if(!has_trait(TRAIT_FAT) && overeatduration < 100) - to_chat(src, "\blue You feel fit again!") - mutations.Remove(FAT) - update_body() - update_mutantrace() - update_mutations() - update_inv_w_uniform() - update_inv_wear_suit() - else - if(has_trait(TRAIT_FAT) || overeatduration > 500) - if(!species.flags[IS_SYNTHETIC] && !species.flags[IS_PLANT]) - mutations.Add(FAT) - update_body() - update_mutantrace() - update_mutations() - update_inv_w_uniform() - update_inv_wear_suit() - - - // nutrition decrease - if (nutrition > 0 && stat != DEAD) - nutrition = max(0, nutrition - metabolism_factor/10) - - if (nutrition > 450) - if(overeatduration < 600) //capped so people don't take forever to unfat - overeatduration++ - else - if(overeatduration > 1) - overeatduration -= 2 //doubled the unfat rate - - if(species.flags[REQUIRE_LIGHT]) - if(nutrition < 200) - take_overall_damage(2,0) - traumatic_shock++ - - 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 - 15) - jitteriness = max(0, jitteriness - 15) - else - dizziness = max(0, dizziness - 3) - jitteriness = max(0, jitteriness - 3) - - if(!species.flags[IS_SYNTHETIC]) - handle_trace_chems() - - updatehealth() - - return //TODO: DEFERRED - -/mob/living/carbon/human/proc/handle_regular_status_updates() - if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP - blinded = 1 - silent = 0 - else //ALIVE. LIGHTS ARE ON - updatehealth() //TODO - if(!in_stasis) - stabilize_body_temperature() //Body temperature adjusts itself - handle_bodyparts() //Optimized. - if(!species.flags[NO_BLOOD] && bodytemperature >= 170) - var/blood_volume = round(vessel.get_reagent_amount("blood")) - if(blood_volume > 0) - handle_blood(blood_volume) - - if(health <= config.health_threshold_dead || brain_op_stage == 4.0) - death() - blinded = 1 - silent = 0 - return 1 - - // the analgesic effect wears off slowly - analgesic = max(0, analgesic - 1) - - //UNCONSCIOUS. NO-ONE IS HOME - if( (getOxyLoss() > 50) || (config.health_threshold_crit > health) ) - Paralyse(3) - - /* Done by handle_breath() - if( health <= 20 && prob(1) ) - spawn(0) - emote("gasp") - if(!reagents.has_reagent("inaprovaline")) - adjustOxyLoss(1)*/ - - if(hallucination) - if(hallucination >= 20) - if(prob(3)) - fake_attack(src) - if(!handling_hal) - spawn handle_hallucinations() //The not boring kind! - - if(hallucination<=2) - hallucination = 0 - halloss = 0 - else - hallucination -= 2 - - else - for(var/atom/a in hallucinations) - qdel(a) - - if(halloss > 100) - //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) - if(prob(3)) - Paralyse(10) - else - Weaken(10) - setHalLoss(99) - - if(paralysis) - AdjustParalysis(-1) - blinded = 1 - stat = UNCONSCIOUS - if(halloss > 0) - adjustHalLoss(-3) - else if(sleeping) - throw_alert("asleep") - speech_problem_flag = 1 - handle_dreams() - adjustHalLoss(-3) - if (mind) - if((mind.active && client != null) || immune_to_ssd) //This also checks whether a client is connected, if not, sleep is not reduced. - sleeping = max(sleeping-1, 0) - blinded = 1 - stat = UNCONSCIOUS - if( prob(2) && health && !hal_crit ) - spawn(0) - emote("snore") - //CONSCIOUS - else - stat = CONSCIOUS - if(halloss > 0) - if(resting) - adjustHalLoss(-3) - else - adjustHalLoss(-1) - if(!sleeping) //No refactor - no life! - clear_alert("asleep") - - if(embedded_flag && !(life_tick % 10)) - var/list/E - E = get_visible_implants(0) - if(!E.len) - embedded_flag = 0 - - - //Eyes - if(sdisabilities & BLIND || has_trait(TRAIT_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(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold) || istype(head, /obj/item/weapon/reagent_containers/glass/bucket)) //resting your eyes with a blindfold heals blurry eyes faster - eye_blurry = max(eye_blurry-3, 0) - blinded = 1 - else if(eye_blurry) //blurry eyes heal slowly - eye_blurry = max(eye_blurry-1, 0) - - //Ears - if(sdisabilities & DEAF || has_trait(TRAIT_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(istype(l_ear, /obj/item/clothing/ears/earmuffs) || istype(r_ear, /obj/item/clothing/ears/earmuffs)) //resting your ears with earmuffs heals ear damage faster - ear_damage = max(ear_damage-0.15, 0) - ear_deaf = max(ear_deaf, 1) - 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) - speech_problem_flag = 1 - AdjustStunned(-1) - - if(weakened) - weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times - - if(stuttering) - speech_problem_flag = 1 - stuttering = max(stuttering-1, 0) - if (slurring) - speech_problem_flag = 1 - slurring = max(slurring-1, 0) - if(silent) - speech_problem_flag = 1 - silent = max(silent-1, 0) - - if(druggy) - druggy = max(druggy-1, 0) - - // If you're dirty, your gloves will become dirty, too. - if(gloves && germ_level > gloves.germ_level && prob(10)) - gloves.germ_level += 1 - - return 1 - -/mob/living/carbon/human/handle_regular_hud_updates() - if(hud_updateflag)//? Below ? - handle_hud_list() - - if(!client) - return 0 - - if(hud_updateflag)//Is there any reason for 2nd check? ~Zve - handle_hud_list() - - for(var/image/hud in client.images) - if(copytext(hud.icon_state,1,4) == "hud") //ugly, but icon comparison is worse, I believe - client.images.Remove(hud) - - if(stat == UNCONSCIOUS && health <= 0) - //Critical damage passage overlay - var/severity = 0 - switch(health) - if(-20 to -10) severity = 1 - if(-30 to -20) severity = 2 - if(-40 to -30) severity = 3 - if(-50 to -40) severity = 4 - if(-60 to -50) severity = 5 - if(-70 to -60) severity = 6 - if(-80 to -70) severity = 7 - if(-90 to -80) severity = 8 - if(-95 to -90) severity = 9 - if(-INFINITY to -95) severity = 10 - overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity) - else - clear_fullscreen("crit") - //Oxygen damage overlay - if(oxyloss) - var/severity = 0 - switch(oxyloss) - if(10 to 20) severity = 1 - if(20 to 25) severity = 2 - if(25 to 30) severity = 3 - if(30 to 35) severity = 4 - if(35 to 40) severity = 5 - if(40 to 45) severity = 6 - if(45 to INFINITY) severity = 7 - overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity) - else - clear_fullscreen("oxy") - - //Fire and Brute damage overlay (BSSR) - var/hurtdamage = src.getBruteLoss() + src.getFireLoss() + damageoverlaytemp - damageoverlaytemp = 0 // We do this so we can detect if someone hits us or not. - if(hurtdamage) - var/severity = 0 - switch(hurtdamage) - if(10 to 25) severity = 1 - if(25 to 40) severity = 2 - if(40 to 55) severity = 3 - if(55 to 70) severity = 4 - if(70 to 85) severity = 5 - if(85 to INFINITY) severity = 6 - overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity) - else - clear_fullscreen("brute") - - if( stat == DEAD ) - sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) - see_in_dark = 8 - if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO - if(healths) healths.icon_state = "health7" //DEAD healthmeter - if(client) - if(client.view != world.view) - if(locate(/obj/item/weapon/gun/energy/sniperrifle, contents)) - var/obj/item/weapon/gun/energy/sniperrifle/s = locate() in src - if(s.zoom) - s.zoom() - - else - sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS) - see_in_dark = species.darksight - see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING - if(dna) - switch(dna.mutantrace) - if("slime") - see_in_dark = 3 - see_invisible = SEE_INVISIBLE_LEVEL_ONE - if("shadow") - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_ONE - - if(XRAY in mutations) - sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS - see_in_dark = 8 - if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO - - if(seer) - var/obj/effect/rune/R = locate() in loc - if(R && istype(R.power, /datum/cult/seer)) - see_invisible = SEE_INVISIBLE_CULT - else - see_invisible = SEE_INVISIBLE_LIVING - seer = FALSE - - if(glasses) - var/obj/item/clothing/glasses/G = glasses - if(istype(G)) - see_in_dark += G.darkness_view - if(G.vision_flags) // MESONS - sight |= G.vision_flags - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM - if(istype(G,/obj/item/clothing/glasses/night/shadowling)) - var/obj/item/clothing/glasses/night/shadowling/S = G - if(S.vision) - see_invisible = SEE_INVISIBLE_LIVING - else - see_invisible = SEE_INVISIBLE_MINIMUM - -/* HUD shit goes here, as long as it doesn't modify sight flags */ -// The purpose of this is to stop xray and w/e from preventing you from using huds -- Love, Doohl - - if(istype(glasses, /obj/item/clothing/glasses/sunglasses/sechud)) - var/obj/item/clothing/glasses/sunglasses/sechud/O = glasses - if(O.hud) - O.hud.process_hud(src) - if(!druggy) - see_invisible = SEE_INVISIBLE_LIVING - else if(istype(glasses, /obj/item/clothing/glasses/hud)) - var/obj/item/clothing/glasses/hud/O = glasses - O.process_hud(src) - if(!druggy) - see_invisible = SEE_INVISIBLE_LIVING - else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/hud/secmed)) - var/obj/item/clothing/glasses/sunglasses/hud/secmed/O = glasses - O.process_hud(src) - if(!druggy) - see_invisible = SEE_INVISIBLE_LIVING - - else if(!seer) - see_invisible = SEE_INVISIBLE_LIVING - - if(istype(wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja)) - var/obj/item/clothing/mask/gas/voice/space_ninja/O = wear_mask - switch(O.mode) - if(0) - var/target_list[] = list() - for(var/mob/living/target in oview(src)) - if( target.mind&&(target.mind.special_role||issilicon(target)) )//They need to have a mind. - target_list += target - if(target_list.len)//Everything else is handled by the ninja mask proc. - O.assess_targets(target_list, src) - if(!druggy) - see_invisible = SEE_INVISIBLE_LIVING - if(1) - see_in_dark = 5 - //client.screen += global_hud.meson - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM - if(2) - sight |= SEE_MOBS - //client.screen += global_hud.thermal - if(!druggy) - see_invisible = SEE_INVISIBLE_LEVEL_TWO - if(3) - sight |= SEE_TURFS - //client.screen += global_hud.meson - if(!druggy) - see_invisible = SEE_INVISIBLE_MINIMUM - - if(changeling_aug) - sight |= SEE_MOBS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - - if(healths) - if (analgesic) - healths.icon_state = "health_health_numb" - else - switch(hal_screwyhud) - if(1) - healths.icon_state = "health6" - if(2) - healths.icon_state = "health7" - else - //switch(health - halloss) - switch(100 - ((species && species.flags[NO_PAIN] && !species.flags[IS_SYNTHETIC]) ? 0 : traumatic_shock)) - 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" - - if(healthdoll) - healthdoll.overlays.Cut() - if(stat == DEAD) - healthdoll.icon_state = "healthdoll_DEAD" - else - healthdoll.icon_state = "healthdoll_OVERLAY" - for(var/obj/item/organ/external/BP in bodyparts) - var/damage = BP.burn_dam + BP.brute_dam - var/comparison = (BP.max_damage / 5) - var/icon_num = 0 - if(damage) - icon_num = 1 - if(damage > (comparison)) - icon_num = 2 - if(damage > (comparison*2)) - icon_num = 3 - if(damage > (comparison*3)) - icon_num = 4 - if(damage > (comparison*4)) - icon_num = 5 - if(icon_num) - healthdoll.overlays += image('icons/mob/screen_gen.dmi',"[BP.body_zone][icon_num]") - - switch(get_nutrition()) - if(NUTRITION_LEVEL_FULL to INFINITY) - throw_alert("nutrition","fat") - if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FULL) - clear_alert("nutrition") - if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) - throw_alert("nutrition","hungry") - else - throw_alert("nutrition","starving") - - if(pressure) - pressure.icon_state = "pressure[pressure_alert]" - - if(pullin) - if(pulling) - pullin.icon_state = "pull1" - else - pullin.icon_state = "pull0" - //OH cmon... - var/nearsighted = 0 - var/impaired = 0 - - if(disabilities & NEARSIGHTED || has_trait(TRAIT_NEARSIGHT)) - nearsighted = 1 - - if(glasses) - var/obj/item/clothing/glasses/G = glasses - if(G.prescription) - nearsighted = 0 - - if(istype(head, /obj/item/clothing/head/welding) || istype(head, /obj/item/clothing/head/helmet/space/unathi)) - var/obj/item/clothing/head/welding/O = head - if(!O.up && tinted_weldhelh) - impaired = 2 - if(istype(wear_mask, /obj/item/clothing/mask/gas/welding) ) - var/obj/item/clothing/mask/gas/welding/O = wear_mask - if(!O.up && tinted_weldhelh) - impaired = 2 - if(istype(glasses, /obj/item/clothing/glasses/welding) ) - var/obj/item/clothing/glasses/welding/O = glasses - if(!O.up && tinted_weldhelh) - impaired = max(impaired, 1) - - if(eye_blurry) - overlay_fullscreen("blurry", /obj/screen/fullscreen/blurry) - else - clear_fullscreen("blurry") - - if(druggy) - overlay_fullscreen("high", /obj/screen/fullscreen/high) - else - clear_fullscreen("high") - if(nearsighted) - overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1) - else - clear_fullscreen("nearsighted") - - if(impaired) - overlay_fullscreen("impaired", /obj/screen/fullscreen/impaired, impaired) - else - clear_fullscreen("impaired") - - if(!machine) - var/isRemoteObserve = 0 - if((REMOTE_VIEW in mutations) && remoteview_target) - if(getBrainLoss() <= 100)//#Z2 We burn our brain with active remote_view mutation - if(remoteview_target.stat==CONSCIOUS) - isRemoteObserve = 1 - if(getBrainLoss() > 50) - adjustBrainLoss(2) - else - adjustBrainLoss(1) - else - to_chat(src, "Too hard to concentrate...") - remoteview_target = null - reset_view(null)//##Z2 - if(!isRemoteObserve && client && !client.adminobs) - remoteview_target = null - reset_view(null) - - - if(mind && mind.changeling) - hud_used.lingchemdisplay.invisibility = 0 - hud_used.lingchemdisplay.maptext = "
                    [mind.changeling.chem_charges]
                    " - else - hud_used.lingchemdisplay.invisibility = 101 - - ..() - - return 1 - -/mob/living/carbon/human/update_sight() - sightglassesmod = null - if(stat == DEAD) - set_EyesVision(transition_time = 0) - return - var/obj/item/clothing/glasses/G = glasses - if(istype(G) && G.active) - if(istype(glasses, /obj/item/clothing/glasses/meson)) - sightglassesmod = "meson" - else if(istype(glasses, /obj/item/clothing/glasses/night) && !istype(glasses, /obj/item/clothing/glasses/night/shadowling)) - sightglassesmod = "nvg" - else if(istype(glasses, /obj/item/clothing/glasses/thermal)) - sightglassesmod = "thermal" - else if(istype(glasses, /obj/item/clothing/glasses/science)) - sightglassesmod = "sci" - - if(species.nighteyes) - if(sightglassesmod) - sightglassesmod = "nightsight_glasses" - else - var/light_amount = 0 - var/turf/T = get_turf(src) - light_amount = round(T.get_lumcount()*10) - if(light_amount > 1) - sightglassesmod = null - else - sightglassesmod = "nightsight" - set_EyesVision(sightglassesmod) - -/mob/living/carbon/human/proc/handle_random_events() - // Puke if toxloss is too high - if(!stat) - if (getToxLoss() >= 45 && nutrition > 20) - vomit() - - //0.1% chance of playing a scary sound to someone who's in complete darkness - if(isturf(loc) && rand(1,1000) == 1) - var/turf/T = loc - if(T.lighting_overlay && T.lighting_overlay.luminosity == 0) - playsound_local(src,pick(scarySounds),50, 1, -1) - -/mob/living/carbon/human/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) //disabled because of symptom that randomly ignites a mob, which triggers this - // var/datum/disease2/disease/V = virus2[ID] - // V.cure(src) - if(life_tick % 3) //don't spam checks over all objects in view every tick. - for(var/obj/effect/decal/cleanable/O in view(1,src)) - if(istype(O,/obj/effect/decal/cleanable/blood)) - var/obj/effect/decal/cleanable/blood/B = O - if(B && B.virus2 && B.virus2.len) - for (var/ID in B.virus2) - var/datum/disease2/disease/V = B.virus2[ID] - if(V.spreadtype == "Contact") - infect_virus2(src,V.getcopy()) - - else if(istype(O,/obj/effect/decal/cleanable/mucus)) - var/obj/effect/decal/cleanable/mucus/M = O - if(M && M.virus2 && M.virus2.len) - for (var/ID in M.virus2) - var/datum/disease2/disease/V = M.virus2[ID] - if(V.spreadtype == "Contact") - infect_virus2(src,V.getcopy()) - - - if(virus2.len) - 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/human/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 != DEAD) - if(M.stat == DEAD) - M.death(1) - stomach_contents.Remove(M) - qdel(M) - continue - if(SSmob.times_fired%3==1) - if(!(M.status_flags & GODMODE)) - M.adjustBruteLoss(5) - nutrition += 10 - -/mob/living/carbon/human/proc/handle_changeling() - if(mind && mind.changeling) - mind.changeling.regenerate() - -/mob/living/carbon/human/handle_shock() - ..() - if(status_flags & GODMODE) return 0 //godmode - if(analgesic || (species && species.flags[NO_PAIN])) return // analgesic avoids all traumatic shock temporarily - - if(health < config.health_threshold_softcrit)// health 0 makes you immediately collapse - shock_stage = max(shock_stage, 61) - - if(traumatic_shock >= 80) - shock_stage += 1 - else if(health < config.health_threshold_softcrit) - shock_stage = max(shock_stage, 61) - else - shock_stage = min(shock_stage, 160) - shock_stage = max(shock_stage-1, 0) - return - - if(shock_stage == 10) - to_chat(src, ""+pick("It hurts so much!", "You really need some painkillers..", "Dear god, the pain!")) - - if(shock_stage >= 30) - if(shock_stage == 30) emote("me",1,"is having trouble keeping their eyes open.") - eye_blurry = max(2, eye_blurry) - stuttering = max(stuttering, 5) - - if(shock_stage == 40) - to_chat(src, ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")) - - if (shock_stage >= 60) - if(shock_stage == 60) emote("me",1,"'s body becomes limp.") - if (prob(2)) - to_chat(src, ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")) - Weaken(20) - - if(shock_stage >= 80) - if (prob(5)) - to_chat(src, ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")) - Weaken(20) - - if(shock_stage >= 120) - if (prob(2)) - to_chat(src, ""+pick("You black out!", "You feel like you could die any moment now.", "You're about to lose consciousness.")) - Paralyse(5) - - if(shock_stage == 150) - emote("me",1,"can no longer stand, collapsing!") - Weaken(20) - - if(shock_stage >= 150) - Weaken(20) - -/mob/living/carbon/human/proc/handle_heart_beat() - - if(pulse == PULSE_NONE) return - - if(pulse == PULSE_2FAST || shock_stage >= 10 || istype(get_turf(src), /turf/space)) - - var/temp = (5 - pulse)/2 - - if(heart_beat >= temp) - heart_beat = 0 - src << sound('sound/effects/singlebeat.ogg',0,0,0,50) - else if(temp != 0) - heart_beat++ - -/mob/living/carbon/human/proc/handle_pulse() - - if(life_tick % 5) - return pulse //update pulse every 5 life ticks (~1 tick/sec, depending on server load) - - if(species && species.flags[NO_BLOOD]) - return PULSE_NONE //No blood, no pulse. - - if(stat == DEAD) - return PULSE_NONE //that's it, you're dead, nothing can influence your pulse - - var/temp = PULSE_NORM - - if(round(vessel.get_reagent_amount("blood")) <= BLOOD_VOLUME_BAD) //how much blood do we have - temp = PULSE_THREADY //not enough :( - - if(status_flags & FAKEDEATH) - temp = PULSE_NONE //pretend that we're dead. unlike actual death, can be inflienced by meds - - //handles different chems' influence on pulse - for(var/datum/reagent/R in reagents.reagent_list) - if(R.id in bradycardics) - if(temp <= PULSE_THREADY && temp >= PULSE_NORM) - temp-- - if(R.id in tachycardics) - if(temp <= PULSE_FAST && temp >= PULSE_NONE) - temp++ - if(R.id in heartstopper) //To avoid using fakedeath - temp = PULSE_NONE - if(R.id in cheartstopper) //Conditional heart-stoppage - if(R.volume >= R.overdose) - temp = PULSE_NONE - - return temp - -/* - Called by life(), instead of having the individual hud items update icons each tick and check for status changes - we only set those statuses and icons upon changes. Then those HUD items will simply add those pre-made images. - This proc below is only called when those HUD elements need to change as determined by the mobs hud_updateflag. -*/ - - -/mob/living/carbon/human/proc/handle_hud_list() - - if(hud_updateflag & 1 << HEALTH_HUD) - var/image/holder = hud_list[HEALTH_HUD] - if(stat == DEAD) - holder.icon_state = "hudhealth-100" // X_X - else - holder.icon_state = "hud[RoundHealth(health)]" - - hud_list[HEALTH_HUD] = holder - - if(hud_updateflag & 1 << STATUS_HUD) - var/foundVirus = 0 - for(var/datum/disease/D in viruses) - if(!D.hidden[SCANNER]) - foundVirus++ - for (var/ID in virus2) - if (ID in virusDB) - foundVirus = 1 - break - - var/image/holder = hud_list[STATUS_HUD] - var/image/holder2 = hud_list[STATUS_HUD_OOC] - if(stat == DEAD) - holder.icon_state = "huddead" - holder2.icon_state = "huddead" - else if(status_flags & XENO_HOST) - holder.icon_state = "hudxeno" - holder2.icon_state = "hudxeno" - else if(foundVirus || iszombie(src)) - holder.icon_state = "hudill" - else if(has_brain_worms()) - var/mob/living/simple_animal/borer/B = has_brain_worms() - if(B.controlling) - holder.icon_state = "hudbrainworm" - else - holder.icon_state = "hudhealthy" - holder2.icon_state = "hudbrainworm" - else - holder.icon_state = "hudhealthy" - if(virus2.len) - holder2.icon_state = "hudill" - else - holder2.icon_state = "hudhealthy" - - hud_list[STATUS_HUD] = holder - hud_list[STATUS_HUD_OOC] = holder2 - - if(hud_updateflag & 1 << ID_HUD) - var/image/holder = hud_list[ID_HUD] - if(wear_id) - var/obj/item/weapon/card/id/I = wear_id.GetID() - if(I) - holder.icon_state = "hud[ckey(I.GetJobName())]" - else - holder.icon_state = "hudunknown" - else - holder.icon_state = "hudunknown" - - - hud_list[ID_HUD] = holder - - if(hud_updateflag & 1 << WANTED_HUD) - var/image/holder = hud_list[WANTED_HUD] - holder.icon_state = "hudblank" - var/perpname = name - if(wear_id) - var/obj/item/weapon/card/id/I = wear_id.GetID() - if(I) - perpname = I.registered_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.security) - if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) - holder.icon_state = "hudwanted" - break - else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Incarcerated")) - holder.icon_state = "hudprisoner" - break - else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Paroled")) - holder.icon_state = "hudparoled" - break - else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Released")) - holder.icon_state = "hudreleased" - break - hud_list[WANTED_HUD] = holder - - if(hud_updateflag & 1 << IMPLOYAL_HUD || hud_updateflag & 1 << IMPCHEM_HUD || hud_updateflag & 1 << IMPTRACK_HUD) - var/image/holder1 = hud_list[IMPTRACK_HUD] - var/image/holder2 = hud_list[IMPLOYAL_HUD] - var/image/holder3 = hud_list[IMPCHEM_HUD] - - holder1.icon_state = "hudblank" - holder2.icon_state = "hudblank" - holder3.icon_state = "hudblank" - - var/has_loyal_implant = FALSE - for(var/obj/item/weapon/implant/I in src) - if(I.implanted) - if(istype(I,/obj/item/weapon/implant/tracking)) - holder1.icon_state = "hud_imp_tracking" - if(istype(I,/obj/item/weapon/implant/mindshield) && !has_loyal_implant) - if(istype(I,/obj/item/weapon/implant/mindshield/loyalty)) - has_loyal_implant = TRUE - holder2.icon_state = "hud_imp_loyal" - else - holder2.icon_state = "hud_imp_mindshield" - if(istype(I,/obj/item/weapon/implant/chem)) - holder3.icon_state = "hud_imp_chem" - - hud_list[IMPTRACK_HUD] = holder1 - hud_list[IMPLOYAL_HUD] = holder2 - hud_list[IMPCHEM_HUD] = holder3 - - if(hud_updateflag & 1 << SPECIALROLE_HUD) - var/image/holder = hud_list[SPECIALROLE_HUD] - holder.icon_state = "hudblank" - if(mind) - - switch(mind.special_role) - if("traitor","Syndicate") - holder.icon_state = "hudsyndicate" - if("Revolutionary") - holder.icon_state = "hudrevolutionary" - if("Head Revolutionary") - holder.icon_state = "hudheadrevolutionary" - if("Cultist") - holder.icon_state = "hudcultist" - if("Changeling") - holder.icon_state = "hudchangeling" - if("Wizard","Fake Wizard") - holder.icon_state = "hudwizard" - if("Death Commando") - holder.icon_state = "huddeathsquad" - if("Ninja") - holder.icon_state = "hudninja" - if("head_loyalist") - holder.icon_state = "hudloyalist" - if("loyalist") - holder.icon_state = "hudloyalist" - if("head_mutineer") - holder.icon_state = "hudmutineer" - if("mutineer") - holder.icon_state = "hudmutineer" - if("shadowling") - holder.icon_state = "hudshadowling" - if("thrall") - holder.icon_state = "hudthrall" - if("Clandestine Gang (A) Boss","Prima Gang (A) Boss","Zero-G Gang (A) Boss","Max Gang (A) Boss","Blasto Gang (A) Boss","Waffle Gang (A) Boss","North Gang (A) Boss","Omni Gang (A) Boss","Newton Gang (A) Boss","Cyber Gang (A) Boss","Donk Gang (A) Boss","Gene Gang (A) Boss","Gib Gang (A) Boss","Tunnel Gang (A) Boss","Diablo Gang (A) Boss","Psyke Gang (A) Boss","Osiron Gang (A) Boss") - holder.icon_state = "gang_boss_a" - if("Clandestine Gang (B) Boss","Prima Gang (B) Boss","Zero-G Gang (B) Boss","Max Gang (B) Boss","Blasto Gang (B) Boss","Waffle Gang (B) Boss","North Gang (B) Boss","Omni Gang (B) Boss","Newton Gang (B) Boss","Cyber Gang (B) Boss","Donk Gang (B) Boss","Gene Gang (B) Boss","Gib Gang (B) Boss","Tunnel Gang (B) Boss","Diablo Gang (B) Boss","Psyke Gang (B) Boss","Osiron Gang (B) Boss") - holder.icon_state = "gang_boss_b" - if("Clandestine Gang (A) Lieutenant","Prima Gang (A) Lieutenant","Zero-G Gang (A) Lieutenant","Max Gang (A) Lieutenant","Blasto Gang (A) Lieutenant","Waffle Gang (A) Lieutenant","North Gang (A) Lieutenant","Omni Gang (A) Lieutenant","Newton Gang (A) Lieutenant","Cyber Gang (A) Lieutenant","Donk Gang (A) Lieutenant","Gene Gang (A) Lieutenant","Gib Gang (A) Lieutenant","Tunnel Gang (A) Lieutenant","Diablo Gang (A) Lieutenant","Psyke Gang (A) Lieutenant","Osiron Gang (A) Lieutenant") - holder.icon_state = "lieutenant_a" - if("Clandestine Gang (B) Lieutenant","Prima Gang (B) Lieutenant","Zero-G Gang (B) Lieutenant","Max Gang (B) Lieutenant","Blasto Gang (B) Lieutenant","Waffle Gang (B) Lieutenant","North Gang (B) Lieutenant","Omni Gang (B) Lieutenant","Newton Gang (B) Lieutenant","Cyber Gang (B) Lieutenant","Donk Gang (B) Lieutenant","Gene Gang (B) Lieutenant","Gib Gang (B) Lieutenant","Tunnel Gang (B) Lieutenant","Diablo Gang (B) Lieutenant","Psyke Gang (B) Lieutenant","Osiron Gang (B) Lieutenant") - holder.icon_state = "lieutenant_b" - if("Clandestine Gang (A)","Prima Gang (A)","Zero-G Gang (A)","Max Gang (A)","Blasto Gang (A)","Waffle Gang (A)","North Gang (A)","Omni Gang (A)","Newton Gang (A)","Cyber Gang (A)","Donk Gang (A)","Gene Gang (A)","Gib Gang (A)","Tunnel Gang (A)","Diablo Gang (A)","Psyke Gang (A)","Osiron Gang (A)") - holder.icon_state = "gangster_a" - if("Clandestine Gang (B)","Prima Gang (B)","Zero-G Gang (B)","Max Gang (B)","Blasto Gang (B)","Waffle Gang (B)","North Gang (B)","Omni Gang (B)","Newton Gang (B)","Cyber Gang (B)","Donk Gang (B)","Gene Gang (B)","Gib Gang (B)","Tunnel Gang (B)","Diablo Gang (B)","Psyke Gang (B)","Osiron Gang (B)") - holder.icon_state = "gangster_b" - - hud_list[SPECIALROLE_HUD] = holder - hud_updateflag = 0 - - -#undef HUMAN_MAX_OXYLOSS -#undef HUMAN_CRIT_MAX_OXYLOSS +//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick! +#define HUMAN_MAX_OXYLOSS 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it. +#define HUMAN_CRIT_MAX_OXYLOSS (SSmob.wait/30) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks. + +#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 1000K point + +#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point +#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point +#define COLD_DAMAGE_LEVEL_3 3 //Amount of damage applied when your body temperature passes the 120K point + +//Note that gas heat damage is only applied once every FOUR ticks. +#define HEAT_GAS_DAMAGE_LEVEL_1 2 //Amount of damage applied when the current breath's temperature just passes the 360.15k safety point +#define HEAT_GAS_DAMAGE_LEVEL_2 4 //Amount of damage applied when the current breath's temperature passes the 400K point +#define HEAT_GAS_DAMAGE_LEVEL_3 8 //Amount of damage applied when the current breath's temperature passes the 1000K point + +#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point +#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point +#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point + +/mob/living/carbon/human + var/prev_gender = null // Debug for plural genders + var/in_stasis = 0 + + +/mob/living/carbon/human/Life() + set invisibility = 0 + set background = 1 + + if (monkeyizing) return + if(!loc) return // Fixing a null error that occurs when the mob isn't found in the world -- TLE + + ..() + + /* + //This code is here to try to determine what causes the gender switch to plural error. Once the error is tracked down and fixed, this code should be deleted + //Also delete var/prev_gender once this is removed. + if(prev_gender != gender) + prev_gender = gender + if(gender in list(PLURAL, NEUTER)) + message_admins("[src] ([ckey]) gender has been changed to plural or neuter. Please record what has happened recently to the person and then notify coders. (?) (VV) (PM) (JMP)") + */ + //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() + + in_stasis = istype(loc, /obj/structure/closet/body_bag/cryobag) && loc:opened == 0 + if(in_stasis) loc:used++ + + if(life_tick%30==15) + hud_updateflag = 1022 + + voice = GetVoice() + + //No need to update all of these procs if the guy is dead. + if(stat != DEAD && !in_stasis) + if(SSmob.times_fired%4==2 || failed_last_breath || (health < config.health_threshold_crit)) //First, resolve location and get a breath + breathe() //Only try to take a breath every 4 ticks, unless suffocating + + 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() + + //Random events (vomiting etc) + handle_random_events() + + handle_virus_updates() + + //stuff in the stomach + handle_stomach() + + handle_shock() + + handle_pain() + + handle_medical_side_effects() + + handle_heart_beat() + + handle_stasis_bag() + + 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 + return //We go ahead and process them 5 times for HUD images and other stuff though. + + //Handle temperature/pressure differences between body and environment + handle_environment(environment) //Optimized a good bit. + + //Check if we're on fire + handle_fire() + if(on_fire && fire_stacks > 0) + fire_stacks -= 0.5 + + //Status updates, death etc. + handle_regular_status_updates() //Optimized a bit + update_canmove() + + //Update our name based on whether our face is obscured/disfigured + name = get_visible_name() + + handle_regular_hud_updates() + + //Updates the number of stored chemicals for powers and essentials + handle_changeling() + + //Species-specific update. + if(species) + species.on_life(src) + + pulse = handle_pulse() + + // Grabbing + for(var/obj/item/weapon/grab/G in src) + G.process() + + +//Much like get_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. +/mob/living/carbon/human/proc/get_pressure_protection(pressure_check = STOPS_PRESSUREDMAGE) + var/pressure_adjustment_coefficient = 1 //Determins how much the clothing you are wearing protects you in percent. + + if((head && (head.flags_pressure & pressure_check))&&(wear_suit && (wear_suit.flags_pressure & pressure_check))) + pressure_adjustment_coefficient = 0 + + //Handles breaches in your space suit. 10 suit damage equals a 100% loss of pressure reduction. + if(istype(wear_suit,/obj/item/clothing/suit/space)) + var/obj/item/clothing/suit/space/S = wear_suit + if(S.can_breach && S.damage) + var/pressure_loss = S.damage * 0.1 + pressure_adjustment_coefficient = pressure_loss + + pressure_adjustment_coefficient = CLAMP01(pressure_adjustment_coefficient) //So it isn't less than 0 or larger than 1. + + return 1 - pressure_adjustment_coefficient //want 0 to be bad protection, 1 to be good protection + +/mob/living/carbon/human/calculate_affecting_pressure(var/pressure) + ..() + var/pressure_difference = abs( pressure - ONE_ATMOSPHERE ) + + if(pressure > ONE_ATMOSPHERE) + pressure_difference = pressure_difference * (1 - get_pressure_protection(STOPS_HIGHPRESSUREDMAGE)) + return ONE_ATMOSPHERE + pressure_difference + else + pressure_difference = pressure_difference * (1 - get_pressure_protection(STOPS_LOWPRESSUREDMAGE)) + return ONE_ATMOSPHERE - pressure_difference + +/mob/living/carbon/human/proc/handle_disabilities() + if (disabilities & EPILEPSY || has_trait(TRAIT_EPILEPSY)) + if ((prob(1) && paralysis < 1)) + to_chat(src, "\red You have a seizure!") + for(var/mob/O in viewers(src, null)) + if(O == src) + continue + O.show_message(text("\red [src] starts having a seizure!"), 1) + Paralyse(10) + make_jittery(1000) + if (disabilities & COUGHING || has_trait(TRAIT_COUGH)) + if ((prob(5) && paralysis <= 1)) + drop_item() + spawn( 0 ) + emote("cough") + return + if (disabilities & TOURETTES || has_trait(TRAIT_TOURETTE)) + speech_problem_flag = 1 + if ((prob(10) && paralysis <= 1)) + Stun(10) + spawn( 0 ) + switch(rand(1, 3)) + if(1) + emote("twitch") + if(2 to 3) + say("[pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]") + var/old_x = pixel_x + var/old_y = pixel_y + pixel_x += rand(-2,2) + pixel_y += rand(-1,1) + sleep(2) + pixel_x = old_x + pixel_y = old_y + return + if (disabilities & NERVOUS || has_trait(TRAIT_NERVOUS)) + speech_problem_flag = 1 + if (prob(10)) + stuttering = max(10, stuttering) + // No. -- cib + //Oh, really? + if (getBrainLoss() >= 60 && stat != DEAD) + if(prob(3)) + if(config.rus_language)//TODO:CYRILLIC dictionary? + switch(pick(1,2,3)) + if(1) + say(pick("!", " !", " !", "[pick("", " ")] [pick("", "", "", "")] [pick("", "", "")] ;!!!", " [pick("","","")]?", " !", " !", " !", " !!!!", "!")) + if(2) + say(pick(" [JA_PLACEHOLDER] ?"," !", "", "[JA_PLACEHOLDER] !", "!", "!!!", " !", "!", "!", "!!!!", " !", "", " ", " !")) + if(3) + emote("drool") + else + switch(pick(1,2,3)) + if(1) + say(pick("IM A PONY NEEEEEEIIIIIIIIIGH", "without oxigen blob don't evoluate?", "CAPTAINS A COMDOM", "[pick("", "that faggot traitor")] [pick("joerge", "george", "gorge", "gdoruge")] [pick("mellens", "melons", "mwrlins")] is grifing me HAL;P!!!", "can u give me [pick("telikesis","halk","eppilapse")]?", "THe saiyans screwed", "Bi is THE BEST OF BOTH WORLDS>", "I WANNA PET TEH monkeyS", "stop grifing me!!!!", "SOTP IT#")) + if(2) + say(pick("FUS RO DAH","fucking 4rries!", "stat me", ">my face", "roll it easy!", "waaaaaagh!!!", "red wonz go fasta", "FOR TEH EMPRAH", "lol2cat", "dem dwarfs man, dem dwarfs", "SPESS MAHREENS", "hwee did eet fhor khayosss", "lifelike texture ;_;", "luv can bloooom", "PACKETS!!!")) + if(3) + emote("drool") + + if(stat != DEAD) + var/rn = rand(0, 200) + if(getBrainLoss() >= 5) + if(0 <= rn && rn <= 3) + custom_pain("Your head feels numb and painful.") + if(getBrainLoss() >= 15) + if(4 <= rn && rn <= 6) if(eye_blurry <= 0) + to_chat(src, "\red It becomes hard to see for some reason.") + eye_blurry = 10 + if(getBrainLoss() >= 35) + if(7 <= rn && rn <= 9) if(get_active_hand()) + to_chat(src, "\red Your hand won't respond properly, you drop what you're holding.") + drop_item() + if(getBrainLoss() >= 50) + if(10 <= rn && rn <= 12) if(!lying) + to_chat(src, "\red Your legs won't respond properly, you fall down.") + resting = 1 + +/mob/living/carbon/human/proc/handle_stasis_bag() + // Handle side effects from stasis bag + if(in_stasis) + // First off, there's no oxygen supply, so the mob will slowly take brain damage + adjustBrainLoss(0.1) + + // Next, the method to induce stasis has some adverse side-effects, manifesting + // as cloneloss + adjustCloneLoss(0.1) + +/mob/living/carbon/human/proc/handle_mutations_and_radiation() + + if(species.flags[IS_SYNTHETIC]) //Robots don't suffer from mutations or radloss. + return + + // DNA2 - Gene processing. + // The HULK stuff that was here is now in the hulk gene. + for(var/datum/dna/gene/gene in dna_genes) + if(!gene.block) + continue + if(gene.is_active(src)) + speech_problem_flag = 1 + gene.OnMobLife(src) + + if(dna_inject_count > 0 && prob(2)) + dna_inject_count-- + + if(radiation) + if(species.flags[RAD_IMMUNE]) + return + + if (radiation > 100) + radiation = 100 + if(!species.flags[RAD_ABSORB]) + Weaken(10) + if(!lying) + to_chat(src, "\red You feel weak.") + emote("collapse") + + if (radiation < 0) + radiation = 0 + + else + + if(species.flags[RAD_ABSORB]) + var/rads = radiation/25 + radiation -= rads + nutrition += rads + adjustBruteLoss(-(rads)) + adjustOxyLoss(-(rads)) + adjustToxLoss(-(rads)) + updatehealth() + return + + var/damage = 0 + radiation-- + if(prob(25)) + damage = 1 + + if(radiation > 50) + radiation-- + damage = 1 + if(prob(5) && prob(radiation) && (h_style != "Bald" || f_style != "Shaved")) + h_style = "Bald" + f_style = "Shaved" + update_hair() + to_chat(src, "Suddenly you lost your hair!") + if(prob(5)) + radiation -= 5 + Weaken(3) + if(!lying) + to_chat(src, "\red You feel weak.") + emote("collapse") + if(radiation > 75) + radiation-- + damage = 3 + if(prob(1)) + to_chat(src, "\red You mutate!") + randmutb(src) + domutcheck(src,null) + emote("gasp") + + if(damage) + adjustToxLoss(damage) + updatehealth() + if (bodyparts.len) + var/obj/item/organ/external/BP = pick(bodyparts) + if(istype(BP)) + BP.add_autopsy_data("Radiation Poisoning", damage) + +/mob/living/carbon/human/proc/breathe() + if(NO_BREATH in src.mutations) + return //#Z2 We need no breath with this mutation + if(reagents.has_reagent("lexorin")) + return + if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) + return + if(species && (species.flags[NO_BREATHE] || species.flags[IS_SYNTHETIC])) + return + if(dna && dna.mutantrace == "adamantine") + return + if(ismob(loc)) + return + + var/datum/gas_mixture/environment = loc.return_air() + var/datum/gas_mixture/breath + + //First, check if we can breathe at all + if(handle_drowning() || health < config.health_threshold_crit && !reagents.has_reagent("inaprovaline")) + losebreath = max(2, losebreath + 1) + + if(losebreath>0) //Suffocating so do not take a breath + losebreath-- + if (prob(10)) //Gasp per 10 ticks? Sounds about right. + 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) // Super hacky -- TLE + //breath = get_breath_from_internal(0.5) // Manually setting to old BREATH_VOLUME amount -- TLE + + //No breath from internal atmosphere so get breath from location + if(!breath) + if(isobj(loc)) + var/obj/location_as_object = loc + breath = location_as_object.handle_internal_lifeform(src, BREATH_MOLES) + else if(isturf(loc)) + 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) + + if(istype(wear_mask, /obj/item/clothing/mask/gas) && breath) + var/obj/item/clothing/mask/gas/G = wear_mask + var/datum/gas_mixture/filtered = new + + for(var/g in list("phoron", "sleeping_agent")) + if(breath.gas[g]) + filtered.gas[g] = breath.gas[g] * G.gas_filter_strength + breath.gas[g] -= filtered.gas[g] + + breath.update_values() + filtered.update_values() + + if(!is_lung_ruptured()) + if(!breath || breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5) + if(prob(5)) + rupture_lung() + + // Handle filtering + var/block = 0 + if(wear_mask) + if(wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT) + block = 1 + if(glasses) + if(glasses.flags & BLOCK_GAS_SMOKE_EFFECT) + block = 1 + if(head) + if(head.flags & BLOCK_GAS_SMOKE_EFFECT) + 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) + + //spread some viruses while we are at it + if (virus2.len > 0) + if (prob(10) && get_infection_chance(src)) +// log_debug("[src] : Exhaling some viruses") + for(var/mob/living/carbon/M in view(1,src)) + src.spread_disease_to(M) + + +/mob/living/carbon/human/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) + return internal.remove_air_volume(volume_needed) + else if(internals) + internals.icon_state = "internal0" + return null + +/mob/living/carbon/human/proc/handle_breath(datum/gas_mixture/breath) + if(status_flags & GODMODE) + return + + if(!breath || (breath.total_moles == 0) || suiciding) + if(suiciding) + adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster + failed_last_breath = 1 + throw_alert("oxy") + return 0 + if(health > config.health_threshold_crit) + adjustOxyLoss(HUMAN_MAX_OXYLOSS) + failed_last_breath = 1 + else + adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) + failed_last_breath = 1 + + throw_alert("oxy") + + return 0 + + var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa + //var/safe_pressure_max = 140 // Maximum safe partial pressure of breathable gas in kPa (Not used for now) + var/safe_exhaled_max = 10 // Yes it's an arbitrary value who cares? + var/safe_toxins_max = 0.005 + var/SA_para_min = 1 + var/SA_sleep_min = 5 + var/inhaled_gas_used = 0 + + var/breath_pressure = (breath.total_moles * R_IDEAL_GAS_EQUATION * breath.temperature) / BREATH_VOLUME + + var/inhaling = breath.gas[species.breath_type] + var/poison = breath.gas[species.poison_type] + var/exhaling = species.exhale_type ? breath.gas[species.exhale_type] : 0 + + var/inhale_pp = (inhaling / breath.total_moles) * breath_pressure + var/toxins_pp = (poison / breath.total_moles) * breath_pressure + var/exhaled_pp = (exhaling / breath.total_moles) * breath_pressure + + if(inhale_pp < safe_pressure_min) + if(prob(20)) + emote("gasp") + if(inhale_pp > 0) + var/ratio = inhale_pp/safe_pressure_min + + // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) + adjustOxyLoss(min(5*(1 - ratio), HUMAN_MAX_OXYLOSS)) + failed_last_breath = 1 + inhaled_gas_used = inhaling*ratio/6 + + else + + adjustOxyLoss(HUMAN_MAX_OXYLOSS) + failed_last_breath = 1 + + throw_alert("oxy") + + else + // We're in safe limits + failed_last_breath = 0 + adjustOxyLoss(-5) + inhaled_gas_used = inhaling/6 + clear_alert("oxy") + + breath.adjust_gas(species.breath_type, -inhaled_gas_used, update = FALSE) //update afterwards + + if(species.exhale_type) + breath.adjust_gas_temp(species.exhale_type, inhaled_gas_used, bodytemperature, update = FALSE) //update afterwards + + // CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2, + // this will hurt you, but only once per 4 ticks, instead of once per tick. + + if(exhaled_pp > safe_exhaled_max) + + // If it's the first breath with too much CO2 in it, lets start a counter, + // then have them pass out after 12s or so. + if(!co2overloadtime) + co2overloadtime = world.time + + else if(world.time - co2overloadtime > 120) + + // Lets hurt em a little, let them know we mean business + Paralyse(3) + adjustOxyLoss(3) + + // They've been in here 30s now, lets start to kill them for their own good! + if(world.time - co2overloadtime > 300) + adjustOxyLoss(8) + + // Lets give them some chance to know somethings not right though I guess. + if(prob(20)) + spawn(0) emote("cough") + else + co2overloadtime = 0 + + // Too much poison in the air. + if(toxins_pp > safe_toxins_max) + var/ratio = (poison/safe_toxins_max) * 10 + if(reagents) + reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) + breath.adjust_gas(species.poison_type, -poison / 6, update = FALSE) //update after + throw_alert("tox_in_air") + else + clear_alert("tox_in_air") + + // If there's some other shit in the air lets deal with it here. + if(breath.gas["sleeping_agent"]) + var/SA_pp = (breath.gas["sleeping_agent"] / breath.total_moles) * breath_pressure + + // Enough to make us paralysed for a bit + if(SA_pp > SA_para_min) + + // 3 gives them one second to wake up and run away a bit! + Paralyse(3) + + // Enough to make us sleep as well + if(SA_pp > SA_sleep_min) + Sleeping(5) + + // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning + else if(SA_pp > 0.15) + if(prob(20)) + emote(pick("giggle", "laugh")) + + breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"] / 6, update = FALSE) //update after + + //handle_temperature_effects(breath) + + // Hot air hurts :( + if( (breath.temperature < species.cold_level_1 || breath.temperature > species.heat_level_1)) + // #Z2 Cold_resistance wont save us anymore, we have no_breath genetics power now @ZVe + + if(status_flags & GODMODE) + return 1 + + switch(breath.temperature) + if(-INFINITY to species.cold_level_3) + apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Cold") + if(species.cold_level_3 to species.cold_level_2) + apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Cold") + if(species.cold_level_2 to species.cold_level_1) + apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Cold") + if(species.heat_level_1 to species.heat_level_2) + apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Heat") + if(species.heat_level_2 to species.heat_level_3) + apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Heat") + if(species.heat_level_3 to INFINITY) + apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Heat") + + //breathing in hot/cold air also heats/cools you a bit + var/temp_adj = breath.temperature - bodytemperature + if (temp_adj < 0) + temp_adj /= (BODYTEMP_COLD_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed + else + temp_adj /= (BODYTEMP_HEAT_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed + + var/relative_density = breath.total_moles / (MOLES_CELLSTANDARD * BREATH_PERCENTAGE) + temp_adj *= relative_density + + if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX + if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX + //world << "Breath: [breath.temperature], [src]: [bodytemperature], Adjusting: [temp_adj]" + bodytemperature += temp_adj + + breath.update_values() + + return 1 + +/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment) + if(!environment) + return + + //Moved pressure calculations here for use in skip-processing check. + var/pressure = environment.return_pressure() + var/adjusted_pressure = calculate_affecting_pressure(pressure) + var/is_in_space = istype(get_turf(src), /turf/space) + + if(!is_in_space) //space is not meant to change your body temperature. + var/loc_temp = get_temperature(environment) + + if(adjusted_pressure < species.warning_high_pressure && adjusted_pressure > species.warning_low_pressure && abs(loc_temp - bodytemperature) < 20 && bodytemperature < species.heat_level_1 && bodytemperature > species.cold_level_1) + clear_alert("pressure") + clear_alert("temp") + return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp + + //Body temperature adjusts depending on surrounding atmosphere based on your thermal protection + var/temp_adj = 0 + if(!on_fire && !(is_type_organ(O_LUNGS, /obj/item/organ/internal/lungs/ipc) && is_bruised_organ(O_LUNGS))) //If you're on fire, you do not heat up or cool down based on surrounding gases. IPC's lungs are the cooling element. If it's broken, IPCs should cool down. + if(loc_temp < bodytemperature) //Place is colder than we are + var/thermal_protection = get_cold_protection(loc_temp) //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) + temp_adj = (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR) //this will be negative + else if (loc_temp > bodytemperature) //Place is hotter than we are + var/thermal_protection = get_heat_protection(loc_temp) //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) + temp_adj = (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR) + + //Use heat transfer as proportional to the gas density. However, we only care about the relative density vs standard 101 kPa/20 C air. Therefore we can use mole ratios + var/relative_density = (environment.total_moles / environment.volume) / (MOLES_CELLSTANDARD / CELL_VOLUME) + temp_adj *= relative_density + + if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX + if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX + //world << "Environment: [loc_temp], [src]: [bodytemperature], Adjusting: [temp_adj]" + bodytemperature += temp_adj + + else if(!species.flags[IS_SYNTHETIC] && !species.flags[IS_PLANT]) + if(istype(loc, /obj/mecha)) + return + if(istype(loc, /obj/structure/transit_tube_pod)) + return + var/protected = 0 + if( (head && istype(head, /obj/item/clothing/head/helmet/space)) && (wear_suit && istype(wear_suit, /obj/item/clothing/suit/space))) + protected = 1 + if(!protected && radiation < 100) + apply_effect(5, IRRADIATE) + + if(status_flags & GODMODE) + return 1 //godmode + + // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. + if(bodytemperature > species.heat_level_1) + //Body temperature is too hot. + if(bodytemperature > species.heat_level_3) + throw_alert("temp","hot",3) + take_overall_damage(burn=HEAT_DAMAGE_LEVEL_3, used_weapon = "High Body Temperature") + else if(bodytemperature > species.heat_level_2) + if(on_fire) + throw_alert("temp","hot",3) + take_overall_damage(burn=HEAT_DAMAGE_LEVEL_3, used_weapon = "High Body Temperature") + else + throw_alert("temp","hot",2) + take_overall_damage(burn=HEAT_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature") + else + throw_alert("temp","hot",1) + take_overall_damage(burn=HEAT_DAMAGE_LEVEL_1, used_weapon = "High Body Temperature") + else if(bodytemperature < species.cold_level_1) + if(!istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell)) + if(bodytemperature < species.cold_level_3) + throw_alert("temp","cold",3) + take_overall_damage(burn=COLD_DAMAGE_LEVEL_3, used_weapon = "Low Body Temperature") + else if(bodytemperature < species.cold_level_2) + throw_alert("temp","cold",2) + take_overall_damage(burn=COLD_DAMAGE_LEVEL_2, used_weapon = "Low Body Temperature") + else + throw_alert("temp","cold",1) + take_overall_damage(burn=COLD_DAMAGE_LEVEL_1, used_weapon = "Low Body Temperature") + else + clear_alert("temp") + else + clear_alert("temp") + + // Account for massive pressure differences. Done by Polymorph + // Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense! + + if(adjusted_pressure >= species.hazard_high_pressure) + var/pressure_damage = min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) + take_overall_damage(brute=pressure_damage, used_weapon = "High Pressure") + throw_alert("pressure","highpressure",2) + else if(adjusted_pressure >= species.warning_high_pressure) + throw_alert("pressure","highpressure",1) + else if(adjusted_pressure >= species.warning_low_pressure) + clear_alert("pressure") + else if(adjusted_pressure >= species.hazard_low_pressure) + throw_alert("pressure","lowpressure",1) + else + throw_alert("pressure","lowpressure",2) + apply_effect(is_in_space ? 15 : 7, AGONY, 0) + take_overall_damage(burn=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure") + + +//#Z2 - No more low pressure resistance with Cold Resistance genetic power, for now + /*if( !(COLD_RESISTANCE in mutations)) + take_overall_damage(brute=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure") + pressure_alert = -2 + else + pressure_alert = -1*/ +//##Z2 + //Check for contaminants before anything else because we don't want to skip it. + for(var/g in environment.gas) + if(gas_data.flags[g] & XGM_GAS_CONTAMINANT && environment.gas[g] > gas_data.overlay_limit[g] + 1) + pl_effects() + break + +///FIRE CODE +/mob/living/carbon/human/handle_fire() + if(..()) + return + var/thermal_protection = get_heat_protection(30000) //If you don't have fire suit level protection, you get a temperature increase + if((1 - thermal_protection) > 0.0001) + bodytemperature += BODYTEMP_HEATING_MAX + return +//END FIRE CODE + + +/* +/mob/living/carbon/human/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 +*/ + +/mob/living/carbon/human/proc/stabilize_body_temperature() + if (species.flags[IS_SYNTHETIC]) + bodytemperature += species.synth_temp_gain //just keep putting out heat. + return + + var/body_temperature_difference = species.body_temperature - bodytemperature + + if (abs(body_temperature_difference) < 0.5) + return //fuck this precision + + if(bodytemperature < species.cold_level_1) //260.15 is 310.15 - 50, the temperature where you start to feel effects. + if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up. + nutrition -= 2 + var/recovery_amt = max((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM) + //world << "Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]" +// log_debug("Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]") + bodytemperature += recovery_amt + else if(species.cold_level_1 <= bodytemperature && bodytemperature <= species.heat_level_1) + var/recovery_amt = body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR + //world << "Norm. Difference = [body_temperature_difference]. Recovering [recovery_amt]" +// log_debug("Norm. Difference = [body_temperature_difference]. Recovering [recovery_amt]") + bodytemperature += recovery_amt + else if(bodytemperature > species.heat_level_1) //360.15 is 310.15 + 50, the temperature where you start to feel effects. + //We totally need a sweat system cause it totally makes sense...~ + var/recovery_amt = min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers + //world << "Hot. Difference = [body_temperature_difference]. Recovering [recovery_amt]" +// log_debug("Hot. Difference = [body_temperature_difference]. Recovering [recovery_amt]") + bodytemperature += recovery_amt + +//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, UPPER_TORSO, LOWER_TORSO, etc. See setup.dm for the full list) +/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to. + var/thermal_protection_flags = 0 + //Handle normal clothing + if(head) + if(head.max_heat_protection_temperature && head.max_heat_protection_temperature >= temperature) + thermal_protection_flags |= head.heat_protection + if(wear_suit) + if(wear_suit.max_heat_protection_temperature && wear_suit.max_heat_protection_temperature >= temperature) + thermal_protection_flags |= wear_suit.heat_protection + if(w_uniform) + if(w_uniform.max_heat_protection_temperature && w_uniform.max_heat_protection_temperature >= temperature) + thermal_protection_flags |= w_uniform.heat_protection + if(shoes) + if(shoes.max_heat_protection_temperature && shoes.max_heat_protection_temperature >= temperature) + thermal_protection_flags |= shoes.heat_protection + if(gloves) + if(gloves.max_heat_protection_temperature && gloves.max_heat_protection_temperature >= temperature) + thermal_protection_flags |= gloves.heat_protection + if(wear_mask) + if(wear_mask.max_heat_protection_temperature && wear_mask.max_heat_protection_temperature >= temperature) + thermal_protection_flags |= wear_mask.heat_protection + + return thermal_protection_flags + +/mob/living/carbon/human/proc/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to. + if(RESIST_HEAT in mutations) //#Z2 + return 1 //Fully protected from the fire. //##Z2 + + var/thermal_protection_flags = get_heat_protection_flags(temperature) + + var/thermal_protection = 0.0 + if(thermal_protection_flags) + if(thermal_protection_flags & HEAD) + thermal_protection += THERMAL_PROTECTION_HEAD + if(thermal_protection_flags & UPPER_TORSO) + thermal_protection += THERMAL_PROTECTION_UPPER_TORSO + if(thermal_protection_flags & LOWER_TORSO) + thermal_protection += THERMAL_PROTECTION_LOWER_TORSO + if(thermal_protection_flags & LEG_LEFT) + thermal_protection += THERMAL_PROTECTION_LEG_LEFT + if(thermal_protection_flags & LEG_RIGHT) + thermal_protection += THERMAL_PROTECTION_LEG_RIGHT + if(thermal_protection_flags & ARM_LEFT) + thermal_protection += THERMAL_PROTECTION_ARM_LEFT + if(thermal_protection_flags & ARM_RIGHT) + thermal_protection += THERMAL_PROTECTION_ARM_RIGHT + + return min(1,thermal_protection) + +//See proc/get_heat_protection_flags(temperature) for the description of this proc. +/mob/living/carbon/human/proc/get_cold_protection_flags(temperature) + var/thermal_protection_flags = 0 + //Handle normal clothing + + if(head) + if(head.min_cold_protection_temperature && head.min_cold_protection_temperature <= temperature) + thermal_protection_flags |= head.cold_protection + if(wear_suit) + if(wear_suit.min_cold_protection_temperature && wear_suit.min_cold_protection_temperature <= temperature) + thermal_protection_flags |= wear_suit.cold_protection + if(w_uniform) + if(w_uniform.min_cold_protection_temperature && w_uniform.min_cold_protection_temperature <= temperature) + thermal_protection_flags |= w_uniform.cold_protection + if(shoes) + if(shoes.min_cold_protection_temperature && shoes.min_cold_protection_temperature <= temperature) + thermal_protection_flags |= shoes.cold_protection + if(gloves) + if(gloves.min_cold_protection_temperature && gloves.min_cold_protection_temperature <= temperature) + thermal_protection_flags |= gloves.cold_protection + if(wear_mask) + if(wear_mask.min_cold_protection_temperature && wear_mask.min_cold_protection_temperature <= temperature) + thermal_protection_flags |= wear_mask.cold_protection + + return thermal_protection_flags + +/mob/living/carbon/human/proc/get_cold_protection(temperature) + + if(COLD_RESISTANCE in mutations) + return 1 //Fully protected from the cold. + + temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K. + var/thermal_protection_flags = get_cold_protection_flags(temperature) + + var/thermal_protection = 0.0 + if(thermal_protection_flags) + if(thermal_protection_flags & HEAD) + thermal_protection += THERMAL_PROTECTION_HEAD + if(thermal_protection_flags & UPPER_TORSO) + thermal_protection += THERMAL_PROTECTION_UPPER_TORSO + if(thermal_protection_flags & LOWER_TORSO) + thermal_protection += THERMAL_PROTECTION_LOWER_TORSO + if(thermal_protection_flags & LEG_LEFT) + thermal_protection += THERMAL_PROTECTION_LEG_LEFT + if(thermal_protection_flags & LEG_RIGHT) + thermal_protection += THERMAL_PROTECTION_LEG_RIGHT + if(thermal_protection_flags & ARM_LEFT) + thermal_protection += THERMAL_PROTECTION_ARM_LEFT + if(thermal_protection_flags & ARM_RIGHT) + thermal_protection += THERMAL_PROTECTION_ARM_RIGHT + + return min(1,thermal_protection) + +/* +/mob/living/carbon/human/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(glasses) + if(glasses.protective_temperature > temp) + fire_prot += (glasses.protective_temperature/10) + if(ears) + if(ears.protective_temperature > temp) + fire_prot += (ears.protective_temperature/10) + if(wear_suit) + if(wear_suit.protective_temperature > temp) + fire_prot += (wear_suit.protective_temperature/10) + if(w_uniform) + if(w_uniform.protective_temperature > temp) + fire_prot += (w_uniform.protective_temperature/10) + if(gloves) + if(gloves.protective_temperature > temp) + fire_prot += (gloves.protective_temperature/10) + if(shoes) + if(shoes.protective_temperature > temp) + fire_prot += (shoes.protective_temperature/10) + + return fire_prot + +/mob/living/carbon/human/proc/handle_temperature_damage(body_part, exposed_temperature, exposed_intensity) + if(nodamage) + return + //world <<"body_part = [body_part], exposed_temperature = [exposed_temperature], exposed_intensity = [exposed_intensity]" + var/discomfort = min(abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0) + + if(exposed_temperature > bodytemperature) + discomfort *= 4 + + if(mutantrace == "plant") + discomfort *= TEMPERATURE_DAMAGE_COEFFICIENT * 2 //I don't like magic numbers. I'll make mutantraces a datum with vars sometime later. -- Urist + else + discomfort *= TEMPERATURE_DAMAGE_COEFFICIENT //Dangercon 2011 - now with less magic numbers! + //world <<"[discomfort]" + + switch(body_part) + if(HEAD) + apply_damage(2.5*discomfort, BURN, BP_HEAD) + if(UPPER_TORSO) + apply_damage(2.5*discomfort, BURN, BP_CHEST) + if(LEGS) + apply_damage(0.6*discomfort, BURN, BP_L_LEG) + apply_damage(0.6*discomfort, BURN, BP_R_LEG) + if(ARMS) + apply_damage(0.4*discomfort, BURN, BP_L_ARM) + apply_damage(0.4*discomfort, BURN, BP_R_ARM) +*/ + +/mob/living/carbon/human/proc/handle_chemicals_in_body() + + if(reagents && !species.flags[IS_SYNTHETIC]) //Synths don't process reagents. + var/alien = null + if(species) + alien = species.name + reagents.metabolize(src,alien) + + var/total_phoronloss = 0 + for(var/obj/item/I in src) + if(I.contaminated) + total_phoronloss += vsc.plc.CONTAMINATION_LOSS + if(!(status_flags & GODMODE)) adjustToxLoss(total_phoronloss) + + if(status_flags & GODMODE) return 0 //godmode + + if(species.flags[REQUIRE_LIGHT]) + 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 + light_amount = round((T.get_lumcount()*10)-5) + + if(is_type_organ(O_LIVER, /obj/item/organ/internal/liver/diona) && !is_bruised_organ(O_LIVER)) // Specie may require light, but only plants, with chlorophyllic plasts can produce nutrition out of light! + nutrition += light_amount + + if(species.flags[IS_PLANT]) + if(is_type_organ(O_KIDNEYS, /obj/item/organ/internal/kidneys/diona)) // Diona's kidneys contain all the nutritious elements. Damaging them means they aren't held. + var/obj/item/organ/internal/kidneys/KS = organs_by_name[O_KIDNEYS] + if(!KS) + nutrition = 0 + else if(nutrition > (500 - KS.damage*5)) + nutrition = 500 - KS.damage*5 + species.regen(src, light_amount) + + if(dna && dna.mutantrace == "shadow") + var/light_amount = 0 + if(isturf(loc)) + var/turf/T = loc + light_amount = round(T.get_lumcount()*10) + + if(light_amount > 2) //if there's enough light, start dying + take_overall_damage(1,1) + else if (light_amount < 2) //heal in the dark + heal_overall_damage(1,1) + + if(dna && dna.mutantrace == "shadowling") + var/light_amount = 0 + nutrition = 450 //i aint never get hongry + if(isturf(loc)) + var/turf/T = loc + light_amount = round(T.get_lumcount()*10) + + if(light_amount > LIGHT_DAM_THRESHOLD) + take_overall_damage(0,LIGHT_DAMAGE_TAKEN) + to_chat(src, "The light burns you!") + src << 'sound/weapons/sear.ogg' + else if (light_amount < LIGHT_HEAL_THRESHOLD) //heal in the dark + heal_overall_damage(5,5) + adjustToxLoss(-3) + adjustBrainLoss(-25) //gibbering shadowlings are hilarious but also bad to have + adjustCloneLoss(-1) + adjustOxyLoss(-10) + SetWeakened(0) + SetStunned(0) + + //The fucking FAT mutation is the dumbest shit ever. It makes the code so difficult to work with + if(FAT in mutations) + if(!has_trait(TRAIT_FAT) && overeatduration < 100) + to_chat(src, "\blue You feel fit again!") + mutations.Remove(FAT) + update_body() + update_mutantrace() + update_mutations() + update_inv_w_uniform() + update_inv_wear_suit() + else + if(has_trait(TRAIT_FAT) || overeatduration > 500) + if(!species.flags[IS_SYNTHETIC] && !species.flags[IS_PLANT]) + mutations.Add(FAT) + update_body() + update_mutantrace() + update_mutations() + update_inv_w_uniform() + update_inv_wear_suit() + + + // nutrition decrease + if (nutrition > 0 && stat != DEAD) + nutrition = max(0, nutrition - metabolism_factor/10) + + if (nutrition > 450) + if(overeatduration < 600) //capped so people don't take forever to unfat + overeatduration++ + else + if(overeatduration > 1) + overeatduration -= 2 //doubled the unfat rate + + if(species.flags[REQUIRE_LIGHT]) + if(nutrition < 200) + take_overall_damage(2,0) + traumatic_shock++ + + 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 - 15) + jitteriness = max(0, jitteriness - 15) + else + dizziness = max(0, dizziness - 3) + jitteriness = max(0, jitteriness - 3) + + if(!species.flags[IS_SYNTHETIC]) + handle_trace_chems() + + updatehealth() + + return //TODO: DEFERRED + +/mob/living/carbon/human/proc/handle_regular_status_updates() + if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP + blinded = 1 + silent = 0 + else //ALIVE. LIGHTS ARE ON + updatehealth() //TODO + if(!in_stasis) + stabilize_body_temperature() //Body temperature adjusts itself + handle_bodyparts() //Optimized. + if(!species.flags[NO_BLOOD] && bodytemperature >= 170) + var/blood_volume = round(vessel.get_reagent_amount("blood")) + if(blood_volume > 0) + handle_blood(blood_volume) + + if(health <= config.health_threshold_dead || brain_op_stage == 4.0) + death() + blinded = 1 + silent = 0 + return 1 + + // the analgesic effect wears off slowly + analgesic = max(0, analgesic - 1) + + //UNCONSCIOUS. NO-ONE IS HOME + if( (getOxyLoss() > 50) || (config.health_threshold_crit > health) ) + Paralyse(3) + + /* Done by handle_breath() + if( health <= 20 && prob(1) ) + spawn(0) + emote("gasp") + if(!reagents.has_reagent("inaprovaline")) + adjustOxyLoss(1)*/ + + if(hallucination) + if(hallucination >= 20) + if(prob(3)) + fake_attack(src) + if(!handling_hal) + spawn handle_hallucinations() //The not boring kind! + + if(hallucination<=2) + hallucination = 0 + halloss = 0 + else + hallucination -= 2 + + else + for(var/atom/a in hallucinations) + qdel(a) + + if(halloss > 100) + //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) + if(prob(3)) + Paralyse(10) + else + Weaken(10) + setHalLoss(99) + + if(paralysis) + AdjustParalysis(-1) + blinded = 1 + stat = UNCONSCIOUS + if(halloss > 0) + adjustHalLoss(-3) + else if(sleeping) + throw_alert("asleep") + speech_problem_flag = 1 + handle_dreams() + adjustHalLoss(-3) + if (mind) + if((mind.active && client != null) || immune_to_ssd) //This also checks whether a client is connected, if not, sleep is not reduced. + sleeping = max(sleeping-1, 0) + blinded = 1 + stat = UNCONSCIOUS + if( prob(2) && health && !hal_crit ) + spawn(0) + emote("snore") + //CONSCIOUS + else + stat = CONSCIOUS + if(halloss > 0) + if(resting) + adjustHalLoss(-3) + else + adjustHalLoss(-1) + if(!sleeping) //No refactor - no life! + clear_alert("asleep") + + if(embedded_flag && !(life_tick % 10)) + var/list/E + E = get_visible_implants(0) + if(!E.len) + embedded_flag = 0 + + + //Eyes + if(sdisabilities & BLIND || has_trait(TRAIT_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(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold) || istype(head, /obj/item/weapon/reagent_containers/glass/bucket)) //resting your eyes with a blindfold heals blurry eyes faster + eye_blurry = max(eye_blurry-3, 0) + blinded = 1 + else if(eye_blurry) //blurry eyes heal slowly + eye_blurry = max(eye_blurry-1, 0) + + //Ears + if(sdisabilities & DEAF || has_trait(TRAIT_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(istype(l_ear, /obj/item/clothing/ears/earmuffs) || istype(r_ear, /obj/item/clothing/ears/earmuffs)) //resting your ears with earmuffs heals ear damage faster + ear_damage = max(ear_damage-0.15, 0) + ear_deaf = max(ear_deaf, 1) + 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) + speech_problem_flag = 1 + AdjustStunned(-1) + + if(weakened) + weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times + + if(stuttering) + speech_problem_flag = 1 + stuttering = max(stuttering-1, 0) + if (slurring) + speech_problem_flag = 1 + slurring = max(slurring-1, 0) + if(silent) + speech_problem_flag = 1 + silent = max(silent-1, 0) + + if(druggy) + druggy = max(druggy-1, 0) + + // If you're dirty, your gloves will become dirty, too. + if(gloves && germ_level > gloves.germ_level && prob(10)) + gloves.germ_level += 1 + + return 1 + +/mob/living/carbon/human/handle_regular_hud_updates() + if(hud_updateflag)//? Below ? + handle_hud_list() + + if(!client) + return 0 + + if(hud_updateflag)//Is there any reason for 2nd check? ~Zve + handle_hud_list() + + for(var/image/hud in client.images) + if(copytext(hud.icon_state,1,4) == "hud") //ugly, but icon comparison is worse, I believe + client.images.Remove(hud) + + if(stat == UNCONSCIOUS && health <= 0) + //Critical damage passage overlay + var/severity = 0 + switch(health) + if(-20 to -10) severity = 1 + if(-30 to -20) severity = 2 + if(-40 to -30) severity = 3 + if(-50 to -40) severity = 4 + if(-60 to -50) severity = 5 + if(-70 to -60) severity = 6 + if(-80 to -70) severity = 7 + if(-90 to -80) severity = 8 + if(-95 to -90) severity = 9 + if(-INFINITY to -95) severity = 10 + overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity) + else + clear_fullscreen("crit") + //Oxygen damage overlay + if(oxyloss) + var/severity = 0 + switch(oxyloss) + if(10 to 20) severity = 1 + if(20 to 25) severity = 2 + if(25 to 30) severity = 3 + if(30 to 35) severity = 4 + if(35 to 40) severity = 5 + if(40 to 45) severity = 6 + if(45 to INFINITY) severity = 7 + overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity) + else + clear_fullscreen("oxy") + + //Fire and Brute damage overlay (BSSR) + var/hurtdamage = src.getBruteLoss() + src.getFireLoss() + damageoverlaytemp + damageoverlaytemp = 0 // We do this so we can detect if someone hits us or not. + if(hurtdamage) + var/severity = 0 + switch(hurtdamage) + if(10 to 25) severity = 1 + if(25 to 40) severity = 2 + if(40 to 55) severity = 3 + if(55 to 70) severity = 4 + if(70 to 85) severity = 5 + if(85 to INFINITY) severity = 6 + overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity) + else + clear_fullscreen("brute") + + if( stat == DEAD ) + sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) + see_in_dark = 8 + if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO + if(healths) healths.icon_state = "health7" //DEAD healthmeter + if(client) + if(client.view != world.view) + if(locate(/obj/item/weapon/gun/energy/sniperrifle, contents)) + var/obj/item/weapon/gun/energy/sniperrifle/s = locate() in src + if(s.zoom) + s.zoom() + + else + sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS) + see_in_dark = species.darksight + see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING + if(dna) + switch(dna.mutantrace) + if("slime") + see_in_dark = 3 + see_invisible = SEE_INVISIBLE_LEVEL_ONE + if("shadow") + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_ONE + + if(XRAY in mutations) + sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + see_in_dark = 8 + if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO + + if(seer) + var/obj/effect/rune/R = locate() in loc + if(R && istype(R.power, /datum/cult/seer)) + see_invisible = SEE_INVISIBLE_CULT + else + see_invisible = SEE_INVISIBLE_LIVING + seer = FALSE + + if(glasses) + var/obj/item/clothing/glasses/G = glasses + if(istype(G)) + see_in_dark += G.darkness_view + if(G.vision_flags) // MESONS + sight |= G.vision_flags + if(!druggy) + see_invisible = SEE_INVISIBLE_MINIMUM + if(istype(G,/obj/item/clothing/glasses/night/shadowling)) + var/obj/item/clothing/glasses/night/shadowling/S = G + if(S.vision) + see_invisible = SEE_INVISIBLE_LIVING + else + see_invisible = SEE_INVISIBLE_MINIMUM + +/* HUD shit goes here, as long as it doesn't modify sight flags */ +// The purpose of this is to stop xray and w/e from preventing you from using huds -- Love, Doohl + + if(istype(glasses, /obj/item/clothing/glasses/sunglasses/sechud)) + var/obj/item/clothing/glasses/sunglasses/sechud/O = glasses + if(O.hud) + O.hud.process_hud(src) + if(!druggy) + see_invisible = SEE_INVISIBLE_LIVING + else if(istype(glasses, /obj/item/clothing/glasses/hud)) + var/obj/item/clothing/glasses/hud/O = glasses + O.process_hud(src) + if(!druggy) + see_invisible = SEE_INVISIBLE_LIVING + else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/hud/secmed)) + var/obj/item/clothing/glasses/sunglasses/hud/secmed/O = glasses + O.process_hud(src) + if(!druggy) + see_invisible = SEE_INVISIBLE_LIVING + + else if(!seer) + see_invisible = SEE_INVISIBLE_LIVING + + if(istype(wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja)) + var/obj/item/clothing/mask/gas/voice/space_ninja/O = wear_mask + switch(O.mode) + if(0) + var/target_list[] = list() + for(var/mob/living/target in oview(src)) + if( target.mind&&(target.mind.special_role||issilicon(target)) )//They need to have a mind. + target_list += target + if(target_list.len)//Everything else is handled by the ninja mask proc. + O.assess_targets(target_list, src) + if(!druggy) + see_invisible = SEE_INVISIBLE_LIVING + if(1) + see_in_dark = 5 + //client.screen += global_hud.meson + if(!druggy) + see_invisible = SEE_INVISIBLE_MINIMUM + if(2) + sight |= SEE_MOBS + //client.screen += global_hud.thermal + if(!druggy) + see_invisible = SEE_INVISIBLE_LEVEL_TWO + if(3) + sight |= SEE_TURFS + //client.screen += global_hud.meson + if(!druggy) + see_invisible = SEE_INVISIBLE_MINIMUM + + if(changeling_aug) + sight |= SEE_MOBS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + + if(healths) + if (analgesic) + healths.icon_state = "health_health_numb" + else + switch(hal_screwyhud) + if(1) + healths.icon_state = "health6" + if(2) + healths.icon_state = "health7" + else + //switch(health - halloss) + switch(100 - ((species && species.flags[NO_PAIN] && !species.flags[IS_SYNTHETIC]) ? 0 : traumatic_shock)) + 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" + + if(healthdoll) + healthdoll.overlays.Cut() + if(stat == DEAD) + healthdoll.icon_state = "healthdoll_DEAD" + else + healthdoll.icon_state = "healthdoll_OVERLAY" + for(var/obj/item/organ/external/BP in bodyparts) + var/damage = BP.burn_dam + BP.brute_dam + var/comparison = (BP.max_damage / 5) + var/icon_num = 0 + if(damage) + icon_num = 1 + if(damage > (comparison)) + icon_num = 2 + if(damage > (comparison*2)) + icon_num = 3 + if(damage > (comparison*3)) + icon_num = 4 + if(damage > (comparison*4)) + icon_num = 5 + if(icon_num) + healthdoll.overlays += image('icons/mob/screen_gen.dmi',"[BP.body_zone][icon_num]") + + switch(get_nutrition()) + if(NUTRITION_LEVEL_FULL to INFINITY) + throw_alert("nutrition","fat") + if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FULL) + clear_alert("nutrition") + if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) + throw_alert("nutrition","hungry") + else + throw_alert("nutrition","starving") + + if(pressure) + pressure.icon_state = "pressure[pressure_alert]" + + if(pullin) + if(pulling) + pullin.icon_state = "pull1" + else + pullin.icon_state = "pull0" + //OH cmon... + var/nearsighted = 0 + var/impaired = 0 + + if(disabilities & NEARSIGHTED || has_trait(TRAIT_NEARSIGHT)) + nearsighted = 1 + + if(glasses) + var/obj/item/clothing/glasses/G = glasses + if(G.prescription) + nearsighted = 0 + + if(istype(head, /obj/item/clothing/head/welding) || istype(head, /obj/item/clothing/head/helmet/space/unathi)) + var/obj/item/clothing/head/welding/O = head + if(!O.up && tinted_weldhelh) + impaired = 2 + if(istype(wear_mask, /obj/item/clothing/mask/gas/welding) ) + var/obj/item/clothing/mask/gas/welding/O = wear_mask + if(!O.up && tinted_weldhelh) + impaired = 2 + if(istype(glasses, /obj/item/clothing/glasses/welding) ) + var/obj/item/clothing/glasses/welding/O = glasses + if(!O.up && tinted_weldhelh) + impaired = max(impaired, 1) + + if(eye_blurry) + overlay_fullscreen("blurry", /obj/screen/fullscreen/blurry) + else + clear_fullscreen("blurry") + + if(druggy) + overlay_fullscreen("high", /obj/screen/fullscreen/high) + else + clear_fullscreen("high") + if(nearsighted) + overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1) + else + clear_fullscreen("nearsighted") + + if(impaired) + overlay_fullscreen("impaired", /obj/screen/fullscreen/impaired, impaired) + else + clear_fullscreen("impaired") + + if(!machine) + var/isRemoteObserve = 0 + if((REMOTE_VIEW in mutations) && remoteview_target) + if(getBrainLoss() <= 100)//#Z2 We burn our brain with active remote_view mutation + if(remoteview_target.stat==CONSCIOUS) + isRemoteObserve = 1 + if(getBrainLoss() > 50) + adjustBrainLoss(2) + else + adjustBrainLoss(1) + else + to_chat(src, "Too hard to concentrate...") + remoteview_target = null + reset_view(null)//##Z2 + if(!isRemoteObserve && client && !client.adminobs) + remoteview_target = null + reset_view(null) + + + if(mind && mind.changeling) + hud_used.lingchemdisplay.invisibility = 0 + hud_used.lingchemdisplay.maptext = "
                    [mind.changeling.chem_charges]
                    " + else + hud_used.lingchemdisplay.invisibility = 101 + + ..() + + return 1 + +/mob/living/carbon/human/update_sight() + sightglassesmod = null + if(stat == DEAD) + set_EyesVision(transition_time = 0) + return + var/obj/item/clothing/glasses/G = glasses + if(istype(G) && G.active) + if(istype(glasses, /obj/item/clothing/glasses/meson)) + sightglassesmod = "meson" + else if(istype(glasses, /obj/item/clothing/glasses/night) && !istype(glasses, /obj/item/clothing/glasses/night/shadowling)) + sightglassesmod = "nvg" + else if(istype(glasses, /obj/item/clothing/glasses/thermal)) + sightglassesmod = "thermal" + else if(istype(glasses, /obj/item/clothing/glasses/science)) + sightglassesmod = "sci" + + if(species.nighteyes) + if(sightglassesmod) + sightglassesmod = "nightsight_glasses" + else + var/light_amount = 0 + var/turf/T = get_turf(src) + light_amount = round(T.get_lumcount()*10) + if(light_amount > 1) + sightglassesmod = null + else + sightglassesmod = "nightsight" + set_EyesVision(sightglassesmod) + +/mob/living/carbon/human/proc/handle_random_events() + // Puke if toxloss is too high + if(!stat) + if (getToxLoss() >= 45 && nutrition > 20) + vomit() + + //0.1% chance of playing a scary sound to someone who's in complete darkness + if(isturf(loc) && rand(1,1000) == 1) + var/turf/T = loc + if(T.lighting_overlay && T.lighting_overlay.luminosity == 0) + playsound_local(src,pick(scarySounds),50, 1, -1) + +/mob/living/carbon/human/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) //disabled because of symptom that randomly ignites a mob, which triggers this + // var/datum/disease2/disease/V = virus2[ID] + // V.cure(src) + if(life_tick % 3) //don't spam checks over all objects in view every tick. + for(var/obj/effect/decal/cleanable/O in view(1,src)) + if(istype(O,/obj/effect/decal/cleanable/blood)) + var/obj/effect/decal/cleanable/blood/B = O + if(B && B.virus2 && B.virus2.len) + for (var/ID in B.virus2) + var/datum/disease2/disease/V = B.virus2[ID] + if(V.spreadtype == "Contact") + infect_virus2(src,V.getcopy()) + + else if(istype(O,/obj/effect/decal/cleanable/mucus)) + var/obj/effect/decal/cleanable/mucus/M = O + if(M && M.virus2 && M.virus2.len) + for (var/ID in M.virus2) + var/datum/disease2/disease/V = M.virus2[ID] + if(V.spreadtype == "Contact") + infect_virus2(src,V.getcopy()) + + + if(virus2.len) + 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/human/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 != DEAD) + if(M.stat == DEAD) + M.death(1) + stomach_contents.Remove(M) + qdel(M) + continue + if(SSmob.times_fired%3==1) + if(!(M.status_flags & GODMODE)) + M.adjustBruteLoss(5) + nutrition += 10 + +/mob/living/carbon/human/proc/handle_changeling() + if(mind && mind.changeling) + mind.changeling.regenerate() + +/mob/living/carbon/human/handle_shock() + ..() + if(status_flags & GODMODE) return 0 //godmode + if(analgesic || (species && species.flags[NO_PAIN])) return // analgesic avoids all traumatic shock temporarily + + if(health < config.health_threshold_softcrit)// health 0 makes you immediately collapse + shock_stage = max(shock_stage, 61) + + if(traumatic_shock >= 80) + shock_stage += 1 + else if(health < config.health_threshold_softcrit) + shock_stage = max(shock_stage, 61) + else + shock_stage = min(shock_stage, 160) + shock_stage = max(shock_stage-1, 0) + return + + if(shock_stage == 10) + to_chat(src, ""+pick("It hurts so much!", "You really need some painkillers..", "Dear god, the pain!")) + + if(shock_stage >= 30) + if(shock_stage == 30) emote("me",1,"is having trouble keeping their eyes open.") + eye_blurry = max(2, eye_blurry) + stuttering = max(stuttering, 5) + + if(shock_stage == 40) + to_chat(src, ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")) + + if (shock_stage >= 60) + if(shock_stage == 60) emote("me",1,"'s body becomes limp.") + if (prob(2)) + to_chat(src, ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")) + Weaken(20) + + if(shock_stage >= 80) + if (prob(5)) + to_chat(src, ""+pick("The pain is excrutiating!", "Please, just end the pain!", "Your whole body is going numb!")) + Weaken(20) + + if(shock_stage >= 120) + if (prob(2)) + to_chat(src, ""+pick("You black out!", "You feel like you could die any moment now.", "You're about to lose consciousness.")) + Paralyse(5) + + if(shock_stage == 150) + emote("me",1,"can no longer stand, collapsing!") + Weaken(20) + + if(shock_stage >= 150) + Weaken(20) + +/mob/living/carbon/human/proc/handle_heart_beat() + + if(pulse == PULSE_NONE) return + + if(pulse == PULSE_2FAST || shock_stage >= 10 || istype(get_turf(src), /turf/space)) + + var/temp = (5 - pulse)/2 + + if(heart_beat >= temp) + heart_beat = 0 + src << sound('sound/effects/singlebeat.ogg',0,0,0,50) + else if(temp != 0) + heart_beat++ + +/mob/living/carbon/human/proc/handle_pulse() + + if(life_tick % 5) + return pulse //update pulse every 5 life ticks (~1 tick/sec, depending on server load) + + if(species && species.flags[NO_BLOOD]) + return PULSE_NONE //No blood, no pulse. + + if(stat == DEAD) + return PULSE_NONE //that's it, you're dead, nothing can influence your pulse + + var/temp = PULSE_NORM + + if(round(vessel.get_reagent_amount("blood")) <= BLOOD_VOLUME_BAD) //how much blood do we have + temp = PULSE_THREADY //not enough :( + + if(status_flags & FAKEDEATH) + temp = PULSE_NONE //pretend that we're dead. unlike actual death, can be inflienced by meds + + //handles different chems' influence on pulse + for(var/datum/reagent/R in reagents.reagent_list) + if(R.id in bradycardics) + if(temp <= PULSE_THREADY && temp >= PULSE_NORM) + temp-- + if(R.id in tachycardics) + if(temp <= PULSE_FAST && temp >= PULSE_NONE) + temp++ + if(R.id in heartstopper) //To avoid using fakedeath + temp = PULSE_NONE + if(R.id in cheartstopper) //Conditional heart-stoppage + if(R.volume >= R.overdose) + temp = PULSE_NONE + + return temp + +/* + Called by life(), instead of having the individual hud items update icons each tick and check for status changes + we only set those statuses and icons upon changes. Then those HUD items will simply add those pre-made images. + This proc below is only called when those HUD elements need to change as determined by the mobs hud_updateflag. +*/ + + +/mob/living/carbon/human/proc/handle_hud_list() + + if(hud_updateflag & 1 << HEALTH_HUD) + var/image/holder = hud_list[HEALTH_HUD] + if(stat == DEAD) + holder.icon_state = "hudhealth-100" // X_X + else + holder.icon_state = "hud[RoundHealth(health)]" + + hud_list[HEALTH_HUD] = holder + + if(hud_updateflag & 1 << STATUS_HUD) + var/foundVirus = 0 + for(var/datum/disease/D in viruses) + if(!D.hidden[SCANNER]) + foundVirus++ + for (var/ID in virus2) + if (ID in virusDB) + foundVirus = 1 + break + + var/image/holder = hud_list[STATUS_HUD] + var/image/holder2 = hud_list[STATUS_HUD_OOC] + if(stat == DEAD) + holder.icon_state = "huddead" + holder2.icon_state = "huddead" + else if(status_flags & XENO_HOST) + holder.icon_state = "hudxeno" + holder2.icon_state = "hudxeno" + else if(foundVirus || iszombie(src)) + holder.icon_state = "hudill" + else if(has_brain_worms()) + var/mob/living/simple_animal/borer/B = has_brain_worms() + if(B.controlling) + holder.icon_state = "hudbrainworm" + else + holder.icon_state = "hudhealthy" + holder2.icon_state = "hudbrainworm" + else + holder.icon_state = "hudhealthy" + if(virus2.len) + holder2.icon_state = "hudill" + else + holder2.icon_state = "hudhealthy" + + hud_list[STATUS_HUD] = holder + hud_list[STATUS_HUD_OOC] = holder2 + + if(hud_updateflag & 1 << ID_HUD) + var/image/holder = hud_list[ID_HUD] + if(wear_id) + var/obj/item/weapon/card/id/I = wear_id.GetID() + if(I) + holder.icon_state = "hud[ckey(I.GetJobName())]" + else + holder.icon_state = "hudunknown" + else + holder.icon_state = "hudunknown" + + + hud_list[ID_HUD] = holder + + if(hud_updateflag & 1 << WANTED_HUD) + var/image/holder = hud_list[WANTED_HUD] + holder.icon_state = "hudblank" + var/perpname = name + if(wear_id) + var/obj/item/weapon/card/id/I = wear_id.GetID() + if(I) + perpname = I.registered_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.security) + if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) + holder.icon_state = "hudwanted" + break + else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Incarcerated")) + holder.icon_state = "hudprisoner" + break + else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Paroled")) + holder.icon_state = "hudparoled" + break + else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Released")) + holder.icon_state = "hudreleased" + break + hud_list[WANTED_HUD] = holder + + if(hud_updateflag & 1 << IMPLOYAL_HUD || hud_updateflag & 1 << IMPCHEM_HUD || hud_updateflag & 1 << IMPTRACK_HUD) + var/image/holder1 = hud_list[IMPTRACK_HUD] + var/image/holder2 = hud_list[IMPLOYAL_HUD] + var/image/holder3 = hud_list[IMPCHEM_HUD] + + holder1.icon_state = "hudblank" + holder2.icon_state = "hudblank" + holder3.icon_state = "hudblank" + + var/has_loyal_implant = FALSE + for(var/obj/item/weapon/implant/I in src) + if(I.implanted) + if(istype(I,/obj/item/weapon/implant/tracking)) + holder1.icon_state = "hud_imp_tracking" + if(istype(I,/obj/item/weapon/implant/mindshield) && !has_loyal_implant) + if(istype(I,/obj/item/weapon/implant/mindshield/loyalty)) + has_loyal_implant = TRUE + holder2.icon_state = "hud_imp_loyal" + else + holder2.icon_state = "hud_imp_mindshield" + if(istype(I,/obj/item/weapon/implant/chem)) + holder3.icon_state = "hud_imp_chem" + + hud_list[IMPTRACK_HUD] = holder1 + hud_list[IMPLOYAL_HUD] = holder2 + hud_list[IMPCHEM_HUD] = holder3 + + if(hud_updateflag & 1 << SPECIALROLE_HUD) + var/image/holder = hud_list[SPECIALROLE_HUD] + holder.icon_state = "hudblank" + if(mind) + + switch(mind.special_role) + if("traitor","Syndicate") + holder.icon_state = "hudsyndicate" + if("Revolutionary") + holder.icon_state = "hudrevolutionary" + if("Head Revolutionary") + holder.icon_state = "hudheadrevolutionary" + if("Cultist") + holder.icon_state = "hudcultist" + if("Changeling") + holder.icon_state = "hudchangeling" + if("Wizard","Fake Wizard") + holder.icon_state = "hudwizard" + if("Death Commando") + holder.icon_state = "huddeathsquad" + if("Ninja") + holder.icon_state = "hudninja" + if("head_loyalist") + holder.icon_state = "hudloyalist" + if("loyalist") + holder.icon_state = "hudloyalist" + if("head_mutineer") + holder.icon_state = "hudmutineer" + if("mutineer") + holder.icon_state = "hudmutineer" + if("shadowling") + holder.icon_state = "hudshadowling" + if("thrall") + holder.icon_state = "hudthrall" + if("Clandestine Gang (A) Boss","Prima Gang (A) Boss","Zero-G Gang (A) Boss","Max Gang (A) Boss","Blasto Gang (A) Boss","Waffle Gang (A) Boss","North Gang (A) Boss","Omni Gang (A) Boss","Newton Gang (A) Boss","Cyber Gang (A) Boss","Donk Gang (A) Boss","Gene Gang (A) Boss","Gib Gang (A) Boss","Tunnel Gang (A) Boss","Diablo Gang (A) Boss","Psyke Gang (A) Boss","Osiron Gang (A) Boss") + holder.icon_state = "gang_boss_a" + if("Clandestine Gang (B) Boss","Prima Gang (B) Boss","Zero-G Gang (B) Boss","Max Gang (B) Boss","Blasto Gang (B) Boss","Waffle Gang (B) Boss","North Gang (B) Boss","Omni Gang (B) Boss","Newton Gang (B) Boss","Cyber Gang (B) Boss","Donk Gang (B) Boss","Gene Gang (B) Boss","Gib Gang (B) Boss","Tunnel Gang (B) Boss","Diablo Gang (B) Boss","Psyke Gang (B) Boss","Osiron Gang (B) Boss") + holder.icon_state = "gang_boss_b" + if("Clandestine Gang (A) Lieutenant","Prima Gang (A) Lieutenant","Zero-G Gang (A) Lieutenant","Max Gang (A) Lieutenant","Blasto Gang (A) Lieutenant","Waffle Gang (A) Lieutenant","North Gang (A) Lieutenant","Omni Gang (A) Lieutenant","Newton Gang (A) Lieutenant","Cyber Gang (A) Lieutenant","Donk Gang (A) Lieutenant","Gene Gang (A) Lieutenant","Gib Gang (A) Lieutenant","Tunnel Gang (A) Lieutenant","Diablo Gang (A) Lieutenant","Psyke Gang (A) Lieutenant","Osiron Gang (A) Lieutenant") + holder.icon_state = "lieutenant_a" + if("Clandestine Gang (B) Lieutenant","Prima Gang (B) Lieutenant","Zero-G Gang (B) Lieutenant","Max Gang (B) Lieutenant","Blasto Gang (B) Lieutenant","Waffle Gang (B) Lieutenant","North Gang (B) Lieutenant","Omni Gang (B) Lieutenant","Newton Gang (B) Lieutenant","Cyber Gang (B) Lieutenant","Donk Gang (B) Lieutenant","Gene Gang (B) Lieutenant","Gib Gang (B) Lieutenant","Tunnel Gang (B) Lieutenant","Diablo Gang (B) Lieutenant","Psyke Gang (B) Lieutenant","Osiron Gang (B) Lieutenant") + holder.icon_state = "lieutenant_b" + if("Clandestine Gang (A)","Prima Gang (A)","Zero-G Gang (A)","Max Gang (A)","Blasto Gang (A)","Waffle Gang (A)","North Gang (A)","Omni Gang (A)","Newton Gang (A)","Cyber Gang (A)","Donk Gang (A)","Gene Gang (A)","Gib Gang (A)","Tunnel Gang (A)","Diablo Gang (A)","Psyke Gang (A)","Osiron Gang (A)") + holder.icon_state = "gangster_a" + if("Clandestine Gang (B)","Prima Gang (B)","Zero-G Gang (B)","Max Gang (B)","Blasto Gang (B)","Waffle Gang (B)","North Gang (B)","Omni Gang (B)","Newton Gang (B)","Cyber Gang (B)","Donk Gang (B)","Gene Gang (B)","Gib Gang (B)","Tunnel Gang (B)","Diablo Gang (B)","Psyke Gang (B)","Osiron Gang (B)") + holder.icon_state = "gangster_b" + + hud_list[SPECIALROLE_HUD] = holder + hud_updateflag = 0 + + +#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 2dc4536073af..144c6d6432f0 100644 --- a/code/modules/mob/living/carbon/human/login.dm +++ b/code/modules/mob/living/carbon/human/login.dm @@ -1,7 +1,7 @@ -/mob/living/carbon/human/Login() - ..() - update_hud() - if(ticker.mode) - 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. - update_golem_hud_icons() - return +/mob/living/carbon/human/Login() + ..() + update_hud() + if(ticker.mode) + 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. + update_golem_hud_icons() + return diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 32960816fefc..602751a69bac 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -1,300 +1,300 @@ -/mob/living/carbon/human/say(message, ignore_appearance) - var/verb = "says" - var/message_range = world.view - var/italics = 0 - var/alt_name = "" - if(client) - if(client.prefs.muted & MUTE_IC) - to_chat(src, "You cannot speak in IC (Muted).") - return - - //Meme stuff - if((!speech_allowed && usr == src) || miming) - to_chat(usr, "You can't speak.") - return - - message = sanitize(message) - - if(stat == DEAD) - if(fake_death) //Our changeling with fake_death status must not speak in dead chat!! - return - return say_dead(message) - - var/message_mode = parse_message_mode(message, "headset") - - if (istype(wear_mask, /obj/item/clothing/mask/muzzle) && !(message_mode == "changeling" || message_mode == "alientalk")) //Todo: Add this to speech_problem_flag checks. - return - - if(copytext(message,1,2) == "*") - return emote(copytext(message,2)) - - if(!ignore_appearance && name != GetVoice()) - alt_name = "(as [get_id_name("Unknown")])" - - //parse the radio code and consume it - if (message_mode) - if (message_mode == "headset") - message = copytext(message,2) //it would be really nice if the parse procs could do this for us. - else - message = copytext(message,3) - - //parse the language code and consume it or use default racial language if forced. - var/datum/language/speaking = parse_language(message) - if (speaking) - message = copytext(message,2+length(speaking.key)) - else if(species.force_racial_language) - speaking = all_languages[species.language] - else - switch(species.name) - if(TAJARAN) - message = replacetext(message, "", pick(list("" , ""))) - message = replacetext(message, "", pick(list("" , ""))) - if(UNATHI) - message = replacetext(message, "", pick(list("" , ""))) - // ... . , . - message = replacetext(message, "", pick(list("" , ""))) - if(ABDUCTOR) - var/mob/living/carbon/human/user = usr - var/sm = sanitize(message) - for(var/mob/living/carbon/human/H in human_list) - if(H.species.name != ABDUCTOR) - continue - if(user.team != H.team) - continue - to_chat(H, text("[user.real_name]: [sm]", user.team)) - //return - technically you can add more aliens to a team - for(var/mob/M in observer_list) - to_chat(M, text("[user.real_name]: [sm]", user.team)) - log_say("Abductor: [name]/[key] : [sm]") - return "" - - message = capitalize(trim(message)) - if(iszombie(src)) - message = zombie_talk(message) - - var/ending = copytext(message, length(message)) - if (speaking) - //If we've gotten this far, keep going! - verb = speaking.get_spoken_verb(ending) - else - if(ending=="!") - verb=pick("exclaims","shouts","yells") - if(ending=="?") - verb="asks" - - if(speech_problem_flag) - var/list/handle_r = handle_speech_problems(message, message_mode) - //var/list/handle_r = handle_speech_problems(message) - message = handle_r[1] - verb = handle_r[2] - speech_problem_flag = handle_r[3] - - if(!message || stat) - return - - var/list/obj/item/used_radios = new - - switch (message_mode) - if("headset") - if(l_ear && istype(l_ear,/obj/item/device/radio)) - var/obj/item/device/radio/R = l_ear - R.talk_into(src,message,null,verb,speaking) - used_radios += l_ear - else if(r_ear && istype(r_ear,/obj/item/device/radio)) - var/obj/item/device/radio/R = r_ear - R.talk_into(src,message,null,verb,speaking) - used_radios += r_ear - - if("right ear") - var/obj/item/device/radio/R - var/has_radio = 0 - if(r_ear && istype(r_ear,/obj/item/device/radio)) - R = r_ear - has_radio = 1 - if(r_hand && istype(r_hand, /obj/item/device/radio)) - R = r_hand - has_radio = 1 - if(has_radio) - R.talk_into(src,message,null,verb,speaking) - used_radios += R - - - if("left ear") - var/obj/item/device/radio/R - var/has_radio = 0 - if(l_ear && istype(l_ear,/obj/item/device/radio)) - R = l_ear - has_radio = 1 - if(l_hand && istype(l_hand,/obj/item/device/radio)) - R = l_hand - has_radio = 1 - if(has_radio) - R.talk_into(src,message,null,verb,speaking) - used_radios += R - - if("intercom") - for(var/obj/item/device/radio/intercom/I in view(1, null)) - I.talk_into(src, message, verb, speaking) - used_radios += I - if("whisper") - whisper_say(message, speaking, alt_name) - return - if("binary") - if(robot_talk_understand || binarycheck()) - robot_talk(message) - return - if("changeling") - if(mind && mind.changeling) - var/n_message = message - log_say("Changeling Mind: [mind.changeling.changelingID]/[mind.name]/[key] : [n_message]") - for(var/mob/Changeling in mob_list) - if(Changeling.mind && Changeling.mind.changeling) - to_chat(Changeling, "[mind.changeling.changelingID]: [n_message]") - for(var/M in Changeling.mind.changeling.essences) - to_chat(M, "[mind.changeling.changelingID]: [n_message]") - - else if(isobserver(Changeling)) - to_chat(Changeling, "[mind.changeling.changelingID]: [n_message]") - return - if("alientalk") - if(mind && mind.changeling) - var/n_message = message - for(var/M in mind.changeling.essences) - to_chat(M, "[mind.changeling.changelingID]: [n_message]") - - for(var/mob/M in observer_list) - if(!M.client) - continue //skip monkeys, leavers and new players - if(M.client.prefs.chat_toggles & CHAT_GHOSTEARS) - to_chat(M, "[mind.changeling.changelingID]: [n_message]") - - to_chat(src, "[mind.changeling.changelingID]: [n_message]") - log_say("Changeling Mind: [mind.changeling.changelingID]/[mind.name]/[key] : [n_message]") - return - else - if(message_mode) - if(message_mode in (radiochannels | "department")) - if(l_ear && istype(l_ear,/obj/item/device/radio)) - l_ear.talk_into(src,message, message_mode, verb, speaking) - used_radios += l_ear - else if(r_ear && istype(r_ear,/obj/item/device/radio)) - r_ear.talk_into(src,message, message_mode, verb, speaking) - used_radios += r_ear - - var/sound/speech_sound - var/sound_vol - if((species.name == VOX || species.name == VOX_ARMALIS) && prob(20)) - speech_sound = sound('sound/voice/shriek1.ogg') - sound_vol = 50 - - ..(message, speaking, verb, alt_name, italics, message_range, used_radios, speech_sound, sound_vol, sanitize = FALSE, message_mode = message_mode) //ohgod we should really be passing a datum here. - -/mob/living/carbon/human/say_understands(mob/other,datum/language/speaking = null) - - 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)) - if(other.languages.len >= 2) //They've sucked down some blood and can speak common now. - return 1 - if (istype(other, /mob/living/silicon)) - return 1 - if (istype(other, /mob/living/carbon/brain)) - return 1 - if (istype(other, /mob/living/carbon/slime)) - return 1 - - //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/GetVoice() - if(istype(src.wear_mask, /obj/item/clothing/mask/gas/voice)) - var/obj/item/clothing/mask/gas/voice/V = src.wear_mask - if(V.vchange) - return V.voice - else - return name - if(mind && mind.changeling && mind.changeling.mimicing) - return mind.changeling.mimicing - if(special_voice) - return special_voice - return real_name - -/* - ***Deprecated*** - let this be handled at the hear_say or hear_radio proc - This is left in for robot speaking when humans gain binary channel access until I get around to rewriting - robot_talk() proc. - There is no language handling build into it however there is at the /mob level so we accept the call - for it but just ignore it. -*/ - -/mob/living/carbon/human/say_quote(message, datum/language/speaking = null) - var/verb = "says" - var/ending = copytext(message, length(message)) - - if(speaking) - verb = speaking.get_spoken_verb(ending) - else - if(ending == "!") - verb=pick("exclaims","shouts","yells") - else if(ending == "?") - verb="asks" - - return verb - - - - -//mob/living/carbon/human/proc/handle_speech_problems(message) -/mob/living/carbon/human/proc/handle_speech_problems(message, message_mode) - var/list/returns[3] - var/verb = "says" - var/handled = 0 - if(silent) - if(message_mode != "changeling") - message = "" - handled = 1 - if(sdisabilities & MUTE) - message = "" - handled = 1 - if(wear_mask) - if(message_mode != "changeling") - message = wear_mask.speechModification(message) - handled = 1 - - if((HULK in mutations) && health >= 25 && length(message)) - message = "[uppertext_(message)]!!!" - verb = pick("yells","roars","hollers") - handled = 1 - if(slurring) - message = slur(message) - verb = pick("stammers","stutters") - handled = 1 - if (stuttering) - message = stutter(message) - verb = pick("stammers","stutters") - handled = 1 - - var/braindam = getBrainLoss() - if(braindam >= 60) - handled = 1 - if(prob(braindam/4)) - message = stutter(message) - verb = pick("stammers", "stutters") - if(prob(braindam)) - message = uppertext_(message) - verb = pick("yells like an idiot","says rather loudly") - - returns[1] = message - returns[2] = verb - returns[3] = handled - - return returns +/mob/living/carbon/human/say(message, ignore_appearance) + var/verb = "says" + var/message_range = world.view + var/italics = 0 + var/alt_name = "" + if(client) + if(client.prefs.muted & MUTE_IC) + to_chat(src, "You cannot speak in IC (Muted).") + return + + //Meme stuff + if((!speech_allowed && usr == src) || miming) + to_chat(usr, "You can't speak.") + return + + message = sanitize(message) + + if(stat == DEAD) + if(fake_death) //Our changeling with fake_death status must not speak in dead chat!! + return + return say_dead(message) + + var/message_mode = parse_message_mode(message, "headset") + + if (istype(wear_mask, /obj/item/clothing/mask/muzzle) && !(message_mode == "changeling" || message_mode == "alientalk")) //Todo: Add this to speech_problem_flag checks. + return + + if(copytext(message,1,2) == "*") + return emote(copytext(message,2)) + + if(!ignore_appearance && name != GetVoice()) + alt_name = "(as [get_id_name("Unknown")])" + + //parse the radio code and consume it + if (message_mode) + if (message_mode == "headset") + message = copytext(message,2) //it would be really nice if the parse procs could do this for us. + else + message = copytext(message,3) + + //parse the language code and consume it or use default racial language if forced. + var/datum/language/speaking = parse_language(message) + if (speaking) + message = copytext(message,2+length(speaking.key)) + else if(species.force_racial_language) + speaking = all_languages[species.language] + else + switch(species.name) + if(TAJARAN) + message = replacetext(message, "", pick(list("" , ""))) + message = replacetext(message, "", pick(list("" , ""))) + if(UNATHI) + message = replacetext(message, "", pick(list("" , ""))) + // ... . , . + message = replacetext(message, "", pick(list("" , ""))) + if(ABDUCTOR) + var/mob/living/carbon/human/user = usr + var/sm = sanitize(message) + for(var/mob/living/carbon/human/H in human_list) + if(H.species.name != ABDUCTOR) + continue + if(user.team != H.team) + continue + to_chat(H, text("[user.real_name]: [sm]", user.team)) + //return - technically you can add more aliens to a team + for(var/mob/M in observer_list) + to_chat(M, text("[user.real_name]: [sm]", user.team)) + log_say("Abductor: [name]/[key] : [sm]") + return "" + + message = capitalize(trim(message)) + if(iszombie(src)) + message = zombie_talk(message) + + var/ending = copytext(message, length(message)) + if (speaking) + //If we've gotten this far, keep going! + verb = speaking.get_spoken_verb(ending) + else + if(ending=="!") + verb=pick("exclaims","shouts","yells") + if(ending=="?") + verb="asks" + + if(speech_problem_flag) + var/list/handle_r = handle_speech_problems(message, message_mode) + //var/list/handle_r = handle_speech_problems(message) + message = handle_r[1] + verb = handle_r[2] + speech_problem_flag = handle_r[3] + + if(!message || stat) + return + + var/list/obj/item/used_radios = new + + switch (message_mode) + if("headset") + if(l_ear && istype(l_ear,/obj/item/device/radio)) + var/obj/item/device/radio/R = l_ear + R.talk_into(src,message,null,verb,speaking) + used_radios += l_ear + else if(r_ear && istype(r_ear,/obj/item/device/radio)) + var/obj/item/device/radio/R = r_ear + R.talk_into(src,message,null,verb,speaking) + used_radios += r_ear + + if("right ear") + var/obj/item/device/radio/R + var/has_radio = 0 + if(r_ear && istype(r_ear,/obj/item/device/radio)) + R = r_ear + has_radio = 1 + if(r_hand && istype(r_hand, /obj/item/device/radio)) + R = r_hand + has_radio = 1 + if(has_radio) + R.talk_into(src,message,null,verb,speaking) + used_radios += R + + + if("left ear") + var/obj/item/device/radio/R + var/has_radio = 0 + if(l_ear && istype(l_ear,/obj/item/device/radio)) + R = l_ear + has_radio = 1 + if(l_hand && istype(l_hand,/obj/item/device/radio)) + R = l_hand + has_radio = 1 + if(has_radio) + R.talk_into(src,message,null,verb,speaking) + used_radios += R + + if("intercom") + for(var/obj/item/device/radio/intercom/I in view(1, null)) + I.talk_into(src, message, verb, speaking) + used_radios += I + if("whisper") + whisper_say(message, speaking, alt_name) + return + if("binary") + if(robot_talk_understand || binarycheck()) + robot_talk(message) + return + if("changeling") + if(mind && mind.changeling) + var/n_message = message + log_say("Changeling Mind: [mind.changeling.changelingID]/[mind.name]/[key] : [n_message]") + for(var/mob/Changeling in mob_list) + if(Changeling.mind && Changeling.mind.changeling) + to_chat(Changeling, "[mind.changeling.changelingID]: [n_message]") + for(var/M in Changeling.mind.changeling.essences) + to_chat(M, "[mind.changeling.changelingID]: [n_message]") + + else if(isobserver(Changeling)) + to_chat(Changeling, "[mind.changeling.changelingID]: [n_message]") + return + if("alientalk") + if(mind && mind.changeling) + var/n_message = message + for(var/M in mind.changeling.essences) + to_chat(M, "[mind.changeling.changelingID]: [n_message]") + + for(var/mob/M in observer_list) + if(!M.client) + continue //skip monkeys, leavers and new players + if(M.client.prefs.chat_toggles & CHAT_GHOSTEARS) + to_chat(M, "[mind.changeling.changelingID]: [n_message]") + + to_chat(src, "[mind.changeling.changelingID]: [n_message]") + log_say("Changeling Mind: [mind.changeling.changelingID]/[mind.name]/[key] : [n_message]") + return + else + if(message_mode) + if(message_mode in (radiochannels | "department")) + if(l_ear && istype(l_ear,/obj/item/device/radio)) + l_ear.talk_into(src,message, message_mode, verb, speaking) + used_radios += l_ear + else if(r_ear && istype(r_ear,/obj/item/device/radio)) + r_ear.talk_into(src,message, message_mode, verb, speaking) + used_radios += r_ear + + var/sound/speech_sound + var/sound_vol + if((species.name == VOX || species.name == VOX_ARMALIS) && prob(20)) + speech_sound = sound('sound/voice/shriek1.ogg') + sound_vol = 50 + + ..(message, speaking, verb, alt_name, italics, message_range, used_radios, speech_sound, sound_vol, sanitize = FALSE, message_mode = message_mode) //ohgod we should really be passing a datum here. + +/mob/living/carbon/human/say_understands(mob/other,datum/language/speaking = null) + + 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)) + if(other.languages.len >= 2) //They've sucked down some blood and can speak common now. + return 1 + if (istype(other, /mob/living/silicon)) + return 1 + if (istype(other, /mob/living/carbon/brain)) + return 1 + if (istype(other, /mob/living/carbon/slime)) + return 1 + + //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/GetVoice() + if(istype(src.wear_mask, /obj/item/clothing/mask/gas/voice)) + var/obj/item/clothing/mask/gas/voice/V = src.wear_mask + if(V.vchange) + return V.voice + else + return name + if(mind && mind.changeling && mind.changeling.mimicing) + return mind.changeling.mimicing + if(special_voice) + return special_voice + return real_name + +/* + ***Deprecated*** + let this be handled at the hear_say or hear_radio proc + This is left in for robot speaking when humans gain binary channel access until I get around to rewriting + robot_talk() proc. + There is no language handling build into it however there is at the /mob level so we accept the call + for it but just ignore it. +*/ + +/mob/living/carbon/human/say_quote(message, datum/language/speaking = null) + var/verb = "says" + var/ending = copytext(message, length(message)) + + if(speaking) + verb = speaking.get_spoken_verb(ending) + else + if(ending == "!") + verb=pick("exclaims","shouts","yells") + else if(ending == "?") + verb="asks" + + return verb + + + + +//mob/living/carbon/human/proc/handle_speech_problems(message) +/mob/living/carbon/human/proc/handle_speech_problems(message, message_mode) + var/list/returns[3] + var/verb = "says" + var/handled = 0 + if(silent) + if(message_mode != "changeling") + message = "" + handled = 1 + if(sdisabilities & MUTE) + message = "" + handled = 1 + if(wear_mask) + if(message_mode != "changeling") + message = wear_mask.speechModification(message) + handled = 1 + + if((HULK in mutations) && health >= 25 && length(message)) + message = "[uppertext_(message)]!!!" + verb = pick("yells","roars","hollers") + handled = 1 + if(slurring) + message = slur(message) + verb = pick("stammers","stutters") + handled = 1 + if (stuttering) + message = stutter(message) + verb = pick("stammers","stutters") + handled = 1 + + var/braindam = getBrainLoss() + if(braindam >= 60) + handled = 1 + if(prob(braindam/4)) + message = stutter(message) + verb = pick("stammers", "stutters") + if(prob(braindam)) + message = uppertext_(message) + verb = pick("yells like an idiot","says rather loudly") + + returns[1] = message + returns[2] = verb + returns[3] = handled + + return returns diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 3462409e3023..8c01a3150367 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1,945 +1,945 @@ - /////////////////////// - //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 - UpdateDamageIcon() //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() - update_inv_l_hand() - update_inv_r_hand() //<---calls update_icons() - - or equivillantly: - update_inv_head() - update_inv_l_hand() - update_inv_r_hand() - 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 -*/ - -//Human Overlays Indexes///////// -#define BODY_LAYER 27 -#define MUTANTRACE_LAYER 26 -#define MUTATIONS_LAYER 25 -#define DAMAGE_LAYER 24 -#define SURGERY_LAYER 23 //bs12 specific. -#define BANDAGE_LAYER 22 -#define UNIFORM_LAYER 21 -#define ID_LAYER 20 -#define SHOES_LAYER 19 -#define TAIL_LAYER 18 //bs12 specific. this hack is probably gonna come back to haunt me -#define GLOVES_LAYER 17 -#define EARS_LAYER 16 -#define SUIT_LAYER 15 -#define GLASSES_LAYER 14 -#define BELT_LAYER 13 //Possible make this an overlay of somethign required to wear a belt? -#define SUIT_STORE_LAYER 12 -#define BACK_LAYER 11 -#define HAIR_LAYER 10 //TODO: make part of head layer? -#define FACEMASK_LAYER 9 -#define HEAD_LAYER 8 -#define COLLAR_LAYER 7 -#define HANDCUFF_LAYER 6 -#define LEGCUFF_LAYER 5 -#define L_HAND_LAYER 4 -#define R_HAND_LAYER 3 -#define TARGETED_LAYER 2 //BS12: Layer for the target overlay from weapon targeting system -#define FIRE_LAYER 1 -#define TOTAL_LAYERS 27 -////////////////////////////////// -//Human Limb Overlays Indexes///// -#define LIMB_HEAD_LAYER 7 -#define LIMB_TORSO_LAYER 6 -#define LIMB_L_ARM_LAYER 5 -#define LIMB_R_ARM_LAYER 4 -#define LIMB_GROIN_LAYER 3 -#define LIMB_L_LEG_LAYER 2 -#define LIMB_R_LEG_LAYER 1 -#define TOTAL_LIMB_LAYERS 7 -////////////////////////////////// - -/mob/living/carbon/human - var/list/overlays_standing[TOTAL_LAYERS] - var/list/overlays_damage[TOTAL_LIMB_LAYERS] - -/mob/living/carbon/human/proc/apply_overlay(cache_index) - var/image/I = overlays_standing[cache_index] - if(I) - overlays += I - -/mob/living/carbon/human/proc/remove_overlay(cache_index) - if(overlays_standing[cache_index]) - overlays -= overlays_standing[cache_index] - overlays_standing[cache_index] = null - -/mob/living/carbon/human/proc/apply_damage_overlay(cache_index) - var/image/I = overlays_damage[cache_index] - if(I) - overlays += I - -/mob/living/carbon/human/proc/remove_damage_overlay(cache_index) - if(overlays_damage[cache_index]) - overlays -= overlays_damage[cache_index] - overlays_damage[cache_index] = null - -//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 - - -//DAMAGE OVERLAYS -/mob/living/carbon/human/UpdateDamageIcon(obj/item/organ/external/BP) - remove_damage_overlay(BP.limb_layer) - if(species.damage_mask && !(BP.status & ORGAN_DESTROYED)) - var/image/standing = image("icon" = 'icons/mob/human_races/damage_overlays.dmi', "icon_state" = "[BP.body_zone]_[BP.damage_state]", "layer" = -DAMAGE_LAYER) - var/datum/dirt_cover/mob = new species.blood_color() - standing.color = mob.color - overlays_damage[BP.limb_layer] = standing - apply_damage_overlay(BP.limb_layer) - - -//BASE MOB SPRITE -/mob/living/carbon/human/proc/update_body() - remove_overlay(BODY_LAYER) - var/list/standing = list() - - var/fat = (FAT in mutations) ? "fat" : null - var/g = (gender == FEMALE ? "f" : "m") - - var/mutable_appearance/base_icon = mutable_appearance(null, null, -BODY_LAYER) - var/race_icon = species.icobase - var/deform_icon = species.deform - - for(var/obj/item/organ/external/BP in bodyparts) - - var/mutable_appearance/temp //Hold the bodypart icon for processing. - - if(BP.status & ORGAN_DESTROYED) - continue - - if(BP.body_zone == BP_CHEST) - temp = BP.get_icon(race_icon, deform_icon, g, fat) - else if (BP.body_zone == BP_GROIN || BP.body_zone == BP_HEAD) - temp = BP.get_icon(race_icon, deform_icon, g) - else - temp = BP.get_icon(race_icon, deform_icon) - - base_icon.overlays += temp - - standing += base_icon - - //Underwear - if((underwear > 0) && (underwear < 12) && species.flags[HAS_UNDERWEAR]) - if(!fat) - standing += mutable_appearance('icons/mob/human.dmi', "underwear[underwear]_[g]_s", -BODY_LAYER) - - if((undershirt > 0) && (undershirt < undershirt_t.len) && species.flags[HAS_UNDERWEAR]) - if(!fat) - standing += mutable_appearance('icons/mob/human_undershirt.dmi', "undershirt[undershirt]_s", -BODY_LAYER) - - if(!fat && socks > 0 && socks < socks_t.len && species.flags[HAS_UNDERWEAR]) - var/obj/item/organ/external/r_foot = bodyparts_by_name[BP_R_LEG] - var/obj/item/organ/external/l_foot = bodyparts_by_name[BP_L_LEG] - if(r_foot && !(r_foot.status & ORGAN_DESTROYED) && l_foot && !(l_foot.status & ORGAN_DESTROYED)) - standing += mutable_appearance('icons/mob/human_socks.dmi', "socks[socks]_s", -BODY_LAYER) - - update_tail_showing() - overlays_standing[BODY_LAYER] = standing - apply_overlay(BODY_LAYER) - - - -//HAIR OVERLAY -/mob/living/carbon/human/proc/update_hair() - //Reset our hair - remove_overlay(HAIR_LAYER) - - var/obj/item/organ/external/head/BP = bodyparts_by_name[BP_HEAD] - if(!BP || (BP.status & ORGAN_DESTROYED)) - return - - //masks and helmets can obscure our hair. - if((HUSK in mutations) || (head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR)) || (wear_suit && (wear_suit.flags & BLOCKHAIR))) - return - - //base icons - var/list/standing = list() - - if(f_style) - var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if(facial_hair_style && facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed)) - var/image/facial_s = image("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s", "layer" = -HAIR_LAYER) - if(facial_hair_style.do_colouration) - if(!facial_painted) - facial_s.color = RGB_CONTRAST(r_facial, g_facial, b_facial) - else - facial_s.color = RGB_CONTRAST(dyed_r_facial, dyed_g_facial, dyed_b_facial) - standing += facial_s - - if(h_style && !(head && (head.flags & BLOCKHEADHAIR))) - var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] - if(hair_style && hair_style.species_allowed && (species.name in hair_style.species_allowed)) - var/image/hair_s = image("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s", "layer" = -HAIR_LAYER) - if(hair_style.do_colouration) - if(!hair_painted) - hair_s.color = RGB_CONTRAST(r_hair, g_hair, b_hair) - else - hair_s.color = RGB_CONTRAST(dyed_r_hair, dyed_g_hair, dyed_b_hair) - standing += hair_s - - if(standing.len) - overlays_standing[HAIR_LAYER] = standing - - if(istype(wear_suit, /obj/item/clothing/suit/wintercoat)) - var/obj/item/clothing/suit/wintercoat/W = wear_suit - if(W.hooded) // used for coat hood due to hair layer viewed over the suit - overlays_standing[HAIR_LAYER] = null - - apply_overlay(HAIR_LAYER) - - -/mob/living/carbon/human/update_mutations() - remove_overlay(MUTATIONS_LAYER) - var/fat - if(FAT in mutations) - fat = "fat" - - var/list/standing = list() - var/g = (gender == FEMALE) ? "f" : "m" - - for(var/datum/dna/gene/gene in dna_genes) - if(!gene.block) - continue - if(gene.is_active(src)) - var/image/underlay = image("icon"='icons/effects/genetics.dmi', "icon_state"=gene.OnDrawUnderlays(src,g,fat), "layer"=-MUTATIONS_LAYER) - if(underlay) - standing += underlay - for(var/mut in mutations) - switch(mut) - /* - if(HULK) - if(fat) - standing.underlays += "hulk_[fat]_s" - else - standing.underlays += "hulk_[g]_s" - if(COLD_RESISTANCE) - standing.underlays += "fire[fat]_s" - if(TK) - standing.underlays += "telekinesishead[fat]_s" - */ - if(LASEREYES) - standing += image("icon"='icons/effects/genetics.dmi', "icon_state"="lasereyes_s", "layer"=-MUTATIONS_LAYER) - if(standing.len) - overlays_standing[MUTATIONS_LAYER] = standing - - apply_overlay(MUTATIONS_LAYER) - - -/mob/living/carbon/human/proc/update_mutantrace() - remove_overlay(MUTANTRACE_LAYER) - - var/fat - if(FAT in mutations) - fat = "fat" - - var/list/standing = list() - if(dna) - switch(dna.mutantrace) - if("slime") - standing += image('icons/effects/genetics.dmi', null, "[dna.mutantrace][fat]_[gender]_[species.name]_s", -MUTANTRACE_LAYER) - if("golem" , "shadow") - standing += image('icons/effects/genetics.dmi', null, "[dna.mutantrace][fat]_[gender]_s", -MUTANTRACE_LAYER) - - if(species.name == SHADOWLING && head) - var/image/eyes = image('icons/mob/shadowling.dmi', null, "[dna.mutantrace]_ms_s", LIGHTING_LAYER + 1) - eyes.plane = LIGHTING_PLANE + 1 - standing += eyes - - if(iszombie(src) && stat != DEAD) - var/image/eyes = image(species.icobase, null, "zombie_ms_s", LIGHTING_LAYER + 1) - eyes.plane = LIGHTING_PLANE + 1 - standing += eyes - - if(!dna || !(dna.mutantrace == "golem")) - update_body() - - if(standing.len) - overlays_standing[MUTANTRACE_LAYER] = standing - - update_hair() - - apply_overlay(MUTANTRACE_LAYER) - - -//Call when target overlay should be added/removed -/mob/living/carbon/human/update_targeted() - remove_overlay(TARGETED_LAYER) - - if(targeted_by && target_locked) - overlays_standing[TARGETED_LAYER] = image("icon"=target_locked, "layer"=-TARGETED_LAYER) - else if (!targeted_by && target_locked) - qdel(target_locked) - - apply_overlay(TARGETED_LAYER) - - -/mob/living/carbon/human/update_fire() //TG-stuff, fire layer - remove_overlay(FIRE_LAYER) - - if(on_fire) - overlays_standing[FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing", "layer"=-FIRE_LAYER) - - apply_overlay(FIRE_LAYER) - - -/* --------------------------------------- */ -//For legacy support. -/mob/living/carbon/human/regenerate_icons() - ..() - if(monkeyizing) return - update_hair() - update_mutations() - update_mutantrace() - update_inv_w_uniform() - update_inv_wear_id() - update_inv_gloves() - update_inv_glasses() - update_inv_ears() - update_inv_shoes() - update_inv_s_store() - update_inv_wear_mask() - update_inv_head() - update_inv_belt() - update_inv_back() - update_inv_wear_suit() - update_inv_r_hand() - update_inv_l_hand() - update_inv_handcuffed() - update_inv_legcuffed() - update_inv_pockets() - update_surgery() - update_bandage() - for(var/obj/item/organ/external/BP in bodyparts) - UpdateDamageIcon(BP) - update_icons() - update_transform() - //Hud Stuff - update_hud() - - -/* --------------------------------------- */ -//vvvvvv UPDATE_INV PROCS vvvvvv - -/mob/living/carbon/human/update_inv_w_uniform() - remove_overlay(UNIFORM_LAYER) - - if(istype(w_uniform, /obj/item/clothing/under)) - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - w_uniform.screen_loc = ui_iclothing //...draw the item in the inventory screen - client.screen += w_uniform //Either way, add the item to the HUD - - var/obj/item/clothing/under/U = w_uniform - var/t_color = U.item_color - if(!t_color) t_color = icon_state - var/image/standing = image("icon_state"="[t_color]_s", "layer"=-UNIFORM_LAYER) - if(!U.icon_custom || U.icon_override || species.sprite_sheets["uniform"]) - standing.icon = (U.icon_override ? U.icon_override : (species.sprite_sheets["uniform"] ? species.sprite_sheets["uniform"] : 'icons/mob/uniform.dmi')) - else - standing = image("icon"=U.icon_custom, "icon_state"="[t_color]_mob", "layer"=-UNIFORM_LAYER) - standing.color = U.color - overlays_standing[UNIFORM_LAYER] = standing - - if(U.dirt_overlay) - var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="uniformblood") - bloodsies.color = U.dirt_overlay.color - standing.overlays += bloodsies - - if(U.accessories.len) - for(var/obj/item/clothing/accessory/A in w_uniform:accessories) - var/tie_color = A.item_color - if(!tie_color) - tie_color = A.icon_state - var/image/tie - if(A.icon_custom) - tie = image("icon" = A.icon_custom, "icon_state" = "[tie_color]_mob", "layer" = -UNIFORM_LAYER + A.layer_priority) - else - tie = image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]", "layer" = -UNIFORM_LAYER + A.layer_priority) - tie.color = A.color - standing.overlays += tie - - if(FAT in mutations) - if(U.flags & ONESIZEFITSALL) - standing.icon = 'icons/mob/uniform_fat.dmi' - else - to_chat(src, "\red You burst out of \the [U]!") - drop_from_inventory(U) - return - - else - // 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)) // - drop_from_inventory(thing) - - apply_overlay(UNIFORM_LAYER) - - -/mob/living/carbon/human/update_inv_wear_id() - remove_overlay(ID_LAYER) - if(wear_id) - wear_id.screen_loc = ui_id - if(client && hud_used) - client.screen += wear_id - - overlays_standing[ID_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="id", "layer"=-ID_LAYER) - - hud_updateflag |= 1 << ID_HUD - hud_updateflag |= 1 << WANTED_HUD - - apply_overlay(ID_LAYER) - - -/mob/living/carbon/human/update_inv_gloves() - remove_overlay(GLOVES_LAYER) - if(gloves) - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - gloves.screen_loc = ui_gloves //...draw the item in the inventory screen - client.screen += gloves //Either way, add the item to the HUD - - var/t_state = gloves.item_state - if(!t_state) t_state = gloves.icon_state - var/image/standing - if(!gloves:icon_custom || gloves.icon_override || species.sprite_sheets["gloves"]) - standing = image("icon"=((gloves.icon_override) ? gloves.icon_override : (species.sprite_sheets["gloves"] ? species.sprite_sheets["gloves"] : 'icons/mob/hands.dmi')), "icon_state"="[t_state]", "layer"=-GLOVES_LAYER) - else - standing = image("icon"=gloves:icon_custom, "icon_state"="[t_state]_mob", "layer"=-GLOVES_LAYER) - standing.color = gloves.color - overlays_standing[GLOVES_LAYER] = standing - - if(gloves.dirt_overlay) - var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands") - bloodsies.color = gloves.dirt_overlay.color - standing.overlays += bloodsies - else - if(blood_DNA) - var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands") - bloodsies.color = hand_dirt_color.color - overlays_standing[GLOVES_LAYER] = bloodsies - - apply_overlay(GLOVES_LAYER) - - -/mob/living/carbon/human/update_inv_glasses() - remove_overlay(GLASSES_LAYER) - - if(glasses) - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - glasses.screen_loc = ui_glasses //...draw the item in the inventory screen - client.screen += glasses //Either way, add the item to the HUD - var/image/standing - if(!glasses:icon_custom || glasses.icon_override || species.sprite_sheets["eyes"]) - standing = image("icon"=((glasses.icon_override) ? glasses.icon_override : (species.sprite_sheets["eyes"] ? species.sprite_sheets["eyes"] : 'icons/mob/eyes.dmi')), "icon_state"="[glasses.icon_state]", "layer"=-GLASSES_LAYER) - else - standing = image("icon"=glasses:icon_custom, "icon_state"="[glasses.icon_state]_mob", "layer"=-GLASSES_LAYER) - standing.color = glasses.color - overlays_standing[GLASSES_LAYER] = standing - - apply_overlay(GLASSES_LAYER) - - -/mob/living/carbon/human/update_inv_ears() - remove_overlay(EARS_LAYER) - - if(l_ear || r_ear) - if(l_ear) - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - l_ear.screen_loc = ui_l_ear //...draw the item in the inventory screen - client.screen += l_ear //Either way, add the item to the HUD - var/image/standing - if(!l_ear:icon_custom || l_ear.icon_override || species.sprite_sheets["ears"]) - standing = image("icon"=((l_ear.icon_override) ? l_ear.icon_override : (species.sprite_sheets["ears"] ? species.sprite_sheets["ears"] : 'icons/mob/ears.dmi')), "icon_state"="[l_ear.icon_state]", "layer"=-EARS_LAYER) - else - standing = image("icon"=l_ear:icon_custom, "icon_state"="[l_ear.icon_state]_mob", "layer"=-EARS_LAYER) - standing.color = l_ear.color - overlays_standing[EARS_LAYER] = standing - if(r_ear) - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - r_ear.screen_loc = ui_r_ear //...draw the item in the inventory screen - client.screen += r_ear //Either way, add the item to the HUD - var/image/standing - if(!r_ear:icon_custom || r_ear.icon_override || species.sprite_sheets["ears"]) - standing = image("icon"=((r_ear.icon_override) ? r_ear.icon_override : (species.sprite_sheets["ears"] ? species.sprite_sheets["ears"] : 'icons/mob/ears.dmi')), "icon_state"="[r_ear.icon_state]", "layer"=-EARS_LAYER) - else - standing = image("icon"=r_ear:icon_custom, "icon_state"="[r_ear.icon_state]_mob", "layer"=-EARS_LAYER) - standing.color = r_ear.color - overlays_standing[EARS_LAYER] = standing - - apply_overlay(EARS_LAYER) - - -/mob/living/carbon/human/update_inv_shoes() - remove_overlay(SHOES_LAYER) - - if(shoes) - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - shoes.screen_loc = ui_shoes //...draw the item in the inventory screen - client.screen += shoes //Either way, add the item to the HUD - - var/image/standing - if(!shoes:icon_custom || shoes.icon_override || species.sprite_sheets["feet"]) - standing = image("icon"=((shoes.icon_override) ? shoes.icon_override : (species.sprite_sheets["feet"] ? species.sprite_sheets["feet"] : 'icons/mob/feet.dmi')), "icon_state"="[shoes.icon_state]", "layer"=-SHOES_LAYER) - else - standing = image("icon"=shoes:icon_custom, "icon_state"="[shoes.icon_state]_mob", "layer"=-SHOES_LAYER) - standing.color = shoes.color - overlays_standing[SHOES_LAYER] = standing - - if(shoes.dirt_overlay) - var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="shoeblood") - bloodsies.color = shoes.dirt_overlay.color - standing.overlays += bloodsies - else - if(feet_blood_DNA) - var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="shoeblood") - bloodsies.color = feet_dirt_color.color - overlays_standing[SHOES_LAYER] = bloodsies - else - overlays_standing[SHOES_LAYER] = null - - apply_overlay(SHOES_LAYER) - - -/mob/living/carbon/human/update_inv_s_store() - remove_overlay(SUIT_STORE_LAYER) - - if(s_store) - s_store.screen_loc = ui_sstore1 - if(client && hud_used) - client.screen += s_store - - var/t_state = s_store.item_state - if(!t_state) t_state = s_store.icon_state - var/image/standing = image("icon"='icons/mob/belt_mirror.dmi', "icon_state"="[t_state]", "layer"=-SUIT_STORE_LAYER) - standing.color = s_store.color - overlays_standing[SUIT_STORE_LAYER] = standing - - apply_overlay(SUIT_STORE_LAYER) - - -/mob/living/carbon/human/update_inv_head() - remove_overlay(HEAD_LAYER) - - if(head) - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - head.screen_loc = ui_head //...draw the item in the inventory screen - client.screen += head //Either way, add the item to the HUD - - var/image/standing - if(istype(head,/obj/item/clothing/head/kitty)) - var/obj/item/clothing/head/kitty/K = head - standing = image("icon"=K.mob, "layer"=-HEAD_LAYER) - else - if(!head:icon_custom || head.icon_override || species.sprite_sheets["head"]) - standing = image("icon"=((head.icon_override) ? head.icon_override : (species.sprite_sheets["head"] ? species.sprite_sheets["head"] : 'icons/mob/head.dmi')), "icon_state"="[head.icon_state]", "layer"=-HEAD_LAYER) - else - standing = image("icon"=head:icon_custom, "icon_state"="[head.icon_state]_mob", "layer"=-HEAD_LAYER) - standing.color = head.color - overlays_standing[HEAD_LAYER] = standing - - if(head.dirt_overlay) - var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="helmetblood") - bloodsies.color = head.dirt_overlay.color - standing.overlays += bloodsies - - apply_overlay(HEAD_LAYER) - - -/mob/living/carbon/human/update_inv_belt() - remove_overlay(BELT_LAYER) - - if(belt) - belt.screen_loc = ui_belt - if(client && hud_used) - client.screen += belt - - var/t_state = belt.item_state - if(!t_state) t_state = belt.icon_state - var/image/standing - if(!belt:icon_custom || belt.icon_override || species.sprite_sheets["belt"]) - standing = image("icon"=((belt.icon_override) ? belt.icon_override : (species.sprite_sheets["belt"] ? species.sprite_sheets["belt"] : 'icons/mob/belt.dmi')), "icon_state"="[t_state]", "layer"=-BELT_LAYER) - else - standing = image("icon"=belt:icon_custom, "icon_state"="[belt.icon_state]_mob", "layer"=-BELT_LAYER) - standing.color = belt.color - overlays_standing[BELT_LAYER] = standing - apply_overlay(BELT_LAYER) - -/mob/living/carbon/human/update_inv_wear_suit() - remove_overlay(SUIT_LAYER) - - if(istype(wear_suit, /obj/item/clothing/suit)) - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - wear_suit.screen_loc = ui_oclothing //...draw the item in the inventory screen - client.screen += wear_suit //Either way, add the item to the HUD - - var/image/standing - if(!wear_suit:icon_custom || wear_suit.icon_override || species.sprite_sheets["suit"]) - standing = image("icon"=((wear_suit.icon_override) ? wear_suit.icon_override : (species.sprite_sheets["suit"] ? species.sprite_sheets["suit"] : 'icons/mob/suit.dmi')), "icon_state"="[wear_suit.icon_state]", "layer"=-SUIT_LAYER) - else - standing = image("icon"=wear_suit:icon_custom, "icon_state"="[wear_suit.icon_state]_mob", "layer"=-SUIT_LAYER) - - if(wear_suit.dirt_overlay) - 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.dirt_overlay.color - standing.overlays += bloodsies - standing.color = wear_suit.color - overlays_standing[SUIT_LAYER] = standing - - if(istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) - drop_from_inventory(handcuffed) - drop_l_hand() - drop_r_hand() - - if(FAT in mutations) - if(!(wear_suit.flags & ONESIZEFITSALL)) - to_chat(src, "\red You burst out of \the [wear_suit]!") - drop_from_inventory(wear_suit) - return - - if(istype(wear_suit,/obj/item/clothing/suit/wintercoat)) - var/obj/item/clothing/suit/wintercoat/W = wear_suit - if(W.hooded) //used for coat hood due to hair layer viewed over the suit - overlays_standing[HAIR_LAYER] = null - overlays_standing[HEAD_LAYER] = null - - update_inv_shoes() - - update_tail_showing() - update_collar() - - apply_overlay(SUIT_LAYER) - - -/mob/living/carbon/human/update_inv_pockets() - if(l_store) - l_store.screen_loc = ui_storage1 - if(client && hud_used) - client.screen += l_store - if(r_store) - r_store.screen_loc = ui_storage2 - if(client && hud_used) - client.screen += r_store - - -/mob/living/carbon/human/update_inv_wear_mask() - remove_overlay(FACEMASK_LAYER) - - if(istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory)) - if(client && hud_used && hud_used.hud_shown) - if(hud_used.inventory_shown) //if the inventory is open ... - wear_mask.screen_loc = ui_mask //...draw the item in the inventory screen - client.screen += wear_mask //Either way, add the item to the HUD - - var/image/standing - if(!wear_mask:icon_custom || wear_mask.icon_override || species.sprite_sheets["mask"]) - standing = image("icon"=((wear_mask.icon_override) ? wear_mask.icon_override : (species.sprite_sheets["mask"] ? species.sprite_sheets["mask"] : 'icons/mob/mask.dmi')), "icon_state"="[wear_mask.icon_state]", "layer"=-FACEMASK_LAYER) - else - standing = image("icon"=wear_mask:icon_custom, "icon_state"="[wear_mask.icon_state]_mob", "layer"=-FACEMASK_LAYER) - standing.color = wear_mask.color - overlays_standing[FACEMASK_LAYER] = standing - - if(wear_mask.dirt_overlay && !istype(wear_mask, /obj/item/clothing/mask/cigarette)) - var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="maskblood") - bloodsies.color = wear_mask.dirt_overlay.color - standing.overlays += bloodsies - - apply_overlay(FACEMASK_LAYER) - - -/mob/living/carbon/human/update_inv_back() - remove_overlay(BACK_LAYER) - - if(back) - back.screen_loc = ui_back - if(client && hud_used && hud_used.hud_shown) - client.screen += back - var/image/standing - if(!back:icon_custom || back.icon_override || species.sprite_sheets["back"]) - standing = image("icon"=((back.icon_override) ? back.icon_override : (species.sprite_sheets["back"] ? species.sprite_sheets["back"] : 'icons/mob/back.dmi')), "icon_state"="[back.icon_state]", "layer"=-BACK_LAYER) - else - standing = image("icon"=back:icon_custom, "icon_state"="[back.icon_state]_mob", "layer"=-BACK_LAYER) - standing.color = back.color - overlays_standing[BACK_LAYER] = standing - apply_overlay(BACK_LAYER) - - -/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 - hud_used.reload_fullscreen() - - -/mob/living/carbon/human/update_inv_handcuffed() - remove_overlay(HANDCUFF_LAYER) - - if(handcuffed) - drop_r_hand() - drop_l_hand() - stop_pulling() //TODO: should be handled elsewhere - overlays_standing[HANDCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="handcuff1", "layer"=-HANDCUFF_LAYER) - apply_overlay(HANDCUFF_LAYER) - - -/mob/living/carbon/human/update_inv_legcuffed() - remove_overlay(LEGCUFF_LAYER) - - if(legcuffed) - 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" - - overlays_standing[LEGCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="legcuff1", "layer"=-LEGCUFF_LAYER) - - apply_overlay(LEGCUFF_LAYER) - - -/mob/living/carbon/human/update_inv_r_hand() - remove_overlay(R_HAND_LAYER) - - if(r_hand) - r_hand.screen_loc = ui_rhand - if(client && hud_used) - client.screen += r_hand - - var/t_state = r_hand.item_state - if(!t_state) - t_state = r_hand.icon_state - var/image/standing - if(!r_hand:icon_custom || r_hand.icon_override || species.sprite_sheets["held"]) - if(r_hand.icon_override || species.sprite_sheets["held"]) t_state = "[t_state]_r" - standing = image("icon"=((r_hand.icon_override) ? r_hand.icon_override : (species.sprite_sheets["held"] ? species.sprite_sheets["held"] : r_hand.righthand_file)), "icon_state"="[t_state]", "layer"=-R_HAND_LAYER) - else - standing = image("icon"=r_hand:icon_custom, "icon_state"="[t_state]_r", "layer"=-R_HAND_LAYER) - standing.color = r_hand.color - overlays_standing[R_HAND_LAYER] = standing - if(handcuffed) - drop_r_hand() - - apply_overlay(R_HAND_LAYER) - - -/mob/living/carbon/human/update_inv_l_hand() - remove_overlay(L_HAND_LAYER) - - if(l_hand) - l_hand.screen_loc = ui_lhand - if(client && hud_used) - client.screen += l_hand - - var/t_state = l_hand.item_state - if(!t_state) - t_state = l_hand.icon_state - var/image/standing - if(!l_hand:icon_custom || l_hand.icon_override || species.sprite_sheets["held"]) - if(l_hand.icon_override || species.sprite_sheets["held"]) t_state = "[t_state]_l" - standing = image("icon"=((l_hand.icon_override) ? l_hand.icon_override : (species.sprite_sheets["held"] ? species.sprite_sheets["held"] : l_hand.lefthand_file)), "icon_state"="[t_state]", "layer"=-L_HAND_LAYER) - else - standing = image("icon"=l_hand:icon_custom, "icon_state"="[t_state]_l", "layer"=-L_HAND_LAYER) - standing.color = l_hand.color - overlays_standing[L_HAND_LAYER] = standing - if(handcuffed) - drop_l_hand() - - apply_overlay(L_HAND_LAYER) - - -/mob/living/carbon/human/proc/update_tail_showing() - remove_overlay(TAIL_LAYER) - - if(species.tail && species.flags[HAS_TAIL] && !(HUSK in mutations)) - if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) - var/image/tail_s = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") - - var/obj/item/organ/external/chest/BP = bodyparts_by_name[BP_CHEST] - - if(BP.status & ORGAN_DEAD) - tail_s.color = NECROSIS_COLOR_MOD - else if(HULK in mutations) - tail_s.color = HULK_SKIN_COLOR - else - tail_s.color = RGB_CONTRAST(r_skin, g_skin, b_skin) - - overlays_standing[TAIL_LAYER] = image("icon" = tail_s, "layer" = -TAIL_LAYER) - - apply_overlay(TAIL_LAYER) - - -//Adds a collar overlay above the helmet layer if the suit has one -// Suit needs an identically named sprite in icons/mob/collar.dmi -/mob/living/carbon/human/proc/update_collar() - remove_overlay(COLLAR_LAYER) - - if(wear_suit) - var/icon/C = new('icons/mob/collar.dmi') - if(wear_suit.icon_state in C.IconStates()) - - var/image/standing = image("icon" = C, "icon_state" = "[wear_suit.icon_state]", "layer"=-COLLAR_LAYER) - standing.color = wear_suit.color - overlays_standing[COLLAR_LAYER] = standing - - apply_overlay(COLLAR_LAYER) - - -/mob/living/carbon/human/proc/update_surgery() - remove_overlay(SURGERY_LAYER) - - var/list/standing = list() - for(var/obj/item/organ/external/BP in bodyparts) - if(BP.open) - standing += image("icon" = 'icons/mob/surgery.dmi', "icon_state" = "[BP.body_zone][round(BP.open)]", "layer" = -SURGERY_LAYER) - - if(standing.len) - overlays_standing[SURGERY_LAYER] = standing - - apply_overlay(SURGERY_LAYER) - -/mob/living/carbon/human/proc/update_bandage() - remove_overlay(BANDAGE_LAYER) - - var/list/standing = list() - for(var/obj/item/organ/external/BP in bodyparts) - if(BP.wounds.len) - for(var/datum/wound/W in BP.wounds) - if(W.bandaged) - standing += image("icon" = 'icons/mob/bandages.dmi', "icon_state" = "[BP.body_zone]", "layer" = -BANDAGE_LAYER) - - if(standing.len) - overlays_standing[BANDAGE_LAYER] = standing - - apply_overlay(BANDAGE_LAYER) - - -/mob/living/carbon/human/proc/get_overlays_copy() - var/list/out = new - out = overlays_standing.Copy() - return out - -//Human Overlays Indexes///////// -#undef BODY_LAYER -#undef MUTANTRACE_LAYER -#undef MUTATIONS_LAYER -#undef DAMAGE_LAYER -#undef SURGERY_LAYER -#undef BANDAGE_LAYER -#undef UNIFORM_LAYER -#undef TAIL_LAYER -#undef ID_LAYER -#undef SHOES_LAYER -#undef GLOVES_LAYER -#undef EARS_LAYER -#undef SUIT_LAYER -#undef GLASSES_LAYER -#undef FACEMASK_LAYER -#undef BELT_LAYER -#undef SUIT_STORE_LAYER -#undef BACK_LAYER -#undef HAIR_LAYER -#undef HEAD_LAYER -#undef COLLAR_LAYER -#undef HANDCUFF_LAYER -#undef LEGCUFF_LAYER -#undef L_HAND_LAYER -#undef R_HAND_LAYER -#undef TARGETED_LAYER -#undef FIRE_LAYER -#undef TOTAL_LAYERS + /////////////////////// + //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 + UpdateDamageIcon() //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() + update_inv_l_hand() + update_inv_r_hand() //<---calls update_icons() + + or equivillantly: + update_inv_head() + update_inv_l_hand() + update_inv_r_hand() + 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 +*/ + +//Human Overlays Indexes///////// +#define BODY_LAYER 27 +#define MUTANTRACE_LAYER 26 +#define MUTATIONS_LAYER 25 +#define DAMAGE_LAYER 24 +#define SURGERY_LAYER 23 //bs12 specific. +#define BANDAGE_LAYER 22 +#define UNIFORM_LAYER 21 +#define ID_LAYER 20 +#define SHOES_LAYER 19 +#define TAIL_LAYER 18 //bs12 specific. this hack is probably gonna come back to haunt me +#define GLOVES_LAYER 17 +#define EARS_LAYER 16 +#define SUIT_LAYER 15 +#define GLASSES_LAYER 14 +#define BELT_LAYER 13 //Possible make this an overlay of somethign required to wear a belt? +#define SUIT_STORE_LAYER 12 +#define BACK_LAYER 11 +#define HAIR_LAYER 10 //TODO: make part of head layer? +#define FACEMASK_LAYER 9 +#define HEAD_LAYER 8 +#define COLLAR_LAYER 7 +#define HANDCUFF_LAYER 6 +#define LEGCUFF_LAYER 5 +#define L_HAND_LAYER 4 +#define R_HAND_LAYER 3 +#define TARGETED_LAYER 2 //BS12: Layer for the target overlay from weapon targeting system +#define FIRE_LAYER 1 +#define TOTAL_LAYERS 27 +////////////////////////////////// +//Human Limb Overlays Indexes///// +#define LIMB_HEAD_LAYER 7 +#define LIMB_TORSO_LAYER 6 +#define LIMB_L_ARM_LAYER 5 +#define LIMB_R_ARM_LAYER 4 +#define LIMB_GROIN_LAYER 3 +#define LIMB_L_LEG_LAYER 2 +#define LIMB_R_LEG_LAYER 1 +#define TOTAL_LIMB_LAYERS 7 +////////////////////////////////// + +/mob/living/carbon/human + var/list/overlays_standing[TOTAL_LAYERS] + var/list/overlays_damage[TOTAL_LIMB_LAYERS] + +/mob/living/carbon/human/proc/apply_overlay(cache_index) + var/image/I = overlays_standing[cache_index] + if(I) + overlays += I + +/mob/living/carbon/human/proc/remove_overlay(cache_index) + if(overlays_standing[cache_index]) + overlays -= overlays_standing[cache_index] + overlays_standing[cache_index] = null + +/mob/living/carbon/human/proc/apply_damage_overlay(cache_index) + var/image/I = overlays_damage[cache_index] + if(I) + overlays += I + +/mob/living/carbon/human/proc/remove_damage_overlay(cache_index) + if(overlays_damage[cache_index]) + overlays -= overlays_damage[cache_index] + overlays_damage[cache_index] = null + +//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 + + +//DAMAGE OVERLAYS +/mob/living/carbon/human/UpdateDamageIcon(obj/item/organ/external/BP) + remove_damage_overlay(BP.limb_layer) + if(species.damage_mask && !(BP.status & ORGAN_DESTROYED)) + var/image/standing = image("icon" = 'icons/mob/human_races/damage_overlays.dmi', "icon_state" = "[BP.body_zone]_[BP.damage_state]", "layer" = -DAMAGE_LAYER) + var/datum/dirt_cover/mob = new species.blood_color() + standing.color = mob.color + overlays_damage[BP.limb_layer] = standing + apply_damage_overlay(BP.limb_layer) + + +//BASE MOB SPRITE +/mob/living/carbon/human/proc/update_body() + remove_overlay(BODY_LAYER) + var/list/standing = list() + + var/fat = (FAT in mutations) ? "fat" : null + var/g = (gender == FEMALE ? "f" : "m") + + var/mutable_appearance/base_icon = mutable_appearance(null, null, -BODY_LAYER) + var/race_icon = species.icobase + var/deform_icon = species.deform + + for(var/obj/item/organ/external/BP in bodyparts) + + var/mutable_appearance/temp //Hold the bodypart icon for processing. + + if(BP.status & ORGAN_DESTROYED) + continue + + if(BP.body_zone == BP_CHEST) + temp = BP.get_icon(race_icon, deform_icon, g, fat) + else if (BP.body_zone == BP_GROIN || BP.body_zone == BP_HEAD) + temp = BP.get_icon(race_icon, deform_icon, g) + else + temp = BP.get_icon(race_icon, deform_icon) + + base_icon.overlays += temp + + standing += base_icon + + //Underwear + if((underwear > 0) && (underwear < 12) && species.flags[HAS_UNDERWEAR]) + if(!fat) + standing += mutable_appearance('icons/mob/human.dmi', "underwear[underwear]_[g]_s", -BODY_LAYER) + + if((undershirt > 0) && (undershirt < undershirt_t.len) && species.flags[HAS_UNDERWEAR]) + if(!fat) + standing += mutable_appearance('icons/mob/human_undershirt.dmi', "undershirt[undershirt]_s", -BODY_LAYER) + + if(!fat && socks > 0 && socks < socks_t.len && species.flags[HAS_UNDERWEAR]) + var/obj/item/organ/external/r_foot = bodyparts_by_name[BP_R_LEG] + var/obj/item/organ/external/l_foot = bodyparts_by_name[BP_L_LEG] + if(r_foot && !(r_foot.status & ORGAN_DESTROYED) && l_foot && !(l_foot.status & ORGAN_DESTROYED)) + standing += mutable_appearance('icons/mob/human_socks.dmi', "socks[socks]_s", -BODY_LAYER) + + update_tail_showing() + overlays_standing[BODY_LAYER] = standing + apply_overlay(BODY_LAYER) + + + +//HAIR OVERLAY +/mob/living/carbon/human/proc/update_hair() + //Reset our hair + remove_overlay(HAIR_LAYER) + + var/obj/item/organ/external/head/BP = bodyparts_by_name[BP_HEAD] + if(!BP || (BP.status & ORGAN_DESTROYED)) + return + + //masks and helmets can obscure our hair. + if((HUSK in mutations) || (head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR)) || (wear_suit && (wear_suit.flags & BLOCKHAIR))) + return + + //base icons + var/list/standing = list() + + if(f_style) + var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] + if(facial_hair_style && facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed)) + var/image/facial_s = image("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s", "layer" = -HAIR_LAYER) + if(facial_hair_style.do_colouration) + if(!facial_painted) + facial_s.color = RGB_CONTRAST(r_facial, g_facial, b_facial) + else + facial_s.color = RGB_CONTRAST(dyed_r_facial, dyed_g_facial, dyed_b_facial) + standing += facial_s + + if(h_style && !(head && (head.flags & BLOCKHEADHAIR))) + var/datum/sprite_accessory/hair_style = hair_styles_list[h_style] + if(hair_style && hair_style.species_allowed && (species.name in hair_style.species_allowed)) + var/image/hair_s = image("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s", "layer" = -HAIR_LAYER) + if(hair_style.do_colouration) + if(!hair_painted) + hair_s.color = RGB_CONTRAST(r_hair, g_hair, b_hair) + else + hair_s.color = RGB_CONTRAST(dyed_r_hair, dyed_g_hair, dyed_b_hair) + standing += hair_s + + if(standing.len) + overlays_standing[HAIR_LAYER] = standing + + if(istype(wear_suit, /obj/item/clothing/suit/wintercoat)) + var/obj/item/clothing/suit/wintercoat/W = wear_suit + if(W.hooded) // used for coat hood due to hair layer viewed over the suit + overlays_standing[HAIR_LAYER] = null + + apply_overlay(HAIR_LAYER) + + +/mob/living/carbon/human/update_mutations() + remove_overlay(MUTATIONS_LAYER) + var/fat + if(FAT in mutations) + fat = "fat" + + var/list/standing = list() + var/g = (gender == FEMALE) ? "f" : "m" + + for(var/datum/dna/gene/gene in dna_genes) + if(!gene.block) + continue + if(gene.is_active(src)) + var/image/underlay = image("icon"='icons/effects/genetics.dmi', "icon_state"=gene.OnDrawUnderlays(src,g,fat), "layer"=-MUTATIONS_LAYER) + if(underlay) + standing += underlay + for(var/mut in mutations) + switch(mut) + /* + if(HULK) + if(fat) + standing.underlays += "hulk_[fat]_s" + else + standing.underlays += "hulk_[g]_s" + if(COLD_RESISTANCE) + standing.underlays += "fire[fat]_s" + if(TK) + standing.underlays += "telekinesishead[fat]_s" + */ + if(LASEREYES) + standing += image("icon"='icons/effects/genetics.dmi', "icon_state"="lasereyes_s", "layer"=-MUTATIONS_LAYER) + if(standing.len) + overlays_standing[MUTATIONS_LAYER] = standing + + apply_overlay(MUTATIONS_LAYER) + + +/mob/living/carbon/human/proc/update_mutantrace() + remove_overlay(MUTANTRACE_LAYER) + + var/fat + if(FAT in mutations) + fat = "fat" + + var/list/standing = list() + if(dna) + switch(dna.mutantrace) + if("slime") + standing += image('icons/effects/genetics.dmi', null, "[dna.mutantrace][fat]_[gender]_[species.name]_s", -MUTANTRACE_LAYER) + if("golem" , "shadow") + standing += image('icons/effects/genetics.dmi', null, "[dna.mutantrace][fat]_[gender]_s", -MUTANTRACE_LAYER) + + if(species.name == SHADOWLING && head) + var/image/eyes = image('icons/mob/shadowling.dmi', null, "[dna.mutantrace]_ms_s", LIGHTING_LAYER + 1) + eyes.plane = LIGHTING_PLANE + 1 + standing += eyes + + if(iszombie(src) && stat != DEAD) + var/image/eyes = image(species.icobase, null, "zombie_ms_s", LIGHTING_LAYER + 1) + eyes.plane = LIGHTING_PLANE + 1 + standing += eyes + + if(!dna || !(dna.mutantrace == "golem")) + update_body() + + if(standing.len) + overlays_standing[MUTANTRACE_LAYER] = standing + + update_hair() + + apply_overlay(MUTANTRACE_LAYER) + + +//Call when target overlay should be added/removed +/mob/living/carbon/human/update_targeted() + remove_overlay(TARGETED_LAYER) + + if(targeted_by && target_locked) + overlays_standing[TARGETED_LAYER] = image("icon"=target_locked, "layer"=-TARGETED_LAYER) + else if (!targeted_by && target_locked) + qdel(target_locked) + + apply_overlay(TARGETED_LAYER) + + +/mob/living/carbon/human/update_fire() //TG-stuff, fire layer + remove_overlay(FIRE_LAYER) + + if(on_fire) + overlays_standing[FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"="Standing", "layer"=-FIRE_LAYER) + + apply_overlay(FIRE_LAYER) + + +/* --------------------------------------- */ +//For legacy support. +/mob/living/carbon/human/regenerate_icons() + ..() + if(monkeyizing) return + update_hair() + update_mutations() + update_mutantrace() + update_inv_w_uniform() + update_inv_wear_id() + update_inv_gloves() + update_inv_glasses() + update_inv_ears() + update_inv_shoes() + update_inv_s_store() + update_inv_wear_mask() + update_inv_head() + update_inv_belt() + update_inv_back() + update_inv_wear_suit() + update_inv_r_hand() + update_inv_l_hand() + update_inv_handcuffed() + update_inv_legcuffed() + update_inv_pockets() + update_surgery() + update_bandage() + for(var/obj/item/organ/external/BP in bodyparts) + UpdateDamageIcon(BP) + update_icons() + update_transform() + //Hud Stuff + update_hud() + + +/* --------------------------------------- */ +//vvvvvv UPDATE_INV PROCS vvvvvv + +/mob/living/carbon/human/update_inv_w_uniform() + remove_overlay(UNIFORM_LAYER) + + if(istype(w_uniform, /obj/item/clothing/under)) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + w_uniform.screen_loc = ui_iclothing //...draw the item in the inventory screen + client.screen += w_uniform //Either way, add the item to the HUD + + var/obj/item/clothing/under/U = w_uniform + var/t_color = U.item_color + if(!t_color) t_color = icon_state + var/image/standing = image("icon_state"="[t_color]_s", "layer"=-UNIFORM_LAYER) + if(!U.icon_custom || U.icon_override || species.sprite_sheets["uniform"]) + standing.icon = (U.icon_override ? U.icon_override : (species.sprite_sheets["uniform"] ? species.sprite_sheets["uniform"] : 'icons/mob/uniform.dmi')) + else + standing = image("icon"=U.icon_custom, "icon_state"="[t_color]_mob", "layer"=-UNIFORM_LAYER) + standing.color = U.color + overlays_standing[UNIFORM_LAYER] = standing + + if(U.dirt_overlay) + var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="uniformblood") + bloodsies.color = U.dirt_overlay.color + standing.overlays += bloodsies + + if(U.accessories.len) + for(var/obj/item/clothing/accessory/A in w_uniform:accessories) + var/tie_color = A.item_color + if(!tie_color) + tie_color = A.icon_state + var/image/tie + if(A.icon_custom) + tie = image("icon" = A.icon_custom, "icon_state" = "[tie_color]_mob", "layer" = -UNIFORM_LAYER + A.layer_priority) + else + tie = image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]", "layer" = -UNIFORM_LAYER + A.layer_priority) + tie.color = A.color + standing.overlays += tie + + if(FAT in mutations) + if(U.flags & ONESIZEFITSALL) + standing.icon = 'icons/mob/uniform_fat.dmi' + else + to_chat(src, "\red You burst out of \the [U]!") + drop_from_inventory(U) + return + + else + // 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)) // + drop_from_inventory(thing) + + apply_overlay(UNIFORM_LAYER) + + +/mob/living/carbon/human/update_inv_wear_id() + remove_overlay(ID_LAYER) + if(wear_id) + wear_id.screen_loc = ui_id + if(client && hud_used) + client.screen += wear_id + + overlays_standing[ID_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="id", "layer"=-ID_LAYER) + + hud_updateflag |= 1 << ID_HUD + hud_updateflag |= 1 << WANTED_HUD + + apply_overlay(ID_LAYER) + + +/mob/living/carbon/human/update_inv_gloves() + remove_overlay(GLOVES_LAYER) + if(gloves) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + gloves.screen_loc = ui_gloves //...draw the item in the inventory screen + client.screen += gloves //Either way, add the item to the HUD + + var/t_state = gloves.item_state + if(!t_state) t_state = gloves.icon_state + var/image/standing + if(!gloves:icon_custom || gloves.icon_override || species.sprite_sheets["gloves"]) + standing = image("icon"=((gloves.icon_override) ? gloves.icon_override : (species.sprite_sheets["gloves"] ? species.sprite_sheets["gloves"] : 'icons/mob/hands.dmi')), "icon_state"="[t_state]", "layer"=-GLOVES_LAYER) + else + standing = image("icon"=gloves:icon_custom, "icon_state"="[t_state]_mob", "layer"=-GLOVES_LAYER) + standing.color = gloves.color + overlays_standing[GLOVES_LAYER] = standing + + if(gloves.dirt_overlay) + var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands") + bloodsies.color = gloves.dirt_overlay.color + standing.overlays += bloodsies + else + if(blood_DNA) + var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands") + bloodsies.color = hand_dirt_color.color + overlays_standing[GLOVES_LAYER] = bloodsies + + apply_overlay(GLOVES_LAYER) + + +/mob/living/carbon/human/update_inv_glasses() + remove_overlay(GLASSES_LAYER) + + if(glasses) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + glasses.screen_loc = ui_glasses //...draw the item in the inventory screen + client.screen += glasses //Either way, add the item to the HUD + var/image/standing + if(!glasses:icon_custom || glasses.icon_override || species.sprite_sheets["eyes"]) + standing = image("icon"=((glasses.icon_override) ? glasses.icon_override : (species.sprite_sheets["eyes"] ? species.sprite_sheets["eyes"] : 'icons/mob/eyes.dmi')), "icon_state"="[glasses.icon_state]", "layer"=-GLASSES_LAYER) + else + standing = image("icon"=glasses:icon_custom, "icon_state"="[glasses.icon_state]_mob", "layer"=-GLASSES_LAYER) + standing.color = glasses.color + overlays_standing[GLASSES_LAYER] = standing + + apply_overlay(GLASSES_LAYER) + + +/mob/living/carbon/human/update_inv_ears() + remove_overlay(EARS_LAYER) + + if(l_ear || r_ear) + if(l_ear) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + l_ear.screen_loc = ui_l_ear //...draw the item in the inventory screen + client.screen += l_ear //Either way, add the item to the HUD + var/image/standing + if(!l_ear:icon_custom || l_ear.icon_override || species.sprite_sheets["ears"]) + standing = image("icon"=((l_ear.icon_override) ? l_ear.icon_override : (species.sprite_sheets["ears"] ? species.sprite_sheets["ears"] : 'icons/mob/ears.dmi')), "icon_state"="[l_ear.icon_state]", "layer"=-EARS_LAYER) + else + standing = image("icon"=l_ear:icon_custom, "icon_state"="[l_ear.icon_state]_mob", "layer"=-EARS_LAYER) + standing.color = l_ear.color + overlays_standing[EARS_LAYER] = standing + if(r_ear) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + r_ear.screen_loc = ui_r_ear //...draw the item in the inventory screen + client.screen += r_ear //Either way, add the item to the HUD + var/image/standing + if(!r_ear:icon_custom || r_ear.icon_override || species.sprite_sheets["ears"]) + standing = image("icon"=((r_ear.icon_override) ? r_ear.icon_override : (species.sprite_sheets["ears"] ? species.sprite_sheets["ears"] : 'icons/mob/ears.dmi')), "icon_state"="[r_ear.icon_state]", "layer"=-EARS_LAYER) + else + standing = image("icon"=r_ear:icon_custom, "icon_state"="[r_ear.icon_state]_mob", "layer"=-EARS_LAYER) + standing.color = r_ear.color + overlays_standing[EARS_LAYER] = standing + + apply_overlay(EARS_LAYER) + + +/mob/living/carbon/human/update_inv_shoes() + remove_overlay(SHOES_LAYER) + + if(shoes) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + shoes.screen_loc = ui_shoes //...draw the item in the inventory screen + client.screen += shoes //Either way, add the item to the HUD + + var/image/standing + if(!shoes:icon_custom || shoes.icon_override || species.sprite_sheets["feet"]) + standing = image("icon"=((shoes.icon_override) ? shoes.icon_override : (species.sprite_sheets["feet"] ? species.sprite_sheets["feet"] : 'icons/mob/feet.dmi')), "icon_state"="[shoes.icon_state]", "layer"=-SHOES_LAYER) + else + standing = image("icon"=shoes:icon_custom, "icon_state"="[shoes.icon_state]_mob", "layer"=-SHOES_LAYER) + standing.color = shoes.color + overlays_standing[SHOES_LAYER] = standing + + if(shoes.dirt_overlay) + var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="shoeblood") + bloodsies.color = shoes.dirt_overlay.color + standing.overlays += bloodsies + else + if(feet_blood_DNA) + var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="shoeblood") + bloodsies.color = feet_dirt_color.color + overlays_standing[SHOES_LAYER] = bloodsies + else + overlays_standing[SHOES_LAYER] = null + + apply_overlay(SHOES_LAYER) + + +/mob/living/carbon/human/update_inv_s_store() + remove_overlay(SUIT_STORE_LAYER) + + if(s_store) + s_store.screen_loc = ui_sstore1 + if(client && hud_used) + client.screen += s_store + + var/t_state = s_store.item_state + if(!t_state) t_state = s_store.icon_state + var/image/standing = image("icon"='icons/mob/belt_mirror.dmi', "icon_state"="[t_state]", "layer"=-SUIT_STORE_LAYER) + standing.color = s_store.color + overlays_standing[SUIT_STORE_LAYER] = standing + + apply_overlay(SUIT_STORE_LAYER) + + +/mob/living/carbon/human/update_inv_head() + remove_overlay(HEAD_LAYER) + + if(head) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + head.screen_loc = ui_head //...draw the item in the inventory screen + client.screen += head //Either way, add the item to the HUD + + var/image/standing + if(istype(head,/obj/item/clothing/head/kitty)) + var/obj/item/clothing/head/kitty/K = head + standing = image("icon"=K.mob, "layer"=-HEAD_LAYER) + else + if(!head:icon_custom || head.icon_override || species.sprite_sheets["head"]) + standing = image("icon"=((head.icon_override) ? head.icon_override : (species.sprite_sheets["head"] ? species.sprite_sheets["head"] : 'icons/mob/head.dmi')), "icon_state"="[head.icon_state]", "layer"=-HEAD_LAYER) + else + standing = image("icon"=head:icon_custom, "icon_state"="[head.icon_state]_mob", "layer"=-HEAD_LAYER) + standing.color = head.color + overlays_standing[HEAD_LAYER] = standing + + if(head.dirt_overlay) + var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="helmetblood") + bloodsies.color = head.dirt_overlay.color + standing.overlays += bloodsies + + apply_overlay(HEAD_LAYER) + + +/mob/living/carbon/human/update_inv_belt() + remove_overlay(BELT_LAYER) + + if(belt) + belt.screen_loc = ui_belt + if(client && hud_used) + client.screen += belt + + var/t_state = belt.item_state + if(!t_state) t_state = belt.icon_state + var/image/standing + if(!belt:icon_custom || belt.icon_override || species.sprite_sheets["belt"]) + standing = image("icon"=((belt.icon_override) ? belt.icon_override : (species.sprite_sheets["belt"] ? species.sprite_sheets["belt"] : 'icons/mob/belt.dmi')), "icon_state"="[t_state]", "layer"=-BELT_LAYER) + else + standing = image("icon"=belt:icon_custom, "icon_state"="[belt.icon_state]_mob", "layer"=-BELT_LAYER) + standing.color = belt.color + overlays_standing[BELT_LAYER] = standing + apply_overlay(BELT_LAYER) + +/mob/living/carbon/human/update_inv_wear_suit() + remove_overlay(SUIT_LAYER) + + if(istype(wear_suit, /obj/item/clothing/suit)) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + wear_suit.screen_loc = ui_oclothing //...draw the item in the inventory screen + client.screen += wear_suit //Either way, add the item to the HUD + + var/image/standing + if(!wear_suit:icon_custom || wear_suit.icon_override || species.sprite_sheets["suit"]) + standing = image("icon"=((wear_suit.icon_override) ? wear_suit.icon_override : (species.sprite_sheets["suit"] ? species.sprite_sheets["suit"] : 'icons/mob/suit.dmi')), "icon_state"="[wear_suit.icon_state]", "layer"=-SUIT_LAYER) + else + standing = image("icon"=wear_suit:icon_custom, "icon_state"="[wear_suit.icon_state]_mob", "layer"=-SUIT_LAYER) + + if(wear_suit.dirt_overlay) + 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.dirt_overlay.color + standing.overlays += bloodsies + standing.color = wear_suit.color + overlays_standing[SUIT_LAYER] = standing + + if(istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) + drop_from_inventory(handcuffed) + drop_l_hand() + drop_r_hand() + + if(FAT in mutations) + if(!(wear_suit.flags & ONESIZEFITSALL)) + to_chat(src, "\red You burst out of \the [wear_suit]!") + drop_from_inventory(wear_suit) + return + + if(istype(wear_suit,/obj/item/clothing/suit/wintercoat)) + var/obj/item/clothing/suit/wintercoat/W = wear_suit + if(W.hooded) //used for coat hood due to hair layer viewed over the suit + overlays_standing[HAIR_LAYER] = null + overlays_standing[HEAD_LAYER] = null + + update_inv_shoes() + + update_tail_showing() + update_collar() + + apply_overlay(SUIT_LAYER) + + +/mob/living/carbon/human/update_inv_pockets() + if(l_store) + l_store.screen_loc = ui_storage1 + if(client && hud_used) + client.screen += l_store + if(r_store) + r_store.screen_loc = ui_storage2 + if(client && hud_used) + client.screen += r_store + + +/mob/living/carbon/human/update_inv_wear_mask() + remove_overlay(FACEMASK_LAYER) + + if(istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory)) + if(client && hud_used && hud_used.hud_shown) + if(hud_used.inventory_shown) //if the inventory is open ... + wear_mask.screen_loc = ui_mask //...draw the item in the inventory screen + client.screen += wear_mask //Either way, add the item to the HUD + + var/image/standing + if(!wear_mask:icon_custom || wear_mask.icon_override || species.sprite_sheets["mask"]) + standing = image("icon"=((wear_mask.icon_override) ? wear_mask.icon_override : (species.sprite_sheets["mask"] ? species.sprite_sheets["mask"] : 'icons/mob/mask.dmi')), "icon_state"="[wear_mask.icon_state]", "layer"=-FACEMASK_LAYER) + else + standing = image("icon"=wear_mask:icon_custom, "icon_state"="[wear_mask.icon_state]_mob", "layer"=-FACEMASK_LAYER) + standing.color = wear_mask.color + overlays_standing[FACEMASK_LAYER] = standing + + if(wear_mask.dirt_overlay && !istype(wear_mask, /obj/item/clothing/mask/cigarette)) + var/image/bloodsies = image("icon"='icons/effects/blood.dmi', "icon_state"="maskblood") + bloodsies.color = wear_mask.dirt_overlay.color + standing.overlays += bloodsies + + apply_overlay(FACEMASK_LAYER) + + +/mob/living/carbon/human/update_inv_back() + remove_overlay(BACK_LAYER) + + if(back) + back.screen_loc = ui_back + if(client && hud_used && hud_used.hud_shown) + client.screen += back + var/image/standing + if(!back:icon_custom || back.icon_override || species.sprite_sheets["back"]) + standing = image("icon"=((back.icon_override) ? back.icon_override : (species.sprite_sheets["back"] ? species.sprite_sheets["back"] : 'icons/mob/back.dmi')), "icon_state"="[back.icon_state]", "layer"=-BACK_LAYER) + else + standing = image("icon"=back:icon_custom, "icon_state"="[back.icon_state]_mob", "layer"=-BACK_LAYER) + standing.color = back.color + overlays_standing[BACK_LAYER] = standing + apply_overlay(BACK_LAYER) + + +/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 + hud_used.reload_fullscreen() + + +/mob/living/carbon/human/update_inv_handcuffed() + remove_overlay(HANDCUFF_LAYER) + + if(handcuffed) + drop_r_hand() + drop_l_hand() + stop_pulling() //TODO: should be handled elsewhere + overlays_standing[HANDCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="handcuff1", "layer"=-HANDCUFF_LAYER) + apply_overlay(HANDCUFF_LAYER) + + +/mob/living/carbon/human/update_inv_legcuffed() + remove_overlay(LEGCUFF_LAYER) + + if(legcuffed) + 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" + + overlays_standing[LEGCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="legcuff1", "layer"=-LEGCUFF_LAYER) + + apply_overlay(LEGCUFF_LAYER) + + +/mob/living/carbon/human/update_inv_r_hand() + remove_overlay(R_HAND_LAYER) + + if(r_hand) + r_hand.screen_loc = ui_rhand + if(client && hud_used) + client.screen += r_hand + + var/t_state = r_hand.item_state + if(!t_state) + t_state = r_hand.icon_state + var/image/standing + if(!r_hand:icon_custom || r_hand.icon_override || species.sprite_sheets["held"]) + if(r_hand.icon_override || species.sprite_sheets["held"]) t_state = "[t_state]_r" + standing = image("icon"=((r_hand.icon_override) ? r_hand.icon_override : (species.sprite_sheets["held"] ? species.sprite_sheets["held"] : r_hand.righthand_file)), "icon_state"="[t_state]", "layer"=-R_HAND_LAYER) + else + standing = image("icon"=r_hand:icon_custom, "icon_state"="[t_state]_r", "layer"=-R_HAND_LAYER) + standing.color = r_hand.color + overlays_standing[R_HAND_LAYER] = standing + if(handcuffed) + drop_r_hand() + + apply_overlay(R_HAND_LAYER) + + +/mob/living/carbon/human/update_inv_l_hand() + remove_overlay(L_HAND_LAYER) + + if(l_hand) + l_hand.screen_loc = ui_lhand + if(client && hud_used) + client.screen += l_hand + + var/t_state = l_hand.item_state + if(!t_state) + t_state = l_hand.icon_state + var/image/standing + if(!l_hand:icon_custom || l_hand.icon_override || species.sprite_sheets["held"]) + if(l_hand.icon_override || species.sprite_sheets["held"]) t_state = "[t_state]_l" + standing = image("icon"=((l_hand.icon_override) ? l_hand.icon_override : (species.sprite_sheets["held"] ? species.sprite_sheets["held"] : l_hand.lefthand_file)), "icon_state"="[t_state]", "layer"=-L_HAND_LAYER) + else + standing = image("icon"=l_hand:icon_custom, "icon_state"="[t_state]_l", "layer"=-L_HAND_LAYER) + standing.color = l_hand.color + overlays_standing[L_HAND_LAYER] = standing + if(handcuffed) + drop_l_hand() + + apply_overlay(L_HAND_LAYER) + + +/mob/living/carbon/human/proc/update_tail_showing() + remove_overlay(TAIL_LAYER) + + if(species.tail && species.flags[HAS_TAIL] && !(HUSK in mutations)) + if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space)) + var/image/tail_s = image("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s") + + var/obj/item/organ/external/chest/BP = bodyparts_by_name[BP_CHEST] + + if(BP.status & ORGAN_DEAD) + tail_s.color = NECROSIS_COLOR_MOD + else if(HULK in mutations) + tail_s.color = HULK_SKIN_COLOR + else + tail_s.color = RGB_CONTRAST(r_skin, g_skin, b_skin) + + overlays_standing[TAIL_LAYER] = image("icon" = tail_s, "layer" = -TAIL_LAYER) + + apply_overlay(TAIL_LAYER) + + +//Adds a collar overlay above the helmet layer if the suit has one +// Suit needs an identically named sprite in icons/mob/collar.dmi +/mob/living/carbon/human/proc/update_collar() + remove_overlay(COLLAR_LAYER) + + if(wear_suit) + var/icon/C = new('icons/mob/collar.dmi') + if(wear_suit.icon_state in C.IconStates()) + + var/image/standing = image("icon" = C, "icon_state" = "[wear_suit.icon_state]", "layer"=-COLLAR_LAYER) + standing.color = wear_suit.color + overlays_standing[COLLAR_LAYER] = standing + + apply_overlay(COLLAR_LAYER) + + +/mob/living/carbon/human/proc/update_surgery() + remove_overlay(SURGERY_LAYER) + + var/list/standing = list() + for(var/obj/item/organ/external/BP in bodyparts) + if(BP.open) + standing += image("icon" = 'icons/mob/surgery.dmi', "icon_state" = "[BP.body_zone][round(BP.open)]", "layer" = -SURGERY_LAYER) + + if(standing.len) + overlays_standing[SURGERY_LAYER] = standing + + apply_overlay(SURGERY_LAYER) + +/mob/living/carbon/human/proc/update_bandage() + remove_overlay(BANDAGE_LAYER) + + var/list/standing = list() + for(var/obj/item/organ/external/BP in bodyparts) + if(BP.wounds.len) + for(var/datum/wound/W in BP.wounds) + if(W.bandaged) + standing += image("icon" = 'icons/mob/bandages.dmi', "icon_state" = "[BP.body_zone]", "layer" = -BANDAGE_LAYER) + + if(standing.len) + overlays_standing[BANDAGE_LAYER] = standing + + apply_overlay(BANDAGE_LAYER) + + +/mob/living/carbon/human/proc/get_overlays_copy() + var/list/out = new + out = overlays_standing.Copy() + return out + +//Human Overlays Indexes///////// +#undef BODY_LAYER +#undef MUTANTRACE_LAYER +#undef MUTATIONS_LAYER +#undef DAMAGE_LAYER +#undef SURGERY_LAYER +#undef BANDAGE_LAYER +#undef UNIFORM_LAYER +#undef TAIL_LAYER +#undef ID_LAYER +#undef SHOES_LAYER +#undef GLOVES_LAYER +#undef EARS_LAYER +#undef SUIT_LAYER +#undef GLASSES_LAYER +#undef FACEMASK_LAYER +#undef BELT_LAYER +#undef SUIT_STORE_LAYER +#undef BACK_LAYER +#undef HAIR_LAYER +#undef HEAD_LAYER +#undef COLLAR_LAYER +#undef HANDCUFF_LAYER +#undef LEGCUFF_LAYER +#undef L_HAND_LAYER +#undef R_HAND_LAYER +#undef TARGETED_LAYER +#undef FIRE_LAYER +#undef TOTAL_LAYERS diff --git a/code/modules/mob/living/carbon/human/whisper.dm b/code/modules/mob/living/carbon/human/whisper.dm index bbd1c922c405..bbbe8cf58dfa 100644 --- a/code/modules/mob/living/carbon/human/whisper.dm +++ b/code/modules/mob/living/carbon/human/whisper.dm @@ -1,133 +1,133 @@ -//Lallander was here -/mob/living/carbon/human/whisper(message as text) - var/alt_name = "" - - if(say_disabled) //This is here to try to identify lag problems - to_chat(usr, "\red Speech is currently admin-disabled.") - return - - log_whisper("[src.name]/[src.key] : [message]") - - if(src.client) - if (src.client.prefs.muted & MUTE_IC) - to_chat(src, "\red You cannot whisper (muted).") - return - - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - - if(!speech_allowed && usr == src) - to_chat(usr, "\red You can't speak.") - return - - if (src.stat == DEAD) - if(fake_death) //Our changeling with fake_death status must not speak in dead chat!! - return - return src.say_dead(message) - - if(src.stat) - return - - message = sanitize(message) //made consistent with say - if(iszombie(src)) - message = zombie_talk(message) - - if(name != GetVoice()) - alt_name = "(as [get_id_name("Unknown")])" - - //parse the language code and consume it - var/datum/language/speaking = parse_language(message) - if(speaking) - message = copytext(message,2+length(speaking.key)) - - whisper_say(message, speaking, alt_name) - - -//This is used by both the whisper verb and human/say() to handle whispering -/mob/living/carbon/human/proc/whisper_say(var/message, var/datum/language/speaking = null, var/alt_name="", var/verb="whispers") - var/message_range = 1 - var/eavesdropping_range = 2 - var/watching_range = 5 - var/italics = 1 - - if (speaking) - verb = speaking.speech_verb + pick(" quietly", " softly") - - message = capitalize(trim(message)) - - //TODO: handle_speech_problems for silent - if(!message || silent || miming) - return - - // Mute disability - //TODO: handle_speech_problems - if(src.sdisabilities & MUTE) - return - - //TODO: handle_speech_problems - if(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) - return - - if(src.species.name == ABDUCTOR) - return - - //TODO: handle_speech_problems - if(src.stuttering) - message = stutter(message) - - var/list/listening = hearers(message_range, src) - listening |= src - - //ghosts - for(var/mob/M in observer_list) //does this include players who joined as observers as well? - if(M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) - listening |= M - - //Pass whispers on to anything inside the immediate listeners. - for(var/mob/L in listening) - for(var/mob/C in L.contents) - if(istype(C,/mob/living)) - listening += C - - //pass on the message to objects that can hear us. - for(var/obj/O in view(message_range, src)) - spawn (0) - if (O) - O.hear_talk(src, message, verb, speaking) - - var/list/eavesdropping = hearers(eavesdropping_range, src) - eavesdropping -= src - eavesdropping -= listening - - var/list/watching = hearers(watching_range, src) - watching -= src - watching -= listening - watching -= eavesdropping - - //now mobs - //speech bubble - var/list/speech_bubble_recipients = list() - for(var/mob/M in listening) //TODO Refactor speech pls, it's disgusting - if(M.client) - speech_bubble_recipients.Add(M.client) - for(var/mob/M in eavesdropping) - if(M.client) - speech_bubble_recipients.Add(M.client) - var/speech_bubble_test = say_test(message) - var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER+1) - I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA - spawn(0) - flick_overlay(I, speech_bubble_recipients, 30) - - for(var/mob/M in listening) - M.hear_say(message, verb, speaking, alt_name, italics, src) - - if(eavesdropping.len) - var/new_message = stars(message) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less. - for(var/mob/M in eavesdropping) - M.hear_say(new_message, verb, speaking, alt_name, italics, src) - - if(watching.len) - var/rendered = "[src.name] whispers something." - for (var/mob/M in watching) - M.show_message(rendered, 2) +//Lallander was here +/mob/living/carbon/human/whisper(message as text) + var/alt_name = "" + + if(say_disabled) //This is here to try to identify lag problems + to_chat(usr, "\red Speech is currently admin-disabled.") + return + + log_whisper("[src.name]/[src.key] : [message]") + + if(src.client) + if (src.client.prefs.muted & MUTE_IC) + to_chat(src, "\red You cannot whisper (muted).") + return + + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + + if(!speech_allowed && usr == src) + to_chat(usr, "\red You can't speak.") + return + + if (src.stat == DEAD) + if(fake_death) //Our changeling with fake_death status must not speak in dead chat!! + return + return src.say_dead(message) + + if(src.stat) + return + + message = sanitize(message) //made consistent with say + if(iszombie(src)) + message = zombie_talk(message) + + if(name != GetVoice()) + alt_name = "(as [get_id_name("Unknown")])" + + //parse the language code and consume it + var/datum/language/speaking = parse_language(message) + if(speaking) + message = copytext(message,2+length(speaking.key)) + + whisper_say(message, speaking, alt_name) + + +//This is used by both the whisper verb and human/say() to handle whispering +/mob/living/carbon/human/proc/whisper_say(var/message, var/datum/language/speaking = null, var/alt_name="", var/verb="whispers") + var/message_range = 1 + var/eavesdropping_range = 2 + var/watching_range = 5 + var/italics = 1 + + if (speaking) + verb = speaking.speech_verb + pick(" quietly", " softly") + + message = capitalize(trim(message)) + + //TODO: handle_speech_problems for silent + if(!message || silent || miming) + return + + // Mute disability + //TODO: handle_speech_problems + if(src.sdisabilities & MUTE) + return + + //TODO: handle_speech_problems + if(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) + return + + if(src.species.name == ABDUCTOR) + return + + //TODO: handle_speech_problems + if(src.stuttering) + message = stutter(message) + + var/list/listening = hearers(message_range, src) + listening |= src + + //ghosts + for(var/mob/M in observer_list) //does this include players who joined as observers as well? + if(M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) + listening |= M + + //Pass whispers on to anything inside the immediate listeners. + for(var/mob/L in listening) + for(var/mob/C in L.contents) + if(istype(C,/mob/living)) + listening += C + + //pass on the message to objects that can hear us. + for(var/obj/O in view(message_range, src)) + spawn (0) + if (O) + O.hear_talk(src, message, verb, speaking) + + var/list/eavesdropping = hearers(eavesdropping_range, src) + eavesdropping -= src + eavesdropping -= listening + + var/list/watching = hearers(watching_range, src) + watching -= src + watching -= listening + watching -= eavesdropping + + //now mobs + //speech bubble + var/list/speech_bubble_recipients = list() + for(var/mob/M in listening) //TODO Refactor speech pls, it's disgusting + if(M.client) + speech_bubble_recipients.Add(M.client) + for(var/mob/M in eavesdropping) + if(M.client) + speech_bubble_recipients.Add(M.client) + var/speech_bubble_test = say_test(message) + var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER+1) + I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + spawn(0) + flick_overlay(I, speech_bubble_recipients, 30) + + for(var/mob/M in listening) + M.hear_say(message, verb, speaking, alt_name, italics, src) + + if(eavesdropping.len) + var/new_message = stars(message) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less. + for(var/mob/M in eavesdropping) + M.hear_say(new_message, verb, speaking, alt_name, italics, src) + + if(watching.len) + var/rendered = "[src.name] whispers something." + for (var/mob/M in watching) + M.show_message(rendered, 2) diff --git a/code/modules/mob/living/carbon/metroid/death.dm b/code/modules/mob/living/carbon/metroid/death.dm index 398f744772f5..38534e945db0 100644 --- a/code/modules/mob/living/carbon/metroid/death.dm +++ b/code/modules/mob/living/carbon/metroid/death.dm @@ -1,29 +1,29 @@ -/mob/living/carbon/slime/death(gibbed) - if(stat == DEAD) - return - stat = DEAD - icon_state = "[colour] baby slime dead" - overlays.len = 0 - - if(!gibbed) - if(istype(src, /mob/living/carbon/slime/adult)) - ghostize(bancheck = TRUE) - var/mob/living/carbon/slime/M1 = new primarytype(loc) - M1.rabid = 1 - var/mob/living/carbon/slime/M2 = new primarytype(loc) - M2.rabid = 1 - M1.regenerate_icons() - M2.regenerate_icons() - M1.Friends = Friends.Copy() - M2.Friends = Friends.Copy() - if(src) - qdel(src) - else - for(var/mob/O in viewers(src, null)) - O.show_message("The [name] seizes up and falls limp...", 1) //ded -- Urist - - update_canmove() - - ticker.mode.check_win() - - return ..(gibbed) +/mob/living/carbon/slime/death(gibbed) + if(stat == DEAD) + return + stat = DEAD + icon_state = "[colour] baby slime dead" + overlays.len = 0 + + if(!gibbed) + if(istype(src, /mob/living/carbon/slime/adult)) + ghostize(bancheck = TRUE) + var/mob/living/carbon/slime/M1 = new primarytype(loc) + M1.rabid = 1 + var/mob/living/carbon/slime/M2 = new primarytype(loc) + M2.rabid = 1 + M1.regenerate_icons() + M2.regenerate_icons() + M1.Friends = Friends.Copy() + M2.Friends = Friends.Copy() + if(src) + qdel(src) + else + for(var/mob/O in viewers(src, null)) + O.show_message("The [name] seizes up and falls limp...", 1) //ded -- Urist + + update_canmove() + + ticker.mode.check_win() + + return ..(gibbed) diff --git a/code/modules/mob/living/carbon/metroid/emote.dm b/code/modules/mob/living/carbon/metroid/emote.dm index bdf69a852d85..cd056220bbad 100644 --- a/code/modules/mob/living/carbon/metroid/emote.dm +++ b/code/modules/mob/living/carbon/metroid/emote.dm @@ -1,105 +1,105 @@ -/mob/living/carbon/slime/emote(act,m_type=1,message = 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/regenerate_icons - - switch(act) - if ("me") - if(silent) - return - if (src.client) - if (client.prefs.muted & MUTE_IC) - to_chat(src, "\red 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("bounce") - message = "The [src.name] bounces in place." - m_type = 1 - - if("jiggle") - message = "The [src.name] jiggles!" - m_type = 1 - - if("light") - message = "The [src.name] lights up for a bit, then stops." - m_type = 1 - - if("moan") - message = "The [src.name] moans." - m_type = 2 - - if("shiver") - message = "The [src.name] shivers." - m_type = 2 - - if("sway") - message = "The [src.name] sways around dizzily." - m_type = 1 - - if("twitch") - message = "The [src.name] twitches." - m_type = 1 - - if("vibrate") - message = "The [src.name] vibrates!" - m_type = 1 - - if("noface") //mfw I have no face - mood = null - regenerate_icons = 1 - - if("smile") - mood = "mischevous" - regenerate_icons = 1 - - if(":3") - mood = ":33" - regenerate_icons = 1 - - if("pout") - mood = "pout" - regenerate_icons = 1 - - if("frown") - mood = "sad" - regenerate_icons = 1 - - if("scowl") - mood = "angry" - regenerate_icons = 1 - - if ("help") //This is an exception - to_chat(src, "Help for slime emotes. You can use these emotes with say \"*emote\":\n\nbounce, jiggle, light, moan, shiver, sway, twitch, vibrate. \n\nYou may also change your face with: \n\nsmile, :3, pout, frown, scowl, noface") - else - to_chat(src, "Unusable emote '[act]'. Say *help for a list.") - if ((message && src.stat == CONSCIOUS)) - 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 (regenerate_icons) - regenerate_icons() - - return +/mob/living/carbon/slime/emote(act,m_type=1,message = 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/regenerate_icons + + switch(act) + if ("me") + if(silent) + return + if (src.client) + if (client.prefs.muted & MUTE_IC) + to_chat(src, "\red 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("bounce") + message = "The [src.name] bounces in place." + m_type = 1 + + if("jiggle") + message = "The [src.name] jiggles!" + m_type = 1 + + if("light") + message = "The [src.name] lights up for a bit, then stops." + m_type = 1 + + if("moan") + message = "The [src.name] moans." + m_type = 2 + + if("shiver") + message = "The [src.name] shivers." + m_type = 2 + + if("sway") + message = "The [src.name] sways around dizzily." + m_type = 1 + + if("twitch") + message = "The [src.name] twitches." + m_type = 1 + + if("vibrate") + message = "The [src.name] vibrates!" + m_type = 1 + + if("noface") //mfw I have no face + mood = null + regenerate_icons = 1 + + if("smile") + mood = "mischevous" + regenerate_icons = 1 + + if(":3") + mood = ":33" + regenerate_icons = 1 + + if("pout") + mood = "pout" + regenerate_icons = 1 + + if("frown") + mood = "sad" + regenerate_icons = 1 + + if("scowl") + mood = "angry" + regenerate_icons = 1 + + if ("help") //This is an exception + to_chat(src, "Help for slime emotes. You can use these emotes with say \"*emote\":\n\nbounce, jiggle, light, moan, shiver, sway, twitch, vibrate. \n\nYou may also change your face with: \n\nsmile, :3, pout, frown, scowl, noface") + else + to_chat(src, "Unusable emote '[act]'. Say *help for a list.") + if ((message && src.stat == CONSCIOUS)) + 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 (regenerate_icons) + regenerate_icons() + + return diff --git a/code/modules/mob/living/carbon/metroid/examine.dm b/code/modules/mob/living/carbon/metroid/examine.dm index 5ae74f0dde73..8a21c62b0b34 100644 --- a/code/modules/mob/living/carbon/metroid/examine.dm +++ b/code/modules/mob/living/carbon/metroid/examine.dm @@ -1,25 +1,25 @@ -/mob/living/carbon/slime/examine(mob/user) - var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n" - if (src.stat == DEAD) - msg += "It is limp and unresponsive.\n" - else - if (src.getBruteLoss()) - msg += "" - if (src.getBruteLoss() < 40) - msg += "It has some punctures in its flesh!" - else - msg += "It has severe punctures and tears in its flesh!" - msg += "\n" - - switch(powerlevel) - if(2 to 3) - msg += "It is flickering gently with a little electrical activity.\n" - if(4 to 5) - msg += "It is glowing gently with moderate levels of electrical activity.\n" - if(6 to 9) - msg += "It is glowing brightly with high levels of electrical activity.\n" - if(10) - msg += "It is radiating with massive levels of electrical activity!\n" - - msg += "*---------*" - to_chat(user, msg) +/mob/living/carbon/slime/examine(mob/user) + var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n" + if (src.stat == DEAD) + msg += "It is limp and unresponsive.\n" + else + if (src.getBruteLoss()) + msg += "" + if (src.getBruteLoss() < 40) + msg += "It has some punctures in its flesh!" + else + msg += "It has severe punctures and tears in its flesh!" + msg += "\n" + + switch(powerlevel) + if(2 to 3) + msg += "It is flickering gently with a little electrical activity.\n" + if(4 to 5) + msg += "It is glowing gently with moderate levels of electrical activity.\n" + if(6 to 9) + msg += "It is glowing brightly with high levels of electrical activity.\n" + if(10) + msg += "It is radiating with massive levels of electrical activity!\n" + + msg += "*---------*" + to_chat(user, msg) diff --git a/code/modules/mob/living/carbon/metroid/hud.dm b/code/modules/mob/living/carbon/metroid/hud.dm index 377bffe53e0c..dfabcbefd916 100644 --- a/code/modules/mob/living/carbon/metroid/hud.dm +++ b/code/modules/mob/living/carbon/metroid/hud.dm @@ -1,2 +1,2 @@ -/mob/living/carbon/slime/regular_hud_updates() - return +/mob/living/carbon/slime/regular_hud_updates() + return diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index 23593c01a778..fb1e9454a318 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -1,769 +1,769 @@ -/mob/living/carbon/slime/Life() - set invisibility = 0 - //set background = 1 - - if (src.monkeyizing) - return - - ..() - - if(stat != DEAD) - //Chemicals in the body - handle_chemicals_in_body() - - handle_nutrition() - - handle_targets() - - if (!ckey) - handle_mood() - handle_speech() - handle_attack() - - - var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE - if(src.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. - src.blinded = null - - // Basically just deletes any screen objects :< - regular_hud_updates() - - //Handle temperature/pressure differences between body and environment - if(environment) - handle_environment(environment) - - //Status updates, death etc. - handle_regular_status_updates() - -/mob/living/carbon/slime - var/AIproc = 0 // determines if the AI loop is activated - var/Atkcool = 0 // attack cooldown - var/Tempstun = 0 // temporary temperature stuns - var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while - var/SStun = 0 // stun variable - -/mob/living/carbon/slime/proc/TargetAttack() - if(!isliving(ATarget)) - return - if(!ATarget || Victim == ATarget) - return - if(ATarget.stat == DEAD || ATarget.stat == UNCONSCIOUS) - if(ATarget == last_pointed) - last_pointed = null - ATarget = null - return - else if(ATarget in view(1, src)) - if(prob(25) && (iscarbon(ATarget) && !isslime(ATarget))) - var/mob/living/carbon/C = ATarget - Feedon(C) - else - ATarget.attack_slime(src) - else if(ATarget in view(7, src)) - if(!ATarget.Adjacent(src)) - step_to(src, ATarget) - else - ATarget = null - return - - -/mob/living/carbon/slime/proc/AIprocess() // the master AI process - - if(AIproc || stat == DEAD || client) return - - var/hungry = 0 - if (nutrition < get_starve_nutrition()) - hungry = 2 - else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition()) - hungry = 1 - - AIproc = 1 - - while(AIproc && stat != DEAD && (attacked || hungry || rabid || Victim)) - if(Victim) // can't eat AND have this little process at the same time - break - - if(!Target || client) - break - - if(Target.health <= -70 || Target.stat == DEAD) - Target = null - AIproc = 0 - break - - if(Target) - for(var/mob/living/carbon/slime/M in view(1,Target)) - if(M.Victim == Target) - Target = null - AIproc = 0 - break - if(!AIproc) - break - - if(Target in view(1,src)) - if(istype(Target, /mob/living/silicon)) - if(!Atkcool) - Atkcool = 1 - spawn(45) - Atkcool = 0 - - if(Target.Adjacent(src)) - Target.attack_slime(src) - return - if(!Target.lying && prob(80)) - - if(Target.client && Target.health >= 20) - if(!Atkcool) - Atkcool = 1 - spawn(45) - Atkcool = 0 - - if(Target.Adjacent(src)) - Target.attack_slime(src) - - else - if(!Atkcool && Target.Adjacent(src)) - Feedon(Target) - - else - if(!Atkcool && Target.Adjacent(src)) - Feedon(Target) - - else - if(Target in view(7, src)) - if(!Target.Adjacent(src)) // Bug of the month candidate: slimes were attempting to move to target only if it was directly next to them, which caused them to target things, but not approach them - step_to(src, Target) - - else - Target = null - AIproc = 0 - break - - var/sleeptime = movement_delay() - if(sleeptime <= 0) sleeptime = 1 - - sleep(sleeptime + 2) // this is about as fast as a player slime can go - - AIproc = 0 - -/mob/living/carbon/slime/handle_environment(datum/gas_mixture/environment) - if(!environment) - adjustToxLoss(rand(10,20)) - return - - //var/environment_heat_capacity = environment.heat_capacity() - var/loc_temp = get_temperature(environment) - /* - if((environment.temperature > (T0C + 50)) || (environment.temperature < (T0C + 10))) - var/transfer_coefficient - - transfer_coefficient = 1 - if(wear_mask && (wear_mask.body_parts_covered & HEAD) && (environment.temperature < wear_mask.protective_temperature)) - transfer_coefficient *= wear_mask.heat_transfer_coefficient - - // handle_temperature_damage(HEAD, environment.temperature, environment_heat_capacity*transfer_coefficient) - */ - - - if(loc_temp < 310.15) // a cold place - bodytemperature += adjust_body_temperature(bodytemperature, loc_temp, 1) - else // a hot place - bodytemperature += adjust_body_temperature(bodytemperature, loc_temp, 1) - - /* - if(stat==2) - bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000) - - */ - //Account for massive pressure differences - - if(bodytemperature < (T0C + 5)) // start calculating temperature damage etc - if(bodytemperature <= (T0C - 40)) // stun temperature - Tempstun = 1 - - if(bodytemperature <= (T0C - 50)) // hurt temperature - if(bodytemperature <= 50) // sqrting negative numbers is bad - adjustToxLoss(200) - else - adjustToxLoss(round(sqrt(bodytemperature)) * 2) - - else - Tempstun = 0 - - updatehealth() - - return //TODO: DEFERRED - - -/mob/living/carbon/slime/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 - -/mob/living/carbon/slime/proc/handle_chemicals_in_body() - - if(reagents) reagents.metabolize(src) - - - src.updatehealth() - - return //TODO: DEFERRED - - -/mob/living/carbon/slime/proc/handle_regular_status_updates() - - if(istype(src, /mob/living/carbon/slime/adult)) - health = 200 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) - else - health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) - - - - - if(health < config.health_threshold_dead && stat != DEAD) - death() - return - - else if(src.health < config.health_threshold_crit) - // if(src.health <= 20 && prob(1)) spawn(0) emote("gasp") - - //if(!src.rejuv) src.oxyloss++ - if(!src.reagents.has_reagent("inaprovaline")) src.adjustOxyLoss(10) - - if(src.stat != DEAD) src.stat = UNCONSCIOUS - - if(prob(30)) - adjustOxyLoss(-1) - adjustToxLoss(-1) - adjustFireLoss(-1) - adjustCloneLoss(-1) - adjustBruteLoss(-1) - - - if (src.stat == DEAD) - - src.lying = 1 - src.blinded = 1 - - else - if (src.paralysis || src.stunned || src.weakened || (status_flags && FAKEDEATH)) //Stunned etc. - if (src.stunned > 0) - AdjustStunned(-1) - src.stat = CONSCIOUS - if (src.weakened > 0) - AdjustWeakened(-1) - src.lying = 0 - src.stat = CONSCIOUS - if (src.paralysis > 0) - AdjustParalysis(-1) - src.blinded = 0 - src.lying = 0 - src.stat = CONSCIOUS - - else - src.lying = 0 - src.stat = CONSCIOUS - - if (src.stuttering) src.stuttering = 0 - - if (src.eye_blind) - src.eye_blind = 0 - src.blinded = 1 - - if (src.ear_deaf > 0) src.ear_deaf = 0 - if (src.ear_damage < 25) - 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 = 0 - - if (src.druggy > 0) - src.druggy = 0 - - return 1 - -/mob/living/carbon/slime/proc/handle_attack() - if(!ATarget) - return - if(Victim && Victim != ATarget) - Feedstop() - TargetAttack() - return -/mob/living/carbon/slime/proc/handle_nutrition() - if(prob(20)) - if(istype(src, /mob/living/carbon/slime/adult)) nutrition-=rand(4,6) - else nutrition-=rand(2,3) - - if(nutrition <= 0) - nutrition = 0 - if(prob(75)) - - adjustToxLoss(rand(0,5)) - - else - if(istype(src, /mob/living/carbon/slime/adult)) - if(nutrition >= 1000) - if(prob(40)) amount_grown++ - - else - if(nutrition >= 800) - if(prob(40)) amount_grown++ - - if(amount_grown >= 10 && !Victim && !Target) - if(istype(src, /mob/living/carbon/slime/adult)) - if(!client) - for(var/i=1,i<=4,i++) - if(prob(70)) - var/mob/living/carbon/slime/M = new primarytype(loc) - M.powerlevel = round(powerlevel/4) - M.Friends = Friends.Copy() - M.tame = tame - M.rabid = rabid - M.Discipline = Discipline - if(i != 1) step_away(M,src) - else - var/mutations = pick("one","two","three","four") - switch(mutations) - if("one") - var/mob/living/carbon/slime/M = new mutationone(loc) - M.powerlevel = round(powerlevel/4) - M.Friends = Friends.Copy() - M.tame = tame - M.rabid = rabid - M.Discipline = Discipline - if(i != 1) step_away(M,src) - if("two") - var/mob/living/carbon/slime/M = new mutationtwo(loc) - M.powerlevel = round(powerlevel/4) - M.Friends = Friends.Copy() - M.tame = tame - M.rabid = rabid - M.Discipline = Discipline - if(i != 1) step_away(M,src) - if("three") - var/mob/living/carbon/slime/M = new mutationthree(loc) - M.powerlevel = round(powerlevel/4) - M.Friends = Friends.Copy() - M.tame = tame - M.rabid = rabid - M.Discipline = Discipline - if(i != 1) step_away(M,src) - if("four") - var/mob/living/carbon/slime/M = new mutationfour(loc) - M.powerlevel = round(powerlevel/4) - M.Friends = Friends.Copy() - M.tame = tame - M.rabid = rabid - M.Discipline = Discipline - if(i != 1) step_away(M,src) - - qdel(src) - - else - if(!client) - var/mob/living/carbon/slime/adult/A = new adulttype(src.loc) - A.nutrition = nutrition -// A.nutrition += 100 - A.powerlevel = max(0, powerlevel-1) - A.Friends = Friends.Copy() - A.tame = tame - A.rabid = rabid - qdel(src) - - -/mob/living/carbon/slime/proc/handle_targets() - if(Tempstun) - if(!Victim) // not while they're eating! - canmove = 0 - else - canmove = 1 - - if(attacked > 50) attacked = 50 - - if(attacked > 0) - attacked-- - - if(Discipline > 0) - - if(Discipline >= 5 && rabid) - if(prob(60)) rabid = 0 - - if(prob(10)) - Discipline-- - - if(!client) - if(!canmove) return - - if(Victim) return // if it's eating someone already, continue eating! - - if(Target) - --target_patience - if (target_patience <= 0 || SStun || Discipline || attacked) // Tired of chasing or something draws out attention - target_patience = 0 - Target = null - - if(AIproc && SStun) return - - var/hungry = 0 // determines if the slime is hungry - - if (nutrition < get_starve_nutrition()) - hungry = 2 - else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition()) - hungry = 1 - - if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends - if(Friends.len > 0 && prob(1)) - var/list/BFriends = list() - for(var/mob/M in Friends) - if(Friends[M] < 10) - BFriends.Add(M) - if(BFriends.len > 0) - var/mob/nofriend = pick(BFriends) - --Friends[nofriend] - - if(!Target) - if(will_hunt() && hungry || attacked || rabid) // Only add to the list if we need to - var/list/targets = list() - - for(var/mob/living/L in view(7,src)) - - if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs - continue - - if(L in Friends) // No eating friends! - continue - - if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence - targets += L // Possible target found! - - if(istype(L, /mob/living/carbon/human)) //Ignore slime(wo)men - var/mob/living/carbon/human/H = L - if(H.dna) - if(H.dna.mutantrace == "slime") - continue - - if(!L.canmove) // Only one slime can latch on at a time. - var/notarget = 0 - for(var/mob/living/carbon/slime/M in view(1,L)) - if(M.Victim == L) - notarget = 1 - if(notarget) - continue - - targets += L // Possible target found! - - if(targets.len > 0) - if(attacked || rabid || hungry == 2) - Target = targets[1] // I am attacked and am fighting back or so hungry I don't even care - else - for(var/mob/living/carbon/C in targets) - if(!Discipline && prob(5)) - if(ishuman(C) || isalienadult(C)) - Target = C - break - - if(islarva(C) || isfacehugger(C) || ismonkey(C)) - Target = C - break - - if (Target) - target_patience = rand(5,7) - if (isslimeadult(src)) - target_patience += 3 - - if(!Target) // If we have no target, we are wandering or following orders - if (Leader) - if(holding_still) - holding_still = max(holding_still - 1, 0) - else if(canmove && isturf(loc)) - step_to(src, Leader) - - else if(hungry) - if (holding_still) - holding_still = max(holding_still - hungry, 0) - else if(canmove && isturf(loc) && prob(50)) - step(src, pick(cardinal)) - - else - if(holding_still) - holding_still = max(holding_still - 1, 0) - else if(canmove && isturf(loc) && prob(33)) - step(src, pick(cardinal)) - else if(!AIproc) - spawn() - AIprocess() - -//TG slime speech & mood port. -/mob/living/carbon/slime/proc/handle_mood() - var/newmood = "" - if (rabid || attacked) - newmood = "angry" - //else if (docile) - // newmood = ":3" - else if (Target) - newmood = "mischevous" - - if (!newmood) - if (Discipline && prob(25)) - newmood = "pout" - else if (prob(1)) - newmood = pick("sad", ":3", "pout") - - if ((mood == "sad" || mood == ":3" || mood == "pout") && !newmood) - if(prob(75)) - newmood = mood - - if (newmood != mood) // This is so we don't redraw them every time - mood = newmood - regenerate_icons() - -/mob/living/carbon/slime/proc/handle_speech() - //Speech understanding starts here - var/to_say - if (speech_buffer.len > 0) - var/who = speech_buffer[1] // Who said it? - var/phrase = lowertext_(speech_buffer[2]) // What did they say? - if ((findtext(phrase, num2text(number)) || findtext(phrase, "slime") || findtext(phrase, "") || findtext(phrase, ""))) // Talking to us - if ( \ - findtext(phrase, "hello") || findtext(phrase, "hi") || \ - findtext(phrase, "") || findtext(phrase, "") \ - ) - to_say = pick("Hello...", "Hi...") - else if ( \ - findtext(phrase, "attack") || findtext(phrase, "kill") || \ - findtext(phrase, "") || findtext(phrase, "") || \ - findtext(phrase, "") \ - ) - if(Friends[who] > 4) - if(last_pointed) - if(!(Friends[last_pointed] >=2) && !(isslime(last_pointed) && Friends[who] > 6)) - if(holding_still) - holding_still = 0 - if(last_pointed != src) - to_say = "I will destroy [last_pointed]..." - ATarget = last_pointed - last_pointed = null - else - to_say = "Please... No...." - Friends.Remove(who) // TRAITOR! - last_pointed = null - else - to_say = "I don't kill my friends...." - last_pointed = null - else - to_say = "Whom...." - else - to_say = "I won't do it..." - else if ( \ - findtext(phrase, "follow") || findtext(phrase, " ") || \ - findtext(phrase, " ") \ - ) - if (Leader) - if (holding_still) - holding_still = 0 - if (Leader == who) // Already following him - to_say = pick("Yes...", "Lead...", "Following...") - else if (Friends[who] > Friends[Leader]) // VIVA - Leader = who - to_say = "Yes... I follow [who]..." - else - to_say = "No... I follow [Leader]..." - else - if (Friends[who] > 2) - if (holding_still) - holding_still = 0 - Leader = who - to_say = "I follow..." - else // Not friendly enough - to_say = pick("No...", "I won't follow...") - else if ( \ - findtext(phrase, "stop") || findtext(phrase, "") || \ - findtext(phrase, "") || findtext(phrase, "") \ - ) - if (Victim) // We are asked to stop feeding - if (Friends[who] > 4) - Victim = null - Target = null - if (Friends[who] < 7 && (Victim != ATarget)) - --Friends[who] - to_say = "Grrr..." // I'm angry but I do it - else - if(Victim == ATarget) - ATarget = null - to_say = "Fine..." - else - to_say = "No..." - else if (Target) // We are asked to stop chasing - if (Friends[who] > 3) - Target = null - if (Friends[who] < 6) - --Friends[who] - to_say = "Grrr..." // I'm angry but I do it - else - to_say = "Fine..." - else if (Leader) // We are asked to stop following - if (Leader == who) - to_say = "Yes... I'll stay..." - Leader = null - else - if (Friends[who] > Friends[Leader]) - Leader = null - to_say = "Yes... I'll stop..." - else - to_say = "No... I'll keep following..." - else if (holding_still) - if(Friends[who] > 2) - to_say = "Fine..." - holding_still = 0 - else - to_say = "No..." - else if (ATarget) - if(Friends[who] > 4) - last_pointed = null - ATarget = null - to_say = "Fine..." - else - to_say = "No..." - - else if ( \ - findtext(phrase, "stay") || findtext(phrase, "") || \ - findtext(phrase, "") || findtext(phrase, " ") \ - ) - if (Leader) - if (Leader == who) - Leader = null - holding_still = Friends[who] * 10 - to_say = "Yes... Staying..." - else if (Friends[who] > Friends[Leader]) - Leader = null - holding_still = (Friends[who] - Friends[Leader]) * 10 - to_say = "Yes... Staying..." - else - to_say = "No... I'll keep following..." - else - if (Friends[who] > 2) - holding_still = Friends[who] * 10 - to_say = "Yes... Staying..." - else - to_say = "No... I won't stay..." - speech_buffer = list() - - //Speech starts here - if (to_say) - say (to_say) - else if(prob(1)) - emote(pick("bounce","sway","light","vibrate","jiggle")) - else - var/t = 10 - var/slimes_near = 0 - var/dead_slimes = 0 - var/friends_near = list() - for (var/mob/living/L in view(7,src)) - if(isslime(L) && L != src) - ++slimes_near - if (L.stat == DEAD) - ++dead_slimes - if (L in Friends) - t += 20 - friends_near += L - if (nutrition < get_hunger_nutrition()) t += 10 - if (nutrition < get_starve_nutrition()) t += 10 - if (prob(2) && prob(t)) - var/phrases = list() - if (Target) phrases += "[Target]... looks tasty..." - if (nutrition < get_starve_nutrition()) - phrases += "So... hungry..." - phrases += "Very... hungry..." - phrases += "Need... food..." - phrases += "Must... eat..." - else if (nutrition < get_hunger_nutrition()) - phrases += "Hungry..." - phrases += "Where is the food?" - phrases += "I want to eat..." - phrases += "Rawr..." - phrases += "Blop..." - phrases += "Blorble..." - if (rabid || attacked) - phrases += "Hrr..." - phrases += "Nhuu..." - phrases += "Unn..." - if (mood == ":3") - phrases += "Purr..." - if (attacked) - phrases += "Grrr..." - if (bodytemperature < T0C) - phrases += "Cold..." - if (bodytemperature < T0C - 30) - phrases += "So... cold..." - phrases += "Very... cold..." - if (bodytemperature < T0C - 50) - phrases += "..." - phrases += "C... c..." - if (Victim) - phrases += "Nom..." - phrases += "Tasty..." - if (powerlevel > 3) phrases += "Bzzz..." - if (powerlevel > 5) phrases += "Zap..." - if (powerlevel > 8) phrases += "Zap... Bzz..." - if (mood == "sad") phrases += "Bored..." - if (slimes_near) phrases += "Brother..." - if (slimes_near > 1) phrases += "Brothers..." - if (dead_slimes) phrases += "What happened?" - if (!slimes_near) - phrases += "Lonely..." - for (var/M in friends_near) - phrases += "[M]... friend..." - if (nutrition < get_hunger_nutrition()) - phrases += "[M]... feed me..." - say (pick(phrases)) - -/mob/living/carbon/slime/proc/will_hunt(var/hunger = -1) // Check for being stopped from feeding and chasing - //if (docile) return 0 - if (hunger == 2 || rabid || attacked) return 1 - if (Leader) return 0 - if (holding_still) return 0 - return 1 - -/mob/living/carbon/slime/proc/get_max_nutrition() // Can't go above it - if (isslimeadult(src)) return 1200 - else return 1000 - -/mob/living/carbon/slime/proc/get_grow_nutrition() // Above it we grow, below it we can eat - if (isslimeadult(src)) return 1000 - else return 800 - -/mob/living/carbon/slime/proc/get_hunger_nutrition() // Below it we will always eat - if (isslimeadult(src)) return 600 - else return 500 - -/mob/living/carbon/slime/proc/get_starve_nutrition() // Below it we will eat before everything else - if(isslimeadult(src)) return 300 - else return 200 - -/mob/living/carbon/slime/slip() - return FALSE +/mob/living/carbon/slime/Life() + set invisibility = 0 + //set background = 1 + + if (src.monkeyizing) + return + + ..() + + if(stat != DEAD) + //Chemicals in the body + handle_chemicals_in_body() + + handle_nutrition() + + handle_targets() + + if (!ckey) + handle_mood() + handle_speech() + handle_attack() + + + var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE + if(src.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. + src.blinded = null + + // Basically just deletes any screen objects :< + regular_hud_updates() + + //Handle temperature/pressure differences between body and environment + if(environment) + handle_environment(environment) + + //Status updates, death etc. + handle_regular_status_updates() + +/mob/living/carbon/slime + var/AIproc = 0 // determines if the AI loop is activated + var/Atkcool = 0 // attack cooldown + var/Tempstun = 0 // temporary temperature stuns + var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while + var/SStun = 0 // stun variable + +/mob/living/carbon/slime/proc/TargetAttack() + if(!isliving(ATarget)) + return + if(!ATarget || Victim == ATarget) + return + if(ATarget.stat == DEAD || ATarget.stat == UNCONSCIOUS) + if(ATarget == last_pointed) + last_pointed = null + ATarget = null + return + else if(ATarget in view(1, src)) + if(prob(25) && (iscarbon(ATarget) && !isslime(ATarget))) + var/mob/living/carbon/C = ATarget + Feedon(C) + else + ATarget.attack_slime(src) + else if(ATarget in view(7, src)) + if(!ATarget.Adjacent(src)) + step_to(src, ATarget) + else + ATarget = null + return + + +/mob/living/carbon/slime/proc/AIprocess() // the master AI process + + if(AIproc || stat == DEAD || client) return + + var/hungry = 0 + if (nutrition < get_starve_nutrition()) + hungry = 2 + else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition()) + hungry = 1 + + AIproc = 1 + + while(AIproc && stat != DEAD && (attacked || hungry || rabid || Victim)) + if(Victim) // can't eat AND have this little process at the same time + break + + if(!Target || client) + break + + if(Target.health <= -70 || Target.stat == DEAD) + Target = null + AIproc = 0 + break + + if(Target) + for(var/mob/living/carbon/slime/M in view(1,Target)) + if(M.Victim == Target) + Target = null + AIproc = 0 + break + if(!AIproc) + break + + if(Target in view(1,src)) + if(istype(Target, /mob/living/silicon)) + if(!Atkcool) + Atkcool = 1 + spawn(45) + Atkcool = 0 + + if(Target.Adjacent(src)) + Target.attack_slime(src) + return + if(!Target.lying && prob(80)) + + if(Target.client && Target.health >= 20) + if(!Atkcool) + Atkcool = 1 + spawn(45) + Atkcool = 0 + + if(Target.Adjacent(src)) + Target.attack_slime(src) + + else + if(!Atkcool && Target.Adjacent(src)) + Feedon(Target) + + else + if(!Atkcool && Target.Adjacent(src)) + Feedon(Target) + + else + if(Target in view(7, src)) + if(!Target.Adjacent(src)) // Bug of the month candidate: slimes were attempting to move to target only if it was directly next to them, which caused them to target things, but not approach them + step_to(src, Target) + + else + Target = null + AIproc = 0 + break + + var/sleeptime = movement_delay() + if(sleeptime <= 0) sleeptime = 1 + + sleep(sleeptime + 2) // this is about as fast as a player slime can go + + AIproc = 0 + +/mob/living/carbon/slime/handle_environment(datum/gas_mixture/environment) + if(!environment) + adjustToxLoss(rand(10,20)) + return + + //var/environment_heat_capacity = environment.heat_capacity() + var/loc_temp = get_temperature(environment) + /* + if((environment.temperature > (T0C + 50)) || (environment.temperature < (T0C + 10))) + var/transfer_coefficient + + transfer_coefficient = 1 + if(wear_mask && (wear_mask.body_parts_covered & HEAD) && (environment.temperature < wear_mask.protective_temperature)) + transfer_coefficient *= wear_mask.heat_transfer_coefficient + + // handle_temperature_damage(HEAD, environment.temperature, environment_heat_capacity*transfer_coefficient) + */ + + + if(loc_temp < 310.15) // a cold place + bodytemperature += adjust_body_temperature(bodytemperature, loc_temp, 1) + else // a hot place + bodytemperature += adjust_body_temperature(bodytemperature, loc_temp, 1) + + /* + if(stat==2) + bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000) + + */ + //Account for massive pressure differences + + if(bodytemperature < (T0C + 5)) // start calculating temperature damage etc + if(bodytemperature <= (T0C - 40)) // stun temperature + Tempstun = 1 + + if(bodytemperature <= (T0C - 50)) // hurt temperature + if(bodytemperature <= 50) // sqrting negative numbers is bad + adjustToxLoss(200) + else + adjustToxLoss(round(sqrt(bodytemperature)) * 2) + + else + Tempstun = 0 + + updatehealth() + + return //TODO: DEFERRED + + +/mob/living/carbon/slime/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 + +/mob/living/carbon/slime/proc/handle_chemicals_in_body() + + if(reagents) reagents.metabolize(src) + + + src.updatehealth() + + return //TODO: DEFERRED + + +/mob/living/carbon/slime/proc/handle_regular_status_updates() + + if(istype(src, /mob/living/carbon/slime/adult)) + health = 200 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) + else + health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) + + + + + if(health < config.health_threshold_dead && stat != DEAD) + death() + return + + else if(src.health < config.health_threshold_crit) + // if(src.health <= 20 && prob(1)) spawn(0) emote("gasp") + + //if(!src.rejuv) src.oxyloss++ + if(!src.reagents.has_reagent("inaprovaline")) src.adjustOxyLoss(10) + + if(src.stat != DEAD) src.stat = UNCONSCIOUS + + if(prob(30)) + adjustOxyLoss(-1) + adjustToxLoss(-1) + adjustFireLoss(-1) + adjustCloneLoss(-1) + adjustBruteLoss(-1) + + + if (src.stat == DEAD) + + src.lying = 1 + src.blinded = 1 + + else + if (src.paralysis || src.stunned || src.weakened || (status_flags && FAKEDEATH)) //Stunned etc. + if (src.stunned > 0) + AdjustStunned(-1) + src.stat = CONSCIOUS + if (src.weakened > 0) + AdjustWeakened(-1) + src.lying = 0 + src.stat = CONSCIOUS + if (src.paralysis > 0) + AdjustParalysis(-1) + src.blinded = 0 + src.lying = 0 + src.stat = CONSCIOUS + + else + src.lying = 0 + src.stat = CONSCIOUS + + if (src.stuttering) src.stuttering = 0 + + if (src.eye_blind) + src.eye_blind = 0 + src.blinded = 1 + + if (src.ear_deaf > 0) src.ear_deaf = 0 + if (src.ear_damage < 25) + 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 = 0 + + if (src.druggy > 0) + src.druggy = 0 + + return 1 + +/mob/living/carbon/slime/proc/handle_attack() + if(!ATarget) + return + if(Victim && Victim != ATarget) + Feedstop() + TargetAttack() + return +/mob/living/carbon/slime/proc/handle_nutrition() + if(prob(20)) + if(istype(src, /mob/living/carbon/slime/adult)) nutrition-=rand(4,6) + else nutrition-=rand(2,3) + + if(nutrition <= 0) + nutrition = 0 + if(prob(75)) + + adjustToxLoss(rand(0,5)) + + else + if(istype(src, /mob/living/carbon/slime/adult)) + if(nutrition >= 1000) + if(prob(40)) amount_grown++ + + else + if(nutrition >= 800) + if(prob(40)) amount_grown++ + + if(amount_grown >= 10 && !Victim && !Target) + if(istype(src, /mob/living/carbon/slime/adult)) + if(!client) + for(var/i=1,i<=4,i++) + if(prob(70)) + var/mob/living/carbon/slime/M = new primarytype(loc) + M.powerlevel = round(powerlevel/4) + M.Friends = Friends.Copy() + M.tame = tame + M.rabid = rabid + M.Discipline = Discipline + if(i != 1) step_away(M,src) + else + var/mutations = pick("one","two","three","four") + switch(mutations) + if("one") + var/mob/living/carbon/slime/M = new mutationone(loc) + M.powerlevel = round(powerlevel/4) + M.Friends = Friends.Copy() + M.tame = tame + M.rabid = rabid + M.Discipline = Discipline + if(i != 1) step_away(M,src) + if("two") + var/mob/living/carbon/slime/M = new mutationtwo(loc) + M.powerlevel = round(powerlevel/4) + M.Friends = Friends.Copy() + M.tame = tame + M.rabid = rabid + M.Discipline = Discipline + if(i != 1) step_away(M,src) + if("three") + var/mob/living/carbon/slime/M = new mutationthree(loc) + M.powerlevel = round(powerlevel/4) + M.Friends = Friends.Copy() + M.tame = tame + M.rabid = rabid + M.Discipline = Discipline + if(i != 1) step_away(M,src) + if("four") + var/mob/living/carbon/slime/M = new mutationfour(loc) + M.powerlevel = round(powerlevel/4) + M.Friends = Friends.Copy() + M.tame = tame + M.rabid = rabid + M.Discipline = Discipline + if(i != 1) step_away(M,src) + + qdel(src) + + else + if(!client) + var/mob/living/carbon/slime/adult/A = new adulttype(src.loc) + A.nutrition = nutrition +// A.nutrition += 100 + A.powerlevel = max(0, powerlevel-1) + A.Friends = Friends.Copy() + A.tame = tame + A.rabid = rabid + qdel(src) + + +/mob/living/carbon/slime/proc/handle_targets() + if(Tempstun) + if(!Victim) // not while they're eating! + canmove = 0 + else + canmove = 1 + + if(attacked > 50) attacked = 50 + + if(attacked > 0) + attacked-- + + if(Discipline > 0) + + if(Discipline >= 5 && rabid) + if(prob(60)) rabid = 0 + + if(prob(10)) + Discipline-- + + if(!client) + if(!canmove) return + + if(Victim) return // if it's eating someone already, continue eating! + + if(Target) + --target_patience + if (target_patience <= 0 || SStun || Discipline || attacked) // Tired of chasing or something draws out attention + target_patience = 0 + Target = null + + if(AIproc && SStun) return + + var/hungry = 0 // determines if the slime is hungry + + if (nutrition < get_starve_nutrition()) + hungry = 2 + else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition()) + hungry = 1 + + if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends + if(Friends.len > 0 && prob(1)) + var/list/BFriends = list() + for(var/mob/M in Friends) + if(Friends[M] < 10) + BFriends.Add(M) + if(BFriends.len > 0) + var/mob/nofriend = pick(BFriends) + --Friends[nofriend] + + if(!Target) + if(will_hunt() && hungry || attacked || rabid) // Only add to the list if we need to + var/list/targets = list() + + for(var/mob/living/L in view(7,src)) + + if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs + continue + + if(L in Friends) // No eating friends! + continue + + if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence + targets += L // Possible target found! + + if(istype(L, /mob/living/carbon/human)) //Ignore slime(wo)men + var/mob/living/carbon/human/H = L + if(H.dna) + if(H.dna.mutantrace == "slime") + continue + + if(!L.canmove) // Only one slime can latch on at a time. + var/notarget = 0 + for(var/mob/living/carbon/slime/M in view(1,L)) + if(M.Victim == L) + notarget = 1 + if(notarget) + continue + + targets += L // Possible target found! + + if(targets.len > 0) + if(attacked || rabid || hungry == 2) + Target = targets[1] // I am attacked and am fighting back or so hungry I don't even care + else + for(var/mob/living/carbon/C in targets) + if(!Discipline && prob(5)) + if(ishuman(C) || isalienadult(C)) + Target = C + break + + if(islarva(C) || isfacehugger(C) || ismonkey(C)) + Target = C + break + + if (Target) + target_patience = rand(5,7) + if (isslimeadult(src)) + target_patience += 3 + + if(!Target) // If we have no target, we are wandering or following orders + if (Leader) + if(holding_still) + holding_still = max(holding_still - 1, 0) + else if(canmove && isturf(loc)) + step_to(src, Leader) + + else if(hungry) + if (holding_still) + holding_still = max(holding_still - hungry, 0) + else if(canmove && isturf(loc) && prob(50)) + step(src, pick(cardinal)) + + else + if(holding_still) + holding_still = max(holding_still - 1, 0) + else if(canmove && isturf(loc) && prob(33)) + step(src, pick(cardinal)) + else if(!AIproc) + spawn() + AIprocess() + +//TG slime speech & mood port. +/mob/living/carbon/slime/proc/handle_mood() + var/newmood = "" + if (rabid || attacked) + newmood = "angry" + //else if (docile) + // newmood = ":3" + else if (Target) + newmood = "mischevous" + + if (!newmood) + if (Discipline && prob(25)) + newmood = "pout" + else if (prob(1)) + newmood = pick("sad", ":3", "pout") + + if ((mood == "sad" || mood == ":3" || mood == "pout") && !newmood) + if(prob(75)) + newmood = mood + + if (newmood != mood) // This is so we don't redraw them every time + mood = newmood + regenerate_icons() + +/mob/living/carbon/slime/proc/handle_speech() + //Speech understanding starts here + var/to_say + if (speech_buffer.len > 0) + var/who = speech_buffer[1] // Who said it? + var/phrase = lowertext_(speech_buffer[2]) // What did they say? + if ((findtext(phrase, num2text(number)) || findtext(phrase, "slime") || findtext(phrase, "") || findtext(phrase, ""))) // Talking to us + if ( \ + findtext(phrase, "hello") || findtext(phrase, "hi") || \ + findtext(phrase, "") || findtext(phrase, "") \ + ) + to_say = pick("Hello...", "Hi...") + else if ( \ + findtext(phrase, "attack") || findtext(phrase, "kill") || \ + findtext(phrase, "") || findtext(phrase, "") || \ + findtext(phrase, "") \ + ) + if(Friends[who] > 4) + if(last_pointed) + if(!(Friends[last_pointed] >=2) && !(isslime(last_pointed) && Friends[who] > 6)) + if(holding_still) + holding_still = 0 + if(last_pointed != src) + to_say = "I will destroy [last_pointed]..." + ATarget = last_pointed + last_pointed = null + else + to_say = "Please... No...." + Friends.Remove(who) // TRAITOR! + last_pointed = null + else + to_say = "I don't kill my friends...." + last_pointed = null + else + to_say = "Whom...." + else + to_say = "I won't do it..." + else if ( \ + findtext(phrase, "follow") || findtext(phrase, " ") || \ + findtext(phrase, " ") \ + ) + if (Leader) + if (holding_still) + holding_still = 0 + if (Leader == who) // Already following him + to_say = pick("Yes...", "Lead...", "Following...") + else if (Friends[who] > Friends[Leader]) // VIVA + Leader = who + to_say = "Yes... I follow [who]..." + else + to_say = "No... I follow [Leader]..." + else + if (Friends[who] > 2) + if (holding_still) + holding_still = 0 + Leader = who + to_say = "I follow..." + else // Not friendly enough + to_say = pick("No...", "I won't follow...") + else if ( \ + findtext(phrase, "stop") || findtext(phrase, "") || \ + findtext(phrase, "") || findtext(phrase, "") \ + ) + if (Victim) // We are asked to stop feeding + if (Friends[who] > 4) + Victim = null + Target = null + if (Friends[who] < 7 && (Victim != ATarget)) + --Friends[who] + to_say = "Grrr..." // I'm angry but I do it + else + if(Victim == ATarget) + ATarget = null + to_say = "Fine..." + else + to_say = "No..." + else if (Target) // We are asked to stop chasing + if (Friends[who] > 3) + Target = null + if (Friends[who] < 6) + --Friends[who] + to_say = "Grrr..." // I'm angry but I do it + else + to_say = "Fine..." + else if (Leader) // We are asked to stop following + if (Leader == who) + to_say = "Yes... I'll stay..." + Leader = null + else + if (Friends[who] > Friends[Leader]) + Leader = null + to_say = "Yes... I'll stop..." + else + to_say = "No... I'll keep following..." + else if (holding_still) + if(Friends[who] > 2) + to_say = "Fine..." + holding_still = 0 + else + to_say = "No..." + else if (ATarget) + if(Friends[who] > 4) + last_pointed = null + ATarget = null + to_say = "Fine..." + else + to_say = "No..." + + else if ( \ + findtext(phrase, "stay") || findtext(phrase, "") || \ + findtext(phrase, "") || findtext(phrase, " ") \ + ) + if (Leader) + if (Leader == who) + Leader = null + holding_still = Friends[who] * 10 + to_say = "Yes... Staying..." + else if (Friends[who] > Friends[Leader]) + Leader = null + holding_still = (Friends[who] - Friends[Leader]) * 10 + to_say = "Yes... Staying..." + else + to_say = "No... I'll keep following..." + else + if (Friends[who] > 2) + holding_still = Friends[who] * 10 + to_say = "Yes... Staying..." + else + to_say = "No... I won't stay..." + speech_buffer = list() + + //Speech starts here + if (to_say) + say (to_say) + else if(prob(1)) + emote(pick("bounce","sway","light","vibrate","jiggle")) + else + var/t = 10 + var/slimes_near = 0 + var/dead_slimes = 0 + var/friends_near = list() + for (var/mob/living/L in view(7,src)) + if(isslime(L) && L != src) + ++slimes_near + if (L.stat == DEAD) + ++dead_slimes + if (L in Friends) + t += 20 + friends_near += L + if (nutrition < get_hunger_nutrition()) t += 10 + if (nutrition < get_starve_nutrition()) t += 10 + if (prob(2) && prob(t)) + var/phrases = list() + if (Target) phrases += "[Target]... looks tasty..." + if (nutrition < get_starve_nutrition()) + phrases += "So... hungry..." + phrases += "Very... hungry..." + phrases += "Need... food..." + phrases += "Must... eat..." + else if (nutrition < get_hunger_nutrition()) + phrases += "Hungry..." + phrases += "Where is the food?" + phrases += "I want to eat..." + phrases += "Rawr..." + phrases += "Blop..." + phrases += "Blorble..." + if (rabid || attacked) + phrases += "Hrr..." + phrases += "Nhuu..." + phrases += "Unn..." + if (mood == ":3") + phrases += "Purr..." + if (attacked) + phrases += "Grrr..." + if (bodytemperature < T0C) + phrases += "Cold..." + if (bodytemperature < T0C - 30) + phrases += "So... cold..." + phrases += "Very... cold..." + if (bodytemperature < T0C - 50) + phrases += "..." + phrases += "C... c..." + if (Victim) + phrases += "Nom..." + phrases += "Tasty..." + if (powerlevel > 3) phrases += "Bzzz..." + if (powerlevel > 5) phrases += "Zap..." + if (powerlevel > 8) phrases += "Zap... Bzz..." + if (mood == "sad") phrases += "Bored..." + if (slimes_near) phrases += "Brother..." + if (slimes_near > 1) phrases += "Brothers..." + if (dead_slimes) phrases += "What happened?" + if (!slimes_near) + phrases += "Lonely..." + for (var/M in friends_near) + phrases += "[M]... friend..." + if (nutrition < get_hunger_nutrition()) + phrases += "[M]... feed me..." + say (pick(phrases)) + +/mob/living/carbon/slime/proc/will_hunt(var/hunger = -1) // Check for being stopped from feeding and chasing + //if (docile) return 0 + if (hunger == 2 || rabid || attacked) return 1 + if (Leader) return 0 + if (holding_still) return 0 + return 1 + +/mob/living/carbon/slime/proc/get_max_nutrition() // Can't go above it + if (isslimeadult(src)) return 1200 + else return 1000 + +/mob/living/carbon/slime/proc/get_grow_nutrition() // Above it we grow, below it we can eat + if (isslimeadult(src)) return 1000 + else return 800 + +/mob/living/carbon/slime/proc/get_hunger_nutrition() // Below it we will always eat + if (isslimeadult(src)) return 600 + else return 500 + +/mob/living/carbon/slime/proc/get_starve_nutrition() // Below it we will eat before everything else + if(isslimeadult(src)) return 300 + else return 200 + +/mob/living/carbon/slime/slip() + return FALSE diff --git a/code/modules/mob/living/carbon/metroid/login.dm b/code/modules/mob/living/carbon/metroid/login.dm index 8ca29bf4818c..d3ac320f2f4f 100644 --- a/code/modules/mob/living/carbon/metroid/login.dm +++ b/code/modules/mob/living/carbon/metroid/login.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/slime/Login() - ..() - update_hud() - return +/mob/living/carbon/slime/Login() + ..() + update_hud() + return diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index 8c79777ce981..c23ba4e6f06c 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -1,1131 +1,1131 @@ -/mob/living/carbon/slime - name = "baby slime" - icon = 'icons/mob/slimes.dmi' - icon_state = "grey baby slime" - pass_flags = PASSTABLE - speak_emote = list("hums") - - layer = 5 - - maxHealth = 150 - health = 150 - gender = NEUTER - - update_icon = 0 - nutrition = 700 // 1000 = max - - see_in_dark = 8 - update_slimes = 0 - - ventcrawler = 2 - - // canstun and canweaken don't affect slimes because they ignore stun and weakened variables - // for the sake of cleanliness, though, here they are. - status_flags = CANPARALYSE|CANPUSH - - var/cores = 1 // the number of /obj/item/slime_extract's the slime has left inside - - var/powerlevel = 0 // 1-10 controls how much electricity they are generating - var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows into an adult - // if adult: if 10: reproduces - - - var/mob/living/Victim = null // the person the slime is currently feeding on - var/mob/living/Target = null // AI variable - tells the slime to hunt this down - var/mob/living/ATarget = null - - var/attacked = 0 // determines if it's been attacked recently. Can be any number, is a cooloff-ish variable - var/tame = 0 // if set to 1, the slime will not eat humans ever, or attack them - var/rabid = 0 // if set to 1, the slime will attack and eat anything it comes in contact with - - var/list/Friends = list() // A list of potential friends - // slimes pass on genetic data, so all their offspring have the same "Friends", - - var/mood = "" // To show its face - var/list/speech_buffer = list() // Last phrase said near it and person who said it - var/number = 0 // Used to understand when someone is talking to it - var/mob/living/Leader = null // AI variable - tells the slime to follow this person - var/holding_still = 0 // AI variable, cooloff-ish for how long it's going to stay in one place - var/target_patience = 0 // AI variable, cooloff-ish for how long it's going to follow its target - - ///////////TIME FOR SUBSPECIES - - var/colour = "grey" - var/primarytype = /mob/living/carbon/slime - var/mutationone = /mob/living/carbon/slime/orange - var/mutationtwo = /mob/living/carbon/slime/metal - var/mutationthree = /mob/living/carbon/slime/blue - var/mutationfour = /mob/living/carbon/slime/purple - var/adulttype = /mob/living/carbon/slime/adult - var/coretype = /obj/item/slime_extract/grey - var/mob/living/last_pointed = null - -/mob/living/carbon/slime/adult - name = "adult slime" - icon = 'icons/mob/slimes.dmi' - icon_state = "grey adult slime" - speak_emote = list("telepathically chirps") - - health = 200 - gender = NEUTER - - update_icon = 0 - nutrition = 800 // 1200 = max - - -/mob/living/carbon/slime/atom_init() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - number = rand(1, 1000) - if(name == "baby slime") - name = text("[colour] baby slime ([number])") - else - name = text("[colour] adult slime ([number])") - real_name = name - - . = ..() - - regenerate_icons() - -/mob/living/carbon/slime/Destroy() - Victim = null - Target = null - ATarget = null - last_pointed = null - Leader = null - if(Friends.len) - Friends.Cut() - return ..() - -/mob/living/carbon/slime/regenerate_icons() - overlays.len = 0 - //var/icon_text = "[colour] [is_adult ? "adult" : "baby"] slime" - //icon_dead = "[icon_text] dead" - //if(stat != DEAD) - //icon_state = icon_text - if(stat != DEAD) - if(mood) - overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]") - //else - //icon_state = icon_dead - ..() - -/mob/living/carbon/slime/movement_delay() - var/tally = 0 - - var/health_deficiency = (100 - health) - if(health_deficiency >= 45) tally += (health_deficiency / 25) - - if (bodytemperature < 183.222) - tally += (283.222 - bodytemperature) / 10 * 1.75 - - if(reagents) - if(reagents.has_reagent("hyperzine")) // hyperzine slows slimes down - tally *= 2 // moves twice as slow - - if(reagents.has_reagent("frostoil")) // frostoil also makes them move VEEERRYYYYY slow - tally *= 5 - - if(pull_debuff) - tally += pull_debuff - - if(health <= 0) // if damaged, the slime moves twice as slow - tally *= 2 - - if (bodytemperature >= 330.23) // 135 F - return -1 // slimes become supercharged at high temperatures - - return tally+config.slime_delay - -/mob/living/carbon/slime/ObjBump(obj/O) - if(!client && powerlevel > 0) - var/probab = 10 - switch(powerlevel) - if(1 to 2) probab = 20 - if(3 to 4) probab = 30 - if(5 to 6) probab = 40 - if(7 to 8) probab = 60 - if(9) probab = 70 - if(10) probab = 95 - if(prob(probab)) - if(istype(O, /obj/structure/window) || istype(O, /obj/structure/grille)) - if(isslimeadult(src)) - if(nutrition <= 600 && !Atkcool) - O.attack_slime(src) - spawn() - Atkcool = 1 - sleep(15) - Atkcool = 0 - else - if(nutrition <= 500 && !Atkcool) - if(prob(5)) - O.attack_slime(src) - spawn() - Atkcool = 1 - sleep(15) - Atkcool = 0 - -/mob/living/carbon/slime/MobBump(mob/M) - if(ishuman(M)) //pushing humans - if(isslimeadult(src) && prob(10)) //only if we're adult, and 10% of the time - return 0 - else - return 1 - -/mob/living/carbon/slime/Process_Spacemove(movement_dir = 0) - return 2 - -/mob/living/carbon/slime/Stat() - ..() - - if(statpanel("Status")) - if(isslimeadult(src)) - stat(null, "Health: [round((health / 200) * 100)]%") - stat(null, "Nutrition: [nutrition]/1200") - if(amount_grown >= 10) - stat(null, "You can reproduce!") - else - stat(null, "Health: [round((health / 150) * 100)]%") - stat(null, "Nutrition: [nutrition]/1000") - if(amount_grown >= 10) - stat(null, "You can evolve!") - - stat(null,"Power Level: [powerlevel]") - - -/mob/living/carbon/slime/adjustFireLoss(amount) - ..(-abs(amount)) // Heals them - return - -/mob/living/carbon/slime/bullet_act(obj/item/projectile/Proj) - attacked += 10 - ..(Proj) - return 0 - - -/mob/living/carbon/slime/emp_act(severity) - powerlevel = 0 // oh no, the power! - ..() - -/mob/living/carbon/slime/ex_act(severity) - - if (stat == DEAD && client) - return - - else if (stat == DEAD && !client) - qdel(src) - return - - var/b_loss = null - var/f_loss = null - switch (severity) - if (1.0) - b_loss += 500 - return - - if (2.0) - - b_loss += 60 - f_loss += 60 - - - if(3.0) - b_loss += 30 - - adjustBruteLoss(b_loss) - adjustFireLoss(f_loss) - - updatehealth() - - -/mob/living/carbon/slime/blob_act() - if (stat == DEAD) - return - var/shielded = 0 - - var/damage = null - if (stat != DEAD) - damage = rand(10,30) - - if(shielded) - damage /= 4 - - //paralysis += 1 - - show_message("\red The blob attacks you!") - - adjustFireLoss(damage) - - updatehealth() - return - - -/mob/living/carbon/slime/u_equip(obj/item/W) - return - - -/mob/living/carbon/slime/attack_ui(slot) - return - -/mob/living/carbon/slime/meteorhit(O) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message(text("\red [] has been hit by []", src, O), 1) - if (health > 0) - adjustBruteLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25)) - adjustFireLoss(30) - - updatehealth() - return - - -/mob/living/carbon/slime/attack_slime(mob/living/carbon/slime/M) - if (!ticker) - to_chat(M, "You cannot attack people before the game has started.") - return - - if(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("\red The [M.name] has glomped []!", src), 1) - - var/damage = rand(1, 3) - attacked += 5 - - if(istype(src, /mob/living/carbon/slime/adult)) - damage = rand(1, 6) - else - damage = rand(1, 3) - - adjustBruteLoss(damage) - - - updatehealth() - - return - - -/mob/living/carbon/slime/attack_animal(mob/living/simple_animal/M) - if(..()) - 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) - visible_message("[M][M.attacktext] [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) - adjustBruteLoss(damage) - updatehealth() - -/mob/living/carbon/slime/attack_paw(mob/living/carbon/monkey/M) - 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 - - 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 ("help") - help_shake_act(M) - else - if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) - return - if (health > 0) - attacked += 10 - //playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [M.name] has attacked [src]!"), 1) - adjustBruteLoss(rand(1, 3)) - updatehealth() - return - - -/mob/living/carbon/slime/attack_hand(mob/living/carbon/human/M) - 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 - - ..() - - if(Victim) - if(Victim == M) - if(prob(60)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [M] attempts to wrestle \the [name] off!", 1) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - - else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [M] manages to wrestle \the [name] off!", 1) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - - if(prob(90) && !client) - Discipline++ - - spawn() - SStun = 1 - sleep(rand(45,60)) - if(src) - SStun = 0 - - Victim = null - anchored = 0 - step_away(src,M) - - return - - else - M.do_attack_animation(src) - if(prob(30)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [M] attempts to wrestle \the [name] off of [Victim]!", 1) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - - else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [M] manages to wrestle \the [name] off of [Victim]!", 1) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - - if(prob(80) && !client) - Discipline++ - - if(!istype(src, /mob/living/carbon/slime/adult)) - if(Discipline == 1) - attacked = 0 - - spawn() - SStun = 1 - sleep(rand(55,65)) - if(src) - SStun = 0 - - Victim = null - anchored = 0 - step_away(src,M) - - 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 == "hurt")//Stungloves. Any contact will stun the alien. - if(G.cell.charge >= 2500) - G.cell.use(2500) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [src] has been touched with the stun gloves by [M]!", 1, "\red You hear someone fall.", 2) - return - else - to_chat(M, "\red Not enough charge! ") - return - - switch(M.a_intent) - - if ("help") - help_shake_act(M) - - if ("grab") - if (M == src || M.lying) - return - var/obj/item/weapon/grab/G = new /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)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) - - else - - var/damage = rand(1, 9) - - attacked += 10 - if (prob(90)) - if (HULK in M.mutations) - damage += 5 - if(Victim) - Victim = null - anchored = 0 - if(prob(80) && !client) - Discipline++ - spawn(0) - - step_away(src,M,15) - sleep(3) - step_away(src,M,15) - - - playsound(loc, "punch", 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has punched []!", M, src), 1) - - 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("\red [] has attempted to punch []!", M, src), 1) - return - - - -/mob/living/carbon/slime/attack_alien(mob/living/carbon/alien/humanoid/M) - 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 ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) - - if ("hurt") - - if ((prob(95) && health > 0)) - attacked += 10 - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - var/damage = rand(15, 30) - if (damage >= 25) - damage = rand(20, 40) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has attacked [name]!", M), 1) - else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has wounded [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("\red [] has attempted to lunge at [name]!", M), 1) - - if ("grab") - if (M == src || M.lying) - return - var/obj/item/weapon/grab/G = new /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("\red [] has grabbed [name] passively!", M), 1) - - if ("disarm") - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - var/damage = 5 - attacked += 10 - - if(prob(95)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has tackled [name]!", M), 1) - - if(Victim) - Victim = null - anchored = 0 - if(prob(80) && !client) - Discipline++ - if(!istype(src, /mob/living/carbon/slime)) - if(Discipline == 1) - attacked = 0 - - spawn() - SStun = 1 - sleep(rand(5,20)) - SStun = 0 - - spawn(0) - - step_away(src,M,15) - sleep(3) - step_away(src,M,15) - - else - drop_item() - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has disarmed [name]!", M), 1) - adjustBruteLoss(damage) - updatehealth() - return - - -/mob/living/carbon/slime/restrained() - return 0 - - -/mob/living/carbon/slime/show_inv(mob/user) - - user.set_machine(src) - var/dat = {" -
                    [name]
                    -


                    -
                    Close -
                    "} - user << browse(entity_ja(dat), text("window=mob[name];size=340x480")) - onclose(user, "mob[name]") - return - -/mob/living/carbon/slime/updatehealth() - if(status_flags & GODMODE) - if(istype(src, /mob/living/carbon/slime/adult)) - health = 200 - else - health = 150 - stat = CONSCIOUS - else - // slimes can't suffocate unless they suicide. They are also not harmed by fire - if(istype(src, /mob/living/carbon/slime/adult)) - health = 200 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) - else - health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) - - -/obj/item/slime_extract - name = "slime extract" - desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"." - icon = 'icons/mob/slimes.dmi' - icon_state = "grey slime extract" - force = 1.0 - w_class = 1.0 - throwforce = 1.0 - throw_speed = 3 - throw_range = 6 - origin_tech = "biotech=4" - var/Uses = 1 // uses before it goes inert - var/enhanced = 0 // has it been enhanced before? - attackby(obj/item/weapon/O, mob/user) - if(istype(O, /obj/item/weapon/slimesteroid2)) - if(enhanced == 1) - to_chat(user, "\red This extract has already been enhanced!") - return ..() - if(Uses == 0) - to_chat(user, "\red You can't enhance a used extract!") - return ..() - to_chat(user, "You apply the enhancer. It now has triple the amount of uses.") - Uses = 3 - enhanced = 1 - qdel(O) - -/obj/item/slime_extract/atom_init() - . = ..() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - -/obj/item/slime_extract/grey - name = "grey slime extract" - icon_state = "grey slime extract" - -/obj/item/slime_extract/gold - name = "gold slime extract" - icon_state = "gold slime extract" - -/obj/item/slime_extract/silver - name = "silver slime extract" - icon_state = "silver slime extract" - -/obj/item/slime_extract/metal - name = "metal slime extract" - icon_state = "metal slime extract" - -/obj/item/slime_extract/purple - name = "purple slime extract" - icon_state = "purple slime extract" - -/obj/item/slime_extract/darkpurple - name = "dark purple slime extract" - icon_state = "dark purple slime extract" - -/obj/item/slime_extract/orange - name = "orange slime extract" - icon_state = "orange slime extract" - -/obj/item/slime_extract/yellow - name = "yellow slime extract" - icon_state = "yellow slime extract" - -/obj/item/slime_extract/red - name = "red slime extract" - icon_state = "red slime extract" - -/obj/item/slime_extract/blue - name = "blue slime extract" - icon_state = "blue slime extract" - -/obj/item/slime_extract/darkblue - name = "dark blue slime extract" - icon_state = "dark blue slime extract" - -/obj/item/slime_extract/pink - name = "pink slime extract" - icon_state = "pink slime extract" - -/obj/item/slime_extract/green - name = "green slime extract" - icon_state = "green slime extract" - -/obj/item/slime_extract/lightpink - name = "light pink slime extract" - icon_state = "light pink slime extract" - -/obj/item/slime_extract/black - name = "black slime extract" - icon_state = "black slime extract" - -/obj/item/slime_extract/oil - name = "oil slime extract" - icon_state = "oil slime extract" - -/obj/item/slime_extract/adamantine - name = "adamantine slime extract" - icon_state = "adamantine slime extract" - -//Zve added -/obj/item/slime_extract/bluespace - name = "bluespace slime extract" - icon_state = "bluespace slime extract" - -/obj/item/slime_extract/pyrite - name = "pyrite slime extract" - icon_state = "pyrite slime extract" - -/obj/item/slime_extract/cerulean - name = "cerulean slime extract" - icon_state = "cerulean slime extract" - -/obj/item/slime_extract/sepia - name = "sepia slime extract" - icon_state = "sepia slime extract" - -/obj/item/slime_extract/rainbow - name = "rainbow slime extract" - icon_state = "rainbow slime extract" - -////Pet Slime Creation/// - -/obj/item/weapon/slimepotion - name = "docility potion" - desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame." - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle19" - - attack(mob/living/carbon/slime/M, mob/user) - if(!istype(M, /mob/living/carbon/slime))//If target is not a slime. - to_chat(user, "\red The potion only works on baby slimes!") - return ..() - if(istype(M, /mob/living/carbon/slime/adult)) //Can't tame adults - to_chat(user, "\red Only baby slimes can be tamed!") - return..() - if(M.stat) - to_chat(user, "\red The slime is dead!") - return..() - var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc) - pet.icon_state = "[M.colour] baby slime" - pet.icon_living = "[M.colour] baby slime" - pet.icon_dead = "[M.colour] baby slime dead" - pet.colour = "[M.colour]" - to_chat(user, "You feed the slime the potion, removing it's powers and calming it.") - qdel(M) - var/newname = sanitize_safe(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text, MAX_NAME_LEN) - - if (!newname) - newname = "pet slime" - pet.name = newname - pet.real_name = newname - qdel(src) - -/obj/item/weapon/slimepotion2 - name = "advanced docility potion" - desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes." - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle19" - - attack(mob/living/carbon/slime/adult/M, mob/user) - if(!istype(M, /mob/living/carbon/slime/adult))//If target is not a slime. - to_chat(user, "\red The potion only works on adult slimes!") - return ..() - if(M.stat) - to_chat(user, "\red The slime is dead!") - return..() - var/mob/living/simple_animal/adultslime/pet = new /mob/living/simple_animal/adultslime(M.loc) - pet.icon_state = "[M.colour] adult slime" - pet.icon_living = "[M.colour] adult slime" - pet.icon_dead = "[M.colour] baby slime dead" - pet.colour = "[M.colour]" - to_chat(user, "You feed the slime the potion, removing it's powers and calming it.") - qdel(M) - var/newname = sanitize_safe(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text, MAX_NAME_LEN) - - if (!newname) - newname = "pet slime" - pet.name = newname - pet.real_name = newname - qdel(src) - - -/obj/item/weapon/slimesteroid - name = "slime steroid" - desc = "A potent chemical mix that will cause a slime to generate more extract." - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - - attack(mob/living/carbon/slime/M, mob/user) - if(!istype(M, /mob/living/carbon/slime))//If target is not a slime. - to_chat(user, "\red The steroid only works on baby slimes!") - return ..() - if(istype(M, /mob/living/carbon/slime/adult)) //Can't tame adults - to_chat(user, "\red Only baby slimes can use the steroid!") - return..() - if(M.stat) - to_chat(user, "\red The slime is dead!") - return..() - if(M.cores == 3) - to_chat(user, "\red The slime already has the maximum amount of extract!") - return..() - - to_chat(user, "You feed the slime the steroid. It now has triple the amount of extract.") - M.cores = 3 - qdel(src) - -/obj/item/weapon/slimesteroid2 - name = "extract enhancer" - desc = "A potent chemical mix that will give a slime extract three uses." - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle17" - -////////Adamantine Golem stuff I dunno where else to put it - -/obj/item/clothing/under/golem - name = "adamantine skin" - desc = "A golem's skin." - icon_state = "golem" - item_state = "golem" - item_color = "golem" - has_sensor = 0 - canremove = 0 - unacidable = 1 - flags = ABSTRACT | DROPDEL - - -/obj/item/clothing/shoes/golem - name = "golem's feet" - desc = "Sturdy adamantine feet." - icon_state = "golem" - item_state = null - canremove = 0 - flags = ABSTRACT | DROPDEL | NOSLIP - unacidable = 1 - - -/obj/item/clothing/mask/gas/golem - name = "golem's face" - desc = "The imposing face of an adamantine golem." - icon_state = "golem" - item_state = "golem" - canremove = 0 - siemens_coefficient = 0 - unacidable = 1 - flags = ABSTRACT | DROPDEL - flags_inv = 0 - - -/obj/item/clothing/gloves/golem - name = "golem's hands" - desc = "Strong adamantine hands." - icon_state = "golem" - item_state = null - siemens_coefficient = 0 - canremove = 0 - unacidable = 1 - flags = ABSTRACT | DROPDEL - - -/obj/item/clothing/head/helmet/space/golem - icon_state = "golem" - item_state = "dermal" - item_color = "dermal" - name = "golem's head" - desc = "A golem's head." - canremove = 0 - unacidable = 1 - - body_parts_covered = HEAD|FACE|EYES - cold_protection = HEAD - min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = HEAD - max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE - - flags = ABSTRACT | DROPDEL - flags_inv = 0 - slowdown = 0 - unacidable = 1 - canremove = 0 - siemens_coefficient = 0 - - armor = list(melee = 77, bullet = 66, laser = 44, energy = 44, bomb = 80, bio = 100, rad = 80) - - -/obj/item/clothing/suit/space/golem - name = "adamantine shell" - desc = "A golem's thick outter shell." - icon_state = "golem" - item_state = "golem" - w_class = 4//bulky item - allowed = null - - body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE - heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE - - flags = ABSTRACT | DROPDEL - flags_inv = HIDEGLOVES | HIDESHOES | HIDEJUMPSUIT - slowdown = 0 - unacidable = 1 - canremove = 0 - siemens_coefficient = 0 - can_breach = 0 - - armor = list(melee = 77, bullet = 66, laser = 44, energy = 44, bomb = 80, bio = 100, rad = 80) - -/obj/effect/golemrune - anchored = 1 - desc = "A strange rune used to create golems. It glows when spirits are nearby." - name = "rune" - icon = 'icons/obj/rune.dmi' - icon_state = "golem" - unacidable = 1 - layer = TURF_LAYER - var/last_ghost_click = 0 - var/mob/dead/observer/spirit - -/obj/effect/golemrune/atom_init() - . = ..() - announce_to_ghosts() - -/obj/effect/golemrune/update_icon() - if(spirit) - icon_state = "golem2" - else - icon_state = "golem" - -/obj/effect/golemrune/process() - check_spirit() - -/obj/effect/golemrune/attack_ghost(mob/dead/observer/user) - if(user.mind && user.mind.current && user.mind.current.stat != DEAD) - to_chat(user, "Your spirit linked to another body.") - return - if(user.golem_rune && user.golem_rune != src) - to_chat(user, "One rune per one poor little spirit.") - return - if(spirit && spirit != user) - to_chat(user, "This rune is taken by another spirit, wait or find new one.") - return - if(last_ghost_click >= world.time) - to_chat(user, "You cannot do this so often.") - return - if(user == spirit) - for(var/image/I in user.client.images) - if(I.loc == src && I.icon_state == "agolem_master") - user.client.images -= I - break - spirit = null - user.golem_rune = null - to_chat(user, "You are no longer queued for golem role.") - else - START_PROCESSING(SSobj, src) - last_ghost_click = world.time + 50 - var/image/I = image('icons/mob/hud.dmi', src, "agolem_master") //If there is alot activated rune close by, we can see which is ours. - user.client.images += I - spirit = user - user.golem_rune = src - to_chat(user, "You are now queued for golem role.") - check_spirit() - -/obj/effect/golemrune/attack_hand(mob/living/user) - if(!check_spirit()) - to_chat(user, "The rune fizzles uselessly. There is no spirit nearby.") - return - user.SetNextMove(CLICK_CD_INTERACT) - var/mob/living/carbon/human/golem/G = new(loc) - G.attack_log = spirit.attack_log //Preserve attack log, if there is any... - G.attack_log += "\[[time_stamp()]\] ======GOLEM LIFE======" - G.key = spirit.key - G.my_master = user - G.update_golem_hud_icons() - if(istype(user, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = user - H.my_golems += G - H.update_golem_hud_icons() - to_chat(G, "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost.") - qdel(src) - -/obj/effect/golemrune/proc/announce_to_ghosts() - for(var/mob/dead/observer/O in player_list) - if(O.client) - var/area/A = get_area(src) - if(A) - to_chat(O, "Golem rune created in [A.name] (JMP).") - -/obj/effect/golemrune/proc/check_spirit() - var/result = 1 - if(!spirit) - result = 0 - else if(spirit && (!spirit.client || spirit.mind && spirit.mind.current && spirit.mind.current.stat != DEAD)) - spirit.golem_rune = null - spirit = null - result = 0 - if(!result) - STOP_PROCESSING(SSobj, src) - update_icon() - return result - -/mob/living/carbon/human/proc/update_golem_hud_icons() - if(client) - if(dna && (dna.mutantrace == "adamantine")) - if(my_master) - var/I = image('icons/mob/hud.dmi', loc = my_master, icon_state = "agolem_master") - client.images += I - else - if(my_golems) - for(var/mob/living/carbon/human/G in my_golems) - var/I = image('icons/mob/hud.dmi', loc = G, icon_state = "agolem_master") - client.images += I - - -/mob/living/carbon/slime/getTrail() - return null - -//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them//////////////////////// - -/* -// Basically this slime Core catalyzes reactions that normally wouldn't happen anywhere -/obj/item/slime_core - name = "slime extract" - desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"." - icon = 'icons/mob/slimes.dmi' - icon_state = "slime extract" - force = 1.0 - w_class = 1.0 - throwforce = 1.0 - throw_speed = 3 - throw_range = 6 - origin_tech = "biotech=4" - var/POWERFLAG = 0 // sshhhhhhh - var/Flush = 30 - var/Uses = 5 // uses before it goes inert - -/obj/item/slime_core/atom_init() - . = ..() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - POWERFLAG = rand(1,10) - Uses = rand(7, 25) - //flags |= NOREACT - - spawn() - Life() - -/obj/item/slime_core/proc/Life() - while(src) - sleep(25) - Flush-- - if(Flush <= 0) - reagents.clear_reagents() - Flush = 30 -*/ - - - -/obj/item/weapon/reagent_containers/food/snacks/egg/slime - name = "slime egg" - desc = "A small, gelatinous egg." - icon = 'icons/mob/mob.dmi' - icon_state = "slime egg-growing" - bitesize = 12 - origin_tech = "biotech=4" - var/grown = 0 - -/obj/item/weapon/reagent_containers/food/snacks/egg/slime/atom_init() - . = ..() - reagents.add_reagent("nutriment", 4) - reagents.add_reagent("slimejelly", 1) - addtimer(CALLBACK(src, .proc/Grow), rand(1200,1500)) // the egg takes a while to "ripen" - -/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Grow() - grown = 1 - icon_state = "slime egg-grown" - START_PROCESSING(SSobj, src) - return - -/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch() - STOP_PROCESSING(SSobj, src) - var/turf/T = get_turf(src) - src.visible_message("\blue The [name] pulsates and quivers!") - spawn(rand(50,100)) - src.visible_message("\blue The [name] bursts open!") - new/mob/living/carbon/slime(T) - qdel(src) - - -/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process() - var/turf/location = get_turf(src) - var/datum/gas_mixture/environment = location.return_air() - if (environment.gas["phoron"] > MOLES_PHORON_VISIBLE)//phoron exposure causes the egg to hatch - src.Hatch() - -/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W, mob/user) - if(istype( W, /obj/item/toy/crayon )) - return - else - ..() +/mob/living/carbon/slime + name = "baby slime" + icon = 'icons/mob/slimes.dmi' + icon_state = "grey baby slime" + pass_flags = PASSTABLE + speak_emote = list("hums") + + layer = 5 + + maxHealth = 150 + health = 150 + gender = NEUTER + + update_icon = 0 + nutrition = 700 // 1000 = max + + see_in_dark = 8 + update_slimes = 0 + + ventcrawler = 2 + + // canstun and canweaken don't affect slimes because they ignore stun and weakened variables + // for the sake of cleanliness, though, here they are. + status_flags = CANPARALYSE|CANPUSH + + var/cores = 1 // the number of /obj/item/slime_extract's the slime has left inside + + var/powerlevel = 0 // 1-10 controls how much electricity they are generating + var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows into an adult + // if adult: if 10: reproduces + + + var/mob/living/Victim = null // the person the slime is currently feeding on + var/mob/living/Target = null // AI variable - tells the slime to hunt this down + var/mob/living/ATarget = null + + var/attacked = 0 // determines if it's been attacked recently. Can be any number, is a cooloff-ish variable + var/tame = 0 // if set to 1, the slime will not eat humans ever, or attack them + var/rabid = 0 // if set to 1, the slime will attack and eat anything it comes in contact with + + var/list/Friends = list() // A list of potential friends + // slimes pass on genetic data, so all their offspring have the same "Friends", + + var/mood = "" // To show its face + var/list/speech_buffer = list() // Last phrase said near it and person who said it + var/number = 0 // Used to understand when someone is talking to it + var/mob/living/Leader = null // AI variable - tells the slime to follow this person + var/holding_still = 0 // AI variable, cooloff-ish for how long it's going to stay in one place + var/target_patience = 0 // AI variable, cooloff-ish for how long it's going to follow its target + + ///////////TIME FOR SUBSPECIES + + var/colour = "grey" + var/primarytype = /mob/living/carbon/slime + var/mutationone = /mob/living/carbon/slime/orange + var/mutationtwo = /mob/living/carbon/slime/metal + var/mutationthree = /mob/living/carbon/slime/blue + var/mutationfour = /mob/living/carbon/slime/purple + var/adulttype = /mob/living/carbon/slime/adult + var/coretype = /obj/item/slime_extract/grey + var/mob/living/last_pointed = null + +/mob/living/carbon/slime/adult + name = "adult slime" + icon = 'icons/mob/slimes.dmi' + icon_state = "grey adult slime" + speak_emote = list("telepathically chirps") + + health = 200 + gender = NEUTER + + update_icon = 0 + nutrition = 800 // 1200 = max + + +/mob/living/carbon/slime/atom_init() + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + number = rand(1, 1000) + if(name == "baby slime") + name = text("[colour] baby slime ([number])") + else + name = text("[colour] adult slime ([number])") + real_name = name + + . = ..() + + regenerate_icons() + +/mob/living/carbon/slime/Destroy() + Victim = null + Target = null + ATarget = null + last_pointed = null + Leader = null + if(Friends.len) + Friends.Cut() + return ..() + +/mob/living/carbon/slime/regenerate_icons() + overlays.len = 0 + //var/icon_text = "[colour] [is_adult ? "adult" : "baby"] slime" + //icon_dead = "[icon_text] dead" + //if(stat != DEAD) + //icon_state = icon_text + if(stat != DEAD) + if(mood) + overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]") + //else + //icon_state = icon_dead + ..() + +/mob/living/carbon/slime/movement_delay() + var/tally = 0 + + var/health_deficiency = (100 - health) + if(health_deficiency >= 45) tally += (health_deficiency / 25) + + if (bodytemperature < 183.222) + tally += (283.222 - bodytemperature) / 10 * 1.75 + + if(reagents) + if(reagents.has_reagent("hyperzine")) // hyperzine slows slimes down + tally *= 2 // moves twice as slow + + if(reagents.has_reagent("frostoil")) // frostoil also makes them move VEEERRYYYYY slow + tally *= 5 + + if(pull_debuff) + tally += pull_debuff + + if(health <= 0) // if damaged, the slime moves twice as slow + tally *= 2 + + if (bodytemperature >= 330.23) // 135 F + return -1 // slimes become supercharged at high temperatures + + return tally+config.slime_delay + +/mob/living/carbon/slime/ObjBump(obj/O) + if(!client && powerlevel > 0) + var/probab = 10 + switch(powerlevel) + if(1 to 2) probab = 20 + if(3 to 4) probab = 30 + if(5 to 6) probab = 40 + if(7 to 8) probab = 60 + if(9) probab = 70 + if(10) probab = 95 + if(prob(probab)) + if(istype(O, /obj/structure/window) || istype(O, /obj/structure/grille)) + if(isslimeadult(src)) + if(nutrition <= 600 && !Atkcool) + O.attack_slime(src) + spawn() + Atkcool = 1 + sleep(15) + Atkcool = 0 + else + if(nutrition <= 500 && !Atkcool) + if(prob(5)) + O.attack_slime(src) + spawn() + Atkcool = 1 + sleep(15) + Atkcool = 0 + +/mob/living/carbon/slime/MobBump(mob/M) + if(ishuman(M)) //pushing humans + if(isslimeadult(src) && prob(10)) //only if we're adult, and 10% of the time + return 0 + else + return 1 + +/mob/living/carbon/slime/Process_Spacemove(movement_dir = 0) + return 2 + +/mob/living/carbon/slime/Stat() + ..() + + if(statpanel("Status")) + if(isslimeadult(src)) + stat(null, "Health: [round((health / 200) * 100)]%") + stat(null, "Nutrition: [nutrition]/1200") + if(amount_grown >= 10) + stat(null, "You can reproduce!") + else + stat(null, "Health: [round((health / 150) * 100)]%") + stat(null, "Nutrition: [nutrition]/1000") + if(amount_grown >= 10) + stat(null, "You can evolve!") + + stat(null,"Power Level: [powerlevel]") + + +/mob/living/carbon/slime/adjustFireLoss(amount) + ..(-abs(amount)) // Heals them + return + +/mob/living/carbon/slime/bullet_act(obj/item/projectile/Proj) + attacked += 10 + ..(Proj) + return 0 + + +/mob/living/carbon/slime/emp_act(severity) + powerlevel = 0 // oh no, the power! + ..() + +/mob/living/carbon/slime/ex_act(severity) + + if (stat == DEAD && client) + return + + else if (stat == DEAD && !client) + qdel(src) + return + + var/b_loss = null + var/f_loss = null + switch (severity) + if (1.0) + b_loss += 500 + return + + if (2.0) + + b_loss += 60 + f_loss += 60 + + + if(3.0) + b_loss += 30 + + adjustBruteLoss(b_loss) + adjustFireLoss(f_loss) + + updatehealth() + + +/mob/living/carbon/slime/blob_act() + if (stat == DEAD) + return + var/shielded = 0 + + var/damage = null + if (stat != DEAD) + damage = rand(10,30) + + if(shielded) + damage /= 4 + + //paralysis += 1 + + show_message("\red The blob attacks you!") + + adjustFireLoss(damage) + + updatehealth() + return + + +/mob/living/carbon/slime/u_equip(obj/item/W) + return + + +/mob/living/carbon/slime/attack_ui(slot) + return + +/mob/living/carbon/slime/meteorhit(O) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message(text("\red [] has been hit by []", src, O), 1) + if (health > 0) + adjustBruteLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25)) + adjustFireLoss(30) + + updatehealth() + return + + +/mob/living/carbon/slime/attack_slime(mob/living/carbon/slime/M) + if (!ticker) + to_chat(M, "You cannot attack people before the game has started.") + return + + if(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("\red The [M.name] has glomped []!", src), 1) + + var/damage = rand(1, 3) + attacked += 5 + + if(istype(src, /mob/living/carbon/slime/adult)) + damage = rand(1, 6) + else + damage = rand(1, 3) + + adjustBruteLoss(damage) + + + updatehealth() + + return + + +/mob/living/carbon/slime/attack_animal(mob/living/simple_animal/M) + if(..()) + 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) + visible_message("[M][M.attacktext] [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) + adjustBruteLoss(damage) + updatehealth() + +/mob/living/carbon/slime/attack_paw(mob/living/carbon/monkey/M) + 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 + + 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 ("help") + help_shake_act(M) + else + if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) + return + if (health > 0) + attacked += 10 + //playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [M.name] has attacked [src]!"), 1) + adjustBruteLoss(rand(1, 3)) + updatehealth() + return + + +/mob/living/carbon/slime/attack_hand(mob/living/carbon/human/M) + 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 + + ..() + + if(Victim) + if(Victim == M) + if(prob(60)) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\red [M] attempts to wrestle \the [name] off!", 1) + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + + else + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\red [M] manages to wrestle \the [name] off!", 1) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + + if(prob(90) && !client) + Discipline++ + + spawn() + SStun = 1 + sleep(rand(45,60)) + if(src) + SStun = 0 + + Victim = null + anchored = 0 + step_away(src,M) + + return + + else + M.do_attack_animation(src) + if(prob(30)) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\red [M] attempts to wrestle \the [name] off of [Victim]!", 1) + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + + else + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\red [M] manages to wrestle \the [name] off of [Victim]!", 1) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + + if(prob(80) && !client) + Discipline++ + + if(!istype(src, /mob/living/carbon/slime/adult)) + if(Discipline == 1) + attacked = 0 + + spawn() + SStun = 1 + sleep(rand(55,65)) + if(src) + SStun = 0 + + Victim = null + anchored = 0 + step_away(src,M) + + 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 == "hurt")//Stungloves. Any contact will stun the alien. + if(G.cell.charge >= 2500) + G.cell.use(2500) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\red [src] has been touched with the stun gloves by [M]!", 1, "\red You hear someone fall.", 2) + return + else + to_chat(M, "\red Not enough charge! ") + return + + switch(M.a_intent) + + if ("help") + help_shake_act(M) + + if ("grab") + if (M == src || M.lying) + return + var/obj/item/weapon/grab/G = new /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)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + + else + + var/damage = rand(1, 9) + + attacked += 10 + if (prob(90)) + if (HULK in M.mutations) + damage += 5 + if(Victim) + Victim = null + anchored = 0 + if(prob(80) && !client) + Discipline++ + spawn(0) + + step_away(src,M,15) + sleep(3) + step_away(src,M,15) + + + playsound(loc, "punch", 25, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has punched []!", M, src), 1) + + 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("\red [] has attempted to punch []!", M, src), 1) + return + + + +/mob/living/carbon/slime/attack_alien(mob/living/carbon/alien/humanoid/M) + 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 ("help") + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) + + if ("hurt") + + if ((prob(95) && health > 0)) + attacked += 10 + playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) + var/damage = rand(15, 30) + if (damage >= 25) + damage = rand(20, 40) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has attacked [name]!", M), 1) + else + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has wounded [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("\red [] has attempted to lunge at [name]!", M), 1) + + if ("grab") + if (M == src || M.lying) + return + var/obj/item/weapon/grab/G = new /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("\red [] has grabbed [name] passively!", M), 1) + + if ("disarm") + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + var/damage = 5 + attacked += 10 + + if(prob(95)) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has tackled [name]!", M), 1) + + if(Victim) + Victim = null + anchored = 0 + if(prob(80) && !client) + Discipline++ + if(!istype(src, /mob/living/carbon/slime)) + if(Discipline == 1) + attacked = 0 + + spawn() + SStun = 1 + sleep(rand(5,20)) + SStun = 0 + + spawn(0) + + step_away(src,M,15) + sleep(3) + step_away(src,M,15) + + else + drop_item() + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has disarmed [name]!", M), 1) + adjustBruteLoss(damage) + updatehealth() + return + + +/mob/living/carbon/slime/restrained() + return 0 + + +/mob/living/carbon/slime/show_inv(mob/user) + + user.set_machine(src) + var/dat = {" +
                    [name]
                    +


                    +
                    Close +
                    "} + user << browse(entity_ja(dat), text("window=mob[name];size=340x480")) + onclose(user, "mob[name]") + return + +/mob/living/carbon/slime/updatehealth() + if(status_flags & GODMODE) + if(istype(src, /mob/living/carbon/slime/adult)) + health = 200 + else + health = 150 + stat = CONSCIOUS + else + // slimes can't suffocate unless they suicide. They are also not harmed by fire + if(istype(src, /mob/living/carbon/slime/adult)) + health = 200 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) + else + health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss()) + + +/obj/item/slime_extract + name = "slime extract" + desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"." + icon = 'icons/mob/slimes.dmi' + icon_state = "grey slime extract" + force = 1.0 + w_class = 1.0 + throwforce = 1.0 + throw_speed = 3 + throw_range = 6 + origin_tech = "biotech=4" + var/Uses = 1 // uses before it goes inert + var/enhanced = 0 // has it been enhanced before? + attackby(obj/item/weapon/O, mob/user) + if(istype(O, /obj/item/weapon/slimesteroid2)) + if(enhanced == 1) + to_chat(user, "\red This extract has already been enhanced!") + return ..() + if(Uses == 0) + to_chat(user, "\red You can't enhance a used extract!") + return ..() + to_chat(user, "You apply the enhancer. It now has triple the amount of uses.") + Uses = 3 + enhanced = 1 + qdel(O) + +/obj/item/slime_extract/atom_init() + . = ..() + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + +/obj/item/slime_extract/grey + name = "grey slime extract" + icon_state = "grey slime extract" + +/obj/item/slime_extract/gold + name = "gold slime extract" + icon_state = "gold slime extract" + +/obj/item/slime_extract/silver + name = "silver slime extract" + icon_state = "silver slime extract" + +/obj/item/slime_extract/metal + name = "metal slime extract" + icon_state = "metal slime extract" + +/obj/item/slime_extract/purple + name = "purple slime extract" + icon_state = "purple slime extract" + +/obj/item/slime_extract/darkpurple + name = "dark purple slime extract" + icon_state = "dark purple slime extract" + +/obj/item/slime_extract/orange + name = "orange slime extract" + icon_state = "orange slime extract" + +/obj/item/slime_extract/yellow + name = "yellow slime extract" + icon_state = "yellow slime extract" + +/obj/item/slime_extract/red + name = "red slime extract" + icon_state = "red slime extract" + +/obj/item/slime_extract/blue + name = "blue slime extract" + icon_state = "blue slime extract" + +/obj/item/slime_extract/darkblue + name = "dark blue slime extract" + icon_state = "dark blue slime extract" + +/obj/item/slime_extract/pink + name = "pink slime extract" + icon_state = "pink slime extract" + +/obj/item/slime_extract/green + name = "green slime extract" + icon_state = "green slime extract" + +/obj/item/slime_extract/lightpink + name = "light pink slime extract" + icon_state = "light pink slime extract" + +/obj/item/slime_extract/black + name = "black slime extract" + icon_state = "black slime extract" + +/obj/item/slime_extract/oil + name = "oil slime extract" + icon_state = "oil slime extract" + +/obj/item/slime_extract/adamantine + name = "adamantine slime extract" + icon_state = "adamantine slime extract" + +//Zve added +/obj/item/slime_extract/bluespace + name = "bluespace slime extract" + icon_state = "bluespace slime extract" + +/obj/item/slime_extract/pyrite + name = "pyrite slime extract" + icon_state = "pyrite slime extract" + +/obj/item/slime_extract/cerulean + name = "cerulean slime extract" + icon_state = "cerulean slime extract" + +/obj/item/slime_extract/sepia + name = "sepia slime extract" + icon_state = "sepia slime extract" + +/obj/item/slime_extract/rainbow + name = "rainbow slime extract" + icon_state = "rainbow slime extract" + +////Pet Slime Creation/// + +/obj/item/weapon/slimepotion + name = "docility potion" + desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame." + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle19" + + attack(mob/living/carbon/slime/M, mob/user) + if(!istype(M, /mob/living/carbon/slime))//If target is not a slime. + to_chat(user, "\red The potion only works on baby slimes!") + return ..() + if(istype(M, /mob/living/carbon/slime/adult)) //Can't tame adults + to_chat(user, "\red Only baby slimes can be tamed!") + return..() + if(M.stat) + to_chat(user, "\red The slime is dead!") + return..() + var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc) + pet.icon_state = "[M.colour] baby slime" + pet.icon_living = "[M.colour] baby slime" + pet.icon_dead = "[M.colour] baby slime dead" + pet.colour = "[M.colour]" + to_chat(user, "You feed the slime the potion, removing it's powers and calming it.") + qdel(M) + var/newname = sanitize_safe(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text, MAX_NAME_LEN) + + if (!newname) + newname = "pet slime" + pet.name = newname + pet.real_name = newname + qdel(src) + +/obj/item/weapon/slimepotion2 + name = "advanced docility potion" + desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes." + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle19" + + attack(mob/living/carbon/slime/adult/M, mob/user) + if(!istype(M, /mob/living/carbon/slime/adult))//If target is not a slime. + to_chat(user, "\red The potion only works on adult slimes!") + return ..() + if(M.stat) + to_chat(user, "\red The slime is dead!") + return..() + var/mob/living/simple_animal/adultslime/pet = new /mob/living/simple_animal/adultslime(M.loc) + pet.icon_state = "[M.colour] adult slime" + pet.icon_living = "[M.colour] adult slime" + pet.icon_dead = "[M.colour] baby slime dead" + pet.colour = "[M.colour]" + to_chat(user, "You feed the slime the potion, removing it's powers and calming it.") + qdel(M) + var/newname = sanitize_safe(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text, MAX_NAME_LEN) + + if (!newname) + newname = "pet slime" + pet.name = newname + pet.real_name = newname + qdel(src) + + +/obj/item/weapon/slimesteroid + name = "slime steroid" + desc = "A potent chemical mix that will cause a slime to generate more extract." + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + + attack(mob/living/carbon/slime/M, mob/user) + if(!istype(M, /mob/living/carbon/slime))//If target is not a slime. + to_chat(user, "\red The steroid only works on baby slimes!") + return ..() + if(istype(M, /mob/living/carbon/slime/adult)) //Can't tame adults + to_chat(user, "\red Only baby slimes can use the steroid!") + return..() + if(M.stat) + to_chat(user, "\red The slime is dead!") + return..() + if(M.cores == 3) + to_chat(user, "\red The slime already has the maximum amount of extract!") + return..() + + to_chat(user, "You feed the slime the steroid. It now has triple the amount of extract.") + M.cores = 3 + qdel(src) + +/obj/item/weapon/slimesteroid2 + name = "extract enhancer" + desc = "A potent chemical mix that will give a slime extract three uses." + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle17" + +////////Adamantine Golem stuff I dunno where else to put it + +/obj/item/clothing/under/golem + name = "adamantine skin" + desc = "A golem's skin." + icon_state = "golem" + item_state = "golem" + item_color = "golem" + has_sensor = 0 + canremove = 0 + unacidable = 1 + flags = ABSTRACT | DROPDEL + + +/obj/item/clothing/shoes/golem + name = "golem's feet" + desc = "Sturdy adamantine feet." + icon_state = "golem" + item_state = null + canremove = 0 + flags = ABSTRACT | DROPDEL | NOSLIP + unacidable = 1 + + +/obj/item/clothing/mask/gas/golem + name = "golem's face" + desc = "The imposing face of an adamantine golem." + icon_state = "golem" + item_state = "golem" + canremove = 0 + siemens_coefficient = 0 + unacidable = 1 + flags = ABSTRACT | DROPDEL + flags_inv = 0 + + +/obj/item/clothing/gloves/golem + name = "golem's hands" + desc = "Strong adamantine hands." + icon_state = "golem" + item_state = null + siemens_coefficient = 0 + canremove = 0 + unacidable = 1 + flags = ABSTRACT | DROPDEL + + +/obj/item/clothing/head/helmet/space/golem + icon_state = "golem" + item_state = "dermal" + item_color = "dermal" + name = "golem's head" + desc = "A golem's head." + canremove = 0 + unacidable = 1 + + body_parts_covered = HEAD|FACE|EYES + cold_protection = HEAD + min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = HEAD + max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE + + flags = ABSTRACT | DROPDEL + flags_inv = 0 + slowdown = 0 + unacidable = 1 + canremove = 0 + siemens_coefficient = 0 + + armor = list(melee = 77, bullet = 66, laser = 44, energy = 44, bomb = 80, bio = 100, rad = 80) + + +/obj/item/clothing/suit/space/golem + name = "adamantine shell" + desc = "A golem's thick outter shell." + icon_state = "golem" + item_state = "golem" + w_class = 4//bulky item + allowed = null + + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE + heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE + + flags = ABSTRACT | DROPDEL + flags_inv = HIDEGLOVES | HIDESHOES | HIDEJUMPSUIT + slowdown = 0 + unacidable = 1 + canremove = 0 + siemens_coefficient = 0 + can_breach = 0 + + armor = list(melee = 77, bullet = 66, laser = 44, energy = 44, bomb = 80, bio = 100, rad = 80) + +/obj/effect/golemrune + anchored = 1 + desc = "A strange rune used to create golems. It glows when spirits are nearby." + name = "rune" + icon = 'icons/obj/rune.dmi' + icon_state = "golem" + unacidable = 1 + layer = TURF_LAYER + var/last_ghost_click = 0 + var/mob/dead/observer/spirit + +/obj/effect/golemrune/atom_init() + . = ..() + announce_to_ghosts() + +/obj/effect/golemrune/update_icon() + if(spirit) + icon_state = "golem2" + else + icon_state = "golem" + +/obj/effect/golemrune/process() + check_spirit() + +/obj/effect/golemrune/attack_ghost(mob/dead/observer/user) + if(user.mind && user.mind.current && user.mind.current.stat != DEAD) + to_chat(user, "Your spirit linked to another body.") + return + if(user.golem_rune && user.golem_rune != src) + to_chat(user, "One rune per one poor little spirit.") + return + if(spirit && spirit != user) + to_chat(user, "This rune is taken by another spirit, wait or find new one.") + return + if(last_ghost_click >= world.time) + to_chat(user, "You cannot do this so often.") + return + if(user == spirit) + for(var/image/I in user.client.images) + if(I.loc == src && I.icon_state == "agolem_master") + user.client.images -= I + break + spirit = null + user.golem_rune = null + to_chat(user, "You are no longer queued for golem role.") + else + START_PROCESSING(SSobj, src) + last_ghost_click = world.time + 50 + var/image/I = image('icons/mob/hud.dmi', src, "agolem_master") //If there is alot activated rune close by, we can see which is ours. + user.client.images += I + spirit = user + user.golem_rune = src + to_chat(user, "You are now queued for golem role.") + check_spirit() + +/obj/effect/golemrune/attack_hand(mob/living/user) + if(!check_spirit()) + to_chat(user, "The rune fizzles uselessly. There is no spirit nearby.") + return + user.SetNextMove(CLICK_CD_INTERACT) + var/mob/living/carbon/human/golem/G = new(loc) + G.attack_log = spirit.attack_log //Preserve attack log, if there is any... + G.attack_log += "\[[time_stamp()]\] ======GOLEM LIFE======" + G.key = spirit.key + G.my_master = user + G.update_golem_hud_icons() + if(istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + H.my_golems += G + H.update_golem_hud_icons() + to_chat(G, "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost.") + qdel(src) + +/obj/effect/golemrune/proc/announce_to_ghosts() + for(var/mob/dead/observer/O in player_list) + if(O.client) + var/area/A = get_area(src) + if(A) + to_chat(O, "Golem rune created in [A.name] (JMP).") + +/obj/effect/golemrune/proc/check_spirit() + var/result = 1 + if(!spirit) + result = 0 + else if(spirit && (!spirit.client || spirit.mind && spirit.mind.current && spirit.mind.current.stat != DEAD)) + spirit.golem_rune = null + spirit = null + result = 0 + if(!result) + STOP_PROCESSING(SSobj, src) + update_icon() + return result + +/mob/living/carbon/human/proc/update_golem_hud_icons() + if(client) + if(dna && (dna.mutantrace == "adamantine")) + if(my_master) + var/I = image('icons/mob/hud.dmi', loc = my_master, icon_state = "agolem_master") + client.images += I + else + if(my_golems) + for(var/mob/living/carbon/human/G in my_golems) + var/I = image('icons/mob/hud.dmi', loc = G, icon_state = "agolem_master") + client.images += I + + +/mob/living/carbon/slime/getTrail() + return null + +//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them//////////////////////// + +/* +// Basically this slime Core catalyzes reactions that normally wouldn't happen anywhere +/obj/item/slime_core + name = "slime extract" + desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"." + icon = 'icons/mob/slimes.dmi' + icon_state = "slime extract" + force = 1.0 + w_class = 1.0 + throwforce = 1.0 + throw_speed = 3 + throw_range = 6 + origin_tech = "biotech=4" + var/POWERFLAG = 0 // sshhhhhhh + var/Flush = 30 + var/Uses = 5 // uses before it goes inert + +/obj/item/slime_core/atom_init() + . = ..() + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + POWERFLAG = rand(1,10) + Uses = rand(7, 25) + //flags |= NOREACT + + spawn() + Life() + +/obj/item/slime_core/proc/Life() + while(src) + sleep(25) + Flush-- + if(Flush <= 0) + reagents.clear_reagents() + Flush = 30 +*/ + + + +/obj/item/weapon/reagent_containers/food/snacks/egg/slime + name = "slime egg" + desc = "A small, gelatinous egg." + icon = 'icons/mob/mob.dmi' + icon_state = "slime egg-growing" + bitesize = 12 + origin_tech = "biotech=4" + var/grown = 0 + +/obj/item/weapon/reagent_containers/food/snacks/egg/slime/atom_init() + . = ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("slimejelly", 1) + addtimer(CALLBACK(src, .proc/Grow), rand(1200,1500)) // the egg takes a while to "ripen" + +/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Grow() + grown = 1 + icon_state = "slime egg-grown" + START_PROCESSING(SSobj, src) + return + +/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch() + STOP_PROCESSING(SSobj, src) + var/turf/T = get_turf(src) + src.visible_message("\blue The [name] pulsates and quivers!") + spawn(rand(50,100)) + src.visible_message("\blue The [name] bursts open!") + new/mob/living/carbon/slime(T) + qdel(src) + + +/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process() + var/turf/location = get_turf(src) + var/datum/gas_mixture/environment = location.return_air() + if (environment.gas["phoron"] > MOLES_PHORON_VISIBLE)//phoron exposure causes the egg to hatch + src.Hatch() + +/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W, mob/user) + if(istype( W, /obj/item/toy/crayon )) + return + else + ..() diff --git a/code/modules/mob/living/carbon/metroid/powers.dm b/code/modules/mob/living/carbon/metroid/powers.dm index 50e7cbd86ef3..e981a4e641a0 100644 --- a/code/modules/mob/living/carbon/metroid/powers.dm +++ b/code/modules/mob/living/carbon/metroid/powers.dm @@ -1,259 +1,259 @@ -/mob/living/carbon/slime/verb/Feed() - set category = "Slime" - set desc = "This will let you feed on any valid creature in the surrounding area. This should also be used to halt the feeding process." - if(Victim) - Feedstop() - return - - if(stat) - to_chat(src, "I must be conscious to do this...") - return - - var/list/choices = list() - for(var/mob/living/C in view(1,src)) - if(C!=src && !istype(C,/mob/living/carbon/slime)) - choices += C - - var/mob/living/carbon/M = input(src,"Who do you wish to feed on?") in null|choices - if(!M) return - if(M in view(1, src)) - - if(!istype(src, /mob/living/carbon/brain)) - if(!istype(M, /mob/living/carbon/slime)) - if(stat != DEAD) - if(health > -70) - - for(var/mob/living/carbon/slime/met in view()) - if(met.Victim == M && met != src) - to_chat(src, "The [met.name] is already feeding on this subject...") - return - to_chat(src, "\blue I have latched onto the subject and begun feeding...") - to_chat(M, "\red The [src.name] has latched onto your head!") - Feedon(M) - - else - to_chat(src, "This subject does not have a strong enough life energy...") - else - to_chat(src, "This subject does not have an edible life energy...") - else - to_chat(src, "I must not feed on my brothers...") - else - to_chat(src, "This subject does not have an edible life energy...") - - - -/mob/living/carbon/slime/proc/Feedon(mob/living/carbon/M) - Victim = M - src.loc = M.loc - canmove = 0 - anchored = 1 - var/lastnut = nutrition - //if(M.client) M << "\red You legs become paralyzed!" - if(istype(src, /mob/living/carbon/slime/adult)) - icon_state = "[colour] adult slime eat" - else - icon_state = "[colour] baby slime eat" - - while(Victim && M.health > -70 && stat != DEAD) - // M.canmove = 0 - canmove = 0 - - if(M in view(1, src)) - loc = M.loc - - if(prob(15) && M.client && istype(M, /mob/living/carbon)) - to_chat(M, "\red [pick("You can feel your body becoming weak!", \ - "You feel like you're about to die!", \ - "You feel every part of your body screaming in agony!", \ - "A low, rolling pain passes through your body!", \ - "Your body feels as if it's falling apart!", \ - "You feel extremely weak!", \ - "A sharp, deep pain bathes every inch of your body!")]") - - if(istype(M, /mob/living/carbon)) - Victim.adjustCloneLoss(rand(1,10)) - Victim.adjustToxLoss(rand(1,2)) - if(Victim.health <= 0) - Victim.adjustToxLoss(rand(2,4)) - - // Heal yourself - adjustToxLoss(-10) - adjustOxyLoss(-10) - adjustBruteLoss(-10) - adjustFireLoss(-10) - adjustCloneLoss(-10) - - if(Victim) - for(var/mob/living/carbon/slime/slime in view(1,M)) - if(slime.Victim == M && slime != src) - slime.Feedstop() - - nutrition += rand(10,25) - if(nutrition >= lastnut + 50) - if(prob(80)) - lastnut = nutrition - powerlevel++ - if(powerlevel > 10) - powerlevel = 10 - - if(istype(src, /mob/living/carbon/slime/adult)) - if(nutrition > 1200) - nutrition = 1200 - else - if(nutrition > 1000) - nutrition = 1000 - - Victim.updatehealth() - updatehealth() - - else - if(prob(25)) - to_chat(src, "\red [pick("This subject is incompatable", \ - "This subject does not have a life energy", "This subject is empty", \ - "I am not satisified", "I can not feed from this subject", \ - "I do not feel nourished", "This subject is not food")]...") - - sleep(rand(15,45)) - - else - break - - if(stat == DEAD) - if(!istype(src, /mob/living/carbon/slime/adult)) - icon_state = "[colour] baby slime dead" - - else - if(istype(src, /mob/living/carbon/slime/adult)) - icon_state = "[colour] adult slime" - else - icon_state = "[colour] baby slime" - - canmove = 1 - anchored = 0 - - if(M) - if(M.health <= -70) - M.canmove = 0 - if(!client) - if(Victim && !rabid && !attacked) - if(Victim.LAssailant && Victim.LAssailant != Victim) - if(prob(50)) - if(!(Victim.LAssailant in Friends)) - Friends[Victim.LAssailant] = 1 - else - ++Friends[Victim.LAssailant] - if(M.client && istype(src, /mob/living/carbon/human)) - if(prob(85)) - rabid = 1 // UUUNNBGHHHH GONNA EAT JUUUUUU - - if(client) - to_chat(src, "This subject does not have a strong enough life energy anymore...") - else - M.canmove = 1 - - if(client) - to_chat(src, "I have stopped feeding...") - else - if(client) - to_chat(src, "I have stopped feeding...") - - Victim = null - -/mob/living/carbon/slime/proc/Feedstop() - if(Victim) - if(Victim.client) - to_chat(Victim, "[src] has let go of your head!") - Victim = null - -/mob/living/carbon/slime/proc/UpdateFeed(mob/M) - if(Victim) - if(Victim == M) - loc = M.loc // simple "attach to head" effect! - - -/mob/living/carbon/slime/verb/Evolve() - set category = "Slime" - set desc = "This will let you evolve from baby to adult slime." - - if(stat) - to_chat(src, "I must be conscious to do this...") - return - if(!istype(src, /mob/living/carbon/slime/adult)) - if(amount_grown >= 10) - var/mob/living/carbon/slime/adult/new_slime = new adulttype(loc) - new_slime.nutrition = nutrition - new_slime.powerlevel = max(0, powerlevel-1) - new_slime.a_intent = "hurt" - new_slime.key = key - new_slime.universal_speak = universal_speak - to_chat(new_slime, "You are now an adult slime.") - qdel(src) - else - to_chat(src, "I am not ready to evolve yet...") - else - to_chat(src, "I have already evolved...") - -/mob/living/carbon/slime/verb/Reproduce() - set category = "Slime" - set desc = "This will make you split into four Slimes. NOTE: this will KILL you, but you will be transferred into one of the babies." - - if(stat) - to_chat(src, "I must be conscious to do this...") - return - - if(istype(src, /mob/living/carbon/slime/adult)) - if(amount_grown >= 10) - //if(input("Are you absolutely sure you want to reproduce? Your current body will cease to be, but your consciousness will be transferred into a produced slime.") in list("Yes","No")=="Yes") - if(stat) - to_chat(src, "I must be conscious to do this...") - return - - var/list/babies = list() - var/new_nutrition = round(nutrition * 0.9) - var/new_powerlevel = round(powerlevel / 4) - for(var/i=1,i<=4,i++) - if(prob(80)) - var/mob/living/carbon/slime/M = new primarytype(loc) - M.nutrition = new_nutrition - M.powerlevel = new_powerlevel - if(i != 1) step_away(M,src) - babies += M - else - var/mutations = pick("one","two","three","four") - switch(mutations) - if("one") - var/mob/living/carbon/slime/M = new mutationone(loc) - M.nutrition = new_nutrition - M.powerlevel = new_powerlevel - if(i != 1) step_away(M,src) - babies += M - if("two") - var/mob/living/carbon/slime/M = new mutationtwo(loc) - M.nutrition = new_nutrition - M.powerlevel = new_powerlevel - if(i != 1) step_away(M,src) - babies += M - if("three") - var/mob/living/carbon/slime/M = new mutationthree(loc) - M.nutrition = new_nutrition - M.powerlevel = new_powerlevel - if(i != 1) step_away(M,src) - babies += M - if("four") - var/mob/living/carbon/slime/M = new mutationfour(loc) - M.nutrition = new_nutrition - M.powerlevel = new_powerlevel - if(i != 1) step_away(M,src) - babies += M - - var/mob/living/carbon/slime/new_slime = pick(babies) - new_slime.a_intent = "hurt" - new_slime.universal_speak = universal_speak - new_slime.key = key - - to_chat(new_slime, "You are now a slime!") - qdel(src) - else - to_chat(src, "I am not ready to reproduce yet...") - else - to_chat(src, "I am not old enough to reproduce yet...") +/mob/living/carbon/slime/verb/Feed() + set category = "Slime" + set desc = "This will let you feed on any valid creature in the surrounding area. This should also be used to halt the feeding process." + if(Victim) + Feedstop() + return + + if(stat) + to_chat(src, "I must be conscious to do this...") + return + + var/list/choices = list() + for(var/mob/living/C in view(1,src)) + if(C!=src && !istype(C,/mob/living/carbon/slime)) + choices += C + + var/mob/living/carbon/M = input(src,"Who do you wish to feed on?") in null|choices + if(!M) return + if(M in view(1, src)) + + if(!istype(src, /mob/living/carbon/brain)) + if(!istype(M, /mob/living/carbon/slime)) + if(stat != DEAD) + if(health > -70) + + for(var/mob/living/carbon/slime/met in view()) + if(met.Victim == M && met != src) + to_chat(src, "The [met.name] is already feeding on this subject...") + return + to_chat(src, "\blue I have latched onto the subject and begun feeding...") + to_chat(M, "\red The [src.name] has latched onto your head!") + Feedon(M) + + else + to_chat(src, "This subject does not have a strong enough life energy...") + else + to_chat(src, "This subject does not have an edible life energy...") + else + to_chat(src, "I must not feed on my brothers...") + else + to_chat(src, "This subject does not have an edible life energy...") + + + +/mob/living/carbon/slime/proc/Feedon(mob/living/carbon/M) + Victim = M + src.loc = M.loc + canmove = 0 + anchored = 1 + var/lastnut = nutrition + //if(M.client) M << "\red You legs become paralyzed!" + if(istype(src, /mob/living/carbon/slime/adult)) + icon_state = "[colour] adult slime eat" + else + icon_state = "[colour] baby slime eat" + + while(Victim && M.health > -70 && stat != DEAD) + // M.canmove = 0 + canmove = 0 + + if(M in view(1, src)) + loc = M.loc + + if(prob(15) && M.client && istype(M, /mob/living/carbon)) + to_chat(M, "\red [pick("You can feel your body becoming weak!", \ + "You feel like you're about to die!", \ + "You feel every part of your body screaming in agony!", \ + "A low, rolling pain passes through your body!", \ + "Your body feels as if it's falling apart!", \ + "You feel extremely weak!", \ + "A sharp, deep pain bathes every inch of your body!")]") + + if(istype(M, /mob/living/carbon)) + Victim.adjustCloneLoss(rand(1,10)) + Victim.adjustToxLoss(rand(1,2)) + if(Victim.health <= 0) + Victim.adjustToxLoss(rand(2,4)) + + // Heal yourself + adjustToxLoss(-10) + adjustOxyLoss(-10) + adjustBruteLoss(-10) + adjustFireLoss(-10) + adjustCloneLoss(-10) + + if(Victim) + for(var/mob/living/carbon/slime/slime in view(1,M)) + if(slime.Victim == M && slime != src) + slime.Feedstop() + + nutrition += rand(10,25) + if(nutrition >= lastnut + 50) + if(prob(80)) + lastnut = nutrition + powerlevel++ + if(powerlevel > 10) + powerlevel = 10 + + if(istype(src, /mob/living/carbon/slime/adult)) + if(nutrition > 1200) + nutrition = 1200 + else + if(nutrition > 1000) + nutrition = 1000 + + Victim.updatehealth() + updatehealth() + + else + if(prob(25)) + to_chat(src, "\red [pick("This subject is incompatable", \ + "This subject does not have a life energy", "This subject is empty", \ + "I am not satisified", "I can not feed from this subject", \ + "I do not feel nourished", "This subject is not food")]...") + + sleep(rand(15,45)) + + else + break + + if(stat == DEAD) + if(!istype(src, /mob/living/carbon/slime/adult)) + icon_state = "[colour] baby slime dead" + + else + if(istype(src, /mob/living/carbon/slime/adult)) + icon_state = "[colour] adult slime" + else + icon_state = "[colour] baby slime" + + canmove = 1 + anchored = 0 + + if(M) + if(M.health <= -70) + M.canmove = 0 + if(!client) + if(Victim && !rabid && !attacked) + if(Victim.LAssailant && Victim.LAssailant != Victim) + if(prob(50)) + if(!(Victim.LAssailant in Friends)) + Friends[Victim.LAssailant] = 1 + else + ++Friends[Victim.LAssailant] + if(M.client && istype(src, /mob/living/carbon/human)) + if(prob(85)) + rabid = 1 // UUUNNBGHHHH GONNA EAT JUUUUUU + + if(client) + to_chat(src, "This subject does not have a strong enough life energy anymore...") + else + M.canmove = 1 + + if(client) + to_chat(src, "I have stopped feeding...") + else + if(client) + to_chat(src, "I have stopped feeding...") + + Victim = null + +/mob/living/carbon/slime/proc/Feedstop() + if(Victim) + if(Victim.client) + to_chat(Victim, "[src] has let go of your head!") + Victim = null + +/mob/living/carbon/slime/proc/UpdateFeed(mob/M) + if(Victim) + if(Victim == M) + loc = M.loc // simple "attach to head" effect! + + +/mob/living/carbon/slime/verb/Evolve() + set category = "Slime" + set desc = "This will let you evolve from baby to adult slime." + + if(stat) + to_chat(src, "I must be conscious to do this...") + return + if(!istype(src, /mob/living/carbon/slime/adult)) + if(amount_grown >= 10) + var/mob/living/carbon/slime/adult/new_slime = new adulttype(loc) + new_slime.nutrition = nutrition + new_slime.powerlevel = max(0, powerlevel-1) + new_slime.a_intent = "hurt" + new_slime.key = key + new_slime.universal_speak = universal_speak + to_chat(new_slime, "You are now an adult slime.") + qdel(src) + else + to_chat(src, "I am not ready to evolve yet...") + else + to_chat(src, "I have already evolved...") + +/mob/living/carbon/slime/verb/Reproduce() + set category = "Slime" + set desc = "This will make you split into four Slimes. NOTE: this will KILL you, but you will be transferred into one of the babies." + + if(stat) + to_chat(src, "I must be conscious to do this...") + return + + if(istype(src, /mob/living/carbon/slime/adult)) + if(amount_grown >= 10) + //if(input("Are you absolutely sure you want to reproduce? Your current body will cease to be, but your consciousness will be transferred into a produced slime.") in list("Yes","No")=="Yes") + if(stat) + to_chat(src, "I must be conscious to do this...") + return + + var/list/babies = list() + var/new_nutrition = round(nutrition * 0.9) + var/new_powerlevel = round(powerlevel / 4) + for(var/i=1,i<=4,i++) + if(prob(80)) + var/mob/living/carbon/slime/M = new primarytype(loc) + M.nutrition = new_nutrition + M.powerlevel = new_powerlevel + if(i != 1) step_away(M,src) + babies += M + else + var/mutations = pick("one","two","three","four") + switch(mutations) + if("one") + var/mob/living/carbon/slime/M = new mutationone(loc) + M.nutrition = new_nutrition + M.powerlevel = new_powerlevel + if(i != 1) step_away(M,src) + babies += M + if("two") + var/mob/living/carbon/slime/M = new mutationtwo(loc) + M.nutrition = new_nutrition + M.powerlevel = new_powerlevel + if(i != 1) step_away(M,src) + babies += M + if("three") + var/mob/living/carbon/slime/M = new mutationthree(loc) + M.nutrition = new_nutrition + M.powerlevel = new_powerlevel + if(i != 1) step_away(M,src) + babies += M + if("four") + var/mob/living/carbon/slime/M = new mutationfour(loc) + M.nutrition = new_nutrition + M.powerlevel = new_powerlevel + if(i != 1) step_away(M,src) + babies += M + + var/mob/living/carbon/slime/new_slime = pick(babies) + new_slime.a_intent = "hurt" + new_slime.universal_speak = universal_speak + new_slime.key = key + + to_chat(new_slime, "You are now a slime!") + qdel(src) + else + to_chat(src, "I am not ready to reproduce yet...") + else + to_chat(src, "I am not old enough to reproduce yet...") diff --git a/code/modules/mob/living/carbon/metroid/subtypes.dm b/code/modules/mob/living/carbon/metroid/subtypes.dm index 233af3f306c8..acfccf0b7b55 100644 --- a/code/modules/mob/living/carbon/metroid/subtypes.dm +++ b/code/modules/mob/living/carbon/metroid/subtypes.dm @@ -1,482 +1,482 @@ - -////////////////Tier 2 - -/mob/living/carbon/slime/purple - colour = "purple" - icon_state = "purple baby slime" - primarytype = /mob/living/carbon/slime/purple - mutationone = /mob/living/carbon/slime/darkpurple - mutationtwo = /mob/living/carbon/slime/darkblue - mutationthree = /mob/living/carbon/slime/green - mutationfour = /mob/living/carbon/slime/green - adulttype = /mob/living/carbon/slime/adult/purple - coretype = /obj/item/slime_extract/purple - -/mob/living/carbon/slime/adult/purple - icon_state = "purple adult slime" - colour = "purple" - primarytype = /mob/living/carbon/slime/purple - mutationone = /mob/living/carbon/slime/darkpurple - mutationtwo = /mob/living/carbon/slime/darkblue - mutationthree = /mob/living/carbon/slime/green - mutationfour = /mob/living/carbon/slime/green - adulttype = /mob/living/carbon/slime/adult/purple - coretype = /obj/item/slime_extract/purple - -/mob/living/carbon/slime/metal - colour = "metal" - icon_state = "metal baby slime" - primarytype = /mob/living/carbon/slime/metal - mutationone = /mob/living/carbon/slime/silver - mutationtwo = /mob/living/carbon/slime/yellow - mutationthree = /mob/living/carbon/slime/gold - mutationfour = /mob/living/carbon/slime/gold - adulttype = /mob/living/carbon/slime/adult/metal - coretype = /obj/item/slime_extract/metal - -/mob/living/carbon/slime/adult/metal - icon_state = "metal adult slime" - colour = "metal" - primarytype = /mob/living/carbon/slime/metal - mutationone = /mob/living/carbon/slime/silver - mutationtwo = /mob/living/carbon/slime/yellow - mutationthree = /mob/living/carbon/slime/gold - mutationfour = /mob/living/carbon/slime/gold - adulttype = /mob/living/carbon/slime/adult/metal - coretype = /obj/item/slime_extract/metal - -/mob/living/carbon/slime/orange - colour = "orange" - icon_state = "orange baby slime" - primarytype = /mob/living/carbon/slime/orange - mutationone = /mob/living/carbon/slime/red - mutationtwo = /mob/living/carbon/slime/red - mutationthree = /mob/living/carbon/slime/darkpurple - mutationfour = /mob/living/carbon/slime/yellow - adulttype = /mob/living/carbon/slime/adult/orange - coretype = /obj/item/slime_extract/orange - -/mob/living/carbon/slime/adult/orange - colour = "orange" - icon_state = "orange adult slime" - primarytype = /mob/living/carbon/slime/orange - mutationone = /mob/living/carbon/slime/red - mutationtwo = /mob/living/carbon/slime/red - mutationthree = /mob/living/carbon/slime/darkpurple - mutationfour = /mob/living/carbon/slime/yellow - adulttype = /mob/living/carbon/slime/adult/orange - coretype = /obj/item/slime_extract/orange - -/mob/living/carbon/slime/blue - colour = "blue" - icon_state = "blue baby slime" - primarytype = /mob/living/carbon/slime/blue - mutationone = /mob/living/carbon/slime/darkblue - mutationtwo = /mob/living/carbon/slime/pink - mutationthree = /mob/living/carbon/slime/pink - mutationfour = /mob/living/carbon/slime/silver - adulttype = /mob/living/carbon/slime/adult/blue - coretype = /obj/item/slime_extract/blue - -/mob/living/carbon/slime/adult/blue - icon_state = "blue adult slime" - colour = "blue" - primarytype = /mob/living/carbon/slime/blue - mutationone = /mob/living/carbon/slime/darkblue - mutationtwo = /mob/living/carbon/slime/pink - mutationthree = /mob/living/carbon/slime/silver - mutationfour = /mob/living/carbon/slime/pink - adulttype = /mob/living/carbon/slime/adult/blue - coretype = /obj/item/slime_extract/blue - - - - -//Tier 3 - -/mob/living/carbon/slime/darkblue - colour = "dark blue" - icon_state = "dark blue baby slime" - primarytype = /mob/living/carbon/slime/darkblue - mutationone = /mob/living/carbon/slime/purple - mutationtwo = /mob/living/carbon/slime/cerulean - mutationthree = /mob/living/carbon/slime/blue - mutationfour = /mob/living/carbon/slime/blue - adulttype = /mob/living/carbon/slime/adult/darkblue - coretype = /obj/item/slime_extract/darkblue - -/mob/living/carbon/slime/adult/darkblue - icon_state = "dark blue adult slime" - colour = "dark blue" - primarytype = /mob/living/carbon/slime/darkblue - mutationone = /mob/living/carbon/slime/purple - mutationtwo = /mob/living/carbon/slime/cerulean - mutationthree = /mob/living/carbon/slime/blue - mutationfour = /mob/living/carbon/slime/blue - adulttype = /mob/living/carbon/slime/adult/darkblue - coretype = /obj/item/slime_extract/darkblue - -/mob/living/carbon/slime/darkpurple - colour = "dark purple" - icon_state = "dark purple baby slime" - primarytype = /mob/living/carbon/slime/darkpurple - mutationone = /mob/living/carbon/slime/purple - mutationtwo = /mob/living/carbon/slime/sepia - mutationthree = /mob/living/carbon/slime/orange - mutationfour = /mob/living/carbon/slime/orange - adulttype = /mob/living/carbon/slime/adult/darkpurple - coretype = /obj/item/slime_extract/darkpurple - -/mob/living/carbon/slime/adult/darkpurple - icon_state = "dark purple adult slime" - colour = "dark purple" - primarytype = /mob/living/carbon/slime/darkpurple - mutationone = /mob/living/carbon/slime/purple - mutationtwo = /mob/living/carbon/slime/sepia - mutationthree = /mob/living/carbon/slime/orange - mutationfour = /mob/living/carbon/slime/orange - adulttype = /mob/living/carbon/slime/adult/darkpurple - coretype = /obj/item/slime_extract/darkpurple - - -/mob/living/carbon/slime/yellow - icon_state = "yellow baby slime" - colour = "yellow" - primarytype = /mob/living/carbon/slime/yellow - mutationone = /mob/living/carbon/slime/metal - mutationtwo = /mob/living/carbon/slime/bluespace - mutationthree = /mob/living/carbon/slime/orange - mutationfour = /mob/living/carbon/slime/orange - adulttype = /mob/living/carbon/slime/adult/yellow - coretype = /obj/item/slime_extract/yellow - -/mob/living/carbon/slime/adult/yellow - icon_state = "yellow adult slime" - colour = "yellow" - primarytype = /mob/living/carbon/slime/yellow - mutationone = /mob/living/carbon/slime/metal - mutationtwo = /mob/living/carbon/slime/bluespace - mutationthree = /mob/living/carbon/slime/orange - mutationfour = /mob/living/carbon/slime/orange - adulttype = /mob/living/carbon/slime/adult/yellow - coretype = /obj/item/slime_extract/yellow - - -/mob/living/carbon/slime/silver - colour = "silver" - icon_state = "silver baby slime" - primarytype = /mob/living/carbon/slime/silver - mutationone = /mob/living/carbon/slime/metal - mutationtwo = /mob/living/carbon/slime/pyrite - mutationthree = /mob/living/carbon/slime/blue - mutationfour = /mob/living/carbon/slime/blue - adulttype = /mob/living/carbon/slime/adult/silver - coretype = /obj/item/slime_extract/silver - -/mob/living/carbon/slime/adult/silver - icon_state = "silver adult slime" - colour = "silver" - primarytype = /mob/living/carbon/slime/silver - mutationone = /mob/living/carbon/slime/metal - mutationtwo = /mob/living/carbon/slime/pyrite - mutationthree = /mob/living/carbon/slime/blue - mutationfour = /mob/living/carbon/slime/blue - adulttype = /mob/living/carbon/slime/adult/silver - coretype = /obj/item/slime_extract/silver - - - -/////////////Tier 4 - - -/mob/living/carbon/slime/pink - colour = "pink" - icon_state = "pink baby slime" - primarytype = /mob/living/carbon/slime/pink - mutationone = /mob/living/carbon/slime/pink - mutationtwo = /mob/living/carbon/slime/pink - mutationthree = /mob/living/carbon/slime/lightpink - mutationfour = /mob/living/carbon/slime/lightpink - adulttype = /mob/living/carbon/slime/adult/pink - coretype = /obj/item/slime_extract/pink - -/mob/living/carbon/slime/adult/pink - icon_state = "pink adult slime" - colour = "pink" - primarytype = /mob/living/carbon/slime/pink - mutationone = /mob/living/carbon/slime/pink - mutationtwo = /mob/living/carbon/slime/pink - mutationthree = /mob/living/carbon/slime/lightpink - mutationfour = /mob/living/carbon/slime/lightpink - adulttype = /mob/living/carbon/slime/adult/pink - coretype = /obj/item/slime_extract/pink - -/mob/living/carbon/slime/red - colour = "red" - icon_state = "red baby slime" - primarytype = /mob/living/carbon/slime/red - mutationone = /mob/living/carbon/slime/red - mutationtwo = /mob/living/carbon/slime/red - mutationthree = /mob/living/carbon/slime/oil - mutationfour = /mob/living/carbon/slime/oil - adulttype = /mob/living/carbon/slime/adult/red - coretype = /obj/item/slime_extract/red - -/mob/living/carbon/slime/adult/red - icon_state = "red adult slime" - colour = "red" - primarytype = /mob/living/carbon/slime/red - mutationone = /mob/living/carbon/slime/red - mutationtwo = /mob/living/carbon/slime/red - mutationthree = /mob/living/carbon/slime/oil - mutationfour = /mob/living/carbon/slime/oil - adulttype = /mob/living/carbon/slime/adult/red - coretype = /obj/item/slime_extract/red - -/mob/living/carbon/slime/gold - colour = "gold" - icon_state = "gold baby slime" - primarytype = /mob/living/carbon/slime/gold - mutationone = /mob/living/carbon/slime/gold - mutationtwo = /mob/living/carbon/slime/gold - mutationthree = /mob/living/carbon/slime/adamantine - mutationfour = /mob/living/carbon/slime/adamantine - adulttype = /mob/living/carbon/slime/adult/gold - coretype = /obj/item/slime_extract/gold - -/mob/living/carbon/slime/adult/gold - icon_state = "gold adult slime" - colour = "gold" - primarytype = /mob/living/carbon/slime/gold - mutationone = /mob/living/carbon/slime/gold - mutationtwo = /mob/living/carbon/slime/gold - mutationthree = /mob/living/carbon/slime/adamantine - mutationfour = /mob/living/carbon/slime/adamantine - adulttype = /mob/living/carbon/slime/adult/gold - coretype = /obj/item/slime_extract/gold - -/mob/living/carbon/slime/green - colour = "green" - icon_state = "green baby slime" - primarytype = /mob/living/carbon/slime/green - mutationone = /mob/living/carbon/slime/green - mutationtwo = /mob/living/carbon/slime/green - mutationthree = /mob/living/carbon/slime/black - mutationfour = /mob/living/carbon/slime/black - adulttype = /mob/living/carbon/slime/adult/green - coretype = /obj/item/slime_extract/green - -/mob/living/carbon/slime/adult/green - icon_state = "green adult slime" - colour = "green" - primarytype = /mob/living/carbon/slime/green - mutationone = /mob/living/carbon/slime/green - mutationtwo = /mob/living/carbon/slime/green - mutationthree = /mob/living/carbon/slime/black - mutationfour = /mob/living/carbon/slime/black - adulttype = /mob/living/carbon/slime/adult/green - coretype = /obj/item/slime_extract/green - - - -// Tier 5 - -/mob/living/carbon/slime/lightpink - colour = "light pink" - icon_state = "light pink baby slime" - primarytype = /mob/living/carbon/slime/lightpink - mutationone = /mob/living/carbon/slime/lightpink - mutationtwo = /mob/living/carbon/slime/lightpink - mutationthree = /mob/living/carbon/slime/lightpink - mutationfour = /mob/living/carbon/slime/lightpink - adulttype = /mob/living/carbon/slime/adult/lightpink - coretype = /obj/item/slime_extract/lightpink - -/mob/living/carbon/slime/adult/lightpink - icon_state = "light pink adult slime" - colour = "light pink" - primarytype = /mob/living/carbon/slime/lightpink - mutationone = /mob/living/carbon/slime/lightpink - mutationtwo = /mob/living/carbon/slime/lightpink - mutationthree = /mob/living/carbon/slime/lightpink - mutationfour = /mob/living/carbon/slime/lightpink - adulttype = /mob/living/carbon/slime/adult/lightpink - coretype = /obj/item/slime_extract/lightpink - - -/mob/living/carbon/slime/oil - icon_state = "oil baby slime" - colour = "oil" - primarytype = /mob/living/carbon/slime/oil - mutationone = /mob/living/carbon/slime/oil - mutationtwo = /mob/living/carbon/slime/oil - mutationthree = /mob/living/carbon/slime/oil - mutationfour = /mob/living/carbon/slime/oil - adulttype = /mob/living/carbon/slime/adult/oil - coretype = /obj/item/slime_extract/oil - -/mob/living/carbon/slime/adult/oil - icon_state = "oil adult slime" - colour = "oil" - primarytype = /mob/living/carbon/slime/oil - mutationone = /mob/living/carbon/slime/oil - mutationtwo = /mob/living/carbon/slime/oil - mutationthree = /mob/living/carbon/slime/oil - mutationfour = /mob/living/carbon/slime/oil - adulttype = /mob/living/carbon/slime/adult/oil - coretype = /obj/item/slime_extract/oil - - -/mob/living/carbon/slime/black - icon_state = "black baby slime" - colour = "black" - primarytype = /mob/living/carbon/slime/black - mutationone = /mob/living/carbon/slime/black - mutationtwo = /mob/living/carbon/slime/black - mutationthree = /mob/living/carbon/slime/black - mutationfour = /mob/living/carbon/slime/black - adulttype = /mob/living/carbon/slime/adult/black - coretype = /obj/item/slime_extract/black - -/mob/living/carbon/slime/adult/black - icon_state = "black adult slime" - colour = "black" - primarytype = /mob/living/carbon/slime/black - mutationone = /mob/living/carbon/slime/black - mutationtwo = /mob/living/carbon/slime/black - mutationthree = /mob/living/carbon/slime/black - mutationfour = /mob/living/carbon/slime/black - adulttype = /mob/living/carbon/slime/adult/black - coretype = /obj/item/slime_extract/black - -/mob/living/carbon/slime/adamantine - icon_state = "adamantine baby slime" - colour = "adamantine" - primarytype = /mob/living/carbon/slime/adamantine - mutationone = /mob/living/carbon/slime/adamantine - mutationtwo = /mob/living/carbon/slime/adamantine - mutationthree = /mob/living/carbon/slime/adamantine - mutationfour = /mob/living/carbon/slime/adamantine - adulttype = /mob/living/carbon/slime/adult/adamantine - coretype = /obj/item/slime_extract/adamantine - -/mob/living/carbon/slime/adult/adamantine - icon_state = "adamantine adult slime" - colour = "adamantine" - primarytype = /mob/living/carbon/slime/adamantine - mutationone = /mob/living/carbon/slime/adamantine - mutationtwo = /mob/living/carbon/slime/adamantine - mutationthree = /mob/living/carbon/slime/adamantine - mutationfour = /mob/living/carbon/slime/adamantine - adulttype = /mob/living/carbon/slime/adult/adamantine - coretype = /obj/item/slime_extract/adamantine - -/mob/living/carbon/slime/bluespace - icon_state = "bluespace baby slime" - colour = "bluespace" - primarytype = /mob/living/carbon/slime/bluespace - mutationone = /mob/living/carbon/slime/bluespace - mutationtwo = /mob/living/carbon/slime/bluespace - mutationthree = /mob/living/carbon/slime/bluespace - mutationfour = /mob/living/carbon/slime/bluespace - adulttype = /mob/living/carbon/slime/adult/bluespace - coretype = /obj/item/slime_extract/bluespace - -/mob/living/carbon/slime/adult/bluespace - icon_state = "bluespace adult slime" - colour = "bluespace" - primarytype = /mob/living/carbon/slime/bluespace - mutationone = /mob/living/carbon/slime/bluespace - mutationtwo = /mob/living/carbon/slime/bluespace - mutationthree = /mob/living/carbon/slime/bluespace - mutationfour = /mob/living/carbon/slime/bluespace - adulttype = /mob/living/carbon/slime/adult/bluespace - coretype = /obj/item/slime_extract/bluespace - -/mob/living/carbon/slime/cerulean - icon_state = "cerulean baby slime" - colour = "cerulean" - primarytype = /mob/living/carbon/slime/cerulean - mutationone = /mob/living/carbon/slime/cerulean - mutationtwo = /mob/living/carbon/slime/cerulean - mutationthree = /mob/living/carbon/slime/cerulean - mutationfour = /mob/living/carbon/slime/cerulean - adulttype = /mob/living/carbon/slime/adult/cerulean - coretype = /obj/item/slime_extract/cerulean - -/mob/living/carbon/slime/adult/cerulean - icon_state = "cerulean adult slime" - colour = "cerulean" - primarytype = /mob/living/carbon/slime/cerulean - mutationone = /mob/living/carbon/slime/cerulean - mutationtwo = /mob/living/carbon/slime/cerulean - mutationthree = /mob/living/carbon/slime/cerulean - mutationfour = /mob/living/carbon/slime/cerulean - adulttype = /mob/living/carbon/slime/adult/cerulean - coretype = /obj/item/slime_extract/cerulean - -/mob/living/carbon/slime/sepia - icon_state = "sepia baby slime" - colour = "sepia" - primarytype = /mob/living/carbon/slime/sepia - mutationone = /mob/living/carbon/slime/sepia - mutationtwo = /mob/living/carbon/slime/sepia - mutationthree = /mob/living/carbon/slime/sepia - mutationfour = /mob/living/carbon/slime/rainbow - adulttype = /mob/living/carbon/slime/adult/sepia - coretype = /obj/item/slime_extract/sepia - -/mob/living/carbon/slime/adult/sepia - icon_state = "sepia adult slime" - colour = "sepia" - primarytype = /mob/living/carbon/slime/sepia - mutationone = /mob/living/carbon/slime/sepia - mutationtwo = /mob/living/carbon/slime/sepia - mutationthree = /mob/living/carbon/slime/sepia - mutationfour = /mob/living/carbon/slime/rainbow - adulttype = /mob/living/carbon/slime/adult/sepia - coretype = /obj/item/slime_extract/sepia - -/mob/living/carbon/slime/pyrite - icon_state = "pyrite baby slime" - colour = "pyrite" - primarytype = /mob/living/carbon/slime/pyrite - mutationone = /mob/living/carbon/slime/pyrite - mutationtwo = /mob/living/carbon/slime/pyrite - mutationthree = /mob/living/carbon/slime/pyrite - mutationfour = /mob/living/carbon/slime/pyrite - adulttype = /mob/living/carbon/slime/adult/pyrite - coretype = /obj/item/slime_extract/pyrite - -/mob/living/carbon/slime/adult/pyrite - icon_state = "pyrite adult slime" - colour = "pyrite" - primarytype = /mob/living/carbon/slime/pyrite - mutationone = /mob/living/carbon/slime/pyrite - mutationtwo = /mob/living/carbon/slime/pyrite - mutationthree = /mob/living/carbon/slime/pyrite - mutationfour = /mob/living/carbon/slime/pyrite - adulttype = /mob/living/carbon/slime/adult/pyrite - coretype = /obj/item/slime_extract/pyrite - -/mob/living/carbon/slime/rainbow - icon_state = "rainbow baby slime" - colour = "rainbow" - primarytype = /mob/living/carbon/slime/rainbow - mutationone = /mob/living/carbon/slime/sepia - mutationtwo = /mob/living/carbon/slime/sepia - mutationthree = /mob/living/carbon/slime/sepia - mutationfour = /mob/living/carbon/slime/rainbow - adulttype = /mob/living/carbon/slime/adult/rainbow - coretype = /obj/item/slime_extract/rainbow - -/mob/living/carbon/slime/adult/rainbow - icon_state = "rainbow adult slime" - colour = "rainbow" - primarytype = /mob/living/carbon/slime/rainbow - mutationone = /mob/living/carbon/slime/sepia - mutationtwo = /mob/living/carbon/slime/sepia - mutationthree = /mob/living/carbon/slime/sepia - mutationfour = /mob/living/carbon/slime/rainbow - adulttype = /mob/living/carbon/slime/adult/rainbow - coretype = /obj/item/slime_extract/rainbow + +////////////////Tier 2 + +/mob/living/carbon/slime/purple + colour = "purple" + icon_state = "purple baby slime" + primarytype = /mob/living/carbon/slime/purple + mutationone = /mob/living/carbon/slime/darkpurple + mutationtwo = /mob/living/carbon/slime/darkblue + mutationthree = /mob/living/carbon/slime/green + mutationfour = /mob/living/carbon/slime/green + adulttype = /mob/living/carbon/slime/adult/purple + coretype = /obj/item/slime_extract/purple + +/mob/living/carbon/slime/adult/purple + icon_state = "purple adult slime" + colour = "purple" + primarytype = /mob/living/carbon/slime/purple + mutationone = /mob/living/carbon/slime/darkpurple + mutationtwo = /mob/living/carbon/slime/darkblue + mutationthree = /mob/living/carbon/slime/green + mutationfour = /mob/living/carbon/slime/green + adulttype = /mob/living/carbon/slime/adult/purple + coretype = /obj/item/slime_extract/purple + +/mob/living/carbon/slime/metal + colour = "metal" + icon_state = "metal baby slime" + primarytype = /mob/living/carbon/slime/metal + mutationone = /mob/living/carbon/slime/silver + mutationtwo = /mob/living/carbon/slime/yellow + mutationthree = /mob/living/carbon/slime/gold + mutationfour = /mob/living/carbon/slime/gold + adulttype = /mob/living/carbon/slime/adult/metal + coretype = /obj/item/slime_extract/metal + +/mob/living/carbon/slime/adult/metal + icon_state = "metal adult slime" + colour = "metal" + primarytype = /mob/living/carbon/slime/metal + mutationone = /mob/living/carbon/slime/silver + mutationtwo = /mob/living/carbon/slime/yellow + mutationthree = /mob/living/carbon/slime/gold + mutationfour = /mob/living/carbon/slime/gold + adulttype = /mob/living/carbon/slime/adult/metal + coretype = /obj/item/slime_extract/metal + +/mob/living/carbon/slime/orange + colour = "orange" + icon_state = "orange baby slime" + primarytype = /mob/living/carbon/slime/orange + mutationone = /mob/living/carbon/slime/red + mutationtwo = /mob/living/carbon/slime/red + mutationthree = /mob/living/carbon/slime/darkpurple + mutationfour = /mob/living/carbon/slime/yellow + adulttype = /mob/living/carbon/slime/adult/orange + coretype = /obj/item/slime_extract/orange + +/mob/living/carbon/slime/adult/orange + colour = "orange" + icon_state = "orange adult slime" + primarytype = /mob/living/carbon/slime/orange + mutationone = /mob/living/carbon/slime/red + mutationtwo = /mob/living/carbon/slime/red + mutationthree = /mob/living/carbon/slime/darkpurple + mutationfour = /mob/living/carbon/slime/yellow + adulttype = /mob/living/carbon/slime/adult/orange + coretype = /obj/item/slime_extract/orange + +/mob/living/carbon/slime/blue + colour = "blue" + icon_state = "blue baby slime" + primarytype = /mob/living/carbon/slime/blue + mutationone = /mob/living/carbon/slime/darkblue + mutationtwo = /mob/living/carbon/slime/pink + mutationthree = /mob/living/carbon/slime/pink + mutationfour = /mob/living/carbon/slime/silver + adulttype = /mob/living/carbon/slime/adult/blue + coretype = /obj/item/slime_extract/blue + +/mob/living/carbon/slime/adult/blue + icon_state = "blue adult slime" + colour = "blue" + primarytype = /mob/living/carbon/slime/blue + mutationone = /mob/living/carbon/slime/darkblue + mutationtwo = /mob/living/carbon/slime/pink + mutationthree = /mob/living/carbon/slime/silver + mutationfour = /mob/living/carbon/slime/pink + adulttype = /mob/living/carbon/slime/adult/blue + coretype = /obj/item/slime_extract/blue + + + + +//Tier 3 + +/mob/living/carbon/slime/darkblue + colour = "dark blue" + icon_state = "dark blue baby slime" + primarytype = /mob/living/carbon/slime/darkblue + mutationone = /mob/living/carbon/slime/purple + mutationtwo = /mob/living/carbon/slime/cerulean + mutationthree = /mob/living/carbon/slime/blue + mutationfour = /mob/living/carbon/slime/blue + adulttype = /mob/living/carbon/slime/adult/darkblue + coretype = /obj/item/slime_extract/darkblue + +/mob/living/carbon/slime/adult/darkblue + icon_state = "dark blue adult slime" + colour = "dark blue" + primarytype = /mob/living/carbon/slime/darkblue + mutationone = /mob/living/carbon/slime/purple + mutationtwo = /mob/living/carbon/slime/cerulean + mutationthree = /mob/living/carbon/slime/blue + mutationfour = /mob/living/carbon/slime/blue + adulttype = /mob/living/carbon/slime/adult/darkblue + coretype = /obj/item/slime_extract/darkblue + +/mob/living/carbon/slime/darkpurple + colour = "dark purple" + icon_state = "dark purple baby slime" + primarytype = /mob/living/carbon/slime/darkpurple + mutationone = /mob/living/carbon/slime/purple + mutationtwo = /mob/living/carbon/slime/sepia + mutationthree = /mob/living/carbon/slime/orange + mutationfour = /mob/living/carbon/slime/orange + adulttype = /mob/living/carbon/slime/adult/darkpurple + coretype = /obj/item/slime_extract/darkpurple + +/mob/living/carbon/slime/adult/darkpurple + icon_state = "dark purple adult slime" + colour = "dark purple" + primarytype = /mob/living/carbon/slime/darkpurple + mutationone = /mob/living/carbon/slime/purple + mutationtwo = /mob/living/carbon/slime/sepia + mutationthree = /mob/living/carbon/slime/orange + mutationfour = /mob/living/carbon/slime/orange + adulttype = /mob/living/carbon/slime/adult/darkpurple + coretype = /obj/item/slime_extract/darkpurple + + +/mob/living/carbon/slime/yellow + icon_state = "yellow baby slime" + colour = "yellow" + primarytype = /mob/living/carbon/slime/yellow + mutationone = /mob/living/carbon/slime/metal + mutationtwo = /mob/living/carbon/slime/bluespace + mutationthree = /mob/living/carbon/slime/orange + mutationfour = /mob/living/carbon/slime/orange + adulttype = /mob/living/carbon/slime/adult/yellow + coretype = /obj/item/slime_extract/yellow + +/mob/living/carbon/slime/adult/yellow + icon_state = "yellow adult slime" + colour = "yellow" + primarytype = /mob/living/carbon/slime/yellow + mutationone = /mob/living/carbon/slime/metal + mutationtwo = /mob/living/carbon/slime/bluespace + mutationthree = /mob/living/carbon/slime/orange + mutationfour = /mob/living/carbon/slime/orange + adulttype = /mob/living/carbon/slime/adult/yellow + coretype = /obj/item/slime_extract/yellow + + +/mob/living/carbon/slime/silver + colour = "silver" + icon_state = "silver baby slime" + primarytype = /mob/living/carbon/slime/silver + mutationone = /mob/living/carbon/slime/metal + mutationtwo = /mob/living/carbon/slime/pyrite + mutationthree = /mob/living/carbon/slime/blue + mutationfour = /mob/living/carbon/slime/blue + adulttype = /mob/living/carbon/slime/adult/silver + coretype = /obj/item/slime_extract/silver + +/mob/living/carbon/slime/adult/silver + icon_state = "silver adult slime" + colour = "silver" + primarytype = /mob/living/carbon/slime/silver + mutationone = /mob/living/carbon/slime/metal + mutationtwo = /mob/living/carbon/slime/pyrite + mutationthree = /mob/living/carbon/slime/blue + mutationfour = /mob/living/carbon/slime/blue + adulttype = /mob/living/carbon/slime/adult/silver + coretype = /obj/item/slime_extract/silver + + + +/////////////Tier 4 + + +/mob/living/carbon/slime/pink + colour = "pink" + icon_state = "pink baby slime" + primarytype = /mob/living/carbon/slime/pink + mutationone = /mob/living/carbon/slime/pink + mutationtwo = /mob/living/carbon/slime/pink + mutationthree = /mob/living/carbon/slime/lightpink + mutationfour = /mob/living/carbon/slime/lightpink + adulttype = /mob/living/carbon/slime/adult/pink + coretype = /obj/item/slime_extract/pink + +/mob/living/carbon/slime/adult/pink + icon_state = "pink adult slime" + colour = "pink" + primarytype = /mob/living/carbon/slime/pink + mutationone = /mob/living/carbon/slime/pink + mutationtwo = /mob/living/carbon/slime/pink + mutationthree = /mob/living/carbon/slime/lightpink + mutationfour = /mob/living/carbon/slime/lightpink + adulttype = /mob/living/carbon/slime/adult/pink + coretype = /obj/item/slime_extract/pink + +/mob/living/carbon/slime/red + colour = "red" + icon_state = "red baby slime" + primarytype = /mob/living/carbon/slime/red + mutationone = /mob/living/carbon/slime/red + mutationtwo = /mob/living/carbon/slime/red + mutationthree = /mob/living/carbon/slime/oil + mutationfour = /mob/living/carbon/slime/oil + adulttype = /mob/living/carbon/slime/adult/red + coretype = /obj/item/slime_extract/red + +/mob/living/carbon/slime/adult/red + icon_state = "red adult slime" + colour = "red" + primarytype = /mob/living/carbon/slime/red + mutationone = /mob/living/carbon/slime/red + mutationtwo = /mob/living/carbon/slime/red + mutationthree = /mob/living/carbon/slime/oil + mutationfour = /mob/living/carbon/slime/oil + adulttype = /mob/living/carbon/slime/adult/red + coretype = /obj/item/slime_extract/red + +/mob/living/carbon/slime/gold + colour = "gold" + icon_state = "gold baby slime" + primarytype = /mob/living/carbon/slime/gold + mutationone = /mob/living/carbon/slime/gold + mutationtwo = /mob/living/carbon/slime/gold + mutationthree = /mob/living/carbon/slime/adamantine + mutationfour = /mob/living/carbon/slime/adamantine + adulttype = /mob/living/carbon/slime/adult/gold + coretype = /obj/item/slime_extract/gold + +/mob/living/carbon/slime/adult/gold + icon_state = "gold adult slime" + colour = "gold" + primarytype = /mob/living/carbon/slime/gold + mutationone = /mob/living/carbon/slime/gold + mutationtwo = /mob/living/carbon/slime/gold + mutationthree = /mob/living/carbon/slime/adamantine + mutationfour = /mob/living/carbon/slime/adamantine + adulttype = /mob/living/carbon/slime/adult/gold + coretype = /obj/item/slime_extract/gold + +/mob/living/carbon/slime/green + colour = "green" + icon_state = "green baby slime" + primarytype = /mob/living/carbon/slime/green + mutationone = /mob/living/carbon/slime/green + mutationtwo = /mob/living/carbon/slime/green + mutationthree = /mob/living/carbon/slime/black + mutationfour = /mob/living/carbon/slime/black + adulttype = /mob/living/carbon/slime/adult/green + coretype = /obj/item/slime_extract/green + +/mob/living/carbon/slime/adult/green + icon_state = "green adult slime" + colour = "green" + primarytype = /mob/living/carbon/slime/green + mutationone = /mob/living/carbon/slime/green + mutationtwo = /mob/living/carbon/slime/green + mutationthree = /mob/living/carbon/slime/black + mutationfour = /mob/living/carbon/slime/black + adulttype = /mob/living/carbon/slime/adult/green + coretype = /obj/item/slime_extract/green + + + +// Tier 5 + +/mob/living/carbon/slime/lightpink + colour = "light pink" + icon_state = "light pink baby slime" + primarytype = /mob/living/carbon/slime/lightpink + mutationone = /mob/living/carbon/slime/lightpink + mutationtwo = /mob/living/carbon/slime/lightpink + mutationthree = /mob/living/carbon/slime/lightpink + mutationfour = /mob/living/carbon/slime/lightpink + adulttype = /mob/living/carbon/slime/adult/lightpink + coretype = /obj/item/slime_extract/lightpink + +/mob/living/carbon/slime/adult/lightpink + icon_state = "light pink adult slime" + colour = "light pink" + primarytype = /mob/living/carbon/slime/lightpink + mutationone = /mob/living/carbon/slime/lightpink + mutationtwo = /mob/living/carbon/slime/lightpink + mutationthree = /mob/living/carbon/slime/lightpink + mutationfour = /mob/living/carbon/slime/lightpink + adulttype = /mob/living/carbon/slime/adult/lightpink + coretype = /obj/item/slime_extract/lightpink + + +/mob/living/carbon/slime/oil + icon_state = "oil baby slime" + colour = "oil" + primarytype = /mob/living/carbon/slime/oil + mutationone = /mob/living/carbon/slime/oil + mutationtwo = /mob/living/carbon/slime/oil + mutationthree = /mob/living/carbon/slime/oil + mutationfour = /mob/living/carbon/slime/oil + adulttype = /mob/living/carbon/slime/adult/oil + coretype = /obj/item/slime_extract/oil + +/mob/living/carbon/slime/adult/oil + icon_state = "oil adult slime" + colour = "oil" + primarytype = /mob/living/carbon/slime/oil + mutationone = /mob/living/carbon/slime/oil + mutationtwo = /mob/living/carbon/slime/oil + mutationthree = /mob/living/carbon/slime/oil + mutationfour = /mob/living/carbon/slime/oil + adulttype = /mob/living/carbon/slime/adult/oil + coretype = /obj/item/slime_extract/oil + + +/mob/living/carbon/slime/black + icon_state = "black baby slime" + colour = "black" + primarytype = /mob/living/carbon/slime/black + mutationone = /mob/living/carbon/slime/black + mutationtwo = /mob/living/carbon/slime/black + mutationthree = /mob/living/carbon/slime/black + mutationfour = /mob/living/carbon/slime/black + adulttype = /mob/living/carbon/slime/adult/black + coretype = /obj/item/slime_extract/black + +/mob/living/carbon/slime/adult/black + icon_state = "black adult slime" + colour = "black" + primarytype = /mob/living/carbon/slime/black + mutationone = /mob/living/carbon/slime/black + mutationtwo = /mob/living/carbon/slime/black + mutationthree = /mob/living/carbon/slime/black + mutationfour = /mob/living/carbon/slime/black + adulttype = /mob/living/carbon/slime/adult/black + coretype = /obj/item/slime_extract/black + +/mob/living/carbon/slime/adamantine + icon_state = "adamantine baby slime" + colour = "adamantine" + primarytype = /mob/living/carbon/slime/adamantine + mutationone = /mob/living/carbon/slime/adamantine + mutationtwo = /mob/living/carbon/slime/adamantine + mutationthree = /mob/living/carbon/slime/adamantine + mutationfour = /mob/living/carbon/slime/adamantine + adulttype = /mob/living/carbon/slime/adult/adamantine + coretype = /obj/item/slime_extract/adamantine + +/mob/living/carbon/slime/adult/adamantine + icon_state = "adamantine adult slime" + colour = "adamantine" + primarytype = /mob/living/carbon/slime/adamantine + mutationone = /mob/living/carbon/slime/adamantine + mutationtwo = /mob/living/carbon/slime/adamantine + mutationthree = /mob/living/carbon/slime/adamantine + mutationfour = /mob/living/carbon/slime/adamantine + adulttype = /mob/living/carbon/slime/adult/adamantine + coretype = /obj/item/slime_extract/adamantine + +/mob/living/carbon/slime/bluespace + icon_state = "bluespace baby slime" + colour = "bluespace" + primarytype = /mob/living/carbon/slime/bluespace + mutationone = /mob/living/carbon/slime/bluespace + mutationtwo = /mob/living/carbon/slime/bluespace + mutationthree = /mob/living/carbon/slime/bluespace + mutationfour = /mob/living/carbon/slime/bluespace + adulttype = /mob/living/carbon/slime/adult/bluespace + coretype = /obj/item/slime_extract/bluespace + +/mob/living/carbon/slime/adult/bluespace + icon_state = "bluespace adult slime" + colour = "bluespace" + primarytype = /mob/living/carbon/slime/bluespace + mutationone = /mob/living/carbon/slime/bluespace + mutationtwo = /mob/living/carbon/slime/bluespace + mutationthree = /mob/living/carbon/slime/bluespace + mutationfour = /mob/living/carbon/slime/bluespace + adulttype = /mob/living/carbon/slime/adult/bluespace + coretype = /obj/item/slime_extract/bluespace + +/mob/living/carbon/slime/cerulean + icon_state = "cerulean baby slime" + colour = "cerulean" + primarytype = /mob/living/carbon/slime/cerulean + mutationone = /mob/living/carbon/slime/cerulean + mutationtwo = /mob/living/carbon/slime/cerulean + mutationthree = /mob/living/carbon/slime/cerulean + mutationfour = /mob/living/carbon/slime/cerulean + adulttype = /mob/living/carbon/slime/adult/cerulean + coretype = /obj/item/slime_extract/cerulean + +/mob/living/carbon/slime/adult/cerulean + icon_state = "cerulean adult slime" + colour = "cerulean" + primarytype = /mob/living/carbon/slime/cerulean + mutationone = /mob/living/carbon/slime/cerulean + mutationtwo = /mob/living/carbon/slime/cerulean + mutationthree = /mob/living/carbon/slime/cerulean + mutationfour = /mob/living/carbon/slime/cerulean + adulttype = /mob/living/carbon/slime/adult/cerulean + coretype = /obj/item/slime_extract/cerulean + +/mob/living/carbon/slime/sepia + icon_state = "sepia baby slime" + colour = "sepia" + primarytype = /mob/living/carbon/slime/sepia + mutationone = /mob/living/carbon/slime/sepia + mutationtwo = /mob/living/carbon/slime/sepia + mutationthree = /mob/living/carbon/slime/sepia + mutationfour = /mob/living/carbon/slime/rainbow + adulttype = /mob/living/carbon/slime/adult/sepia + coretype = /obj/item/slime_extract/sepia + +/mob/living/carbon/slime/adult/sepia + icon_state = "sepia adult slime" + colour = "sepia" + primarytype = /mob/living/carbon/slime/sepia + mutationone = /mob/living/carbon/slime/sepia + mutationtwo = /mob/living/carbon/slime/sepia + mutationthree = /mob/living/carbon/slime/sepia + mutationfour = /mob/living/carbon/slime/rainbow + adulttype = /mob/living/carbon/slime/adult/sepia + coretype = /obj/item/slime_extract/sepia + +/mob/living/carbon/slime/pyrite + icon_state = "pyrite baby slime" + colour = "pyrite" + primarytype = /mob/living/carbon/slime/pyrite + mutationone = /mob/living/carbon/slime/pyrite + mutationtwo = /mob/living/carbon/slime/pyrite + mutationthree = /mob/living/carbon/slime/pyrite + mutationfour = /mob/living/carbon/slime/pyrite + adulttype = /mob/living/carbon/slime/adult/pyrite + coretype = /obj/item/slime_extract/pyrite + +/mob/living/carbon/slime/adult/pyrite + icon_state = "pyrite adult slime" + colour = "pyrite" + primarytype = /mob/living/carbon/slime/pyrite + mutationone = /mob/living/carbon/slime/pyrite + mutationtwo = /mob/living/carbon/slime/pyrite + mutationthree = /mob/living/carbon/slime/pyrite + mutationfour = /mob/living/carbon/slime/pyrite + adulttype = /mob/living/carbon/slime/adult/pyrite + coretype = /obj/item/slime_extract/pyrite + +/mob/living/carbon/slime/rainbow + icon_state = "rainbow baby slime" + colour = "rainbow" + primarytype = /mob/living/carbon/slime/rainbow + mutationone = /mob/living/carbon/slime/sepia + mutationtwo = /mob/living/carbon/slime/sepia + mutationthree = /mob/living/carbon/slime/sepia + mutationfour = /mob/living/carbon/slime/rainbow + adulttype = /mob/living/carbon/slime/adult/rainbow + coretype = /obj/item/slime_extract/rainbow + +/mob/living/carbon/slime/adult/rainbow + icon_state = "rainbow adult slime" + colour = "rainbow" + primarytype = /mob/living/carbon/slime/rainbow + mutationone = /mob/living/carbon/slime/sepia + mutationtwo = /mob/living/carbon/slime/sepia + mutationthree = /mob/living/carbon/slime/sepia + mutationfour = /mob/living/carbon/slime/rainbow + adulttype = /mob/living/carbon/slime/adult/rainbow + coretype = /obj/item/slime_extract/rainbow diff --git a/code/modules/mob/living/carbon/metroid/update_icons.dm b/code/modules/mob/living/carbon/metroid/update_icons.dm index 7ae91b0de936..fda5ae5f8b24 100644 --- a/code/modules/mob/living/carbon/metroid/update_icons.dm +++ b/code/modules/mob/living/carbon/metroid/update_icons.dm @@ -1,2 +1,2 @@ -/mob/living/carbon/slime/update_transform() - return +/mob/living/carbon/slime/update_transform() + return diff --git a/code/modules/mob/living/carbon/monkey/death.dm b/code/modules/mob/living/carbon/monkey/death.dm index 0339806bc62d..cffbef7630f9 100644 --- a/code/modules/mob/living/carbon/monkey/death.dm +++ b/code/modules/mob/living/carbon/monkey/death.dm @@ -1,55 +1,55 @@ -/mob/living/carbon/monkey/gib() - death(1) - var/atom/movable/overlay/animation = null - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - animation = new(loc) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - - flick("gibbed-m", animation) - gibs(loc, viruses, dna) - - spawn(15) - if(animation) qdel(animation) - if(src) qdel(src) - -/mob/living/carbon/monkey/dust() - death(1) - var/atom/movable/overlay/animation = null - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - animation = new(loc) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - - flick("dust-m", animation) - new /obj/effect/decal/cleanable/ash(loc) - - spawn(15) - if(animation) qdel(animation) - if(src) 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() - - ticker.mode.check_win() - - return ..(gibbed) +/mob/living/carbon/monkey/gib() + death(1) + var/atom/movable/overlay/animation = null + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + animation = new(loc) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + + flick("gibbed-m", animation) + gibs(loc, viruses, dna) + + spawn(15) + if(animation) qdel(animation) + if(src) qdel(src) + +/mob/living/carbon/monkey/dust() + death(1) + var/atom/movable/overlay/animation = null + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + animation = new(loc) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + + flick("dust-m", animation) + new /obj/effect/decal/cleanable/ash(loc) + + spawn(15) + if(animation) qdel(animation) + if(src) 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() + + ticker.mode.check_win() + + return ..(gibbed) diff --git a/code/modules/mob/living/carbon/monkey/emote.dm b/code/modules/mob/living/carbon/monkey/emote.dm index 72ccfca7452b..8b4367a645c5 100644 --- a/code/modules/mob/living/carbon/monkey/emote.dm +++ b/code/modules/mob/living/carbon/monkey/emote.dm @@ -1,147 +1,147 @@ -/mob/living/carbon/monkey/emote(act,m_type=1,message = null) - - 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, "\red 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 ("chirp") - if(istype(src,/mob/living/carbon/monkey/diona)) - message = "The [src.name] chirps!" - playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0) - m_type = 2 - if("sign") - if (!src.restrained()) - message = text("The monkey signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) - m_type = 1 - if("scratch") - if (!src.restrained()) - message = "The [src.name] scratches." - m_type = 1 - if("whimper") - if (!muzzled) - message = "The [src.name] whimpers." - m_type = 2 - if("roar") - if (!muzzled) - message = "The [src.name] roars." - m_type = 2 - if("tail") - message = "The [src.name] waves his tail." - m_type = 1 - if("gasp") - message = "The [src.name] gasps." - m_type = 2 - if("shiver") - message = "The [src.name] shivers." - m_type = 2 - if("drool") - message = "The [src.name] drools." - m_type = 1 - if("paw") - if (!src.restrained()) - message = "The [src.name] flails his paw." - m_type = 1 - if("scretch") - if (!muzzled) - message = "The [src.name] scretches." - m_type = 2 - if("choke") - message = "The [src.name] chokes." - m_type = 2 - if("moan") - message = "The [src.name] moans!" - m_type = 2 - if("nod") - message = "The [src.name] nods his head." - m_type = 1 - if("sit") - message = "The [src.name] sits down." - m_type = 1 - if("sway") - message = "The [src.name] sways around dizzily." - m_type = 1 - if("sulk") - message = "The [src.name] sulks down sadly." - m_type = 1 - if("twitch") - message = "The [src.name] twitches violently." - m_type = 1 - if("dance") - if (!src.restrained()) - message = "The [src.name] dances around happily." - m_type = 1 - if("roll") - if (!src.restrained()) - message = "The [src.name] rolls." - m_type = 1 - if("shake") - message = "The [src.name] shakes his head." - m_type = 1 - if("gnarl") - if (!muzzled) - message = "The [src.name] gnarls and shows his teeth.." - m_type = 2 - if("jump") - message = "The [src.name] jumps!" - m_type = 1 - if("collapse") - Paralyse(2) - message = text("[] collapses!", src) - m_type = 2 - if("deathgasp") - message = "The [src.name] lets out a faint chimper as it collapses and stops moving..." - m_type = 1 - if("cough") - if(istype(src,/mob/living/carbon/monkey/diona)) - message = "The [src.name] shrinks and twitches slightly" - m_type = 1 - else - message = "The [src.name] coughs!" - m_type = 2 - if("help") - var/text = "choke, " - if(istype(src,/mob/living/carbon/monkey/diona)) - text += "chirp, " - text += "collapse, cough, dance, deathgasp, drool, gasp, shiver, gnarl, jump, paw, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper" - to_chat(src, text) - else - to_chat(src, text("Invalid Emote: []", act)) - if ((message && src.stat == CONSCIOUS)) - if(src.client) - log_emote("[name]/[key] : [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 +/mob/living/carbon/monkey/emote(act,m_type=1,message = null) + + 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, "\red 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 ("chirp") + if(istype(src,/mob/living/carbon/monkey/diona)) + message = "The [src.name] chirps!" + playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0) + m_type = 2 + if("sign") + if (!src.restrained()) + message = text("The monkey signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) + m_type = 1 + if("scratch") + if (!src.restrained()) + message = "The [src.name] scratches." + m_type = 1 + if("whimper") + if (!muzzled) + message = "The [src.name] whimpers." + m_type = 2 + if("roar") + if (!muzzled) + message = "The [src.name] roars." + m_type = 2 + if("tail") + message = "The [src.name] waves his tail." + m_type = 1 + if("gasp") + message = "The [src.name] gasps." + m_type = 2 + if("shiver") + message = "The [src.name] shivers." + m_type = 2 + if("drool") + message = "The [src.name] drools." + m_type = 1 + if("paw") + if (!src.restrained()) + message = "The [src.name] flails his paw." + m_type = 1 + if("scretch") + if (!muzzled) + message = "The [src.name] scretches." + m_type = 2 + if("choke") + message = "The [src.name] chokes." + m_type = 2 + if("moan") + message = "The [src.name] moans!" + m_type = 2 + if("nod") + message = "The [src.name] nods his head." + m_type = 1 + if("sit") + message = "The [src.name] sits down." + m_type = 1 + if("sway") + message = "The [src.name] sways around dizzily." + m_type = 1 + if("sulk") + message = "The [src.name] sulks down sadly." + m_type = 1 + if("twitch") + message = "The [src.name] twitches violently." + m_type = 1 + if("dance") + if (!src.restrained()) + message = "The [src.name] dances around happily." + m_type = 1 + if("roll") + if (!src.restrained()) + message = "The [src.name] rolls." + m_type = 1 + if("shake") + message = "The [src.name] shakes his head." + m_type = 1 + if("gnarl") + if (!muzzled) + message = "The [src.name] gnarls and shows his teeth.." + m_type = 2 + if("jump") + message = "The [src.name] jumps!" + m_type = 1 + if("collapse") + Paralyse(2) + message = text("[] collapses!", src) + m_type = 2 + if("deathgasp") + message = "The [src.name] lets out a faint chimper as it collapses and stops moving..." + m_type = 1 + if("cough") + if(istype(src,/mob/living/carbon/monkey/diona)) + message = "The [src.name] shrinks and twitches slightly" + m_type = 1 + else + message = "The [src.name] coughs!" + m_type = 2 + if("help") + var/text = "choke, " + if(istype(src,/mob/living/carbon/monkey/diona)) + text += "chirp, " + text += "collapse, cough, dance, deathgasp, drool, gasp, shiver, gnarl, jump, paw, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper" + to_chat(src, text) + else + to_chat(src, text("Invalid Emote: []", act)) + if ((message && src.stat == CONSCIOUS)) + if(src.client) + log_emote("[name]/[key] : [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 diff --git a/code/modules/mob/living/carbon/monkey/examine.dm b/code/modules/mob/living/carbon/monkey/examine.dm index d17a1f613f6e..40e1c538f1ee 100644 --- a/code/modules/mob/living/carbon/monkey/examine.dm +++ b/code/modules/mob/living/carbon/monkey/examine.dm @@ -1,45 +1,45 @@ -/mob/living/carbon/monkey/examine() - set src in oview() - - if(!usr || !src) return - if( (usr.sdisabilities & BLIND || usr.blinded || usr.stat) && !istype(usr,/mob/dead/observer) ) - to_chat(usr, "Something is there but you can't see it.") - return - - var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n" - - if (src.handcuffed) - msg += "It is [bicon(src.handcuffed)] handcuffed!\n" - if (src.wear_mask) - msg += "It has [bicon(src.wear_mask)] \a [src.wear_mask] on its head.\n" - if (src.l_hand) - msg += "It has [bicon(src.l_hand)] \a [src.l_hand] in its left hand.\n" - if (src.r_hand) - msg += "It has [bicon(src.r_hand)] \a [src.r_hand] in its right hand.\n" - if (src.back) - msg += "It has [bicon(src.back)] \a [src.back] on its back.\n" - if (src.stat == DEAD) - 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 moving its body in an unnatural and blatantly unsimian manner.\n" - - msg += "*---------*" - - to_chat(usr, msg) - return +/mob/living/carbon/monkey/examine() + set src in oview() + + if(!usr || !src) return + if( (usr.sdisabilities & BLIND || usr.blinded || usr.stat) && !istype(usr,/mob/dead/observer) ) + to_chat(usr, "Something is there but you can't see it.") + return + + var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n" + + if (src.handcuffed) + msg += "It is [bicon(src.handcuffed)] handcuffed!\n" + if (src.wear_mask) + msg += "It has [bicon(src.wear_mask)] \a [src.wear_mask] on its head.\n" + if (src.l_hand) + msg += "It has [bicon(src.l_hand)] \a [src.l_hand] in its left hand.\n" + if (src.r_hand) + msg += "It has [bicon(src.r_hand)] \a [src.r_hand] in its right hand.\n" + if (src.back) + msg += "It has [bicon(src.back)] \a [src.back] on its back.\n" + if (src.stat == DEAD) + 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 moving its body in an unnatural and blatantly unsimian manner.\n" + + msg += "*---------*" + + to_chat(usr, msg) + return diff --git a/code/modules/mob/living/carbon/monkey/inventory.dm b/code/modules/mob/living/carbon/monkey/inventory.dm index 68140e0dfffe..7deac9a08560 100644 --- a/code/modules/mob/living/carbon/monkey/inventory.dm +++ b/code/modules/mob/living/carbon/monkey/inventory.dm @@ -1,217 +1,217 @@ -/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) - if("pockets") - message = text("[] is trying to empty []'s pockets.",source, target) - - 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(!in_range(s_loc, t_loc)) 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.remove_from_mob(W) - W.add_fingerprint(source) - else - if (istype(item, /obj/item/clothing/mask)) - source.drop_item() - loc = target - item.layer = ABOVE_HUD_LAYER - item.plane = ABOVE_HUD_PLANE - item.appearance_flags = APPEARANCE_UI - target.wear_mask = item - item.loc = target - if("l_hand") - if (target.l_hand) - var/obj/item/W = target.l_hand - target.remove_from_mob(W) - W.add_fingerprint(source) - else - if (istype(item, /obj/item)) - source.drop_item() - loc = target - item.layer = ABOVE_HUD_LAYER - item.plane = ABOVE_HUD_PLANE - item.appearance_flags = APPEARANCE_UI - 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.remove_from_mob(W) - W.add_fingerprint(source) - else - if (istype(item, /obj/item)) - source.drop_item() - loc = target - item.layer = ABOVE_HUD_LAYER - item.plane = ABOVE_HUD_PLANE - item.appearance_flags = APPEARANCE_UI - 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.remove_from_mob(W) - W.add_fingerprint(source) - else - if ((istype(item, /obj/item) && item.slot_flags & SLOT_BACK )) - source.drop_item() - loc = target - item.layer = ABOVE_HUD_LAYER - item.plane = ABOVE_HUD_PLANE - item.appearance_flags = APPEARANCE_UI - target.back = item - item.loc = target - if("handcuff") - if (target.handcuffed) - var/obj/item/W = target.handcuffed - target.remove_from_mob(W) - W.add_fingerprint(source) - else - if (istype(item, /obj/item/weapon/handcuffs)) - source.drop_item() - 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) - 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, slot, redraw_mob = 1) - if(!slot) return - if(!istype(W)) return - - if(W == get_active_hand()) - u_equip(W) - - switch(slot) - if(slot_back) - src.back = W - equip_to_slot_if_possible(W,slot,0,1) - update_inv_back(redraw_mob) - if(slot_wear_mask) - src.wear_mask = W - equip_to_slot_if_possible(W,slot,0,1) - update_inv_wear_mask(redraw_mob) - if(slot_handcuffed) - src.handcuffed = W - update_inv_handcuffed(redraw_mob) - if(slot_legcuffed) - src.legcuffed = W - equip_to_slot_if_possible(W,slot,0,1) - update_inv_legcuffed(redraw_mob) - if(slot_l_hand) - src.l_hand = W - equip_to_slot_if_possible(W,slot,0,1) - update_inv_l_hand(redraw_mob) - if(slot_r_hand) - src.r_hand = W - equip_to_slot_if_possible(W,slot,0,1) - update_inv_r_hand(redraw_mob) - if(slot_in_backpack) - W.forceMove(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 = ABOVE_HUD_LAYER - W.plane = ABOVE_HUD_PLANE - W.appearance_flags = APPEARANCE_UI - - return +/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) + if("pockets") + message = text("[] is trying to empty []'s pockets.",source, target) + + 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(!in_range(s_loc, t_loc)) 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.remove_from_mob(W) + W.add_fingerprint(source) + else + if (istype(item, /obj/item/clothing/mask)) + source.drop_item() + loc = target + item.layer = ABOVE_HUD_LAYER + item.plane = ABOVE_HUD_PLANE + item.appearance_flags = APPEARANCE_UI + target.wear_mask = item + item.loc = target + if("l_hand") + if (target.l_hand) + var/obj/item/W = target.l_hand + target.remove_from_mob(W) + W.add_fingerprint(source) + else + if (istype(item, /obj/item)) + source.drop_item() + loc = target + item.layer = ABOVE_HUD_LAYER + item.plane = ABOVE_HUD_PLANE + item.appearance_flags = APPEARANCE_UI + 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.remove_from_mob(W) + W.add_fingerprint(source) + else + if (istype(item, /obj/item)) + source.drop_item() + loc = target + item.layer = ABOVE_HUD_LAYER + item.plane = ABOVE_HUD_PLANE + item.appearance_flags = APPEARANCE_UI + 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.remove_from_mob(W) + W.add_fingerprint(source) + else + if ((istype(item, /obj/item) && item.slot_flags & SLOT_BACK )) + source.drop_item() + loc = target + item.layer = ABOVE_HUD_LAYER + item.plane = ABOVE_HUD_PLANE + item.appearance_flags = APPEARANCE_UI + target.back = item + item.loc = target + if("handcuff") + if (target.handcuffed) + var/obj/item/W = target.handcuffed + target.remove_from_mob(W) + W.add_fingerprint(source) + else + if (istype(item, /obj/item/weapon/handcuffs)) + source.drop_item() + 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) + 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, slot, redraw_mob = 1) + if(!slot) return + if(!istype(W)) return + + if(W == get_active_hand()) + u_equip(W) + + switch(slot) + if(slot_back) + src.back = W + equip_to_slot_if_possible(W,slot,0,1) + update_inv_back(redraw_mob) + if(slot_wear_mask) + src.wear_mask = W + equip_to_slot_if_possible(W,slot,0,1) + update_inv_wear_mask(redraw_mob) + if(slot_handcuffed) + src.handcuffed = W + update_inv_handcuffed(redraw_mob) + if(slot_legcuffed) + src.legcuffed = W + equip_to_slot_if_possible(W,slot,0,1) + update_inv_legcuffed(redraw_mob) + if(slot_l_hand) + src.l_hand = W + equip_to_slot_if_possible(W,slot,0,1) + update_inv_l_hand(redraw_mob) + if(slot_r_hand) + src.r_hand = W + equip_to_slot_if_possible(W,slot,0,1) + update_inv_r_hand(redraw_mob) + if(slot_in_backpack) + W.forceMove(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 = ABOVE_HUD_LAYER + W.plane = ABOVE_HUD_PLANE + W.appearance_flags = APPEARANCE_UI + + return diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index c523c931073d..ddc459464bcb 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -1,659 +1,659 @@ -/mob/living/carbon/monkey/Life() - set invisibility = 0 - //set background = 1 - 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) - if(!istype(src,/mob/living/carbon/monkey/diona)) - //First, resolve location and get a breath - if(SSmob.times_fired%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() - if(on_fire && fire_stacks > 0) - fire_stacks -= 0.5 - - - //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")) - updatehealth() - - -/mob/living/carbon/monkey/calculate_affecting_pressure(pressure) - ..() - return pressure - -/mob/living/carbon/monkey - - proc/handle_disabilities() - - if (disabilities & EPILEPSY || has_trait(TRAIT_EPILEPSY)) - if ((prob(1) && paralysis < 10)) - to_chat(src, "\red You have a seizure!") - Paralyse(10) - if (disabilities & COUGHING || has_trait(TRAIT_COUGH)) - if ((prob(5) && paralysis <= 1)) - drop_item() - spawn( 0 ) - emote("cough") - return - if (disabilities & TOURETTES || has_trait(TRAIT_TOURETTE)) - if ((prob(10) && paralysis <= 1)) - Stun(10) - spawn( 0 ) - emote("twitch") - return - if (disabilities & NERVOUS || has_trait(TRAIT_NERVOUS)) - if (prob(10)) - stuttering = max(10, stuttering) - - proc/handle_mutations_and_radiation() - - if(getFireLoss()) - if((COLD_RESISTANCE in mutations) || prob(50)) - switch(getFireLoss()) - if(1 to 50) - adjustFireLoss(-1) - if(51 to 100) - adjustFireLoss(-5) - - if ((HULK in mutations) && health <= 25) - mutations.Remove(HULK) - to_chat(src, "\red You suddenly feel very weak.") - Weaken(3) - emote("collapse") - - 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)) - return - - if (radiation > 100) - radiation = 100 - Weaken(10) - if(!lying) - to_chat(src, "\red You feel weak.") - emote("collapse") - - 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 - Weaken(3) - if(!lying) - to_chat(src, "\red You feel weak.") - emote("collapse") - - if(75 to 100) - radiation -= 3 - adjustToxLoss(3) - if(prob(1)) - to_chat(src, "\red You mutate!") - randmutb(src) - domutcheck(src,null) - emote("gasp") - - 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) - - for(var/obj/effect/decal/cleanable/O in view(1,src)) - if(istype(O,/obj/effect/decal/cleanable/blood)) - var/obj/effect/decal/cleanable/blood/B = O - if(B.virus2.len) - for (var/ID in B.virus2) - var/datum/disease2/disease/V = B.virus2[ID] - infect_virus2(src,V) - - else if(istype(O,/obj/effect/decal/cleanable/mucus)) - var/obj/effect/decal/cleanable/mucus/M = O - - if(M.virus2.len) - for (var/ID in M.virus2) - var/datum/disease2/disease/V = M.virus2[ID] - infect_virus2(src,V) - - if(virus2.len) - 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 - - proc/breathe() - if(reagents) - - if(reagents.has_reagent("lexorin")) return - - if(!loc) return //probably ought to make a proper fix for this, but :effort: --NeoFite - if(istype(loc, /obj/item/weapon/holder)) return // типа быстрофикс на обезьянок что берут на руки, хотя бы не будут умирать.. но нужно нормальное решение. - - var/datum/gas_mixture/environment = loc.return_air() - var/datum/gas_mixture/breath - if(handle_drowning() || health < 0) - losebreath = max(2, losebreath + 1) - 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) - - if(istype(wear_mask, /obj/item/clothing/mask/gas)) - var/obj/item/clothing/mask/gas/G = wear_mask - var/datum/gas_mixture/filtered = new - - for(var/g in list("phoron", "sleeping_agent")) - if(breath.gas[g]) - filtered.gas[g] = breath.gas[g] * G.gas_filter_strength - breath.gas[g] -= filtered.gas[g] - - breath.update_values() - filtered.update_values() - - // 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) - - - 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) - 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_phoron_max = 0.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.gas["oxygen"] / breath.total_moles) * breath_pressure - // Same, but for the phoron - var/Toxins_pp = (breath.gas["phoron"] / 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.gas["carbon_dioxide"] / breath.total_moles) * breath_pressure - - if(O2_pp < safe_oxygen_min) // Too little oxygen - if(prob(20)) - 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.gas["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.gas["oxygen"] / 6 - oxygen_alert = 0 - - breath.adjust_gas("oxygen", oxygen_used, update = FALSE) - breath.adjust_gas_temp("carbon_dioxide", oxygen_used, bodytemperature, update = FALSE) //update afterwards - - 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_phoron_max) // Too much phoron - var/ratio = (breath.gas["phoron"] / safe_phoron_max) * 10 - //adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) //Limit amount of damage toxin exposure can do per second - if(reagents) - reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) - phoron_alert = max(phoron_alert, 1) - else - phoron_alert = 0 - - if(breath.gas["sleeping_agent"]) // If there's some other shit in the air lets deal with it here. - var/SA_pp = (breath.gas["sleeping_agent"] / 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(5) - 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")) - - breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"] / 6, update = FALSE) //update after - - if(breath.temperature > (T0C + 66)) // Hot air hurts :( - if(prob(20)) - to_chat(src, "\red You feel a searing heat in your lungs!") - fire_alert = max(fire_alert, 2) - else - fire_alert = 0 - - breath.update_values() - - //Temporary fixes to the alerts. - - return 1 - - handle_environment(datum/gas_mixture/environment) - if(!environment) - return - - //Moved these vars here for use in the fuck-it-skip-processing check. - var/pressure = environment.return_pressure() - var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. - - if(adjusted_pressure < warning_high_pressure && adjusted_pressure > warning_low_pressure && abs(environment.temperature - 293.15) < 20 && abs(bodytemperature - 310.14) < 0.5) - - //Hopefully should fix the walk-inside-still-pressure-warning issue. - if(pressure_alert) - clear_alert("pressure") - - return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp - - var/environment_heat_capacity = environment.heat_capacity() - if(istype(get_turf(src), /turf/space)) - var/turf/heat_turf = get_turf(src) - environment_heat_capacity = heat_turf.heat_capacity - if(!on_fire) - 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 - switch(adjusted_pressure) - if(hazard_high_pressure to INFINITY) - adjustBruteLoss( min( ( (adjusted_pressure / hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) ) - throw_alert("pressure","highpressure",2) - if(warning_high_pressure to hazard_high_pressure) - throw_alert("pressure","highpressure",1) - if(warning_low_pressure to warning_high_pressure) - clear_alert("pressure") - if(hazard_low_pressure to warning_low_pressure) - throw_alert("pressure","lowpressure",1) - else - if( !(COLD_RESISTANCE in mutations) ) - adjustBruteLoss( LOW_PRESSURE_DAMAGE ) - throw_alert("pressure","lowpressure",2) - else - throw_alert("pressure","lowpressure",1) - - return - - 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) - - proc/handle_chemicals_in_body() - - if(reagents && reagents.reagent_list.len) - reagents.metabolize(src,race) - - if (drowsyness) - drowsyness-- - eye_blurry = max(2, eye_blurry) - if (prob(5)) - sleeping += 1 - Paralyse(5) - - if(confused) - confused = max(0, confused - 1) - - if(resting) - dizziness = max(0, dizziness - 5) - else - dizziness = max(0, dizziness - 1) - - return //TODO: DEFERRED - - proc/handle_regular_status_updates() - - 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 || brain_op_stage == 4.0) - 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 - - - handle_regular_hud_updates() - if(!client) - return 0 - - if (stat == DEAD || (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 != DEAD) - if(changeling_aug) - sight &= ~SEE_TURFS - sight |= SEE_MOBS - sight &= ~SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - else - sight &= ~SEE_TURFS - sight &= ~SEE_MOBS - sight &= ~SEE_OBJS - see_in_dark = 2 - see_invisible = SEE_INVISIBLE_LIVING - - if (healths) - if (stat != DEAD) - 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]" - - ..() - - return 1 - - proc/handle_random_events() - if (prob(1) && prob(2)) - spawn(0) - emote("scratch") - return - - - proc/handle_changeling() - if(mind && mind.changeling) - mind.changeling.regenerate() - hud_used.lingchemdisplay.invisibility = 0 - hud_used.lingchemdisplay.maptext = "
                    [src.mind.changeling.chem_charges]
                    " - return - -///FIRE CODE - handle_fire() - if(..()) - return - adjustFireLoss(6) - return -//END FIRE CODE - -/mob/living/carbon/monkey/diona/Life() - if(stat != DEAD) - var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing - if(gestalt && isturf(gestalt.loc)) - var/turf/T = gestalt.loc - light_amount = round((T.get_lumcount()*10)-5) - else if(isturf(loc)) //else, there's considered to be no light - var/turf/T = loc - light_amount = round((T.get_lumcount()*10)-5) - - nutrition += light_amount - traumatic_shock -= light_amount - - if(nutrition > 400) - nutrition = 400 - if(light_amount > 2) //if there's enough light, heal - adjustBruteLoss(-1) - adjustToxLoss(-1) - adjustOxyLoss(-1) - - if(injecting) - if(gestalt && nutrition > 210) - gestalt.reagents.add_reagent(injecting,1) - nutrition -= 10 - else - injecting = null - ..() +/mob/living/carbon/monkey/Life() + set invisibility = 0 + //set background = 1 + 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) + if(!istype(src,/mob/living/carbon/monkey/diona)) + //First, resolve location and get a breath + if(SSmob.times_fired%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() + if(on_fire && fire_stacks > 0) + fire_stacks -= 0.5 + + + //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")) + updatehealth() + + +/mob/living/carbon/monkey/calculate_affecting_pressure(pressure) + ..() + return pressure + +/mob/living/carbon/monkey + + proc/handle_disabilities() + + if (disabilities & EPILEPSY || has_trait(TRAIT_EPILEPSY)) + if ((prob(1) && paralysis < 10)) + to_chat(src, "\red You have a seizure!") + Paralyse(10) + if (disabilities & COUGHING || has_trait(TRAIT_COUGH)) + if ((prob(5) && paralysis <= 1)) + drop_item() + spawn( 0 ) + emote("cough") + return + if (disabilities & TOURETTES || has_trait(TRAIT_TOURETTE)) + if ((prob(10) && paralysis <= 1)) + Stun(10) + spawn( 0 ) + emote("twitch") + return + if (disabilities & NERVOUS || has_trait(TRAIT_NERVOUS)) + if (prob(10)) + stuttering = max(10, stuttering) + + proc/handle_mutations_and_radiation() + + if(getFireLoss()) + if((COLD_RESISTANCE in mutations) || prob(50)) + switch(getFireLoss()) + if(1 to 50) + adjustFireLoss(-1) + if(51 to 100) + adjustFireLoss(-5) + + if ((HULK in mutations) && health <= 25) + mutations.Remove(HULK) + to_chat(src, "\red You suddenly feel very weak.") + Weaken(3) + emote("collapse") + + 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)) + return + + if (radiation > 100) + radiation = 100 + Weaken(10) + if(!lying) + to_chat(src, "\red You feel weak.") + emote("collapse") + + 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 + Weaken(3) + if(!lying) + to_chat(src, "\red You feel weak.") + emote("collapse") + + if(75 to 100) + radiation -= 3 + adjustToxLoss(3) + if(prob(1)) + to_chat(src, "\red You mutate!") + randmutb(src) + domutcheck(src,null) + emote("gasp") + + 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) + + for(var/obj/effect/decal/cleanable/O in view(1,src)) + if(istype(O,/obj/effect/decal/cleanable/blood)) + var/obj/effect/decal/cleanable/blood/B = O + if(B.virus2.len) + for (var/ID in B.virus2) + var/datum/disease2/disease/V = B.virus2[ID] + infect_virus2(src,V) + + else if(istype(O,/obj/effect/decal/cleanable/mucus)) + var/obj/effect/decal/cleanable/mucus/M = O + + if(M.virus2.len) + for (var/ID in M.virus2) + var/datum/disease2/disease/V = M.virus2[ID] + infect_virus2(src,V) + + if(virus2.len) + 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 + + proc/breathe() + if(reagents) + + if(reagents.has_reagent("lexorin")) return + + if(!loc) return //probably ought to make a proper fix for this, but :effort: --NeoFite + if(istype(loc, /obj/item/weapon/holder)) return // типа быстрофикс на обезьянок что берут на руки, хотя бы не будут умирать.. но нужно нормальное решение. + + var/datum/gas_mixture/environment = loc.return_air() + var/datum/gas_mixture/breath + if(handle_drowning() || health < 0) + losebreath = max(2, losebreath + 1) + 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) + + if(istype(wear_mask, /obj/item/clothing/mask/gas)) + var/obj/item/clothing/mask/gas/G = wear_mask + var/datum/gas_mixture/filtered = new + + for(var/g in list("phoron", "sleeping_agent")) + if(breath.gas[g]) + filtered.gas[g] = breath.gas[g] * G.gas_filter_strength + breath.gas[g] -= filtered.gas[g] + + breath.update_values() + filtered.update_values() + + // 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) + + + 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) + 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_phoron_max = 0.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.gas["oxygen"] / breath.total_moles) * breath_pressure + // Same, but for the phoron + var/Toxins_pp = (breath.gas["phoron"] / 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.gas["carbon_dioxide"] / breath.total_moles) * breath_pressure + + if(O2_pp < safe_oxygen_min) // Too little oxygen + if(prob(20)) + 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.gas["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.gas["oxygen"] / 6 + oxygen_alert = 0 + + breath.adjust_gas("oxygen", oxygen_used, update = FALSE) + breath.adjust_gas_temp("carbon_dioxide", oxygen_used, bodytemperature, update = FALSE) //update afterwards + + 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_phoron_max) // Too much phoron + var/ratio = (breath.gas["phoron"] / safe_phoron_max) * 10 + //adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) //Limit amount of damage toxin exposure can do per second + if(reagents) + reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) + phoron_alert = max(phoron_alert, 1) + else + phoron_alert = 0 + + if(breath.gas["sleeping_agent"]) // If there's some other shit in the air lets deal with it here. + var/SA_pp = (breath.gas["sleeping_agent"] / 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(5) + 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")) + + breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"] / 6, update = FALSE) //update after + + if(breath.temperature > (T0C + 66)) // Hot air hurts :( + if(prob(20)) + to_chat(src, "\red You feel a searing heat in your lungs!") + fire_alert = max(fire_alert, 2) + else + fire_alert = 0 + + breath.update_values() + + //Temporary fixes to the alerts. + + return 1 + + handle_environment(datum/gas_mixture/environment) + if(!environment) + return + + //Moved these vars here for use in the fuck-it-skip-processing check. + var/pressure = environment.return_pressure() + var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. + + if(adjusted_pressure < warning_high_pressure && adjusted_pressure > warning_low_pressure && abs(environment.temperature - 293.15) < 20 && abs(bodytemperature - 310.14) < 0.5) + + //Hopefully should fix the walk-inside-still-pressure-warning issue. + if(pressure_alert) + clear_alert("pressure") + + return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp + + var/environment_heat_capacity = environment.heat_capacity() + if(istype(get_turf(src), /turf/space)) + var/turf/heat_turf = get_turf(src) + environment_heat_capacity = heat_turf.heat_capacity + if(!on_fire) + 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 + switch(adjusted_pressure) + if(hazard_high_pressure to INFINITY) + adjustBruteLoss( min( ( (adjusted_pressure / hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) ) + throw_alert("pressure","highpressure",2) + if(warning_high_pressure to hazard_high_pressure) + throw_alert("pressure","highpressure",1) + if(warning_low_pressure to warning_high_pressure) + clear_alert("pressure") + if(hazard_low_pressure to warning_low_pressure) + throw_alert("pressure","lowpressure",1) + else + if( !(COLD_RESISTANCE in mutations) ) + adjustBruteLoss( LOW_PRESSURE_DAMAGE ) + throw_alert("pressure","lowpressure",2) + else + throw_alert("pressure","lowpressure",1) + + return + + 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) + + proc/handle_chemicals_in_body() + + if(reagents && reagents.reagent_list.len) + reagents.metabolize(src,race) + + if (drowsyness) + drowsyness-- + eye_blurry = max(2, eye_blurry) + if (prob(5)) + sleeping += 1 + Paralyse(5) + + if(confused) + confused = max(0, confused - 1) + + if(resting) + dizziness = max(0, dizziness - 5) + else + dizziness = max(0, dizziness - 1) + + return //TODO: DEFERRED + + proc/handle_regular_status_updates() + + 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 || brain_op_stage == 4.0) + 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 + + + handle_regular_hud_updates() + if(!client) + return 0 + + if (stat == DEAD || (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 != DEAD) + if(changeling_aug) + sight &= ~SEE_TURFS + sight |= SEE_MOBS + sight &= ~SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + else + sight &= ~SEE_TURFS + sight &= ~SEE_MOBS + sight &= ~SEE_OBJS + see_in_dark = 2 + see_invisible = SEE_INVISIBLE_LIVING + + if (healths) + if (stat != DEAD) + 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]" + + ..() + + return 1 + + proc/handle_random_events() + if (prob(1) && prob(2)) + spawn(0) + emote("scratch") + return + + + proc/handle_changeling() + if(mind && mind.changeling) + mind.changeling.regenerate() + hud_used.lingchemdisplay.invisibility = 0 + hud_used.lingchemdisplay.maptext = "
                    [src.mind.changeling.chem_charges]
                    " + return + +///FIRE CODE + handle_fire() + if(..()) + return + adjustFireLoss(6) + return +//END FIRE CODE + +/mob/living/carbon/monkey/diona/Life() + if(stat != DEAD) + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(gestalt && isturf(gestalt.loc)) + var/turf/T = gestalt.loc + light_amount = round((T.get_lumcount()*10)-5) + else if(isturf(loc)) //else, there's considered to be no light + var/turf/T = loc + light_amount = round((T.get_lumcount()*10)-5) + + nutrition += light_amount + traumatic_shock -= light_amount + + if(nutrition > 400) + nutrition = 400 + if(light_amount > 2) //if there's enough light, heal + adjustBruteLoss(-1) + adjustToxLoss(-1) + adjustOxyLoss(-1) + + if(injecting) + if(gestalt && nutrition > 210) + gestalt.reagents.add_reagent(injecting,1) + nutrition -= 10 + else + injecting = null + ..() diff --git a/code/modules/mob/living/carbon/monkey/login.dm b/code/modules/mob/living/carbon/monkey/login.dm index 3b7e5dcb971b..7f09b63a2197 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 2f8d516c8830..e0bbafe60dd0 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -1,523 +1,523 @@ -/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 - ventcrawler = 1 - var/hazard_high_pressure = HAZARD_HIGH_PRESSURE - var/warning_high_pressure = WARNING_HIGH_PRESSURE - var/warning_low_pressure = WARNING_LOW_PRESSURE - var/hazard_low_pressure = HAZARD_LOW_PRESSURE - var/blood_datum = /datum/dirt_cover/red_blood - 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/race = HUMAN // Used for restrictions checking. - holder_type = /obj/item/weapon/holder/monkey - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/monkey = 5) - -/mob/living/carbon/monkey/tajara - name = "farwa" - voice_name = "farwa" - speak_emote = list("mews") - icon_state = "tajkey1" - uni_append = list(0x0A0,0xE00) // 0A0E00 - race = TAJARAN - holder_type = /obj/item/weapon/holder/monkey/farwa - -/mob/living/carbon/monkey/skrell - name = "neaera" - voice_name = "neaera" - speak_emote = list("squicks") - icon_state = "skrellkey1" - uni_append = list(0x01C,0xC92) // 01CC92 - metabolism_factor = SKRELL_METABOLISM_FACTOR - race = SKRELL - holder_type = /obj/item/weapon/holder/monkey/neaera - blood_datum = /datum/dirt_cover/purple_blood - -/mob/living/carbon/monkey/unathi - name = "stok" - voice_name = "stok" - speak_emote = list("hisses") - icon_state = "stokkey1" - uni_append = list(0x044,0xC5D) // 044C5D - race = UNATHI - holder_type = /obj/item/weapon/holder/monkey/stok - -/mob/living/carbon/monkey/atom_init() - 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) - gender = pick(MALE, FEMALE) - dna = new /datum/dna( null ) - dna.real_name = real_name - 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 - - . = ..() - - monkey_list += src - update_icons() - -/mob/living/carbon/monkey/Destroy() - monkey_list -= src - return ..() - -/mob/living/carbon/monkey/unathi/atom_init() - - . = ..() - dna.mutantrace = "lizard" - greaterform = UNATHI - add_language("Sinta'unathi") - -/mob/living/carbon/monkey/skrell/atom_init() - - . = ..() - dna.mutantrace = "skrell" - greaterform = SKRELL - add_language("Skrellian") - -/mob/living/carbon/monkey/tajara/atom_init() - - . = ..() - dna.mutantrace = "tajaran" - greaterform = TAJARAN - add_language("Siik'tajr") - -/mob/living/carbon/monkey/diona/atom_init() - - . = ..() - gender = NEUTER - dna.mutantrace = "plant" - greaterform = DIONA - add_language("Rootspeak") - -/mob/living/carbon/monkey/diona/movement_delay() - return ..(tally = 3.5) - -/mob/living/carbon/monkey/movement_delay(tally = 0) - if(reagents && reagents.has_reagent("hyperzine") || reagents.has_reagent("nuka_cola")) - return -1 - - var/health_deficiency = (100 - health) - if(health_deficiency >= 45) tally += (health_deficiency / 25) - - if(pull_debuff) - tally += pull_debuff - - if (bodytemperature < 283.222) - tally += (283.222 - bodytemperature) / 10 * 1.75 - return tally+config.monkey_delay - -/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/item/item = usr.get_active_hand() - if(item && (item.flags & (ABSTRACT | DROPDEL))) - return - var/obj/effect/equip_e/monkey/O = new /obj/effect/equip_e/monkey( ) - O.source = usr - O.target = src - O.item = item - O.s_loc = usr.loc - O.t_loc = loc - O.place = href_list["item"] - requests += O - spawn( 0 ) - O.process() - return - ..() - return - -/mob/living/carbon/monkey/meteorhit(obj/O) - for(var/mob/M in viewers(src, null)) - M.show_message(text("\red [] has been hit by []", src, O), 1) - if (health > 0) - var/shielded = 0 - adjustBruteLoss(30) - if ((O.icon_state == "flaming" && !( shielded ))) - adjustFireLoss(40) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - return - -//mob/living/carbon/monkey/bullet_act(obj/item/projectile/Proj)taken care of in living - - -/mob/living/carbon/monkey/attack_paw(mob/M) - ..() - - if (M.a_intent == "help") - help_shake_act(M) - else - if ((M.a_intent == "hurt" && !( istype(wear_mask, /obj/item/clothing/mask/muzzle) ))) - M.do_attack_animation(src) - 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("\red [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(istype(D, /datum/disease/jungle_fever)) - contract_disease(D,1,0) - else - for(var/mob/O in viewers(src, null)) - O.show_message("\red [M.name] has attempted to bite [name]!", 1) - return - -/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M) - 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 - - 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 == "hurt")//Stungloves. Any contact will stun the alien. - if(G.cell.charge >= 2500) - G.cell.use(2500) - apply_effects(0,0,0,0,5,0,0,150) - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() - s.set_up(3, 1, src) - s.start() - - M.do_attack_animation(src) - for(var/mob/O in viewers(src, null)) - if (O.client) - O.show_message("\red [src] has been touched with the stun gloves by [M]!", 1, "\red You hear someone fall", 2) - return - else - to_chat(M, "\red Not enough charge! ") - return - - if (M.a_intent == "help") - help_shake_act(M) - get_scooped(M) - else - if (M.a_intent == "hurt") - M.do_attack_animation(src) - if ((prob(75) && health > 0)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has punched [name]!", M), 1) - - playsound(loc, "punch", 25, 1, -1) - var/damage = rand(5, 10) - if (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("\red [] 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("\red [] has attempted to punch [name]!", M), 1) - else - if (M.a_intent == "grab") - if (M == src || anchored || M.lying) - return - - var/obj/item/weapon/grab/G = new /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("\red [] 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("\red [] 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("\red [] has disarmed [name]!", M), 1) - return - -/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M) - 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 ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) - - if ("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("\red [] has wounded [name]!", M), 1) - else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] 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("\red [] has attempted to lunge at [name]!", M), 1) - - if ("grab") - if (M == src || anchored || M.lying) - return - var/obj/item/weapon/grab/G = new /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("\red [] has grabbed [name] passively!", M), 1) - - if ("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("\red [] 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("\red [] has disarmed [name]!", M), 1) - adjustBruteLoss(damage) - updatehealth() - return - -/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M) - if(..()) - 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) - visible_message("[M][M.attacktext] [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) - adjustBruteLoss(damage) - updatehealth() - - -/mob/living/carbon/monkey/attack_slime(mob/living/carbon/slime/M) - 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("\red 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("\red 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, "Intent: [a_intent]") - stat(null, "Move Mode: [m_intent]") - if(istype(src, /mob/living/carbon/monkey/diona)) - stat(null, "Nutriment: [nutrition]/400") - CHANGELING_STATPANEL_STATS(null) - - CHANGELING_STATPANEL_POWERS(null) - -/mob/living/carbon/monkey/verb/removeinternal() - set name = "Remove Internals" - set category = "IC" - internal = null - return - -/mob/living/carbon/monkey/emp_act(severity) - if(wear_id) wear_id.emp_act(severity) - ..() - -/mob/living/carbon/monkey/ex_act(severity) - if(!blinded) - flash_eyes() - - switch(severity) - if(1.0) - if (stat != DEAD) - adjustBruteLoss(200) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - if(2.0) - if (stat != DEAD) - adjustBruteLoss(60) - adjustFireLoss(60) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - if(3.0) - if (stat != DEAD) - adjustBruteLoss(30) - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - if (prob(50)) - Paralyse(10) - else - return - -/mob/living/carbon/monkey/blob_act() - if (stat != DEAD) - 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 0 - -/mob/living/carbon/monkey/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/italics=0, var/message_range = world.view, var/list/used_radios = list()) - if(stat) - return - - if(copytext(message,1,2) == "*") - return emote(copytext(message,2)) - - if(stat) - return - - if(speak_emote.len) - verb = pick(speak_emote) - - message = capitalize(trim_left(message)) - - ..(message, speaking, verb, alt_name, italics, message_range, used_radios) +/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 + ventcrawler = 1 + var/hazard_high_pressure = HAZARD_HIGH_PRESSURE + var/warning_high_pressure = WARNING_HIGH_PRESSURE + var/warning_low_pressure = WARNING_LOW_PRESSURE + var/hazard_low_pressure = HAZARD_LOW_PRESSURE + var/blood_datum = /datum/dirt_cover/red_blood + 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/race = HUMAN // Used for restrictions checking. + holder_type = /obj/item/weapon/holder/monkey + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/monkey = 5) + +/mob/living/carbon/monkey/tajara + name = "farwa" + voice_name = "farwa" + speak_emote = list("mews") + icon_state = "tajkey1" + uni_append = list(0x0A0,0xE00) // 0A0E00 + race = TAJARAN + holder_type = /obj/item/weapon/holder/monkey/farwa + +/mob/living/carbon/monkey/skrell + name = "neaera" + voice_name = "neaera" + speak_emote = list("squicks") + icon_state = "skrellkey1" + uni_append = list(0x01C,0xC92) // 01CC92 + metabolism_factor = SKRELL_METABOLISM_FACTOR + race = SKRELL + holder_type = /obj/item/weapon/holder/monkey/neaera + blood_datum = /datum/dirt_cover/purple_blood + +/mob/living/carbon/monkey/unathi + name = "stok" + voice_name = "stok" + speak_emote = list("hisses") + icon_state = "stokkey1" + uni_append = list(0x044,0xC5D) // 044C5D + race = UNATHI + holder_type = /obj/item/weapon/holder/monkey/stok + +/mob/living/carbon/monkey/atom_init() + 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) + gender = pick(MALE, FEMALE) + dna = new /datum/dna( null ) + dna.real_name = real_name + 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 + + . = ..() + + monkey_list += src + update_icons() + +/mob/living/carbon/monkey/Destroy() + monkey_list -= src + return ..() + +/mob/living/carbon/monkey/unathi/atom_init() + + . = ..() + dna.mutantrace = "lizard" + greaterform = UNATHI + add_language("Sinta'unathi") + +/mob/living/carbon/monkey/skrell/atom_init() + + . = ..() + dna.mutantrace = "skrell" + greaterform = SKRELL + add_language("Skrellian") + +/mob/living/carbon/monkey/tajara/atom_init() + + . = ..() + dna.mutantrace = "tajaran" + greaterform = TAJARAN + add_language("Siik'tajr") + +/mob/living/carbon/monkey/diona/atom_init() + + . = ..() + gender = NEUTER + dna.mutantrace = "plant" + greaterform = DIONA + add_language("Rootspeak") + +/mob/living/carbon/monkey/diona/movement_delay() + return ..(tally = 3.5) + +/mob/living/carbon/monkey/movement_delay(tally = 0) + if(reagents && reagents.has_reagent("hyperzine") || reagents.has_reagent("nuka_cola")) + return -1 + + var/health_deficiency = (100 - health) + if(health_deficiency >= 45) tally += (health_deficiency / 25) + + if(pull_debuff) + tally += pull_debuff + + if (bodytemperature < 283.222) + tally += (283.222 - bodytemperature) / 10 * 1.75 + return tally+config.monkey_delay + +/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/item/item = usr.get_active_hand() + if(item && (item.flags & (ABSTRACT | DROPDEL))) + return + var/obj/effect/equip_e/monkey/O = new /obj/effect/equip_e/monkey( ) + O.source = usr + O.target = src + O.item = item + O.s_loc = usr.loc + O.t_loc = loc + O.place = href_list["item"] + requests += O + spawn( 0 ) + O.process() + return + ..() + return + +/mob/living/carbon/monkey/meteorhit(obj/O) + for(var/mob/M in viewers(src, null)) + M.show_message(text("\red [] has been hit by []", src, O), 1) + if (health > 0) + var/shielded = 0 + adjustBruteLoss(30) + if ((O.icon_state == "flaming" && !( shielded ))) + adjustFireLoss(40) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + return + +//mob/living/carbon/monkey/bullet_act(obj/item/projectile/Proj)taken care of in living + + +/mob/living/carbon/monkey/attack_paw(mob/M) + ..() + + if (M.a_intent == "help") + help_shake_act(M) + else + if ((M.a_intent == "hurt" && !( istype(wear_mask, /obj/item/clothing/mask/muzzle) ))) + M.do_attack_animation(src) + 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("\red [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(istype(D, /datum/disease/jungle_fever)) + contract_disease(D,1,0) + else + for(var/mob/O in viewers(src, null)) + O.show_message("\red [M.name] has attempted to bite [name]!", 1) + return + +/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M) + 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 + + 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 == "hurt")//Stungloves. Any contact will stun the alien. + if(G.cell.charge >= 2500) + G.cell.use(2500) + apply_effects(0,0,0,0,5,0,0,150) + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread() + s.set_up(3, 1, src) + s.start() + + M.do_attack_animation(src) + for(var/mob/O in viewers(src, null)) + if (O.client) + O.show_message("\red [src] has been touched with the stun gloves by [M]!", 1, "\red You hear someone fall", 2) + return + else + to_chat(M, "\red Not enough charge! ") + return + + if (M.a_intent == "help") + help_shake_act(M) + get_scooped(M) + else + if (M.a_intent == "hurt") + M.do_attack_animation(src) + if ((prob(75) && health > 0)) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has punched [name]!", M), 1) + + playsound(loc, "punch", 25, 1, -1) + var/damage = rand(5, 10) + if (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("\red [] 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("\red [] has attempted to punch [name]!", M), 1) + else + if (M.a_intent == "grab") + if (M == src || anchored || M.lying) + return + + var/obj/item/weapon/grab/G = new /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("\red [] 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("\red [] 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("\red [] has disarmed [name]!", M), 1) + return + +/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M) + 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 ("help") + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) + + if ("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("\red [] has wounded [name]!", M), 1) + else + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] 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("\red [] has attempted to lunge at [name]!", M), 1) + + if ("grab") + if (M == src || anchored || M.lying) + return + var/obj/item/weapon/grab/G = new /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("\red [] has grabbed [name] passively!", M), 1) + + if ("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("\red [] 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("\red [] has disarmed [name]!", M), 1) + adjustBruteLoss(damage) + updatehealth() + return + +/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M) + if(..()) + 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) + visible_message("[M][M.attacktext] [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) + adjustBruteLoss(damage) + updatehealth() + + +/mob/living/carbon/monkey/attack_slime(mob/living/carbon/slime/M) + 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("\red 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("\red 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, "Intent: [a_intent]") + stat(null, "Move Mode: [m_intent]") + if(istype(src, /mob/living/carbon/monkey/diona)) + stat(null, "Nutriment: [nutrition]/400") + CHANGELING_STATPANEL_STATS(null) + + CHANGELING_STATPANEL_POWERS(null) + +/mob/living/carbon/monkey/verb/removeinternal() + set name = "Remove Internals" + set category = "IC" + internal = null + return + +/mob/living/carbon/monkey/emp_act(severity) + if(wear_id) wear_id.emp_act(severity) + ..() + +/mob/living/carbon/monkey/ex_act(severity) + if(!blinded) + flash_eyes() + + switch(severity) + if(1.0) + if (stat != DEAD) + adjustBruteLoss(200) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + if(2.0) + if (stat != DEAD) + adjustBruteLoss(60) + adjustFireLoss(60) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + if(3.0) + if (stat != DEAD) + adjustBruteLoss(30) + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + if (prob(50)) + Paralyse(10) + else + return + +/mob/living/carbon/monkey/blob_act() + if (stat != DEAD) + 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 0 + +/mob/living/carbon/monkey/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/italics=0, var/message_range = world.view, var/list/used_radios = list()) + if(stat) + return + + if(copytext(message,1,2) == "*") + return emote(copytext(message,2)) + + if(stat) + return + + if(speak_emote.len) + verb = pick(speak_emote) + + message = capitalize(trim_left(message)) + + ..(message, speaking, verb, alt_name, italics, message_range, used_radios) diff --git a/code/modules/mob/living/carbon/monkey/powers.dm b/code/modules/mob/living/carbon/monkey/powers.dm index 042749e0a18e..d074fa78eba8 100644 --- a/code/modules/mob/living/carbon/monkey/powers.dm +++ b/code/modules/mob/living/carbon/monkey/powers.dm @@ -1,6 +1,6 @@ -/*/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 = "Monkey" - handle_ventcrawl()*/ -//Old system +/*/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 = "Monkey" + handle_ventcrawl()*/ +//Old system diff --git a/code/modules/mob/living/carbon/monkey/update_icons.dm b/code/modules/mob/living/carbon/monkey/update_icons.dm index 5da9e0f461af..f4c01248da7b 100644 --- a/code/modules/mob/living/carbon/monkey/update_icons.dm +++ b/code/modules/mob/living/carbon/monkey/update_icons.dm @@ -1,136 +1,136 @@ -//Monkey Overlays Indexes//////// -#define M_MASK_LAYER 1 -#define M_BACK_LAYER 2 -#define M_HANDCUFF_LAYER 3 -#define M_L_HAND_LAYER 4 -#define M_R_HAND_LAYER 5 -#define TARGETED_LAYER 6 -#define M_FIRE_LAYER 7 -#define M_TOTAL_LAYERS 7 -///////////////////////////////// - -/mob/living/carbon/monkey - var/list/overlays_standing[M_TOTAL_LAYERS] - -/mob/living/carbon/monkey/regenerate_icons() - ..() - update_inv_wear_mask(0) - update_inv_back(0) - update_inv_r_hand(0) - update_inv_l_hand(0) - update_inv_handcuffed(0) - update_icons() - update_transform() - //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.Cut() - for(var/image/I in overlays_standing) - overlays += I - - - -//////// -/mob/living/carbon/monkey/update_inv_wear_mask(var/update_icons=1) - if( wear_mask && istype(wear_mask, /obj/item/clothing/mask) ) - if(wear_mask:icon_custom) - overlays_standing[M_MASK_LAYER] = image("icon" = wear_mask:icon_custom, "icon_state" = "[wear_mask.icon_state]_mob") - else - 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 - if(!t_state) t_state = r_hand.icon_state - if(r_hand:icon_custom) - overlays_standing[M_R_HAND_LAYER] = image("icon" = r_hand:icon_custom, "icon_state" = "[t_state]_r") - else - overlays_standing[M_R_HAND_LAYER] = image("icon" = r_hand.righthand_file, "icon_state" = t_state) - r_hand.screen_loc = ui_rhand - if (handcuffed) drop_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 - if(!t_state) t_state = l_hand.icon_state - if(l_hand:icon_custom) - overlays_standing[M_L_HAND_LAYER] = image("icon" = l_hand:icon_custom, "icon_state" = "[t_state]_l") - else - overlays_standing[M_L_HAND_LAYER] = image("icon" = l_hand.lefthand_file, "icon_state" = t_state) - l_hand.screen_loc = ui_lhand - if (handcuffed) drop_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) - if(back:icon_custom) - overlays_standing[M_BACK_LAYER] = image("icon" = back:icon_custom, "icon_state" = "[back.icon_state]_mob") - else - 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_r_hand() - drop_l_hand() - 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 - -//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) - qdel(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") - overlays += overlays_standing[M_FIRE_LAYER] - return - else - overlays_standing[M_FIRE_LAYER] = null - -//Monkey Overlays Indexes//////// -#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_FIRE_LAYER -#undef M_TOTAL_LAYERS - +//Monkey Overlays Indexes//////// +#define M_MASK_LAYER 1 +#define M_BACK_LAYER 2 +#define M_HANDCUFF_LAYER 3 +#define M_L_HAND_LAYER 4 +#define M_R_HAND_LAYER 5 +#define TARGETED_LAYER 6 +#define M_FIRE_LAYER 7 +#define M_TOTAL_LAYERS 7 +///////////////////////////////// + +/mob/living/carbon/monkey + var/list/overlays_standing[M_TOTAL_LAYERS] + +/mob/living/carbon/monkey/regenerate_icons() + ..() + update_inv_wear_mask(0) + update_inv_back(0) + update_inv_r_hand(0) + update_inv_l_hand(0) + update_inv_handcuffed(0) + update_icons() + update_transform() + //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.Cut() + for(var/image/I in overlays_standing) + overlays += I + + + +//////// +/mob/living/carbon/monkey/update_inv_wear_mask(var/update_icons=1) + if( wear_mask && istype(wear_mask, /obj/item/clothing/mask) ) + if(wear_mask:icon_custom) + overlays_standing[M_MASK_LAYER] = image("icon" = wear_mask:icon_custom, "icon_state" = "[wear_mask.icon_state]_mob") + else + 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 + if(!t_state) t_state = r_hand.icon_state + if(r_hand:icon_custom) + overlays_standing[M_R_HAND_LAYER] = image("icon" = r_hand:icon_custom, "icon_state" = "[t_state]_r") + else + overlays_standing[M_R_HAND_LAYER] = image("icon" = r_hand.righthand_file, "icon_state" = t_state) + r_hand.screen_loc = ui_rhand + if (handcuffed) drop_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 + if(!t_state) t_state = l_hand.icon_state + if(l_hand:icon_custom) + overlays_standing[M_L_HAND_LAYER] = image("icon" = l_hand:icon_custom, "icon_state" = "[t_state]_l") + else + overlays_standing[M_L_HAND_LAYER] = image("icon" = l_hand.lefthand_file, "icon_state" = t_state) + l_hand.screen_loc = ui_lhand + if (handcuffed) drop_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) + if(back:icon_custom) + overlays_standing[M_BACK_LAYER] = image("icon" = back:icon_custom, "icon_state" = "[back.icon_state]_mob") + else + 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_r_hand() + drop_l_hand() + 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 + +//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) + qdel(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") + overlays += overlays_standing[M_FIRE_LAYER] + return + else + overlays_standing[M_FIRE_LAYER] = null + +//Monkey Overlays Indexes//////// +#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_FIRE_LAYER +#undef M_TOTAL_LAYERS + diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index f375aa582ab5..9c974268bc66 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -1,83 +1,83 @@ - -/* - 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(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, damage_flags = 0, used_weapon = null) - if(!damage || (blocked >= 100)) - return FALSE - - switch(damagetype) - if(BRUTE) - adjustBruteLoss(damage * blocked_mult(blocked)) - if(BURN) - adjustFireLoss(damage * blocked_mult(blocked)) - if(TOX) - adjustToxLoss(damage * blocked_mult(blocked)) - if(OXY) - adjustOxyLoss(damage * blocked_mult(blocked)) - if(CLONE) - adjustCloneLoss(damage * blocked_mult(blocked)) - if(HALLOSS) - adjustHalLoss(damage * blocked_mult(blocked)) - - flash_weak_pain() - updatehealth() - return TRUE - - -/mob/living/proc/apply_damages(brute = 0, burn = 0, tox = 0, oxy = 0, clone = 0, halloss = 0, def_zone = null, blocked = 0) - if(blocked >= 100) 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(effect = 0,effecttype = STUN, blocked = 0) - if(status_flags & GODMODE) - return 0 - blocked = (100-blocked)/100 - if(!effect || (blocked <= 0)) return 0 - switch(effecttype) - if(STUN) - Stun(effect * blocked) - if(WEAKEN) - Weaken(effect * blocked) - if(PARALYZE) - Paralyse(effect * blocked) - if(AGONY) - halloss += effect // Useful for objects that cause "subdual" damage. PAIN! - if(IRRADIATE) - radiation += max(effect * ((100-run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm."))/100),0)//Rads auto check armor - if(STUTTER) - if(status_flags & CANSTUN) // stun is usually associated with stutter - stuttering = max(stuttering,(effect * blocked)) - if(EYE_BLUR) - eye_blurry = max(eye_blurry,(effect * blocked)) - if(DROWSY) - drowsyness = max(drowsyness,(effect * blocked)) - updatehealth() - return 1 - - -/mob/living/proc/apply_effects(stun = 0, weaken = 0, paralyze = 0, irradiate = 0, stutter = 0, eyeblur = 0, drowsy = 0, agony = 0, blocked = 0) - if(blocked >= 100) 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 + +/* + 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(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, damage_flags = 0, used_weapon = null) + if(!damage || (blocked >= 100)) + return FALSE + + switch(damagetype) + if(BRUTE) + adjustBruteLoss(damage * blocked_mult(blocked)) + if(BURN) + adjustFireLoss(damage * blocked_mult(blocked)) + if(TOX) + adjustToxLoss(damage * blocked_mult(blocked)) + if(OXY) + adjustOxyLoss(damage * blocked_mult(blocked)) + if(CLONE) + adjustCloneLoss(damage * blocked_mult(blocked)) + if(HALLOSS) + adjustHalLoss(damage * blocked_mult(blocked)) + + flash_weak_pain() + updatehealth() + return TRUE + + +/mob/living/proc/apply_damages(brute = 0, burn = 0, tox = 0, oxy = 0, clone = 0, halloss = 0, def_zone = null, blocked = 0) + if(blocked >= 100) 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(effect = 0,effecttype = STUN, blocked = 0) + if(status_flags & GODMODE) + return 0 + blocked = (100-blocked)/100 + if(!effect || (blocked <= 0)) return 0 + switch(effecttype) + if(STUN) + Stun(effect * blocked) + if(WEAKEN) + Weaken(effect * blocked) + if(PARALYZE) + Paralyse(effect * blocked) + if(AGONY) + halloss += effect // Useful for objects that cause "subdual" damage. PAIN! + if(IRRADIATE) + radiation += max(effect * ((100-run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm."))/100),0)//Rads auto check armor + if(STUTTER) + if(status_flags & CANSTUN) // stun is usually associated with stutter + stuttering = max(stuttering,(effect * blocked)) + if(EYE_BLUR) + eye_blurry = max(eye_blurry,(effect * blocked)) + if(DROWSY) + drowsyness = max(drowsyness,(effect * blocked)) + updatehealth() + return 1 + + +/mob/living/proc/apply_effects(stun = 0, weaken = 0, paralyze = 0, irradiate = 0, stutter = 0, eyeblur = 0, drowsy = 0, agony = 0, blocked = 0) + if(blocked >= 100) 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 diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 7717900285a6..2cf4f80dcef3 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -1,299 +1,299 @@ -/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = null, soften_text = null) - var/armor = getarmor(def_zone, attack_flag) - if(armor >= 100) - if(absorb_text) - to_chat(src, "[absorb_text]") - else - to_chat(src, "Your armor absorbs the blow!") - else if(armor > 0) - if(soften_text) - to_chat(src, "[soften_text]") - else - to_chat(src, "Your armor softens the blow!") - return armor - -//if null is passed for def_zone, then this should return something appropriate for all zones (e.g. area effect damage) -/mob/living/proc/getarmor(def_zone, type) - return 0 - - -/mob/living/bullet_act(obj/item/projectile/P, def_zone) - flash_weak_pain() - - //Being hit while using a deadman switch - 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)) - attack_log += "\[[time_stamp()]\]triggers their deadman's switch!" - message_admins("\blue [key_name_admin(src)] triggers their deadman's switch! ([ADMIN_JMP(src)])") - log_game("\blue [key_name(src)] triggers their deadman's switch!") - src.visible_message("\red [src] triggers their deadman's switch!") - signaler.signal() - - //Armor - var/damage = P.damage - var/flags = P.damage_flags() - var/absorb = run_armor_check(def_zone, P.flag) - if (prob(absorb)) - if(flags & DAM_LASER) - //the armour causes the heat energy to spread out, which reduces the damage (and the blood loss) - //this is mostly so that armour doesn't cause people to lose MORE fluid from lasers than they would otherwise - damage *= FLUIDLOSS_CONC_BURN / FLUIDLOSS_WIDE_BURN - flags &= ~(DAM_SHARP | DAM_EDGE | DAM_LASER) - - if(!P.nodamage) - apply_damage(damage, P.damage_type, def_zone, absorb, flags, P) - P.on_hit(src, absorb, def_zone) - - return absorb - -//this proc handles being hit by a thrown atom -/mob/living/hitby(atom/movable/AM)//Standardization and logging -Sieve - if(istype(AM,/obj/)) - var/obj/O = AM - var/dtype = BRUTE - if(istype(O,/obj/item/weapon)) - var/obj/item/weapon/W = O - dtype = W.damtype - var/throw_damage = O.throwforce * (AM.fly_speed / 5) - - var/zone - var/mob/living/L = isliving(O.thrower) ? O.thrower : null - if(L) - zone = check_zone(L.zone_sel.selecting) - else - zone = ran_zone(BP_CHEST, 75) // Hits a random part of the body, geared towards the chest - - //check if we hit - if(O.throw_source) - var/distance = get_dist(O.throw_source, loc) - zone = get_zone_with_miss_chance(zone, src, min(15 * (distance - 2), 0)) - else - zone = get_zone_with_miss_chance(zone, src, 15) - - if(!zone) - visible_message("\The [O] misses [src] narrowly!") - return - - if(O.thrower != src && check_shields(throw_damage, "[O]", get_dir(O,src))) - return - - resolve_thrown_attack(O, throw_damage, dtype, zone) - - if(L) - var/client/assailant = L.client - if(assailant) - src.attack_log += text("\[[time_stamp()]\] Has been hit with a [O], thrown by [L.name] ([assailant.ckey])") - L.attack_log += text("\[[time_stamp()]\] Hit [src.name] ([src.ckey]) with a thrown [O]") - if(!ismouse(src)) - msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [L.name] ([assailant.ckey]) [ADMIN_JMP(src)]") - - // Begin BS12 momentum-transfer code. - if(O.throw_source && AM.fly_speed >= 15) - var/obj/item/weapon/W = O - - visible_message("[src] staggers under the impact!", - "You stagger under the impact!") - - var/atom/throw_target = get_edge_target_turf(src, get_dir(O.throw_source, src)) - throw_at(throw_target, 5, 1, O.thrower, FALSE, null, null, CALLBACK(src, .proc/pin_to_turf, W)) - - -/mob/living/proc/resolve_thrown_attack(obj/O, throw_damage, dtype, zone, armor) - - if(isnull(armor)) // Armor arg passed by human - armor = run_armor_check(null, "melee") - visible_message("[src] has been hit by [O].") - - var/damage_flags = O.damage_flags() - - if(prob(armor)) - damage_flags &= ~(DAM_SHARP | DAM_EDGE) - - var/created_wound = apply_damage(throw_damage, dtype, null, armor, damage_flags, O) - - //thrown weapon embedded object code. - if(dtype == BRUTE && istype(O, /obj/item)) - var/obj/item/I = O - if(!I.can_embed || I.is_robot_module()) - return - - var/sharp = is_sharp(I) - - var/damage = throw_damage //the effective damage used for embedding purposes, no actual damage is dealt here - if (armor) - damage *= blocked_mult(armor) - - //blunt objects should really not be embedding in things unless a huge amount of force is involved - var/embed_chance = sharp ? (damage / (I.w_class / 2)) : (damage / (I.w_class * 3)) - var/embed_threshold = sharp ? 5 * I.w_class : 15 * I.w_class - - //Sharp objects will always embed if they do enough damage. - //Thrown sharp objects have some momentum already and have a small chance to embed even if the damage is below the threshold - if(sharp && prob(damage / (10 * I.w_class) * 100) || (damage > embed_threshold && prob(embed_chance))) - embed(I, zone, created_wound) - -/mob/living/proc/embed(obj/item/I) - I.loc = src - embedded += I - verbs += /mob/proc/yank_out_object - -/mob/living/proc/pin_to_turf(obj/item/I) - if(!I) - return - - if(I.sharp && I.loc == src) // Projectile is suitable for pinning. - - var/turf/T = near_wall(I.dir, 2, TRUE) - if(!T) - return - - if(loc != T) - return - - visible_message("[src] is pinned to the [T] by [I]!", - "You are pinned to the wall by [I]!") - anchored = TRUE - pinned += I - update_canmove() // instant update, no need to wait Life() tick - -//This is called when the mob is thrown into a dense turf -/mob/living/proc/turf_collision(turf/T) - visible_message("[src] crashed into \the [T]!","You are crashed into \the [T]!") - take_bodypart_damage(fly_speed * 5) - -/mob/living/proc/near_wall(direction, distance = 1, check_dense_objs = FALSE) - var/turf/T = get_step(get_turf(src), direction) - var/turf/last_turf = loc - var/i = 1 - - while(i > 0 && i <= distance) - if(T.density) //Turf is a wall! - return last_turf - if(check_dense_objs) - for(var/obj/O in T.contents) - if(O.density) - return last_turf - i++ - last_turf = T - T = get_step(T, direction) - - return FALSE - -// End BS12 momentum-transfer code. - -/mob/living/proc/check_shields(damage = 0, attack_text = "the attack", hit_dir = 0) - return FALSE - -//Mobs on Fire -/mob/living/proc/IgniteMob() - if(fire_stacks > 0 && !on_fire) - on_fire = 1 - set_light(light_range + 3) - update_fire() - -/mob/living/proc/ExtinguishMob() - if(on_fire) - on_fire = 0 - fire_stacks = 0 - set_light(max(0, light_range - 3)) - update_fire() - -/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(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/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment - if(G.get_by_flag(XGM_GAS_OXIDIZER) < 1) - ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire - return - for(var/obj/item/I in contents) - if(I.wet) - ExtinguishMob() - break - if(fire_stacks == 0) - ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire - return - var/turf/location = get_turf(src) - location.hotspot_expose(fire_burn_temperature(), 50) - -/mob/living/fire_act() - adjust_fire_stacks(0.5) - IgniteMob() - -//Finds the effective temperature that the mob is burning at. -/mob/living/proc/fire_burn_temperature() - if (fire_stacks <= 0) - return 0 - - //Scale quadratically so that single digit numbers of fire stacks don't burn ridiculously hot. - //lower limit of 700 K, same as matches and roughly the temperature of a cool flame. - return max(2.25 * round(FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE * (fire_stacks / FIRE_MAX_FIRESUIT_STACKS) ** 2), 700) - -//Mobs on Fire end - -/mob/living/regular_hud_updates() - ..() - update_action_buttons() - -/mob/living/update_action_buttons() - if(!hud_used) return - if(!client) return - - if(hud_used.hud_shown != 1) //Hud toggled to minimal - return - - client.screen -= hud_used.hide_actions_toggle - for(var/datum/action/A in actions) - if(A.button) - client.screen -= A.button - - if(hud_used.action_buttons_hidden) - if(!hud_used.hide_actions_toggle) - hud_used.hide_actions_toggle = new(hud_used) - hud_used.hide_actions_toggle.UpdateIcon() - - if(!hud_used.hide_actions_toggle.moved) - hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(1) - //hud_used.SetButtonCoords(hud_used.hide_actions_toggle,1) - - client.screen += hud_used.hide_actions_toggle - return - - var/button_number = 0 - for(var/datum/action/A in actions) - button_number++ - if(A.button == null) - var/obj/screen/movable/action_button/N = new(hud_used) - N.owner = A - A.button = N - - var/obj/screen/movable/action_button/B = A.button - - B.UpdateIcon() - - B.name = A.UpdateName() - - client.screen += B - - if(!B.moved) - B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number) - //hud_used.SetButtonCoords(B,button_number) - - if(button_number > 0) - if(!hud_used.hide_actions_toggle) - hud_used.hide_actions_toggle = new(hud_used) - hud_used.hide_actions_toggle.InitialiseIcon(src) - if(!hud_used.hide_actions_toggle.moved) - hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1) - //hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1) - client.screen += hud_used.hide_actions_toggle - -/mob/living/incapacitated(restrained_type = ARMS) - if(stat || paralysis || stunned || weakened || restrained(restrained_type)) - return 1 +/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = null, soften_text = null) + var/armor = getarmor(def_zone, attack_flag) + if(armor >= 100) + if(absorb_text) + to_chat(src, "[absorb_text]") + else + to_chat(src, "Your armor absorbs the blow!") + else if(armor > 0) + if(soften_text) + to_chat(src, "[soften_text]") + else + to_chat(src, "Your armor softens the blow!") + return armor + +//if null is passed for def_zone, then this should return something appropriate for all zones (e.g. area effect damage) +/mob/living/proc/getarmor(def_zone, type) + return 0 + + +/mob/living/bullet_act(obj/item/projectile/P, def_zone) + flash_weak_pain() + + //Being hit while using a deadman switch + 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)) + attack_log += "\[[time_stamp()]\]triggers their deadman's switch!" + message_admins("\blue [key_name_admin(src)] triggers their deadman's switch! ([ADMIN_JMP(src)])") + log_game("\blue [key_name(src)] triggers their deadman's switch!") + src.visible_message("\red [src] triggers their deadman's switch!") + signaler.signal() + + //Armor + var/damage = P.damage + var/flags = P.damage_flags() + var/absorb = run_armor_check(def_zone, P.flag) + if (prob(absorb)) + if(flags & DAM_LASER) + //the armour causes the heat energy to spread out, which reduces the damage (and the blood loss) + //this is mostly so that armour doesn't cause people to lose MORE fluid from lasers than they would otherwise + damage *= FLUIDLOSS_CONC_BURN / FLUIDLOSS_WIDE_BURN + flags &= ~(DAM_SHARP | DAM_EDGE | DAM_LASER) + + if(!P.nodamage) + apply_damage(damage, P.damage_type, def_zone, absorb, flags, P) + P.on_hit(src, absorb, def_zone) + + return absorb + +//this proc handles being hit by a thrown atom +/mob/living/hitby(atom/movable/AM)//Standardization and logging -Sieve + if(istype(AM,/obj/)) + var/obj/O = AM + var/dtype = BRUTE + if(istype(O,/obj/item/weapon)) + var/obj/item/weapon/W = O + dtype = W.damtype + var/throw_damage = O.throwforce * (AM.fly_speed / 5) + + var/zone + var/mob/living/L = isliving(O.thrower) ? O.thrower : null + if(L) + zone = check_zone(L.zone_sel.selecting) + else + zone = ran_zone(BP_CHEST, 75) // Hits a random part of the body, geared towards the chest + + //check if we hit + if(O.throw_source) + var/distance = get_dist(O.throw_source, loc) + zone = get_zone_with_miss_chance(zone, src, min(15 * (distance - 2), 0)) + else + zone = get_zone_with_miss_chance(zone, src, 15) + + if(!zone) + visible_message("\The [O] misses [src] narrowly!") + return + + if(O.thrower != src && check_shields(throw_damage, "[O]", get_dir(O,src))) + return + + resolve_thrown_attack(O, throw_damage, dtype, zone) + + if(L) + var/client/assailant = L.client + if(assailant) + src.attack_log += text("\[[time_stamp()]\] Has been hit with a [O], thrown by [L.name] ([assailant.ckey])") + L.attack_log += text("\[[time_stamp()]\] Hit [src.name] ([src.ckey]) with a thrown [O]") + if(!ismouse(src)) + msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [L.name] ([assailant.ckey]) [ADMIN_JMP(src)]") + + // Begin BS12 momentum-transfer code. + if(O.throw_source && AM.fly_speed >= 15) + var/obj/item/weapon/W = O + + visible_message("[src] staggers under the impact!", + "You stagger under the impact!") + + var/atom/throw_target = get_edge_target_turf(src, get_dir(O.throw_source, src)) + throw_at(throw_target, 5, 1, O.thrower, FALSE, null, null, CALLBACK(src, .proc/pin_to_turf, W)) + + +/mob/living/proc/resolve_thrown_attack(obj/O, throw_damage, dtype, zone, armor) + + if(isnull(armor)) // Armor arg passed by human + armor = run_armor_check(null, "melee") + visible_message("[src] has been hit by [O].") + + var/damage_flags = O.damage_flags() + + if(prob(armor)) + damage_flags &= ~(DAM_SHARP | DAM_EDGE) + + var/created_wound = apply_damage(throw_damage, dtype, null, armor, damage_flags, O) + + //thrown weapon embedded object code. + if(dtype == BRUTE && istype(O, /obj/item)) + var/obj/item/I = O + if(!I.can_embed || I.is_robot_module()) + return + + var/sharp = is_sharp(I) + + var/damage = throw_damage //the effective damage used for embedding purposes, no actual damage is dealt here + if (armor) + damage *= blocked_mult(armor) + + //blunt objects should really not be embedding in things unless a huge amount of force is involved + var/embed_chance = sharp ? (damage / (I.w_class / 2)) : (damage / (I.w_class * 3)) + var/embed_threshold = sharp ? 5 * I.w_class : 15 * I.w_class + + //Sharp objects will always embed if they do enough damage. + //Thrown sharp objects have some momentum already and have a small chance to embed even if the damage is below the threshold + if(sharp && prob(damage / (10 * I.w_class) * 100) || (damage > embed_threshold && prob(embed_chance))) + embed(I, zone, created_wound) + +/mob/living/proc/embed(obj/item/I) + I.loc = src + embedded += I + verbs += /mob/proc/yank_out_object + +/mob/living/proc/pin_to_turf(obj/item/I) + if(!I) + return + + if(I.sharp && I.loc == src) // Projectile is suitable for pinning. + + var/turf/T = near_wall(I.dir, 2, TRUE) + if(!T) + return + + if(loc != T) + return + + visible_message("[src] is pinned to the [T] by [I]!", + "You are pinned to the wall by [I]!") + anchored = TRUE + pinned += I + update_canmove() // instant update, no need to wait Life() tick + +//This is called when the mob is thrown into a dense turf +/mob/living/proc/turf_collision(turf/T) + visible_message("[src] crashed into \the [T]!","You are crashed into \the [T]!") + take_bodypart_damage(fly_speed * 5) + +/mob/living/proc/near_wall(direction, distance = 1, check_dense_objs = FALSE) + var/turf/T = get_step(get_turf(src), direction) + var/turf/last_turf = loc + var/i = 1 + + while(i > 0 && i <= distance) + if(T.density) //Turf is a wall! + return last_turf + if(check_dense_objs) + for(var/obj/O in T.contents) + if(O.density) + return last_turf + i++ + last_turf = T + T = get_step(T, direction) + + return FALSE + +// End BS12 momentum-transfer code. + +/mob/living/proc/check_shields(damage = 0, attack_text = "the attack", hit_dir = 0) + return FALSE + +//Mobs on Fire +/mob/living/proc/IgniteMob() + if(fire_stacks > 0 && !on_fire) + on_fire = 1 + set_light(light_range + 3) + update_fire() + +/mob/living/proc/ExtinguishMob() + if(on_fire) + on_fire = 0 + fire_stacks = 0 + set_light(max(0, light_range - 3)) + update_fire() + +/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(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/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment + if(G.get_by_flag(XGM_GAS_OXIDIZER) < 1) + ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire + return + for(var/obj/item/I in contents) + if(I.wet) + ExtinguishMob() + break + if(fire_stacks == 0) + ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire + return + var/turf/location = get_turf(src) + location.hotspot_expose(fire_burn_temperature(), 50) + +/mob/living/fire_act() + adjust_fire_stacks(0.5) + IgniteMob() + +//Finds the effective temperature that the mob is burning at. +/mob/living/proc/fire_burn_temperature() + if (fire_stacks <= 0) + return 0 + + //Scale quadratically so that single digit numbers of fire stacks don't burn ridiculously hot. + //lower limit of 700 K, same as matches and roughly the temperature of a cool flame. + return max(2.25 * round(FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE * (fire_stacks / FIRE_MAX_FIRESUIT_STACKS) ** 2), 700) + +//Mobs on Fire end + +/mob/living/regular_hud_updates() + ..() + update_action_buttons() + +/mob/living/update_action_buttons() + if(!hud_used) return + if(!client) return + + if(hud_used.hud_shown != 1) //Hud toggled to minimal + return + + client.screen -= hud_used.hide_actions_toggle + for(var/datum/action/A in actions) + if(A.button) + client.screen -= A.button + + if(hud_used.action_buttons_hidden) + if(!hud_used.hide_actions_toggle) + hud_used.hide_actions_toggle = new(hud_used) + hud_used.hide_actions_toggle.UpdateIcon() + + if(!hud_used.hide_actions_toggle.moved) + hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(1) + //hud_used.SetButtonCoords(hud_used.hide_actions_toggle,1) + + client.screen += hud_used.hide_actions_toggle + return + + var/button_number = 0 + for(var/datum/action/A in actions) + button_number++ + if(A.button == null) + var/obj/screen/movable/action_button/N = new(hud_used) + N.owner = A + A.button = N + + var/obj/screen/movable/action_button/B = A.button + + B.UpdateIcon() + + B.name = A.UpdateName() + + client.screen += B + + if(!B.moved) + B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number) + //hud_used.SetButtonCoords(B,button_number) + + if(button_number > 0) + if(!hud_used.hide_actions_toggle) + hud_used.hide_actions_toggle = new(hud_used) + hud_used.hide_actions_toggle.InitialiseIcon(src) + if(!hud_used.hide_actions_toggle.moved) + hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1) + //hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1) + client.screen += hud_used.hide_actions_toggle + +/mob/living/incapacitated(restrained_type = ARMS) + if(stat || paralysis || stunned || weakened || restrained(restrained_type)) + return 1 diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 1d8900bbf235..4472e35db5ac 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -1,54 +1,54 @@ -/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 - - //Damage related vars, NOTE: THESE SHOULD ONLY BE MODIFIED BY PROCS - var/bruteloss = 0.0 //Brutal damage caused by brute force (punching, being clubbed by a toolbox ect... this also accounts for pressure damage) - var/oxyloss = 0.0 //Oxygen depravation damage (no air in lungs) - var/toxloss = 0.0 //Toxic damage caused by being poisoned or radiated - var/fireloss = 0.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/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out. - - //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. - var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas. - - var/t_phoron = null - var/t_oxygen = null - var/t_sl_gas = null - var/t_n2 = null - - var/now_pushing = null - - var/mob/living/cameraFollow = null - var/list/datum/action/actions = list() - - var/tod = null // Time of death - var/update_slimes = 1 - var/silent = null //Can't talk. Value goes down every life proc. - var/pull_debuff = 0 //Movement debuff when pulling - - var/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/tesla_ignore = FALSE - var/list/butcher_results = null - - var/isHandsBusy = FALSE - - var/list/recent_tastes = list() - var/lasttaste = 0 // Prevent tastes spam - - var/list/roundstart_quirks = list() +/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 + + //Damage related vars, NOTE: THESE SHOULD ONLY BE MODIFIED BY PROCS + var/bruteloss = 0.0 //Brutal damage caused by brute force (punching, being clubbed by a toolbox ect... this also accounts for pressure damage) + var/oxyloss = 0.0 //Oxygen depravation damage (no air in lungs) + var/toxloss = 0.0 //Toxic damage caused by being poisoned or radiated + var/fireloss = 0.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/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out. + + //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. + var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas. + + var/t_phoron = null + var/t_oxygen = null + var/t_sl_gas = null + var/t_n2 = null + + var/now_pushing = null + + var/mob/living/cameraFollow = null + var/list/datum/action/actions = list() + + var/tod = null // Time of death + var/update_slimes = 1 + var/silent = null //Can't talk. Value goes down every life proc. + var/pull_debuff = 0 //Movement debuff when pulling + + var/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/tesla_ignore = FALSE + var/list/butcher_results = null + + var/isHandsBusy = FALSE + + var/list/recent_tastes = list() + var/lasttaste = 0 // Prevent tastes spam + + var/list/roundstart_quirks = list() diff --git a/code/modules/mob/living/logout.dm b/code/modules/mob/living/logout.dm index 8fdcdb0ec46c..0d1aae3dba7e 100644 --- a/code/modules/mob/living/logout.dm +++ b/code/modules/mob/living/logout.dm @@ -1,7 +1,7 @@ -/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. - 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. + 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. diff --git a/code/modules/mob/living/parasite/meme.dm b/code/modules/mob/living/parasite/meme.dm index 0a553bef9a03..9a159cc380d1 100644 --- a/code/modules/mob/living/parasite/meme.dm +++ b/code/modules/mob/living/parasite/meme.dm @@ -1,651 +1,651 @@ -//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:05 - -// === MEMETIC ANOMALY === -// ======================= - -/** -This life form is a form of parasite that can gain a certain level of control -over its host. Its player will share vision and hearing with the host, and it'll -be able to influence the host through various commands. -**/ - -// The maximum amount of points a meme can gather. -var/global/const/MAXIMUM_MEME_POINTS = 750 - - -// === PARASITE === -// ================ - -// a list of all the parasites in the mob -mob/living/carbon/var/list/parasites = list() - -mob/living/parasite - var/mob/living/carbon/host // the host that this parasite occupies - -/mob/living/parasite/Login() - ..() - if(host) - client.eye = host - else - client.eye = loc - client.perspective = EYE_PERSPECTIVE - sleeping = 0 - -/mob/living/parasite/proc/enter_host(mob/living/carbon/host) - src.host = host - loc = host - host.parasites.Add(src) - if(client) - client.eye = host - return TRUE - -/mob/living/parasite/proc/exit_host() - host.parasites.Remove(src) - host = null - loc = null - return TRUE - - -// === MEME === -// ============ - -/mob/living/parasite/meme - var/meme_points = 100 - var/dormant = 0 - var/meme_death = "stoxin" - var/list/indoctrinated = list() - -/mob/living/parasite/meme/atom_init() - . = ..() - name = "[pick("Meme")] [rand(1000,9999)]" - -/mob/living/parasite/meme/enter_host(mob/living/carbon/human/host) - if(locate(/mob/living/parasite/meme) in host.parasites) - return FALSE - return ..() - -mob/living/parasite/meme/Life() - ..() - - - if(client) - if(blinded) - client.eye = null - else - client.eye = host - - if(!host) - return - - // recover meme points slowly - var/gain = 3 - if(dormant) gain = 9 // dormant recovers points faster - - meme_points = min(meme_points + gain, MAXIMUM_MEME_POINTS) - // if there are sleep toxins in the host's body, that's bad - - if (meme_death == "bdam") - if(host.brainloss > 60) - to_chat(src, "\red Something in your host's brain makes you lose consciousness.. you fade away..") - src.death() - return - else if (meme_death == "burns") - if(host.on_fire) - to_chat(src, "\red Something on your host's skin makes you unstable.. you fade away..") - src.death() - return - else if(host.reagents.has_reagent(meme_death)) - to_chat(src, "\red Something in your host's blood makes you lose consciousness.. you fade away..") - src.death() - return - - // a host without brain is no good - else if(!host.mind) - to_chat(src, "\red Your host has no mind.. you fade away..") - src.death() - return - else if(host.stat == DEAD) - to_chat(src, "\red Your host has died.. you fade away..") - src.death() - return - - else if(host.blinded && host.stat != UNCONSCIOUS) - src.blinded = 1 - else - src.blinded = 0 - - -mob/living/parasite/meme/death() - // make sure the mob is on the actual map before gibbing - if(host) src.loc = host.loc - src.stat = DEAD - ..() - qdel(src) - -// When a meme speaks, it speaks through its host -mob/living/parasite/meme/say(message as text) - if(dormant) - to_chat(usr, "\red You're dormant!") - return - if(!host) - to_chat(usr, "\red You can't speak without host!") - return - - return host.say(message) - -// Same as speak, just with whisper -mob/living/parasite/meme/whisper(message as text) - if(dormant) - to_chat(usr, "\red You're dormant!") - return - if(!host) - to_chat(usr, "\red You can't speak without host!") - return - - return host.whisper(message) - -// Make the host do things -mob/living/parasite/meme/me_verb(message as text) - set name = "Me" - - - if(dormant) - to_chat(usr, "\red You're dormant!") - return - - if(!host) - to_chat(usr, "\red You can't emote without host!") - return - - return host.custom_emote(1, message) - -// A meme understands everything their host understands -mob/living/parasite/meme/say_understands(mob/other) - if(!host) - return 0 - - return host.say_understands(other) - -// Try to use amount points, return 1 if successful -mob/living/parasite/meme/proc/use_points(amount) - if(dormant) - to_chat(usr, "\red You're dormant!") - return - if(src.meme_points < amount) - to_chat(src, "* You don't have enough meme points(need [amount]).") - return 0 - - src.meme_points -= round(amount) - return 1 - -// Let the meme choose one of his indoctrinated mobs as target -mob/living/parasite/meme/proc/select_indoctrinated(title, message) - var/list/candidates - - // Can only affect other mobs thant he host if not blinded - if(blinded) - candidates = list() - to_chat(src, "\red You are blinded, so you can not affect mobs other than your host.") - else - candidates = indoctrinated.Copy() - - candidates.Add(src.host) - - var/mob/target = null - if(candidates.len == 1) - target = candidates[1] - else - var/selected - - var/list/text_candidates = list() - var/list/map_text_to_mob = list() - - for(var/mob/living/carbon/human/M in candidates) - text_candidates += M.real_name - map_text_to_mob[M.real_name] = M - - selected = input(message,title) as null|anything in text_candidates - if(!selected) - return null - - target = map_text_to_mob[selected] - - return target - - -// A meme can make people hear things with the thought ability -mob/living/parasite/meme/verb/Thought() - set category = "Meme" - set name = "Thought(50)" - set desc = "Implants a thought into the target, making them think they heard someone talk." - - if(meme_points < 50) - // just call use_points() to give the standard failure message - use_points(50) - return - - var/list/candidates = indoctrinated.Copy() - if(!(src.host in candidates)) - candidates.Add(src.host) - - var/mob/target = select_indoctrinated("Thought", "Select a target which will hear your thought.") - - if(!target) - return - - var/speaker = sanitize(input("Select the voice in which you would like to make yourself heard.", "Voice") as null|text, MAX_NAME_LEN) - if(!speaker) - return - - var/message = sanitize(input("What would you like to say?", "Message") as null|text) - if(!message) - return - - // Use the points at the end rather than the beginning, because the user might cancel - if(!use_points(50)) - return - - //message = say_quote(message) - var/rendered = "[speaker] [message]" - //target.show_message(rendered) - to_chat(target, rendered) - to_chat(usr, "You make [target] hear: [rendered]") - for(var/mob/dead/observer/G in observer_list) - G.show_message("[usr] makes [target] hear: [rendered]") - log_say("Memetic Thought: [key_name(usr)] makes [key_name(target)] hear: [speaker] [message]") - -// Mutes the host -mob/living/parasite/meme/verb/Mute() - set category = "Meme" - set name = "Mute(250)" - set desc = "Prevents your host from talking for a while." - - if(!src.host) return - if(!host.speech_allowed) - to_chat(usr, "\red Your host already can't speak..") - return - if(!use_points(250)) - return - - spawn - // backup the host incase we switch hosts after using the verb - var/mob/host = src.host - - to_chat(host, "\red Your tongue feels numb.. You lose your ability to speak.") - to_chat(usr, "\red Your host can't speak anymore.") - - host.speech_allowed = 0 - - sleep(1200) - - host.speech_allowed = 1 - to_chat(host, "\red Your tongue has feeling again..") - to_chat(usr, "\red [host] can speak again.") - -// Makes the host unable to emote -mob/living/parasite/meme/verb/Paralyze() - set category = "Meme" - set name = "Paralyze(250)" - set desc = "Prevents your host from using emote for a while." - - if(!src.host) - return - if(!host.use_me) - to_chat(usr, "\red Your host already can't use body language..") - return - if(!use_points(250)) - return - - spawn - // backup the host incase we switch hosts after using the verb - var/mob/host = src.host - - to_chat(host, "\red Your body feels numb.. You lose your ability to use body language.") - to_chat(usr, "\red Your host can't use body language anymore.") - - host.use_me = 0 - - sleep(1200) - - host.use_me = 1 - to_chat(host, "\red Your body has feeling again..") - to_chat(usr, "\red [host] can use body language again.") - - - -// Cause great agony with the host, used for conditioning the host -mob/living/parasite/meme/verb/Agony() - set category = "Meme" - set name = "Agony(200)" - set desc = "Causes significant pain in your host." - - if(!src.host) - return - if(!use_points(200)) - return - - spawn - // backup the host incase we switch hosts after using the verb - var/mob/host = src.host - - host.paralysis = max(host.paralysis, 2) - - host.flash_weak_pain() - to_chat(host, "\red You feel excrutiating pain all over your body! It is so bad you can't think or articulate yourself properly..") - - to_chat(usr, "You send a jolt of agonizing pain through [host], they should be unable to concentrate on anything else for half a minute.") - - host.emote("scream",,, 1) - - for(var/i=0, i<10, i++) - host.stuttering = 2 - sleep(50) - if(prob(80)) - host.flash_weak_pain() - if(prob(10)) - host.paralysis = max(host.paralysis, 2) - if(prob(15)) - host.emote("twitch") - else if(prob(15)) - host.emote("scream",,, 1) - else if(prob(10)) - host.emote("collapse") - - if(i == 10) - to_chat(host, "\red THE PAIN! AGHH, THE PAIN! MAKE IT STOP! ANYTHING TO MAKE IT STOP!") - - to_chat(host, "\red The pain subsides..") - -// Cause great joy with the host, used for conditioning the host -mob/living/parasite/meme/verb/Joy() - set category = "Meme" - set name = "Joy(200)" - set desc = "Causes significant joy in your host." - - if(!src.host) - return - if(!use_points(200)) - return - - spawn - var/mob/host = src.host - host.druggy = max(host.druggy, 50) - host.slurring = max(host.slurring, 10) - - to_chat(usr, "You stimulate [host.name]'s brain, injecting waves of endorphines and dopamine into the tissue. They should now forget all their worries, particularly relating to you, for around a minute.") - - to_chat(host, "\red You are feeling wonderful! Your head is numb and drowsy, and you can't help forgetting all the worries in the world.") - - while(host.druggy > 0) - sleep(10) - - to_chat(host, "\red You are feeling clear-headed again..") - -// Cause the target to hallucinate. -mob/living/parasite/meme/verb/Hallucinate() - set category = "Meme" - set name = "Hallucinate(300)" - set desc = "Makes your host hallucinate, has a short delay." - - var/mob/living/target = select_indoctrinated("Hallucination", "Who should hallucinate?") - - if(!target) - return - if(!use_points(300)) - return - - target.hallucination += 100 - - to_chat(usr, "You make [target] hallucinate.") - -// Jump to a closeby target through a whisper -mob/living/parasite/meme/verb/SubtleJump(mob/living/carbon/human/target as mob in human_list) - set category = "Meme" - set name = "Subtle Jump(350)" - set desc = "Move to a closeby human through a whisper." - - if(!istype(target, /mob/living/carbon/human) || !target.mind) - to_chat(src, "You can't jump to this creature..") - return - if(!(target in view(1, host)+src)) - to_chat(src, "The target is not close enough.") - return - - // Find out whether we can speak - if (host.silent || (host.disabilities & 64)) - to_chat(src, "Your host can't speak..") - return - - if(!use_points(350)) - return - - for(var/mob/M in view(1, host)) - M.show_message("[host] whispers something incoherent.",2) // 2 stands for hearable message - - // Find out whether the target can hear - if(target.disabilities & 32 || target.ear_deaf) - to_chat(src, "Your target doesn't seem to hear you..") - return - - if(target.parasites.len > 0) - to_chat(src, "Your target already is possessed by something..") - return - - src.exit_host() - src.enter_host(target) - - to_chat(usr, "You successfully jumped to [target].") - log_admin("[src.key] has jumped to [target]") - message_admins("[src.key] has jumped to [target] (JMP)") - -// Jump to a distant target through a shout -mob/living/parasite/meme/verb/ObviousJump(mob/living/carbon/human/target as mob in human_list) - set category = "Meme" - set name = "Obvious Jump(750)" - set desc = "Move to any mob in view through a shout." - - if(!istype(target, /mob/living/carbon/human) || !target.mind) - to_chat(src, "You can't jump to this creature..") - return - if(!(target in view(host))) - to_chat(src, "The target is not close enough.") - return - - // Find out whether we can speak - if (host.silent || (host.disabilities & 64)) - to_chat(src, "Your host can't speak..") - return - - if(!use_points(750)) - return - - for(var/mob/M in view(host)+src) - M.show_message("[host] screams something incoherent!",2) // 2 stands for hearable message - - // Find out whether the target can hear - if(target.disabilities & 32 || target.ear_deaf) - to_chat(src, "Your target doesn't seem to hear you..") - return - - if(target.parasites.len > 0) - to_chat(src, "Your target already is possessed by something..") - return - - src.exit_host() - src.enter_host(target) - - to_chat(usr, "You successfully jumped to [target].") - log_admin("[src.key] has jumped to [target]") - message_admins("[src.key] has jumped to [target] (JMP)") - -// Jump to an attuned mob for free -mob/living/parasite/meme/verb/AttunedJump(mob/living/carbon/human/target as mob in human_list) - set category = "Meme" - set name = "Attuned Jump(0)" - set desc = "Move to a mob in sight that you have already attuned." - - if(!istype(target, /mob/living/carbon/human) || !target.mind) - to_chat(src, "You can't jump to this creature..") - return - if(!(target in view(host))) - to_chat(src, "You need to make eye-contact with the target.") - return - if(!(target in indoctrinated)) - to_chat(src, "You need to attune the target first.") - return - - if(target.parasites.len > 0) - to_chat(src, "Your target already is possessed by something..") - return - - src.exit_host() - src.enter_host(target) - - to_chat(usr, "You successfully jumped to [target].") - - log_admin("[src.key] has jumped to [target]") - message_admins("[src.key] has jumped to [target] (JMP)") - -// ATTUNE a mob, adding it to the indoctrinated list -mob/living/parasite/meme/verb/Attune() - set category = "Meme" - set name = "Attune(400)" - set desc = "Change the host's brain structure, making it easier for you to manipulate him." - - if(host in src.indoctrinated) - to_chat(usr, "You have already attuned this host.") - return - - if(!host) - return - if(!use_points(400)) - return - - src.indoctrinated.Add(host) - - to_chat(usr, "You successfully indoctrinated [host].") - to_chat(host, "\red Your head feels a bit roomier..") - - log_admin("[src.key] has attuned [host]") - message_admins("[src.key] has attuned [host] (JMP)") - -// Enables the mob to take a lot more damage -mob/living/parasite/meme/verb/Analgesic() - set category = "Meme" - set name = "Analgesic(500)" - set desc = "Combat drug that the host to move normally, even under life-threatening pain." - - if(!host) - return - if(!(host in indoctrinated)) - to_chat(usr, "\red You need to attune the host first.") - return - if(!use_points(500)) - return - - to_chat(usr, "You inject drugs into [host].") - to_chat(host, "\red You feel your body strengthen and your pain subside..") - host.analgesic = 60 - while(host.analgesic > 0) - sleep(10) - to_chat(host, "\red The dizziness wears off, and you can feel pain again..") - - -mob/proc/clearHUD() - if(client) - client.screen.Cut() - -// Take control of the mob -mob/living/parasite/meme/verb/Possession() - set category = "Meme" - set name = "Possession(500)" - set desc = "Take direct control of the host for a while." - - if(!host) - return - if(!(host in indoctrinated)) - to_chat(usr, "\red You need to attune the host first.") - return - if(!use_points(500)) - return - - to_chat(usr, "You take control of [host]!") - to_chat(host, "\red Everything goes black..") - - spawn - var/mob/dummy = new() - dummy.loc = 0 - dummy.sight = BLIND - - var/datum/mind/host_mind = host.mind - var/datum/mind/meme_mind = src.mind - var/mob/living/carbon/human/H = host - - host_mind.transfer_to(dummy) - meme_mind.transfer_to(host) - host_mind.current.clearHUD() - H.update_body() - - to_chat(dummy, "\blue You feel very drowsy.. Your eyelids become heavy...") - - log_admin("[meme_mind.key] has taken possession of [host]([host_mind.key])") - message_admins("[meme_mind.key] has taken possession of [host]([host_mind.key]) (JMP)") - - sleep(600) - - log_admin("[meme_mind.key] has lost possession of [host]([host_mind.key])") - message_admins("[meme_mind.key] has lost possession of [host]([host_mind.key]) (JMP)") - - meme_mind.transfer_to(src) - host_mind.transfer_to(host) - meme_mind.current.clearHUD() - H.update_body() - to_chat(src, "\red You lose control..") - - qdel(dummy) - -// Enter dormant mode, increases meme point gain -mob/living/parasite/meme/verb/Dormant() - set category = "Meme" - set name = "Dormant(100)" - set desc = "Speed up point recharging, will force you to cease all actions until all points are recharged." - - if(!host) - return - if(!use_points(100)) - return - - to_chat(usr, "You enter dormant mode.. You won't be able to take action until all your points have recharged.") - - dormant = 1 - - while(meme_points < MAXIMUM_MEME_POINTS) - sleep(10) - - dormant = 0 - - to_chat(usr, "\red You have regained all points and exited dormant mode!") - -mob/living/parasite/meme/verb/Show_Points() - set category = "Meme" - - to_chat(usr, "Meme Points: [src.meme_points]/[MAXIMUM_MEME_POINTS]") - -// Stat panel to show meme points, copypasted from alien -/mob/living/parasite/meme/Stat() - ..() - if(statpanel("Status")) - stat(null, "Meme Points: [meme_points]") - -// Game mode helpers, used for theft objectives -// -------------------------------------------- -mob/living/parasite/check_contents_for(t) - if(!host) - return 0 - - return host.check_contents_for(t) - -/*mob/living/parasite/check_contents_for_reagent(t) - if(!host) return 0 - - return host.check_contents_for_reagent(t) */ +//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:05 + +// === MEMETIC ANOMALY === +// ======================= + +/** +This life form is a form of parasite that can gain a certain level of control +over its host. Its player will share vision and hearing with the host, and it'll +be able to influence the host through various commands. +**/ + +// The maximum amount of points a meme can gather. +var/global/const/MAXIMUM_MEME_POINTS = 750 + + +// === PARASITE === +// ================ + +// a list of all the parasites in the mob +mob/living/carbon/var/list/parasites = list() + +mob/living/parasite + var/mob/living/carbon/host // the host that this parasite occupies + +/mob/living/parasite/Login() + ..() + if(host) + client.eye = host + else + client.eye = loc + client.perspective = EYE_PERSPECTIVE + sleeping = 0 + +/mob/living/parasite/proc/enter_host(mob/living/carbon/host) + src.host = host + loc = host + host.parasites.Add(src) + if(client) + client.eye = host + return TRUE + +/mob/living/parasite/proc/exit_host() + host.parasites.Remove(src) + host = null + loc = null + return TRUE + + +// === MEME === +// ============ + +/mob/living/parasite/meme + var/meme_points = 100 + var/dormant = 0 + var/meme_death = "stoxin" + var/list/indoctrinated = list() + +/mob/living/parasite/meme/atom_init() + . = ..() + name = "[pick("Meme")] [rand(1000,9999)]" + +/mob/living/parasite/meme/enter_host(mob/living/carbon/human/host) + if(locate(/mob/living/parasite/meme) in host.parasites) + return FALSE + return ..() + +mob/living/parasite/meme/Life() + ..() + + + if(client) + if(blinded) + client.eye = null + else + client.eye = host + + if(!host) + return + + // recover meme points slowly + var/gain = 3 + if(dormant) gain = 9 // dormant recovers points faster + + meme_points = min(meme_points + gain, MAXIMUM_MEME_POINTS) + // if there are sleep toxins in the host's body, that's bad + + if (meme_death == "bdam") + if(host.brainloss > 60) + to_chat(src, "\red Something in your host's brain makes you lose consciousness.. you fade away..") + src.death() + return + else if (meme_death == "burns") + if(host.on_fire) + to_chat(src, "\red Something on your host's skin makes you unstable.. you fade away..") + src.death() + return + else if(host.reagents.has_reagent(meme_death)) + to_chat(src, "\red Something in your host's blood makes you lose consciousness.. you fade away..") + src.death() + return + + // a host without brain is no good + else if(!host.mind) + to_chat(src, "\red Your host has no mind.. you fade away..") + src.death() + return + else if(host.stat == DEAD) + to_chat(src, "\red Your host has died.. you fade away..") + src.death() + return + + else if(host.blinded && host.stat != UNCONSCIOUS) + src.blinded = 1 + else + src.blinded = 0 + + +mob/living/parasite/meme/death() + // make sure the mob is on the actual map before gibbing + if(host) src.loc = host.loc + src.stat = DEAD + ..() + qdel(src) + +// When a meme speaks, it speaks through its host +mob/living/parasite/meme/say(message as text) + if(dormant) + to_chat(usr, "\red You're dormant!") + return + if(!host) + to_chat(usr, "\red You can't speak without host!") + return + + return host.say(message) + +// Same as speak, just with whisper +mob/living/parasite/meme/whisper(message as text) + if(dormant) + to_chat(usr, "\red You're dormant!") + return + if(!host) + to_chat(usr, "\red You can't speak without host!") + return + + return host.whisper(message) + +// Make the host do things +mob/living/parasite/meme/me_verb(message as text) + set name = "Me" + + + if(dormant) + to_chat(usr, "\red You're dormant!") + return + + if(!host) + to_chat(usr, "\red You can't emote without host!") + return + + return host.custom_emote(1, message) + +// A meme understands everything their host understands +mob/living/parasite/meme/say_understands(mob/other) + if(!host) + return 0 + + return host.say_understands(other) + +// Try to use amount points, return 1 if successful +mob/living/parasite/meme/proc/use_points(amount) + if(dormant) + to_chat(usr, "\red You're dormant!") + return + if(src.meme_points < amount) + to_chat(src, "* You don't have enough meme points(need [amount]).") + return 0 + + src.meme_points -= round(amount) + return 1 + +// Let the meme choose one of his indoctrinated mobs as target +mob/living/parasite/meme/proc/select_indoctrinated(title, message) + var/list/candidates + + // Can only affect other mobs thant he host if not blinded + if(blinded) + candidates = list() + to_chat(src, "\red You are blinded, so you can not affect mobs other than your host.") + else + candidates = indoctrinated.Copy() + + candidates.Add(src.host) + + var/mob/target = null + if(candidates.len == 1) + target = candidates[1] + else + var/selected + + var/list/text_candidates = list() + var/list/map_text_to_mob = list() + + for(var/mob/living/carbon/human/M in candidates) + text_candidates += M.real_name + map_text_to_mob[M.real_name] = M + + selected = input(message,title) as null|anything in text_candidates + if(!selected) + return null + + target = map_text_to_mob[selected] + + return target + + +// A meme can make people hear things with the thought ability +mob/living/parasite/meme/verb/Thought() + set category = "Meme" + set name = "Thought(50)" + set desc = "Implants a thought into the target, making them think they heard someone talk." + + if(meme_points < 50) + // just call use_points() to give the standard failure message + use_points(50) + return + + var/list/candidates = indoctrinated.Copy() + if(!(src.host in candidates)) + candidates.Add(src.host) + + var/mob/target = select_indoctrinated("Thought", "Select a target which will hear your thought.") + + if(!target) + return + + var/speaker = sanitize(input("Select the voice in which you would like to make yourself heard.", "Voice") as null|text, MAX_NAME_LEN) + if(!speaker) + return + + var/message = sanitize(input("What would you like to say?", "Message") as null|text) + if(!message) + return + + // Use the points at the end rather than the beginning, because the user might cancel + if(!use_points(50)) + return + + //message = say_quote(message) + var/rendered = "[speaker] [message]" + //target.show_message(rendered) + to_chat(target, rendered) + to_chat(usr, "You make [target] hear: [rendered]") + for(var/mob/dead/observer/G in observer_list) + G.show_message("[usr] makes [target] hear: [rendered]") + log_say("Memetic Thought: [key_name(usr)] makes [key_name(target)] hear: [speaker] [message]") + +// Mutes the host +mob/living/parasite/meme/verb/Mute() + set category = "Meme" + set name = "Mute(250)" + set desc = "Prevents your host from talking for a while." + + if(!src.host) return + if(!host.speech_allowed) + to_chat(usr, "\red Your host already can't speak..") + return + if(!use_points(250)) + return + + spawn + // backup the host incase we switch hosts after using the verb + var/mob/host = src.host + + to_chat(host, "\red Your tongue feels numb.. You lose your ability to speak.") + to_chat(usr, "\red Your host can't speak anymore.") + + host.speech_allowed = 0 + + sleep(1200) + + host.speech_allowed = 1 + to_chat(host, "\red Your tongue has feeling again..") + to_chat(usr, "\red [host] can speak again.") + +// Makes the host unable to emote +mob/living/parasite/meme/verb/Paralyze() + set category = "Meme" + set name = "Paralyze(250)" + set desc = "Prevents your host from using emote for a while." + + if(!src.host) + return + if(!host.use_me) + to_chat(usr, "\red Your host already can't use body language..") + return + if(!use_points(250)) + return + + spawn + // backup the host incase we switch hosts after using the verb + var/mob/host = src.host + + to_chat(host, "\red Your body feels numb.. You lose your ability to use body language.") + to_chat(usr, "\red Your host can't use body language anymore.") + + host.use_me = 0 + + sleep(1200) + + host.use_me = 1 + to_chat(host, "\red Your body has feeling again..") + to_chat(usr, "\red [host] can use body language again.") + + + +// Cause great agony with the host, used for conditioning the host +mob/living/parasite/meme/verb/Agony() + set category = "Meme" + set name = "Agony(200)" + set desc = "Causes significant pain in your host." + + if(!src.host) + return + if(!use_points(200)) + return + + spawn + // backup the host incase we switch hosts after using the verb + var/mob/host = src.host + + host.paralysis = max(host.paralysis, 2) + + host.flash_weak_pain() + to_chat(host, "\red You feel excrutiating pain all over your body! It is so bad you can't think or articulate yourself properly..") + + to_chat(usr, "You send a jolt of agonizing pain through [host], they should be unable to concentrate on anything else for half a minute.") + + host.emote("scream",,, 1) + + for(var/i=0, i<10, i++) + host.stuttering = 2 + sleep(50) + if(prob(80)) + host.flash_weak_pain() + if(prob(10)) + host.paralysis = max(host.paralysis, 2) + if(prob(15)) + host.emote("twitch") + else if(prob(15)) + host.emote("scream",,, 1) + else if(prob(10)) + host.emote("collapse") + + if(i == 10) + to_chat(host, "\red THE PAIN! AGHH, THE PAIN! MAKE IT STOP! ANYTHING TO MAKE IT STOP!") + + to_chat(host, "\red The pain subsides..") + +// Cause great joy with the host, used for conditioning the host +mob/living/parasite/meme/verb/Joy() + set category = "Meme" + set name = "Joy(200)" + set desc = "Causes significant joy in your host." + + if(!src.host) + return + if(!use_points(200)) + return + + spawn + var/mob/host = src.host + host.druggy = max(host.druggy, 50) + host.slurring = max(host.slurring, 10) + + to_chat(usr, "You stimulate [host.name]'s brain, injecting waves of endorphines and dopamine into the tissue. They should now forget all their worries, particularly relating to you, for around a minute.") + + to_chat(host, "\red You are feeling wonderful! Your head is numb and drowsy, and you can't help forgetting all the worries in the world.") + + while(host.druggy > 0) + sleep(10) + + to_chat(host, "\red You are feeling clear-headed again..") + +// Cause the target to hallucinate. +mob/living/parasite/meme/verb/Hallucinate() + set category = "Meme" + set name = "Hallucinate(300)" + set desc = "Makes your host hallucinate, has a short delay." + + var/mob/living/target = select_indoctrinated("Hallucination", "Who should hallucinate?") + + if(!target) + return + if(!use_points(300)) + return + + target.hallucination += 100 + + to_chat(usr, "You make [target] hallucinate.") + +// Jump to a closeby target through a whisper +mob/living/parasite/meme/verb/SubtleJump(mob/living/carbon/human/target as mob in human_list) + set category = "Meme" + set name = "Subtle Jump(350)" + set desc = "Move to a closeby human through a whisper." + + if(!istype(target, /mob/living/carbon/human) || !target.mind) + to_chat(src, "You can't jump to this creature..") + return + if(!(target in view(1, host)+src)) + to_chat(src, "The target is not close enough.") + return + + // Find out whether we can speak + if (host.silent || (host.disabilities & 64)) + to_chat(src, "Your host can't speak..") + return + + if(!use_points(350)) + return + + for(var/mob/M in view(1, host)) + M.show_message("[host] whispers something incoherent.",2) // 2 stands for hearable message + + // Find out whether the target can hear + if(target.disabilities & 32 || target.ear_deaf) + to_chat(src, "Your target doesn't seem to hear you..") + return + + if(target.parasites.len > 0) + to_chat(src, "Your target already is possessed by something..") + return + + src.exit_host() + src.enter_host(target) + + to_chat(usr, "You successfully jumped to [target].") + log_admin("[src.key] has jumped to [target]") + message_admins("[src.key] has jumped to [target] (JMP)") + +// Jump to a distant target through a shout +mob/living/parasite/meme/verb/ObviousJump(mob/living/carbon/human/target as mob in human_list) + set category = "Meme" + set name = "Obvious Jump(750)" + set desc = "Move to any mob in view through a shout." + + if(!istype(target, /mob/living/carbon/human) || !target.mind) + to_chat(src, "You can't jump to this creature..") + return + if(!(target in view(host))) + to_chat(src, "The target is not close enough.") + return + + // Find out whether we can speak + if (host.silent || (host.disabilities & 64)) + to_chat(src, "Your host can't speak..") + return + + if(!use_points(750)) + return + + for(var/mob/M in view(host)+src) + M.show_message("[host] screams something incoherent!",2) // 2 stands for hearable message + + // Find out whether the target can hear + if(target.disabilities & 32 || target.ear_deaf) + to_chat(src, "Your target doesn't seem to hear you..") + return + + if(target.parasites.len > 0) + to_chat(src, "Your target already is possessed by something..") + return + + src.exit_host() + src.enter_host(target) + + to_chat(usr, "You successfully jumped to [target].") + log_admin("[src.key] has jumped to [target]") + message_admins("[src.key] has jumped to [target] (JMP)") + +// Jump to an attuned mob for free +mob/living/parasite/meme/verb/AttunedJump(mob/living/carbon/human/target as mob in human_list) + set category = "Meme" + set name = "Attuned Jump(0)" + set desc = "Move to a mob in sight that you have already attuned." + + if(!istype(target, /mob/living/carbon/human) || !target.mind) + to_chat(src, "You can't jump to this creature..") + return + if(!(target in view(host))) + to_chat(src, "You need to make eye-contact with the target.") + return + if(!(target in indoctrinated)) + to_chat(src, "You need to attune the target first.") + return + + if(target.parasites.len > 0) + to_chat(src, "Your target already is possessed by something..") + return + + src.exit_host() + src.enter_host(target) + + to_chat(usr, "You successfully jumped to [target].") + + log_admin("[src.key] has jumped to [target]") + message_admins("[src.key] has jumped to [target] (JMP)") + +// ATTUNE a mob, adding it to the indoctrinated list +mob/living/parasite/meme/verb/Attune() + set category = "Meme" + set name = "Attune(400)" + set desc = "Change the host's brain structure, making it easier for you to manipulate him." + + if(host in src.indoctrinated) + to_chat(usr, "You have already attuned this host.") + return + + if(!host) + return + if(!use_points(400)) + return + + src.indoctrinated.Add(host) + + to_chat(usr, "You successfully indoctrinated [host].") + to_chat(host, "\red Your head feels a bit roomier..") + + log_admin("[src.key] has attuned [host]") + message_admins("[src.key] has attuned [host] (JMP)") + +// Enables the mob to take a lot more damage +mob/living/parasite/meme/verb/Analgesic() + set category = "Meme" + set name = "Analgesic(500)" + set desc = "Combat drug that the host to move normally, even under life-threatening pain." + + if(!host) + return + if(!(host in indoctrinated)) + to_chat(usr, "\red You need to attune the host first.") + return + if(!use_points(500)) + return + + to_chat(usr, "You inject drugs into [host].") + to_chat(host, "\red You feel your body strengthen and your pain subside..") + host.analgesic = 60 + while(host.analgesic > 0) + sleep(10) + to_chat(host, "\red The dizziness wears off, and you can feel pain again..") + + +mob/proc/clearHUD() + if(client) + client.screen.Cut() + +// Take control of the mob +mob/living/parasite/meme/verb/Possession() + set category = "Meme" + set name = "Possession(500)" + set desc = "Take direct control of the host for a while." + + if(!host) + return + if(!(host in indoctrinated)) + to_chat(usr, "\red You need to attune the host first.") + return + if(!use_points(500)) + return + + to_chat(usr, "You take control of [host]!") + to_chat(host, "\red Everything goes black..") + + spawn + var/mob/dummy = new() + dummy.loc = 0 + dummy.sight = BLIND + + var/datum/mind/host_mind = host.mind + var/datum/mind/meme_mind = src.mind + var/mob/living/carbon/human/H = host + + host_mind.transfer_to(dummy) + meme_mind.transfer_to(host) + host_mind.current.clearHUD() + H.update_body() + + to_chat(dummy, "\blue You feel very drowsy.. Your eyelids become heavy...") + + log_admin("[meme_mind.key] has taken possession of [host]([host_mind.key])") + message_admins("[meme_mind.key] has taken possession of [host]([host_mind.key]) (JMP)") + + sleep(600) + + log_admin("[meme_mind.key] has lost possession of [host]([host_mind.key])") + message_admins("[meme_mind.key] has lost possession of [host]([host_mind.key]) (JMP)") + + meme_mind.transfer_to(src) + host_mind.transfer_to(host) + meme_mind.current.clearHUD() + H.update_body() + to_chat(src, "\red You lose control..") + + qdel(dummy) + +// Enter dormant mode, increases meme point gain +mob/living/parasite/meme/verb/Dormant() + set category = "Meme" + set name = "Dormant(100)" + set desc = "Speed up point recharging, will force you to cease all actions until all points are recharged." + + if(!host) + return + if(!use_points(100)) + return + + to_chat(usr, "You enter dormant mode.. You won't be able to take action until all your points have recharged.") + + dormant = 1 + + while(meme_points < MAXIMUM_MEME_POINTS) + sleep(10) + + dormant = 0 + + to_chat(usr, "\red You have regained all points and exited dormant mode!") + +mob/living/parasite/meme/verb/Show_Points() + set category = "Meme" + + to_chat(usr, "Meme Points: [src.meme_points]/[MAXIMUM_MEME_POINTS]") + +// Stat panel to show meme points, copypasted from alien +/mob/living/parasite/meme/Stat() + ..() + if(statpanel("Status")) + stat(null, "Meme Points: [meme_points]") + +// Game mode helpers, used for theft objectives +// -------------------------------------------- +mob/living/parasite/check_contents_for(t) + if(!host) + return 0 + + return host.check_contents_for(t) + +/*mob/living/parasite/check_contents_for_reagent(t) + if(!host) return 0 + + return host.check_contents_for_reagent(t) */ diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 8ff2459ec79a..47b008a3f4ac 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -1,213 +1,213 @@ -var/list/department_radio_keys = list( - ":r" = "right ear", "#r" = "right ear", ".r" = "right ear", - ":l" = "left ear", "#l" = "left ear", ".l" = "left ear", - ":i" = "intercom", "#i" = "intercom", ".i" = "intercom", - ":h" = "department", "#h" = "department", ".h" = "department", - ":c" = "Command", "#c" = "Command", ".c" = "Command", - ":n" = "Science", "#n" = "Science", ".n" = "Science", - ":m" = "Medical", "#m" = "Medical", ".m" = "Medical", - ":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering", - ":s" = "Security", "#s" = "Security", ".s" = "Security", - ":w" = "whisper", "#w" = "whisper", ".w" = "whisper", - ":b" = "binary", "#b" = "binary", ".b" = "binary", - ":a" = "alientalk", "#a" = "alientalk", ".a" = "alientalk", - ":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate", - ":u" = "Supply", "#u" = "Supply", ".u" = "Supply", - ":g" = "changeling", "#g" = "changeling", ".g" = "changeling", - ":d" = "dronechat", "#d" = "dronechat", ".d" = "dronechat", - - ":R" = "right ear", "#R" = "right ear", ".R" = "right ear", - ":L" = "left ear", "#L" = "left ear", ".L" = "left ear", - ":I" = "intercom", "#I" = "intercom", ".I" = "intercom", - ":H" = "department", "#H" = "department", ".H" = "department", - ":C" = "Command", "#C" = "Command", ".C" = "Command", - ":N" = "Science", "#N" = "Science", ".N" = "Science", - ":M" = "Medical", "#M" = "Medical", ".M" = "Medical", - ":E" = "Engineering", "#E" = "Engineering", ".E" = "Engineering", - ":S" = "Security", "#S" = "Security", ".S" = "Security", - ":W" = "whisper", "#W" = "whisper", ".W" = "whisper", - ":B" = "binary", "#B" = "binary", ".B" = "binary", - ":A" = "alientalk", "#A" = "alientalk", ".A" = "alientalk", - ":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate", - ":U" = "Supply", "#U" = "Supply", ".U" = "Supply", - ":G" = "changeling", "#G" = "changeling", ".G" = "changeling", - ":D" = "dronechat", "#D" = "dronechat", ".D" = "dronechat", - - //kinda localization -- rastaf0 - //same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding. - ":" = "right ear", "#" = "right ear", "." = "right ear", - ":" = "left ear", "#" = "left ear", "." = "left ear", - ":" = "intercom", "#" = "intercom", "." = "intercom", - ":" = "department", "#" = "department", "." = "department", - ":" = "Command", "#" = "Command", "." = "Command", - ":" = "Science", "#" = "Science", "." = "Science", - ":" = "Medical", "#" = "Medical", "." = "Medical", - ":" = "Engineering", "#" = "Engineering", "." = "Engineering", - ":" = "Security", "#" = "Security", "." = "Security", - ":" = "whisper", "#" = "whisper", "." = "whisper", - ":" = "binary", "#" = "binary", "." = "binary", - ":" = "alientalk", "#" = "alientalk", "." = "alientalk", - ":" = "Syndicate", "#" = "Syndicate", "." = "Syndicate", - ":" = "Supply", "#" = "Supply", "." = "Supply", - ":" = "changeling", "#" = "changeling", "." = "changeling", - ":" = "dronechat", "#" = "dronechat", "." = "dronechat", - - ":" = "right ear", "#" = "right ear", "." = "right ear", - ":" = "left ear", "#" = "left ear", "." = "left ear", - ":" = "intercom", "#" = "intercom", "." = "intercom", - ":" = "department", "#" = "department", "." = "department", - ":" = "Command", "#" = "Command", "." = "Command", - ":" = "Science", "#" = "Science", "." = "Science", - ":" = "Medical", "#" = "Medical", "." = "Medical", - ":" = "Engineering", "#" = "Engineering", "." = "Engineering", - ":" = "Security", "#" = "Security", "." = "Security", - ":" = "whisper", "#" = "whisper", "." = "whisper", - ":" = "binary", "#" = "binary", "." = "binary", - ":" = "alientalk", "#" = "alientalk", "." = "alientalk", - ":" = "Syndicate", "#" = "Syndicate", "." = "Syndicate", - ":" = "Supply", "#" = "Supply", "." = "Supply", - ":" = "changeling", "#" = "changeling", "." = "changeling", - ":" = "dronechat", "#" = "dronechat", "." = "dronechat" -) - -/mob/living/proc/binarycheck() - if (istype(src, /mob/living/silicon/pai)) - return - if (issilicon(src)) - return 1 - if (!ishuman(src)) - return - var/mob/living/carbon/human/H = src - if (H.l_ear || H.r_ear) - var/obj/item/device/radio/headset/dongle - if(istype(H.l_ear,/obj/item/device/radio/headset)) - dongle = H.l_ear - else - dongle = H.r_ear - if(!istype(dongle)) - return - if(dongle.translate_binary) - return 1 - -/mob/living/proc/hivecheck() - if (isalien(src)) - return 1 - if (!ishuman(src)) - return - var/mob/living/carbon/human/H = src - if (H.l_ear || H.r_ear) - var/obj/item/device/radio/headset/dongle - if(istype(H.l_ear,/obj/item/device/radio/headset)) - dongle = H.l_ear - else - dongle = H.r_ear - if(!istype(dongle)) - return - if(dongle.translate_binary) - return 1 - -/mob/living/say(message, datum/language/speaking = null, verb="says", alt_name="", italics=FALSE, message_range = world.view, list/used_radios = list(), sound/speech_sound, sound_vol, sanitize = TRUE, message_mode = FALSE) - 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(sanitize) - message = sanitize(message) - - var/turf/T = get_turf(src) - - //handle nonverbal and sign languages here - if (speaking) - if (speaking.flags & NONVERBAL) - if (prob(30)) - src.custom_emote(1, "[pick(speaking.signlang_verb)].") - - if (speaking.flags & SIGNLANG) - say_signlang(message, pick(speaking.signlang_verb), speaking) - return 1 - - //speaking into radios - if(used_radios.len) - italics = 1 - message_range = 1 - - if (!istype(src, /mob/living/silicon/ai)) // Atlantis: Prevents nearby people from hearing the AI when it talks using it's integrated radio. - for(var/mob/living/M in hearers(5, src)) - if(M != src) - M.show_message("[src] talks into [used_radios.len ? used_radios[1] : "the radio."]") - if (speech_sound) - src.playsound_local(get_turf(src), speech_sound, sound_vol * 0.5, 1) - - speech_sound = null //so we don't play it twice. - - //make sure the air can transmit speech - var/datum/gas_mixture/environment = T.return_air() - if(environment) - var/pressure = environment.return_pressure() - if(pressure < SOUND_MINIMUM_PRESSURE) - italics = 1 - message_range = 1 - - if (speech_sound) - sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact - - var/list/listening = list() - var/list/listening_obj = list() - - if(T) - var/list/hear = hear(message_range, T) - var/list/hearturfs = list() - - for(var/I in hear) - if(istype(I, /mob/)) - var/mob/M = I - listening += M - hearturfs += M.locs[1] - for(var/obj/O in M.contents) - listening_obj |= O - else if(istype(I, /obj/)) - var/obj/O = I - hearturfs += O.locs[1] - listening_obj |= O - - for(var/mob/M in player_list) - if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) - listening |= M - continue - if(M.loc && M.locs[1] in hearturfs) - listening |= M - - //speech bubble - var/list/speech_bubble_recipients = list() - for(var/mob/M in listening) - if(M.client) - speech_bubble_recipients.Add(M.client) - var/speech_bubble_test = say_test(message) - var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER+1) - I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA - spawn(0) - flick_overlay(I, speech_bubble_recipients, 30) - for(var/mob/M in listening) - M.hear_say(message, verb, speaking, alt_name, italics, src, used_radios.len, speech_sound, sound_vol) - - for(var/obj/O in listening_obj) - spawn(0) - if(O) //It's possible that it could be deleted in the meantime. - O.hear_talk(src, message, verb, speaking) - - var/area/A = get_area(src) - log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]: [message]") - return 1 - -/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language) - for (var/mob/O in viewers(src, null)) - O.hear_signlang(message, verb, language, src) - -/obj/effect/speech_bubble - var/mob/parent - -/mob/living/proc/GetVoice() - return name +var/list/department_radio_keys = list( + ":r" = "right ear", "#r" = "right ear", ".r" = "right ear", + ":l" = "left ear", "#l" = "left ear", ".l" = "left ear", + ":i" = "intercom", "#i" = "intercom", ".i" = "intercom", + ":h" = "department", "#h" = "department", ".h" = "department", + ":c" = "Command", "#c" = "Command", ".c" = "Command", + ":n" = "Science", "#n" = "Science", ".n" = "Science", + ":m" = "Medical", "#m" = "Medical", ".m" = "Medical", + ":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering", + ":s" = "Security", "#s" = "Security", ".s" = "Security", + ":w" = "whisper", "#w" = "whisper", ".w" = "whisper", + ":b" = "binary", "#b" = "binary", ".b" = "binary", + ":a" = "alientalk", "#a" = "alientalk", ".a" = "alientalk", + ":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate", + ":u" = "Supply", "#u" = "Supply", ".u" = "Supply", + ":g" = "changeling", "#g" = "changeling", ".g" = "changeling", + ":d" = "dronechat", "#d" = "dronechat", ".d" = "dronechat", + + ":R" = "right ear", "#R" = "right ear", ".R" = "right ear", + ":L" = "left ear", "#L" = "left ear", ".L" = "left ear", + ":I" = "intercom", "#I" = "intercom", ".I" = "intercom", + ":H" = "department", "#H" = "department", ".H" = "department", + ":C" = "Command", "#C" = "Command", ".C" = "Command", + ":N" = "Science", "#N" = "Science", ".N" = "Science", + ":M" = "Medical", "#M" = "Medical", ".M" = "Medical", + ":E" = "Engineering", "#E" = "Engineering", ".E" = "Engineering", + ":S" = "Security", "#S" = "Security", ".S" = "Security", + ":W" = "whisper", "#W" = "whisper", ".W" = "whisper", + ":B" = "binary", "#B" = "binary", ".B" = "binary", + ":A" = "alientalk", "#A" = "alientalk", ".A" = "alientalk", + ":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate", + ":U" = "Supply", "#U" = "Supply", ".U" = "Supply", + ":G" = "changeling", "#G" = "changeling", ".G" = "changeling", + ":D" = "dronechat", "#D" = "dronechat", ".D" = "dronechat", + + //kinda localization -- rastaf0 + //same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding. + ":" = "right ear", "#" = "right ear", "." = "right ear", + ":" = "left ear", "#" = "left ear", "." = "left ear", + ":" = "intercom", "#" = "intercom", "." = "intercom", + ":" = "department", "#" = "department", "." = "department", + ":" = "Command", "#" = "Command", "." = "Command", + ":" = "Science", "#" = "Science", "." = "Science", + ":" = "Medical", "#" = "Medical", "." = "Medical", + ":" = "Engineering", "#" = "Engineering", "." = "Engineering", + ":" = "Security", "#" = "Security", "." = "Security", + ":" = "whisper", "#" = "whisper", "." = "whisper", + ":" = "binary", "#" = "binary", "." = "binary", + ":" = "alientalk", "#" = "alientalk", "." = "alientalk", + ":" = "Syndicate", "#" = "Syndicate", "." = "Syndicate", + ":" = "Supply", "#" = "Supply", "." = "Supply", + ":" = "changeling", "#" = "changeling", "." = "changeling", + ":" = "dronechat", "#" = "dronechat", "." = "dronechat", + + ":" = "right ear", "#" = "right ear", "." = "right ear", + ":" = "left ear", "#" = "left ear", "." = "left ear", + ":" = "intercom", "#" = "intercom", "." = "intercom", + ":" = "department", "#" = "department", "." = "department", + ":" = "Command", "#" = "Command", "." = "Command", + ":" = "Science", "#" = "Science", "." = "Science", + ":" = "Medical", "#" = "Medical", "." = "Medical", + ":" = "Engineering", "#" = "Engineering", "." = "Engineering", + ":" = "Security", "#" = "Security", "." = "Security", + ":" = "whisper", "#" = "whisper", "." = "whisper", + ":" = "binary", "#" = "binary", "." = "binary", + ":" = "alientalk", "#" = "alientalk", "." = "alientalk", + ":" = "Syndicate", "#" = "Syndicate", "." = "Syndicate", + ":" = "Supply", "#" = "Supply", "." = "Supply", + ":" = "changeling", "#" = "changeling", "." = "changeling", + ":" = "dronechat", "#" = "dronechat", "." = "dronechat" +) + +/mob/living/proc/binarycheck() + if (istype(src, /mob/living/silicon/pai)) + return + if (issilicon(src)) + return 1 + if (!ishuman(src)) + return + var/mob/living/carbon/human/H = src + if (H.l_ear || H.r_ear) + var/obj/item/device/radio/headset/dongle + if(istype(H.l_ear,/obj/item/device/radio/headset)) + dongle = H.l_ear + else + dongle = H.r_ear + if(!istype(dongle)) + return + if(dongle.translate_binary) + return 1 + +/mob/living/proc/hivecheck() + if (isalien(src)) + return 1 + if (!ishuman(src)) + return + var/mob/living/carbon/human/H = src + if (H.l_ear || H.r_ear) + var/obj/item/device/radio/headset/dongle + if(istype(H.l_ear,/obj/item/device/radio/headset)) + dongle = H.l_ear + else + dongle = H.r_ear + if(!istype(dongle)) + return + if(dongle.translate_binary) + return 1 + +/mob/living/say(message, datum/language/speaking = null, verb="says", alt_name="", italics=FALSE, message_range = world.view, list/used_radios = list(), sound/speech_sound, sound_vol, sanitize = TRUE, message_mode = FALSE) + 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(sanitize) + message = sanitize(message) + + var/turf/T = get_turf(src) + + //handle nonverbal and sign languages here + if (speaking) + if (speaking.flags & NONVERBAL) + if (prob(30)) + src.custom_emote(1, "[pick(speaking.signlang_verb)].") + + if (speaking.flags & SIGNLANG) + say_signlang(message, pick(speaking.signlang_verb), speaking) + return 1 + + //speaking into radios + if(used_radios.len) + italics = 1 + message_range = 1 + + if (!istype(src, /mob/living/silicon/ai)) // Atlantis: Prevents nearby people from hearing the AI when it talks using it's integrated radio. + for(var/mob/living/M in hearers(5, src)) + if(M != src) + M.show_message("[src] talks into [used_radios.len ? used_radios[1] : "the radio."]") + if (speech_sound) + src.playsound_local(get_turf(src), speech_sound, sound_vol * 0.5, 1) + + speech_sound = null //so we don't play it twice. + + //make sure the air can transmit speech + var/datum/gas_mixture/environment = T.return_air() + if(environment) + var/pressure = environment.return_pressure() + if(pressure < SOUND_MINIMUM_PRESSURE) + italics = 1 + message_range = 1 + + if (speech_sound) + sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact + + var/list/listening = list() + var/list/listening_obj = list() + + if(T) + var/list/hear = hear(message_range, T) + var/list/hearturfs = list() + + for(var/I in hear) + if(istype(I, /mob/)) + var/mob/M = I + listening += M + hearturfs += M.locs[1] + for(var/obj/O in M.contents) + listening_obj |= O + else if(istype(I, /obj/)) + var/obj/O = I + hearturfs += O.locs[1] + listening_obj |= O + + for(var/mob/M in player_list) + if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) + listening |= M + continue + if(M.loc && M.locs[1] in hearturfs) + listening |= M + + //speech bubble + var/list/speech_bubble_recipients = list() + for(var/mob/M in listening) + if(M.client) + speech_bubble_recipients.Add(M.client) + var/speech_bubble_test = say_test(message) + var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER+1) + I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + spawn(0) + flick_overlay(I, speech_bubble_recipients, 30) + for(var/mob/M in listening) + M.hear_say(message, verb, speaking, alt_name, italics, src, used_radios.len, speech_sound, sound_vol) + + for(var/obj/O in listening_obj) + spawn(0) + if(O) //It's possible that it could be deleted in the meantime. + O.hear_talk(src, message, verb, speaking) + + var/area/A = get_area(src) + log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]: [message]") + return 1 + +/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language) + for (var/mob/O in viewers(src, null)) + O.hear_signlang(message, verb, language, src) + +/obj/effect/speech_bubble + var/mob/parent + +/mob/living/proc/GetVoice() + return name diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 38b4d6a97630..22124cb3f6ae 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -1,902 +1,902 @@ -#define AI_CHECK_WIRELESS 1 -#define AI_CHECK_RADIO 2 - -var/list/ai_verbs_default = list( -// /mob/living/silicon/ai/proc/ai_recall_shuttle, - /mob/living/silicon/ai/proc/ai_goto_location, - /mob/living/silicon/ai/proc/ai_remove_location, - /mob/living/silicon/ai/proc/ai_hologram_change, - /mob/living/silicon/ai/proc/ai_network_change, - /mob/living/silicon/ai/proc/ai_statuschange, - /mob/living/silicon/ai/proc/ai_store_location, - /mob/living/silicon/ai/proc/pick_icon, - /mob/living/silicon/ai/proc/show_laws_verb, - /mob/living/silicon/ai/proc/toggle_acceleration, - /mob/living/silicon/ai/proc/change_floor -) - -//Not sure why this is necessary... -/proc/AutoUpdateAI(obj/subject) - var/is_in_use = FALSE - 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 = TRUE - subject.attack_ai(M) - return is_in_use - -/mob/living/silicon/ai - name = "AI" - icon = 'icons/mob/AI.dmi'// - icon_state = "ai" - anchored = TRUE // -- TLE - density = TRUE - canmove = FALSE - status_flags = CANSTUN|CANPARALYSE - shouldnt_see = list(/obj/effect/rune) - var/list/network = list("SS13") - var/obj/machinery/camera/camera = null - var/list/connected_robots = list() - var/aiRestorePowerRoutine = 0 - //var/list/laws = list() - var/viewalerts = 0 - var/lawcheck[1] - var/holohack = FALSE - var/datum/AI_Module/active_module = null - var/ioncheck[1] - var/lawchannel = "Common" // Default channel on which to state laws - var/icon/holo_icon//Default is assigned when AI is created. - var/obj/item/device/multitool/aiMulti = null - var/obj/item/device/radio/headset/heads/ai_integrated/aiRadio = null - var/custom_sprite = 0 //For our custom sprites -//Hud stuff - - //MALFUNCTION - var/processing_time = 100 - var/list/datum/AI_Module/current_modules = list() - var/fire_res_on_core = 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/apc_override = 0 //hack for letting the AI use its APC even when visionless - - var/camera_light_on = 0 //Defines if the AI toggled the light on the camera it's looking through. - var/datum/trackable/track = null - var/last_announcement = "" - var/wipe_timer_id = 0 - -/mob/living/silicon/ai/proc/add_ai_verbs() - verbs |= ai_verbs_default - -/mob/living/silicon/ai/proc/hcattack_ai(atom/A) - if(!holo || !isliving(A) || !in_range(eyeobj, A)) - return FALSE - if(get_dist(eyeobj, holo) > holo.holo_range) // some scums can catch a moment between ticks in process to make unwanted attack - return FALSE - SetNextMove(CLICK_CD_MELEE * 3) - var/mob/living/L = A - eyeobj.visible_message("space carp nashes at [A]") - L.apply_damage(15, BRUTE, BP_CHEST, L.run_armor_check(BP_CHEST, "melee"), DAM_SHARP|DAM_EDGE) - playsound(eyeobj, 'sound/weapons/bite.ogg', 100) - return TRUE - - -/mob/living/silicon/ai/proc/remove_ai_verbs() - verbs -= ai_verbs_default - -/mob/living/silicon/ai/atom_init(mapload, datum/ai_laws/L, obj/item/device/mmi/B, safety = 0) - . = ..() - var/list/possibleNames = ai_names - - var/pickedName = null - while(!pickedName) - pickedName = pick(ai_names) - for (var/mob/living/silicon/ai/A in ai_list) - if (A.real_name == pickedName && possibleNames.len > 1) //fixing the theoretically possible infinite loop - possibleNames -= pickedName - pickedName = null - - real_name = pickedName - name = real_name - - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) - - proc_holder_list = new() - - if(L) - if (istype(L, /datum/ai_laws)) - laws = L - else - laws = new base_law_type - - pda = new/obj/item/device/pda/silicon(src) - pda.owner = name - pda.ownjob = "AI" - pda.name = name + " (" + pda.ownjob + ")" - - aiMulti = new(src) - aiRadio = new(src) - aiRadio.myAi = src - - aiCamera = new/obj/item/device/camera/siliconcam/ai_camera(src) - - if (isturf(loc)) - add_ai_verbs(src) - - //Languages - add_language("Sol Common", 0) - add_language("Sinta'unathi", 0) - add_language("Siik'maas", 0) - add_language("Siik'tajr", 0) - add_language("Skrellian", 0) - add_language("Rootspeak", 0) - add_language("Tradeband", 1) - add_language("Trinary", 1) - add_language("Gutter", 0) - - if(!safety) // Only used by AIize() to successfully spawn an AI. - if(!B) // If there is no player/brain inside. - empty_playable_ai_cores += new/obj/structure/AIcore/deactivated(loc)//New empty terminal. - return INITIALIZE_HINT_QDEL // Delete AI. - 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" - - new /obj/machinery/ai_powersupply(src) - - hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - - ai_list += src - -/mob/living/silicon/ai/Destroy() - connected_robots.Cut() - ai_list -= src - qdel(eyeobj) - return ..() - - -/* - The AI Power supply is a dummy object used for powering the AI since only machinery should be using power. - The alternative was to rewrite a bunch of AI code instead here we are. -*/ -/obj/machinery/ai_powersupply - name="Power Supply" - active_power_usage=1000 - use_power = 2 - power_channel = EQUIP - var/mob/living/silicon/ai/powered_ai = null - invisibility = 100 - -/obj/machinery/ai_powersupply/atom_init() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/ai_powersupply/atom_init_late() - var/mob/living/silicon/ai/ai = loc - powered_ai = ai - if(isnull(powered_ai)) - qdel(src) - return - - forceMove(powered_ai.loc) - use_power(1) // Just incase we need to wake up the power system. - -/obj/machinery/ai_powersupply/process() - if(!powered_ai || powered_ai.stat & DEAD) - qdel(src) - return - if(!powered_ai.anchored) - forceMove(powered_ai.loc) - use_power = 0 - if(powered_ai.anchored) - use_power = 2 - -/mob/living/silicon/ai/proc/pick_icon() - set category = "AI Commands" - set name = "Set AI Core Display" - if(stat || aiRestorePowerRoutine) - return - 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 = splittext(file, "\n") - - for(var/line in lines) - // split & clean up - var/list/Entry = splittext(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 = "" - if (custom_sprite == 1) icontype = ("Custom")//automagically selects custom sprite if one is available - else icontype = input("Select an icon!", "AI", null, null) in list("Monochrome", "Rainbow","Clown", "Blue", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Static", "Triumvirate", "Triumvirate Static", "Soviet", "Trapped", "Heartline","No Pulse","President","BANNED","Helios","House","Yuki","Hiss!","Alter Ego","Urist","Totally Not A Malf","Fuzz","Goon","Database","Glitchman","AmericAI","NT","Gentoo","Hal 9000") - switch(icontype) - if("Custom") icon_state = "[src.ckey]-ai" - if("Rainbow") icon_state = "ai-clown" - 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-red" - if("Static") 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("Soviet") icon_state = "ai-redoctober" - if("Trapped") icon_state = "ai-hades" - if("Heartline") icon_state = "ai-heartline" - if("No Pulse") icon_state = "ai-heartline_dead" - if("President") icon_state = "ai-president" - if("BANNED") icon_state = "ai-banned" - if("Helios") icon_state = "ai-helios" - if("House") icon_state = "ai-house" - if("Gigyas") icon_state = "ai-gigyas" - if("Yuki") icon_state = "ai-yuki" - if("SyndiCat") icon_state = "ai-syndicatmeow" - if("Yuki") icon_state = "ai-yuki" - if("Hiss!") icon_state = "ai-alien" - if("Alter Ego") icon_state = "ai-alterego" - if("Urist") icon_state = "ai-toodeep" - if("Totally Not A Malf") icon_state = "ai-malf" - if("Fuzz") icon_state = "ai-fuzz" - if("Goon") icon_state = "ai-goon" - if("Database") icon_state = "ai-database" - if("Glitchman") icon_state = "ai-glitchman" - if("AmericAI") icon_state = "ai-murica" - if("NT") icon_state = "ai-nanotrasen" - if("Gentoo") icon_state = "ai-gentoo" - if("Hal 9000") icon_state = "ai-hal" - else icon_state = "ai" - //else - //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 >= APC_MIN_TO_MALF_DECLARE) - stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/APC_MIN_TO_MALF_DECLARE), 0)] seconds") - - -/mob/living/silicon/ai/show_alerts() - - var/dat = "Current Station Alerts\n" - dat += "Close

                    " - for (var/cat in alarms) - dat += text("[]
                    \n", cat) - var/list/alarmlist = alarms[cat] - if (alarmlist.len) - for (var/area_name in alarmlist) - var/datum/alarm/alarm = alarmlist[area_name] - dat += "" - - var/cameratext = "" - if (alarm.cameras) - for (var/obj/machinery/camera/I in alarm.cameras) - cameratext += text("[][]", (cameratext=="") ? "" : " | ", src, I, I.c_tag) - dat += text("-- [] ([])", alarm.area.name, (cameratext)? cameratext : "No Camera") - - if (alarm.sources.len > 1) - dat += text(" - [] sources", alarm.sources.len) - dat += "
                    \n" - else - dat += "-- All Systems Nominal
                    \n" - dat += "
                    \n" - - viewalerts = 1 - src << browse(entity_ja(dat), "window=aialerts&can_close=0") - -/mob/living/silicon/ai/var/message_cooldown = 0 -/mob/living/silicon/ai/proc/ai_announcement() - - if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) - return - - if(message_cooldown) - to_chat(src, "Please allow one minute to pass between announcements.") - return - var/input = sanitize(input(usr, "Please write a message to announce to the station crew.", "A.I. Announcement")) - if(!input) - return - - if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) - return - - captain_announce(input, "A.I. Announcement", src.name) - log_say("[key_name(usr)] has made an AI announcement: [input]") - message_admins("[key_name_admin(usr)] has made an AI announcement.") - message_cooldown = 1 - spawn(600)//One minute cooldown - message_cooldown = 0 - -/mob/living/silicon/ai/proc/ai_call_shuttle() - - if(check_unable(AI_CHECK_WIRELESS)) - return - - var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No") - - if(check_unable(AI_CHECK_WIRELESS)) - return - - if(confirm == "Yes") - call_shuttle_proc(src) - - // hack to display shuttle timer - if(SSshuttle.online) - var/obj/machinery/computer/communications/C = locate() in communications_list - if(C) - C.post_status("shuttle") - - return - -/mob/living/silicon/ai/proc/change_floor() - set category = "AI Commands" - set name = "Change Floor" - - var/f_color = input("Choose your color, dark colors are not recommended!") as color|null - if(!f_color) - return - for(var/turf/simulated/floor/whitegreed/F in world) - F.color = f_color - - to_chat(usr, "Floor color was change to [f_color]") - -/mob/living/silicon/ai/proc/ai_recall_shuttle() - set category = "AI Commands" - set name = "Recall Emergency Shuttle" - - if(check_unable(AI_CHECK_WIRELESS)) - return - - var/confirm = alert("Are you sure you want to recall the shuttle?", "Confirm Shuttle Recall", "Yes", "No") - if(check_unable(AI_CHECK_WIRELESS)) - return - - if(confirm == "Yes") - cancel_call_proc(src) - -/mob/living/silicon/ai/check_eye(mob/user) - if (!camera) - return null - user.reset_view(camera) - return 1 - -/mob/living/silicon/ai/blob_act() - if (stat != DEAD) - adjustBruteLoss(60) - updatehealth() - return 1 - return 0 - -/mob/living/silicon/ai/restrained() - return 0 - -/mob/living/silicon/ai/emp_act(severity) - if (prob(30)) - switch(pick(1,2)) - if(1) - view_core() - if(2) - ai_call_shuttle() - ..() - -/mob/living/silicon/ai/ex_act(severity) - if(!blinded) - flash_eyes() - - switch(severity) - if(1.0) - if (stat != DEAD) - adjustBruteLoss(100) - adjustFireLoss(100) - if(2.0) - if (stat != DEAD) - adjustBruteLoss(60) - adjustFireLoss(60) - if(3.0) - if (stat != DEAD) - 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"]) - show_alerts() - //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["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" -// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) - checklaws() - - if (href_list["lawr"]) // Selects on which channel to state laws - var/setchannel = input(usr, "Specify channel.", "Channel selection") in list("State","Common","Science","Command","Medical","Engineering","Security","Supply","Binary","Holopad", "Cancel") - if(setchannel == "Cancel") - return - lawchannel = setchannel - checklaws() - - //Uncomment this line of code if you are enabling the AI Vocal (VOX) announcements. -/* - if(href_list["say_word"]) - play_vox_word(href_list["say_word"], null, src) - return -*/ - - 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" -// 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 living_list - if(target && (!istype(target, /mob/living/carbon/human) || html_decode(href_list["trackname"]) == target:get_face_name())) - ai_actual_track(target) - else - to_chat(src, "System error. Cannot locate [html_decode(href_list["trackname"])].") - return - - else if (href_list["faketrack"]) - var/mob/target = locate(href_list["track"]) in living_list - var/mob/living/silicon/ai/A = locate(href_list["track2"]) in ai_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 - - return - -/mob/living/silicon/ai/meteorhit(obj/O) - for(var/mob/M in viewers(src, null)) - M.show_message(text("\red [] has been hit by []", src, O), 1) - //Foreach goto(19) - if (health > 0) - adjustBruteLoss(30) - if ((O.icon_state == "flaming")) - adjustFireLoss(40) - updatehealth() - return - -/mob/living/silicon/ai/bullet_act(obj/item/projectile/Proj) - ..(Proj) - updatehealth() - return 2 - -/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M) - 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 ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [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("\red [] has slashed at []!", M, src), 1) - if(prob(8)) - flash_eyes(affect_silicon = 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("\red [] took a swipe at []!", M, src), 1) - return - -/mob/living/silicon/ai/attack_animal(mob/living/simple_animal/M) - M.do_attack_animation(src) - 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] [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) - adjustBruteLoss(damage) - updatehealth() - -/mob/living/silicon/ai/reset_view(atom/A) - if(camera) - camera.set_light(0) - if(istype(A,/obj/machinery/camera)) - camera = A - ..() - if(istype(A,/obj/machinery/camera)) - if(camera_light_on) A.set_light(AI_CAMERA_LUMINOSITY) - else A.set_light(0) - - -/mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C) - - src.cameraFollow = null - - if (!C || stat == DEAD) //C.can_use()) - return 0 - - if(!src.eyeobj) - view_core() - return - // ok, we're alive, camera is good and in our network... - eyeobj.setLoc(get_turf(C)) - //machine = src - - return 1 - -/mob/living/silicon/ai/triggerAlarm(class, area/A, list/cameralist, source) - if (stat == DEAD) - return 1 - - ..() - - var/cameratext = "" - for (var/obj/machinery/camera/C in cameralist) - cameratext += "[(cameratext == "")? "" : "|"][C.c_tag]" - - queueAlarm("--- [class] alarm detected in [A.name]! ([(cameratext)? cameratext : "No Camera"])", class) - - if(viewalerts) - show_alerts() - -/mob/living/silicon/ai/cancelAlarm(class, area/A, source) - var/has_alarm = ..() - - if (!has_alarm) - queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0) - if(viewalerts) - show_alerts() - - return has_alarm - -/mob/living/silicon/ai/cancel_camera() - set category = "AI Commands" - set name = "Cancel Camera View" - - //src.cameraFollow = null - 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(check_unable()) - return - - var/mob/living/silicon/ai/U = usr - - for (var/obj/machinery/camera/C in cameranet.cameras) - if(!C.can_use()) - continue - - if(C.hidden) - 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 - return - else - for(var/obj/machinery/camera/C in cameranet.cameras) - if(!C.can_use()) - continue - if(network in C.network) - U.eyeobj.setLoc(get_turf(C)) - break - to_chat(src, "\blue Switched to [network] camera network.") -//End of code by Mord_Sith - - - - -/mob/living/silicon/ai/proc/ai_statuschange() - set category = "AI Commands" - set name = "AI Status" - - if(check_unable(AI_CHECK_WIRELESS)) - return - - var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "HAL") - var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions - for (var/obj/machinery/M in machines) //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" - - if(check_unable()) - return - - 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", - "alien", - "carp", - "queen", - "rommie", - "sonny", - "miku", - "medbot" - ) - input = input("Please select a hologram:") as null|anything in icon_list - if(input) - qdel(holo_icon) - 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("alien") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3")) - if("carp") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) - if("queen") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo5")) - if("rommie") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo6")) - if("sonny") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo7")) - if("miku") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo8")) - if("medbot") - holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo9")) - 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, "\blue 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/proc/toggle_camera_light() - - if(check_unable()) - return - - camera_light_on = !camera_light_on - to_chat(src, "Camera lights [camera_light_on ? "activated" : "deactivated"].") - if(!camera_light_on) - if(camera) - camera.set_light(0) - camera = null - else - lightNearbyCamera() - - - -// Handled camera lighting, when toggled. -// It will get the nearest camera from the eyeobj, lighting it. - -/mob/living/silicon/ai/proc/lightNearbyCamera() - if(camera_light_on && camera_light_on < world.timeofday) - if(src.camera) - var/obj/machinery/camera/camera = near_range_camera(src.eyeobj) - if(camera && src.camera != camera) - src.camera.set_light(0) - if(!camera.light_disabled) - src.camera = camera - src.camera.set_light(AI_CAMERA_LUMINOSITY) - else - src.camera = null - else if(isnull(camera)) - src.camera.set_light(0) - src.camera = null - else - var/obj/machinery/camera/camera = near_range_camera(src.eyeobj) - if(camera && !camera.light_disabled) - src.camera = camera - src.camera.set_light(AI_CAMERA_LUMINOSITY) - camera_light_on = world.timeofday + 1 * 20 // Update the light every 2 seconds. - - -/mob/living/silicon/ai/attackby(obj/item/weapon/W, mob/user) - if(istype(W, /obj/item/weapon/wrench)) - if(user.is_busy()) return - if(anchored) - user.visible_message("\blue \The [user] starts to unbolt \the [src] from the plating...") - if(!do_after(user,40,target = src)) - user.visible_message("\blue \The [user] decides not to unbolt \the [src].") - return - user.visible_message("\blue \The [user] finishes unfastening \the [src]!") - anchored = 0 - return - else - user.visible_message("\blue \The [user] starts to bolt \the [src] to the plating...") - if(!do_after(user,40,target = src)) - user.visible_message("\blue \The [user] decides not to bolt \the [src].") - return - user.visible_message("\blue \The [user] finishes fastening down \the [src]!") - anchored = 1 - return - else - return ..() - -/mob/living/silicon/ai/proc/control_integrated_radio() - - if(check_unable(AI_CHECK_RADIO)) - return - - to_chat(src, "Accessing Subspace Transceiver control...") - if (src.aiRadio) - src.aiRadio.interact(src) - -/mob/living/silicon/ai/proc/check_unable(flags = 0) - if(stat == DEAD) - to_chat(usr, "\red You are dead!") - return 1 - - if((flags & AI_CHECK_WIRELESS) && src.control_disabled) - to_chat(usr, "\red Wireless control is disabled!") - return 1 - if((flags & AI_CHECK_RADIO) && src.aiRadio.disabledAi) - to_chat(src, "\red System Error - Transceiver Disabled!") - return 1 - return 0 - -/mob/living/silicon/ai/proc/is_in_chassis() - return istype(loc, /turf) - -/mob/living/silicon/ai/proc/toggle_small_alt_click_module(new_mod_name) - var/datum/AI_Module/small/new_mod = current_modules[new_mod_name] - if(!new_mod) - to_chat(src, "ERROR: CAN'T FIND MODULE!") - return - if(new_mod.uses) - if(active_module != new_mod) - active_module = new_mod - to_chat(src, "[new_mod_name] module active. Alt+click to choose a machine to overload.") - else - active_module = null - to_chat(src, "[new_mod_name] module deactivated.") - else - to_chat(src, "[new_mod_name] module activation failed. Out of uses.") - -#undef AI_CHECK_WIRELESS -#undef AI_CHECK_RADIO +#define AI_CHECK_WIRELESS 1 +#define AI_CHECK_RADIO 2 + +var/list/ai_verbs_default = list( +// /mob/living/silicon/ai/proc/ai_recall_shuttle, + /mob/living/silicon/ai/proc/ai_goto_location, + /mob/living/silicon/ai/proc/ai_remove_location, + /mob/living/silicon/ai/proc/ai_hologram_change, + /mob/living/silicon/ai/proc/ai_network_change, + /mob/living/silicon/ai/proc/ai_statuschange, + /mob/living/silicon/ai/proc/ai_store_location, + /mob/living/silicon/ai/proc/pick_icon, + /mob/living/silicon/ai/proc/show_laws_verb, + /mob/living/silicon/ai/proc/toggle_acceleration, + /mob/living/silicon/ai/proc/change_floor +) + +//Not sure why this is necessary... +/proc/AutoUpdateAI(obj/subject) + var/is_in_use = FALSE + 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 = TRUE + subject.attack_ai(M) + return is_in_use + +/mob/living/silicon/ai + name = "AI" + icon = 'icons/mob/AI.dmi'// + icon_state = "ai" + anchored = TRUE // -- TLE + density = TRUE + canmove = FALSE + status_flags = CANSTUN|CANPARALYSE + shouldnt_see = list(/obj/effect/rune) + var/list/network = list("SS13") + var/obj/machinery/camera/camera = null + var/list/connected_robots = list() + var/aiRestorePowerRoutine = 0 + //var/list/laws = list() + var/viewalerts = 0 + var/lawcheck[1] + var/holohack = FALSE + var/datum/AI_Module/active_module = null + var/ioncheck[1] + var/lawchannel = "Common" // Default channel on which to state laws + var/icon/holo_icon//Default is assigned when AI is created. + var/obj/item/device/multitool/aiMulti = null + var/obj/item/device/radio/headset/heads/ai_integrated/aiRadio = null + var/custom_sprite = 0 //For our custom sprites +//Hud stuff + + //MALFUNCTION + var/processing_time = 100 + var/list/datum/AI_Module/current_modules = list() + var/fire_res_on_core = 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/apc_override = 0 //hack for letting the AI use its APC even when visionless + + var/camera_light_on = 0 //Defines if the AI toggled the light on the camera it's looking through. + var/datum/trackable/track = null + var/last_announcement = "" + var/wipe_timer_id = 0 + +/mob/living/silicon/ai/proc/add_ai_verbs() + verbs |= ai_verbs_default + +/mob/living/silicon/ai/proc/hcattack_ai(atom/A) + if(!holo || !isliving(A) || !in_range(eyeobj, A)) + return FALSE + if(get_dist(eyeobj, holo) > holo.holo_range) // some scums can catch a moment between ticks in process to make unwanted attack + return FALSE + SetNextMove(CLICK_CD_MELEE * 3) + var/mob/living/L = A + eyeobj.visible_message("space carp nashes at [A]") + L.apply_damage(15, BRUTE, BP_CHEST, L.run_armor_check(BP_CHEST, "melee"), DAM_SHARP|DAM_EDGE) + playsound(eyeobj, 'sound/weapons/bite.ogg', 100) + return TRUE + + +/mob/living/silicon/ai/proc/remove_ai_verbs() + verbs -= ai_verbs_default + +/mob/living/silicon/ai/atom_init(mapload, datum/ai_laws/L, obj/item/device/mmi/B, safety = 0) + . = ..() + var/list/possibleNames = ai_names + + var/pickedName = null + while(!pickedName) + pickedName = pick(ai_names) + for (var/mob/living/silicon/ai/A in ai_list) + if (A.real_name == pickedName && possibleNames.len > 1) //fixing the theoretically possible infinite loop + possibleNames -= pickedName + pickedName = null + + real_name = pickedName + name = real_name + + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1")) + + proc_holder_list = new() + + if(L) + if (istype(L, /datum/ai_laws)) + laws = L + else + laws = new base_law_type + + pda = new/obj/item/device/pda/silicon(src) + pda.owner = name + pda.ownjob = "AI" + pda.name = name + " (" + pda.ownjob + ")" + + aiMulti = new(src) + aiRadio = new(src) + aiRadio.myAi = src + + aiCamera = new/obj/item/device/camera/siliconcam/ai_camera(src) + + if (isturf(loc)) + add_ai_verbs(src) + + //Languages + add_language("Sol Common", 0) + add_language("Sinta'unathi", 0) + add_language("Siik'maas", 0) + add_language("Siik'tajr", 0) + add_language("Skrellian", 0) + add_language("Rootspeak", 0) + add_language("Tradeband", 1) + add_language("Trinary", 1) + add_language("Gutter", 0) + + if(!safety) // Only used by AIize() to successfully spawn an AI. + if(!B) // If there is no player/brain inside. + empty_playable_ai_cores += new/obj/structure/AIcore/deactivated(loc)//New empty terminal. + return INITIALIZE_HINT_QDEL // Delete AI. + 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" + + new /obj/machinery/ai_powersupply(src) + + hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + + ai_list += src + +/mob/living/silicon/ai/Destroy() + connected_robots.Cut() + ai_list -= src + qdel(eyeobj) + return ..() + + +/* + The AI Power supply is a dummy object used for powering the AI since only machinery should be using power. + The alternative was to rewrite a bunch of AI code instead here we are. +*/ +/obj/machinery/ai_powersupply + name="Power Supply" + active_power_usage=1000 + use_power = 2 + power_channel = EQUIP + var/mob/living/silicon/ai/powered_ai = null + invisibility = 100 + +/obj/machinery/ai_powersupply/atom_init() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/ai_powersupply/atom_init_late() + var/mob/living/silicon/ai/ai = loc + powered_ai = ai + if(isnull(powered_ai)) + qdel(src) + return + + forceMove(powered_ai.loc) + use_power(1) // Just incase we need to wake up the power system. + +/obj/machinery/ai_powersupply/process() + if(!powered_ai || powered_ai.stat & DEAD) + qdel(src) + return + if(!powered_ai.anchored) + forceMove(powered_ai.loc) + use_power = 0 + if(powered_ai.anchored) + use_power = 2 + +/mob/living/silicon/ai/proc/pick_icon() + set category = "AI Commands" + set name = "Set AI Core Display" + if(stat || aiRestorePowerRoutine) + return + 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 = splittext(file, "\n") + + for(var/line in lines) + // split & clean up + var/list/Entry = splittext(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 = "" + if (custom_sprite == 1) icontype = ("Custom")//automagically selects custom sprite if one is available + else icontype = input("Select an icon!", "AI", null, null) in list("Monochrome", "Rainbow","Clown", "Blue", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Static", "Triumvirate", "Triumvirate Static", "Soviet", "Trapped", "Heartline","No Pulse","President","BANNED","Helios","House","Yuki","Hiss!","Alter Ego","Urist","Totally Not A Malf","Fuzz","Goon","Database","Glitchman","AmericAI","NT","Gentoo","Hal 9000") + switch(icontype) + if("Custom") icon_state = "[src.ckey]-ai" + if("Rainbow") icon_state = "ai-clown" + 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-red" + if("Static") 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("Soviet") icon_state = "ai-redoctober" + if("Trapped") icon_state = "ai-hades" + if("Heartline") icon_state = "ai-heartline" + if("No Pulse") icon_state = "ai-heartline_dead" + if("President") icon_state = "ai-president" + if("BANNED") icon_state = "ai-banned" + if("Helios") icon_state = "ai-helios" + if("House") icon_state = "ai-house" + if("Gigyas") icon_state = "ai-gigyas" + if("Yuki") icon_state = "ai-yuki" + if("SyndiCat") icon_state = "ai-syndicatmeow" + if("Yuki") icon_state = "ai-yuki" + if("Hiss!") icon_state = "ai-alien" + if("Alter Ego") icon_state = "ai-alterego" + if("Urist") icon_state = "ai-toodeep" + if("Totally Not A Malf") icon_state = "ai-malf" + if("Fuzz") icon_state = "ai-fuzz" + if("Goon") icon_state = "ai-goon" + if("Database") icon_state = "ai-database" + if("Glitchman") icon_state = "ai-glitchman" + if("AmericAI") icon_state = "ai-murica" + if("NT") icon_state = "ai-nanotrasen" + if("Gentoo") icon_state = "ai-gentoo" + if("Hal 9000") icon_state = "ai-hal" + else icon_state = "ai" + //else + //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 >= APC_MIN_TO_MALF_DECLARE) + stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/APC_MIN_TO_MALF_DECLARE), 0)] seconds") + + +/mob/living/silicon/ai/show_alerts() + + var/dat = "Current Station Alerts\n" + dat += "Close

                    " + for (var/cat in alarms) + dat += text("[]
                    \n", cat) + var/list/alarmlist = alarms[cat] + if (alarmlist.len) + for (var/area_name in alarmlist) + var/datum/alarm/alarm = alarmlist[area_name] + dat += "" + + var/cameratext = "" + if (alarm.cameras) + for (var/obj/machinery/camera/I in alarm.cameras) + cameratext += text("[][]", (cameratext=="") ? "" : " | ", src, I, I.c_tag) + dat += text("-- [] ([])", alarm.area.name, (cameratext)? cameratext : "No Camera") + + if (alarm.sources.len > 1) + dat += text(" - [] sources", alarm.sources.len) + dat += "
                    \n" + else + dat += "-- All Systems Nominal
                    \n" + dat += "
                    \n" + + viewalerts = 1 + src << browse(entity_ja(dat), "window=aialerts&can_close=0") + +/mob/living/silicon/ai/var/message_cooldown = 0 +/mob/living/silicon/ai/proc/ai_announcement() + + if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) + return + + if(message_cooldown) + to_chat(src, "Please allow one minute to pass between announcements.") + return + var/input = sanitize(input(usr, "Please write a message to announce to the station crew.", "A.I. Announcement")) + if(!input) + return + + if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) + return + + captain_announce(input, "A.I. Announcement", src.name) + log_say("[key_name(usr)] has made an AI announcement: [input]") + message_admins("[key_name_admin(usr)] has made an AI announcement.") + message_cooldown = 1 + spawn(600)//One minute cooldown + message_cooldown = 0 + +/mob/living/silicon/ai/proc/ai_call_shuttle() + + if(check_unable(AI_CHECK_WIRELESS)) + return + + var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No") + + if(check_unable(AI_CHECK_WIRELESS)) + return + + if(confirm == "Yes") + call_shuttle_proc(src) + + // hack to display shuttle timer + if(SSshuttle.online) + var/obj/machinery/computer/communications/C = locate() in communications_list + if(C) + C.post_status("shuttle") + + return + +/mob/living/silicon/ai/proc/change_floor() + set category = "AI Commands" + set name = "Change Floor" + + var/f_color = input("Choose your color, dark colors are not recommended!") as color|null + if(!f_color) + return + for(var/turf/simulated/floor/whitegreed/F in world) + F.color = f_color + + to_chat(usr, "Floor color was change to [f_color]") + +/mob/living/silicon/ai/proc/ai_recall_shuttle() + set category = "AI Commands" + set name = "Recall Emergency Shuttle" + + if(check_unable(AI_CHECK_WIRELESS)) + return + + var/confirm = alert("Are you sure you want to recall the shuttle?", "Confirm Shuttle Recall", "Yes", "No") + if(check_unable(AI_CHECK_WIRELESS)) + return + + if(confirm == "Yes") + cancel_call_proc(src) + +/mob/living/silicon/ai/check_eye(mob/user) + if (!camera) + return null + user.reset_view(camera) + return 1 + +/mob/living/silicon/ai/blob_act() + if (stat != DEAD) + adjustBruteLoss(60) + updatehealth() + return 1 + return 0 + +/mob/living/silicon/ai/restrained() + return 0 + +/mob/living/silicon/ai/emp_act(severity) + if (prob(30)) + switch(pick(1,2)) + if(1) + view_core() + if(2) + ai_call_shuttle() + ..() + +/mob/living/silicon/ai/ex_act(severity) + if(!blinded) + flash_eyes() + + switch(severity) + if(1.0) + if (stat != DEAD) + adjustBruteLoss(100) + adjustFireLoss(100) + if(2.0) + if (stat != DEAD) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3.0) + if (stat != DEAD) + 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"]) + show_alerts() + //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["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" +// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1]) + checklaws() + + if (href_list["lawr"]) // Selects on which channel to state laws + var/setchannel = input(usr, "Specify channel.", "Channel selection") in list("State","Common","Science","Command","Medical","Engineering","Security","Supply","Binary","Holopad", "Cancel") + if(setchannel == "Cancel") + return + lawchannel = setchannel + checklaws() + + //Uncomment this line of code if you are enabling the AI Vocal (VOX) announcements. +/* + if(href_list["say_word"]) + play_vox_word(href_list["say_word"], null, src) + return +*/ + + 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" +// 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 living_list + if(target && (!istype(target, /mob/living/carbon/human) || html_decode(href_list["trackname"]) == target:get_face_name())) + ai_actual_track(target) + else + to_chat(src, "System error. Cannot locate [html_decode(href_list["trackname"])].") + return + + else if (href_list["faketrack"]) + var/mob/target = locate(href_list["track"]) in living_list + var/mob/living/silicon/ai/A = locate(href_list["track2"]) in ai_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 + + return + +/mob/living/silicon/ai/meteorhit(obj/O) + for(var/mob/M in viewers(src, null)) + M.show_message(text("\red [] has been hit by []", src, O), 1) + //Foreach goto(19) + if (health > 0) + adjustBruteLoss(30) + if ((O.icon_state == "flaming")) + adjustFireLoss(40) + updatehealth() + return + +/mob/living/silicon/ai/bullet_act(obj/item/projectile/Proj) + ..(Proj) + updatehealth() + return 2 + +/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M) + 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 ("help") + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\blue [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("\red [] has slashed at []!", M, src), 1) + if(prob(8)) + flash_eyes(affect_silicon = 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("\red [] took a swipe at []!", M, src), 1) + return + +/mob/living/silicon/ai/attack_animal(mob/living/simple_animal/M) + M.do_attack_animation(src) + 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] [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) + adjustBruteLoss(damage) + updatehealth() + +/mob/living/silicon/ai/reset_view(atom/A) + if(camera) + camera.set_light(0) + if(istype(A,/obj/machinery/camera)) + camera = A + ..() + if(istype(A,/obj/machinery/camera)) + if(camera_light_on) A.set_light(AI_CAMERA_LUMINOSITY) + else A.set_light(0) + + +/mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C) + + src.cameraFollow = null + + if (!C || stat == DEAD) //C.can_use()) + return 0 + + if(!src.eyeobj) + view_core() + return + // ok, we're alive, camera is good and in our network... + eyeobj.setLoc(get_turf(C)) + //machine = src + + return 1 + +/mob/living/silicon/ai/triggerAlarm(class, area/A, list/cameralist, source) + if (stat == DEAD) + return 1 + + ..() + + var/cameratext = "" + for (var/obj/machinery/camera/C in cameralist) + cameratext += "[(cameratext == "")? "" : "|"][C.c_tag]" + + queueAlarm("--- [class] alarm detected in [A.name]! ([(cameratext)? cameratext : "No Camera"])", class) + + if(viewalerts) + show_alerts() + +/mob/living/silicon/ai/cancelAlarm(class, area/A, source) + var/has_alarm = ..() + + if (!has_alarm) + queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0) + if(viewalerts) + show_alerts() + + return has_alarm + +/mob/living/silicon/ai/cancel_camera() + set category = "AI Commands" + set name = "Cancel Camera View" + + //src.cameraFollow = null + 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(check_unable()) + return + + var/mob/living/silicon/ai/U = usr + + for (var/obj/machinery/camera/C in cameranet.cameras) + if(!C.can_use()) + continue + + if(C.hidden) + 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 + return + else + for(var/obj/machinery/camera/C in cameranet.cameras) + if(!C.can_use()) + continue + if(network in C.network) + U.eyeobj.setLoc(get_turf(C)) + break + to_chat(src, "\blue Switched to [network] camera network.") +//End of code by Mord_Sith + + + + +/mob/living/silicon/ai/proc/ai_statuschange() + set category = "AI Commands" + set name = "AI Status" + + if(check_unable(AI_CHECK_WIRELESS)) + return + + var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "HAL") + var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions + for (var/obj/machinery/M in machines) //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" + + if(check_unable()) + return + + 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", + "alien", + "carp", + "queen", + "rommie", + "sonny", + "miku", + "medbot" + ) + input = input("Please select a hologram:") as null|anything in icon_list + if(input) + qdel(holo_icon) + 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("alien") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3")) + if("carp") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4")) + if("queen") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo5")) + if("rommie") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo6")) + if("sonny") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo7")) + if("miku") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo8")) + if("medbot") + holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo9")) + 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, "\blue 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/proc/toggle_camera_light() + + if(check_unable()) + return + + camera_light_on = !camera_light_on + to_chat(src, "Camera lights [camera_light_on ? "activated" : "deactivated"].") + if(!camera_light_on) + if(camera) + camera.set_light(0) + camera = null + else + lightNearbyCamera() + + + +// Handled camera lighting, when toggled. +// It will get the nearest camera from the eyeobj, lighting it. + +/mob/living/silicon/ai/proc/lightNearbyCamera() + if(camera_light_on && camera_light_on < world.timeofday) + if(src.camera) + var/obj/machinery/camera/camera = near_range_camera(src.eyeobj) + if(camera && src.camera != camera) + src.camera.set_light(0) + if(!camera.light_disabled) + src.camera = camera + src.camera.set_light(AI_CAMERA_LUMINOSITY) + else + src.camera = null + else if(isnull(camera)) + src.camera.set_light(0) + src.camera = null + else + var/obj/machinery/camera/camera = near_range_camera(src.eyeobj) + if(camera && !camera.light_disabled) + src.camera = camera + src.camera.set_light(AI_CAMERA_LUMINOSITY) + camera_light_on = world.timeofday + 1 * 20 // Update the light every 2 seconds. + + +/mob/living/silicon/ai/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/wrench)) + if(user.is_busy()) return + if(anchored) + user.visible_message("\blue \The [user] starts to unbolt \the [src] from the plating...") + if(!do_after(user,40,target = src)) + user.visible_message("\blue \The [user] decides not to unbolt \the [src].") + return + user.visible_message("\blue \The [user] finishes unfastening \the [src]!") + anchored = 0 + return + else + user.visible_message("\blue \The [user] starts to bolt \the [src] to the plating...") + if(!do_after(user,40,target = src)) + user.visible_message("\blue \The [user] decides not to bolt \the [src].") + return + user.visible_message("\blue \The [user] finishes fastening down \the [src]!") + anchored = 1 + return + else + return ..() + +/mob/living/silicon/ai/proc/control_integrated_radio() + + if(check_unable(AI_CHECK_RADIO)) + return + + to_chat(src, "Accessing Subspace Transceiver control...") + if (src.aiRadio) + src.aiRadio.interact(src) + +/mob/living/silicon/ai/proc/check_unable(flags = 0) + if(stat == DEAD) + to_chat(usr, "\red You are dead!") + return 1 + + if((flags & AI_CHECK_WIRELESS) && src.control_disabled) + to_chat(usr, "\red Wireless control is disabled!") + return 1 + if((flags & AI_CHECK_RADIO) && src.aiRadio.disabledAi) + to_chat(src, "\red System Error - Transceiver Disabled!") + return 1 + return 0 + +/mob/living/silicon/ai/proc/is_in_chassis() + return istype(loc, /turf) + +/mob/living/silicon/ai/proc/toggle_small_alt_click_module(new_mod_name) + var/datum/AI_Module/small/new_mod = current_modules[new_mod_name] + if(!new_mod) + to_chat(src, "ERROR: CAN'T FIND MODULE!") + return + if(new_mod.uses) + if(active_module != new_mod) + active_module = new_mod + to_chat(src, "[new_mod_name] module active. Alt+click to choose a machine to overload.") + else + active_module = null + to_chat(src, "[new_mod_name] module deactivated.") + else + to_chat(src, "[new_mod_name] module activation failed. Out of uses.") + +#undef AI_CHECK_WIRELESS +#undef AI_CHECK_RADIO diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index e967ec1bcdf8..6dc222e8351f 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -1,66 +1,66 @@ -/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" - if("[icon_state]_dead" in icon_states(src.icon,1)) - icon_state = "[icon_state]_dead" - else - icon_state = "ai_dead" - - update_canmove() - if(eyeobj) - eyeobj.setLoc(get_turf(src)) - sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - client.screen.Cut() - remove_ai_verbs(src) - - var/callshuttle = 0 - - for(var/obj/machinery/computer/communications/commconsole in communications_list) - if(commconsole.z == ZLEVEL_CENTCOMM) - continue - if(istype(commconsole.loc,/turf)) - break - callshuttle++ - - for(var/obj/item/weapon/circuitboard/communications/commboard in circuitboard_communications_list) - if(commboard.z == ZLEVEL_CENTCOMM) - 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 == ZLEVEL_CENTCOMM) - 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 - SSshuttle.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.") - captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") - 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 ai_status_display_list) //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) - - return ..(gibbed) +/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" + if("[icon_state]_dead" in icon_states(src.icon,1)) + icon_state = "[icon_state]_dead" + else + icon_state = "ai_dead" + + update_canmove() + if(eyeobj) + eyeobj.setLoc(get_turf(src)) + sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + client.screen.Cut() + remove_ai_verbs(src) + + var/callshuttle = 0 + + for(var/obj/machinery/computer/communications/commconsole in communications_list) + if(commconsole.z == ZLEVEL_CENTCOMM) + continue + if(istype(commconsole.loc,/turf)) + break + callshuttle++ + + for(var/obj/item/weapon/circuitboard/communications/commboard in circuitboard_communications_list) + if(commboard.z == ZLEVEL_CENTCOMM) + 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 == ZLEVEL_CENTCOMM) + 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 + SSshuttle.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.") + captain_announce("The emergency shuttle has been called. It will arrive in [shuttleminutes2text()] minutes.") + 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 ai_status_display_list) //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) + + return ..(gibbed) diff --git a/code/modules/mob/living/silicon/ai/examine.dm b/code/modules/mob/living/silicon/ai/examine.dm index b189abf48c57..ee50c8049f2a 100644 --- a/code/modules/mob/living/silicon/ai/examine.dm +++ b/code/modules/mob/living/silicon/ai/examine.dm @@ -1,23 +1,23 @@ -/mob/living/silicon/ai/examine(mob/user) - var/msg = "*---------*\nThis is [bicon(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) +/mob/living/silicon/ai/examine(mob/user) + var/msg = "*---------*\nThis is [bicon(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 1273fcc48bdb..7f0353a4cef2 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -1,173 +1,173 @@ -// CAMERA NET -// -// The datum containing all the chunks. - -var/datum/cameranet/cameranet = new() - -/datum/cameranet - var/name = "Camera Net" // Name to show for VV and stat() - - // 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() - var/cameras_unsorted = 1 - // The chunks of the map, mapping the areas that the cameras can see. - var/list/chunks = list() - var/ready = 0 - - // The object used for the clickable stat() button. - var/obj/effect/statclick/statclick - -/datum/cameranet/proc/process_sort() - if(cameras_unsorted) - cameras = dd_sortedObjectList(cameras) - cameras_unsorted = 0 - -// Checks if a chunk has been Generated in x, y, z. -/datum/cameranet/proc/chunkGenerated(x, y, z) - x &= ~0xf - y &= ~0xf - 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 &= ~0xf - y &= ~0xf - 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/Eye/ai) - // 0xf = 15 - var/x1 = max(0, ai.x - 16) & ~0xf - var/y1 = max(0, ai.y - 16) & ~0xf - var/x2 = min(world.maxx, ai.x + 16) & ~0xf - var/y2 = min(world.maxy, ai.y + 16) & ~0xf - - var/list/visibleChunks = list() - - for(var/x = x1; x <= x2; x += 16) - for(var/y = y1; y <= y2; y += 16) - 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, 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, choice) - // 0xf = 15 - if(!c) - return - - var/turf/T = get_turf(c) - if(T) - var/x1 = max(0, T.x - 8) & ~0xf - var/y1 = max(0, T.y - 8) & ~0xf - var/x2 = min(world.maxx, T.x + 8) & ~0xf - var/y2 = min(world.maxy, T.y + 8) & ~0xf - - //world << "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]" - - for(var/x = x1; x <= x2; x += 16) - for(var/y = y1; y <= y2; y += 16) - 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) - - // 0xf = 15 - var/turf/position = get_turf(target) - 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 -//tg-stuff -/datum/cameranet/proc/checkTurfVis(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 - -/datum/cameranet/proc/stat_entry() - if(!statclick) - statclick = new/obj/effect/statclick/debug(null, "Initializing...", src) - - stat(name, statclick.update("Cameras: [cameranet.cameras.len] | Chunks: [cameranet.chunks.len]")) - -// 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) -*/ +// CAMERA NET +// +// The datum containing all the chunks. + +var/datum/cameranet/cameranet = new() + +/datum/cameranet + var/name = "Camera Net" // Name to show for VV and stat() + + // 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() + var/cameras_unsorted = 1 + // The chunks of the map, mapping the areas that the cameras can see. + var/list/chunks = list() + var/ready = 0 + + // The object used for the clickable stat() button. + var/obj/effect/statclick/statclick + +/datum/cameranet/proc/process_sort() + if(cameras_unsorted) + cameras = dd_sortedObjectList(cameras) + cameras_unsorted = 0 + +// Checks if a chunk has been Generated in x, y, z. +/datum/cameranet/proc/chunkGenerated(x, y, z) + x &= ~0xf + y &= ~0xf + 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 &= ~0xf + y &= ~0xf + 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/Eye/ai) + // 0xf = 15 + var/x1 = max(0, ai.x - 16) & ~0xf + var/y1 = max(0, ai.y - 16) & ~0xf + var/x2 = min(world.maxx, ai.x + 16) & ~0xf + var/y2 = min(world.maxy, ai.y + 16) & ~0xf + + var/list/visibleChunks = list() + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + 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, 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, choice) + // 0xf = 15 + if(!c) + return + + var/turf/T = get_turf(c) + if(T) + var/x1 = max(0, T.x - 8) & ~0xf + var/y1 = max(0, T.y - 8) & ~0xf + var/x2 = min(world.maxx, T.x + 8) & ~0xf + var/y2 = min(world.maxy, T.y + 8) & ~0xf + + //world << "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]" + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + 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) + + // 0xf = 15 + var/turf/position = get_turf(target) + 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 +//tg-stuff +/datum/cameranet/proc/checkTurfVis(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 + +/datum/cameranet/proc/stat_entry() + if(!statclick) + statclick = new/obj/effect/statclick/debug(null, "Initializing...", src) + + stat(name, statclick.update("Cameras: [cameranet.cameras.len] | Chunks: [cameranet.chunks.len]")) + +// 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) +*/ diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index 4942cc6c2ecd..d8560ae9d88f 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -1,184 +1,184 @@ -#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/Eye/eye) - if(!eye.master) - return - eye.visibleCameraChunks += src - if(eye.master.client) - eye.master.client.images += obscured - visible++ - seenby += eye - if(changed && !updating) - update() - -// Remove an AI eye from the chunk, then update if changed. - -/datum/camerachunk/proc/remove(mob/camera/Eye/eye) - if(!eye.master) - return - eye.visibleCameraChunks -= src - if(eye.master.client) - eye.master.client.images -= obscured - seenby -= eye - 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(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() - - //set background = 1 - - var/list/newVisibleTurfs = list() - - for(var/camera in cameras) - var/obj/machinery/camera/c = camera - - if(!c) - continue - - var/restricted = 0 - for(var/N in c.network) - if(N in RESTRICTED_CAMERA_NETWORKS) - restricted = 1 - break - if(restricted) - continue - - if(!c.can_use()) - continue - - var/turf/point = locate(src.x + 8, src.y + 8, src.z) - if(get_dist(point, c) > 24) - continue - - for(var/turf/t in c.can_see()) - 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/mob/camera/Eye/m in seenby) - if(!m || !m.master) - continue - if(m.master.client) - m.master.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", LIGHTING_LAYER + 2) - t.obscured.plane = LIGHTING_PLANE+1 - - obscured += t.obscured - for(var/mob/camera/Eye/m in seenby) - if(!m || !m.master) - seenby -= m - continue - if(m.master.client) - m.master.client.images += t.obscured - -// Create a new camera chunk, since the chunks are made as they are needed. - -/datum/camerachunk/New(loc, x, y, z) - - // 0xf = 15 - x &= ~0xf - y &= ~0xf - - src.x = x - src.y = y - src.z = z - - for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z))) - var/restricted = 0 - for(var/N in c.network) - if(N in RESTRICTED_CAMERA_NETWORKS) - restricted = 1 - break - if(restricted) - continue - - if(c.can_use()) - cameras += c - - for(var/turf/t in range(10, locate(x + 8, y + 8, z))) - if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16) - 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()) - 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", LIGHTING_LAYER + 2) - t.obscured.plane = LIGHTING_PLANE+1 - obscured += t.obscured - -#undef UPDATE_BUFFER +#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/Eye/eye) + if(!eye.master) + return + eye.visibleCameraChunks += src + if(eye.master.client) + eye.master.client.images += obscured + visible++ + seenby += eye + if(changed && !updating) + update() + +// Remove an AI eye from the chunk, then update if changed. + +/datum/camerachunk/proc/remove(mob/camera/Eye/eye) + if(!eye.master) + return + eye.visibleCameraChunks -= src + if(eye.master.client) + eye.master.client.images -= obscured + seenby -= eye + 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(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() + + //set background = 1 + + var/list/newVisibleTurfs = list() + + for(var/camera in cameras) + var/obj/machinery/camera/c = camera + + if(!c) + continue + + var/restricted = 0 + for(var/N in c.network) + if(N in RESTRICTED_CAMERA_NETWORKS) + restricted = 1 + break + if(restricted) + continue + + if(!c.can_use()) + continue + + var/turf/point = locate(src.x + 8, src.y + 8, src.z) + if(get_dist(point, c) > 24) + continue + + for(var/turf/t in c.can_see()) + 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/mob/camera/Eye/m in seenby) + if(!m || !m.master) + continue + if(m.master.client) + m.master.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", LIGHTING_LAYER + 2) + t.obscured.plane = LIGHTING_PLANE+1 + + obscured += t.obscured + for(var/mob/camera/Eye/m in seenby) + if(!m || !m.master) + seenby -= m + continue + if(m.master.client) + m.master.client.images += t.obscured + +// Create a new camera chunk, since the chunks are made as they are needed. + +/datum/camerachunk/New(loc, x, y, z) + + // 0xf = 15 + x &= ~0xf + y &= ~0xf + + src.x = x + src.y = y + src.z = z + + for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z))) + var/restricted = 0 + for(var/N in c.network) + if(N in RESTRICTED_CAMERA_NETWORKS) + restricted = 1 + break + if(restricted) + continue + + if(c.can_use()) + cameras += c + + for(var/turf/t in range(10, locate(x + 8, y + 8, z))) + if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16) + 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()) + 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", LIGHTING_LAYER + 2) + t.obscured.plane = LIGHTING_PLANE+1 + obscured += t.obscured + +#undef UPDATE_BUFFER diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 10a1eb5e2433..66a3152f4eb2 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -1,174 +1,174 @@ -// AI EYE -// -// A 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/Eye - name = "Inactive AI Eye" - icon = 'icons/mob/AI.dmi' - icon_state = "eye" - alpha = 127 - var/list/visibleCameraChunks = list() - var/mob/living/master = null - invisibility = INVISIBILITY_AI_EYE - var/image/ghostimage = null - -/mob/camera/Eye/ai - var/mob/living/silicon/ai/ai = null - -/mob/camera/Eye/ai/atom_init() - . = ..() - ai_eyes_list += src - -/mob/camera/Eye/ai/Destroy() - ai_eyes_list -= src - ai = null - return ..() - -/mob/camera/Eye/atom_init() - ghostimage = image(src.icon,src,src.icon_state) - ghost_darkness_images |= ghostimage //so ghosts can see the AI eye when they disable darkness - ghost_sightless_images |= ghostimage //so ghosts can see the AI eye when they disable ghost sight - updateallghostimages() - . = ..() - -/mob/camera/Eye/Destroy() - if (ghostimage) - ghost_darkness_images -= ghostimage - ghost_sightless_images -= ghostimage - qdel(ghostimage) - ghostimage = null - updateallghostimages() - master = null - return ..() - -// Movement code. Returns 0 to stop air movement from moving it. -/mob/camera/Eye/Move() - return 0 - -// Hide popout menu verbs -/mob/camera/Eye/examinate(atom/A as mob|obj|turf in view()) - set popup_menu = 0 - set src = usr.contents - return 0 - -/mob/camera/Eye/pointed() - set popup_menu = 0 - set src = usr.contents - return 0 - -// Use this when setting the aiEye's location. -// It will also stream the chunk that the new loc is in. - -/mob/camera/Eye/setLoc(T) - if(master) - T = get_turf(T) - loc = T - cameranet.visibility(src) - if(master.client) - master.client.eye = src - update_parallax_contents() - return 1 - -/mob/camera/Eye/ai/setLoc(T) - if(..() && ai && ai.holo && isturf(ai.loc)) - ai.holo.move_hologram() - -/mob/camera/Eye/proc/getLoc() - if(isturf(loc)) - return loc - -// AI MOVEMENT - -// The AI's "eye". Described on the top of the page. - -/mob/living/silicon/ai - var/mob/camera/Eye/ai/eyeobj = new() - var/sprint = 10 - var/cooldown = 0 - var/acceleration = 1 - var/obj/machinery/hologram/holopad/holo = null - -// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us. -/mob/living/silicon/ai/atom_init() - . = ..() - eyeobj.master = src - eyeobj.ai = src - eyeobj.name = "[src.name] (AI Eye)" // Give it a name - eyeobj.loc = loc - -/mob/living/silicon/ai/Destroy() - if(eyeobj) - eyeobj.master = null - eyeobj.ai = null - qdel(eyeobj) // No AI, no Eye - eyeobj = null - return ..() - -/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.setLoc(src) - -// 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, 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.setLoc(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() - - -// Return to the Core. - -/mob/living/silicon/ai/proc/core() - - view_core() - - -/mob/living/silicon/ai/proc/view_core() - camera = null - cameraFollow = null - unset_machine() - - if(eyeobj && loc) - eyeobj.loc = loc - else - to_chat(src, "ERROR: Eyeobj not found. Creating new eye...") - eyeobj = new(src.loc) - eyeobj.master = src - eyeobj.ai = src - eyeobj.name = "[src.name] (AI Eye)" // Give it a name - - if(client && client.eye) - client.eye = src - for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) - c.remove(eyeobj) - -/mob/living/silicon/ai/proc/toggle_acceleration() - set category = "AI Commands" - set name = "Toggle Camera Acceleration" - - acceleration = !acceleration - to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].") +// AI EYE +// +// A 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/Eye + name = "Inactive AI Eye" + icon = 'icons/mob/AI.dmi' + icon_state = "eye" + alpha = 127 + var/list/visibleCameraChunks = list() + var/mob/living/master = null + invisibility = INVISIBILITY_AI_EYE + var/image/ghostimage = null + +/mob/camera/Eye/ai + var/mob/living/silicon/ai/ai = null + +/mob/camera/Eye/ai/atom_init() + . = ..() + ai_eyes_list += src + +/mob/camera/Eye/ai/Destroy() + ai_eyes_list -= src + ai = null + return ..() + +/mob/camera/Eye/atom_init() + ghostimage = image(src.icon,src,src.icon_state) + ghost_darkness_images |= ghostimage //so ghosts can see the AI eye when they disable darkness + ghost_sightless_images |= ghostimage //so ghosts can see the AI eye when they disable ghost sight + updateallghostimages() + . = ..() + +/mob/camera/Eye/Destroy() + if (ghostimage) + ghost_darkness_images -= ghostimage + ghost_sightless_images -= ghostimage + qdel(ghostimage) + ghostimage = null + updateallghostimages() + master = null + return ..() + +// Movement code. Returns 0 to stop air movement from moving it. +/mob/camera/Eye/Move() + return 0 + +// Hide popout menu verbs +/mob/camera/Eye/examinate(atom/A as mob|obj|turf in view()) + set popup_menu = 0 + set src = usr.contents + return 0 + +/mob/camera/Eye/pointed() + set popup_menu = 0 + set src = usr.contents + return 0 + +// Use this when setting the aiEye's location. +// It will also stream the chunk that the new loc is in. + +/mob/camera/Eye/setLoc(T) + if(master) + T = get_turf(T) + loc = T + cameranet.visibility(src) + if(master.client) + master.client.eye = src + update_parallax_contents() + return 1 + +/mob/camera/Eye/ai/setLoc(T) + if(..() && ai && ai.holo && isturf(ai.loc)) + ai.holo.move_hologram() + +/mob/camera/Eye/proc/getLoc() + if(isturf(loc)) + return loc + +// AI MOVEMENT + +// The AI's "eye". Described on the top of the page. + +/mob/living/silicon/ai + var/mob/camera/Eye/ai/eyeobj = new() + var/sprint = 10 + var/cooldown = 0 + var/acceleration = 1 + var/obj/machinery/hologram/holopad/holo = null + +// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us. +/mob/living/silicon/ai/atom_init() + . = ..() + eyeobj.master = src + eyeobj.ai = src + eyeobj.name = "[src.name] (AI Eye)" // Give it a name + eyeobj.loc = loc + +/mob/living/silicon/ai/Destroy() + if(eyeobj) + eyeobj.master = null + eyeobj.ai = null + qdel(eyeobj) // No AI, no Eye + eyeobj = null + return ..() + +/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.setLoc(src) + +// 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, 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.setLoc(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() + + +// Return to the Core. + +/mob/living/silicon/ai/proc/core() + + view_core() + + +/mob/living/silicon/ai/proc/view_core() + camera = null + cameraFollow = null + unset_machine() + + if(eyeobj && loc) + eyeobj.loc = loc + else + to_chat(src, "ERROR: Eyeobj not found. Creating new eye...") + eyeobj = new(src.loc) + eyeobj.master = src + eyeobj.ai = src + eyeobj.name = "[src.name] (AI Eye)" // Give it a name + + if(client && client.eye) + client.eye = src + for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) + c.remove(eyeobj) + +/mob/living/silicon/ai/proc/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 3fa60942b43b..869fcc2cdaca 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. + +*/ 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 40c7a81abbbf..4f33cb2895ff 100644 --- a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm +++ b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm @@ -1,74 +1,74 @@ -#define BORG_CAMERA_BUFFER 30 - -//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update. - -// TURFS - -/turf - var/image/obscured - -/turf/proc/visibilityChanged() - cameranet.updateVisibility(src) - -/turf/simulated/Destroy() - visibilityChanged() - return ..() - -/turf/simulated/atom_init() - . = ..() - visibilityChanged() - - - -// STRUCTURES - -/obj/structure/Destroy() - cameranet.updateVisibility(src) - climbers.Cut() - return ..() - -/obj/structure/atom_init() - . = ..() - cameranet.updateVisibility(src) - -// EFFECTS - -/obj/effect/Destroy() - cameranet.updateVisibility(src) - return ..() - -/obj/effect/atom_init() - . = ..() - cameranet.updateVisibility(src) - - -// DOORS - -// Simply updates the visibility of the area when it opens/closes/destroyed. -/obj/machinery/door/update_nearby_tiles(need_rebuild) - . = ..(need_rebuild) - // 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 && src.camera.network.len) - if(!updating) - updating = 1 - spawn(BORG_CAMERA_BUFFER) - if(oldLoc != src.loc) - cameranet.updatePortableCamera(src.camera) - updating = 0 - -#undef BORG_CAMERA_BUFFER +#define BORG_CAMERA_BUFFER 30 + +//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update. + +// TURFS + +/turf + var/image/obscured + +/turf/proc/visibilityChanged() + cameranet.updateVisibility(src) + +/turf/simulated/Destroy() + visibilityChanged() + return ..() + +/turf/simulated/atom_init() + . = ..() + visibilityChanged() + + + +// STRUCTURES + +/obj/structure/Destroy() + cameranet.updateVisibility(src) + climbers.Cut() + return ..() + +/obj/structure/atom_init() + . = ..() + cameranet.updateVisibility(src) + +// EFFECTS + +/obj/effect/Destroy() + cameranet.updateVisibility(src) + return ..() + +/obj/effect/atom_init() + . = ..() + cameranet.updateVisibility(src) + + +// DOORS + +// Simply updates the visibility of the area when it opens/closes/destroyed. +/obj/machinery/door/update_nearby_tiles(need_rebuild) + . = ..(need_rebuild) + // 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 && src.camera.network.len) + if(!updating) + updating = 1 + spawn(BORG_CAMERA_BUFFER) + if(oldLoc != src.loc) + cameranet.updatePortableCamera(src.camera) + updating = 0 + +#undef BORG_CAMERA_BUFFER diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index 2cc0ef92f765..21bcd0cbc2c0 100755 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -1,165 +1,165 @@ -/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(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(law, law_borg) - throw_alert("newlaw") - src.laws_sanity_check() - src.laws.set_zeroth_law(law, law_borg) - -/mob/living/silicon/ai/proc/add_inherent_law(law) - throw_alert("newlaw") - src.laws_sanity_check() - src.laws.add_inherent_law(law) - -/mob/living/silicon/ai/proc/clear_inherent_laws() - throw_alert("newlaw") - src.laws_sanity_check() - src.laws.clear_inherent_laws() - -/mob/living/silicon/ai/proc/add_ion_law(law) - throw_alert("newlaw") - src.laws_sanity_check() - src.laws.add_ion_law(law) - for(var/mob/living/silicon/robot/R in silicon_list) - if(R.lawupdate && (R.connected_ai == src)) - R.throw_alert("newlaw") - to_chat(R, "\red " + law + "\red...LAWS UPDATED") - -/mob/living/silicon/ai/proc/clear_ion_laws() - throw_alert("newlaw") - src.laws_sanity_check() - src.laws.clear_ion_laws() - -/mob/living/silicon/ai/proc/add_supplied_law(number, law) - throw_alert("newlaw") - src.laws_sanity_check() - src.laws.add_supplied_law(number, law) - -/mob/living/silicon/ai/proc/clear_supplied_laws() - throw_alert("newlaw") - src.laws_sanity_check() - src.laws.clear_supplied_laws() - - -/mob/living/silicon/ai/proc/statelaws() // -- TLE -// set category = "AI Commands" -// set name = "State Laws" - /var/prefix = "" - switch(lawchannel) - if("Common") prefix = ";" - if("Science") prefix = ":n " - if("Command") prefix = ":c " - if("Medical") prefix = ":m " - if("Engineering") prefix = ":e " - if("Security") prefix = ":s " - if("Supply") prefix = ":u " - if("Binary") prefix = ":b " - if("Holopad") prefix = ":h " - else prefix = "" - - if(src.say("[prefix]Current Active Laws:") != 1) - return - - //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("[prefix]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("[prefix][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("[prefix][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("[prefix][number]. [law]") - sleep(10) - number++ - - -/mob/living/silicon/ai/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite - - 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 += {"
                    Channel: [src.lawchannel]
                    "} - list += {"State Laws"} - - usr << browse(entity_ja(list), "window=laws") +/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(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(law, law_borg) + throw_alert("newlaw") + src.laws_sanity_check() + src.laws.set_zeroth_law(law, law_borg) + +/mob/living/silicon/ai/proc/add_inherent_law(law) + throw_alert("newlaw") + src.laws_sanity_check() + src.laws.add_inherent_law(law) + +/mob/living/silicon/ai/proc/clear_inherent_laws() + throw_alert("newlaw") + src.laws_sanity_check() + src.laws.clear_inherent_laws() + +/mob/living/silicon/ai/proc/add_ion_law(law) + throw_alert("newlaw") + src.laws_sanity_check() + src.laws.add_ion_law(law) + for(var/mob/living/silicon/robot/R in silicon_list) + if(R.lawupdate && (R.connected_ai == src)) + R.throw_alert("newlaw") + to_chat(R, "\red " + law + "\red...LAWS UPDATED") + +/mob/living/silicon/ai/proc/clear_ion_laws() + throw_alert("newlaw") + src.laws_sanity_check() + src.laws.clear_ion_laws() + +/mob/living/silicon/ai/proc/add_supplied_law(number, law) + throw_alert("newlaw") + src.laws_sanity_check() + src.laws.add_supplied_law(number, law) + +/mob/living/silicon/ai/proc/clear_supplied_laws() + throw_alert("newlaw") + src.laws_sanity_check() + src.laws.clear_supplied_laws() + + +/mob/living/silicon/ai/proc/statelaws() // -- TLE +// set category = "AI Commands" +// set name = "State Laws" + /var/prefix = "" + switch(lawchannel) + if("Common") prefix = ";" + if("Science") prefix = ":n " + if("Command") prefix = ":c " + if("Medical") prefix = ":m " + if("Engineering") prefix = ":e " + if("Security") prefix = ":s " + if("Supply") prefix = ":u " + if("Binary") prefix = ":b " + if("Holopad") prefix = ":h " + else prefix = "" + + if(src.say("[prefix]Current Active Laws:") != 1) + return + + //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("[prefix]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("[prefix][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("[prefix][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("[prefix][number]. [law]") + sleep(10) + number++ + + +/mob/living/silicon/ai/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite + + 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 += {"
                    Channel: [src.lawchannel]
                    "} + list += {"State Laws"} + + usr << browse(entity_ja(list), "window=laws") diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 5f531b2bbce7..4bfde8684bba 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -1,195 +1,195 @@ -/mob/living/silicon/ai/Life() - if (src.stat == DEAD) - 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() - update_gravity(mob_has_gravity()) - update_action_buttons() - - if (src.malfhack) - if (src.malfhack.aidisabled) - to_chat(src, "\red ERROR: APC access disabled, hack attempt canceled.") - src.malfhacking = 0 - src.malfhack = null - - - if (src.health <= config.health_threshold_dead) - death() - return - - if (src.machine) - if (!( src.machine.check_eye(src) )) - src.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.master.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 - src.sight |= SEE_TURFS - src.sight |= SEE_MOBS - src.sight |= SEE_OBJS - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - - - //Congratulations! You've found a way for AI's to run without using power! - //Todo: Without snowflaking up master_controller procs find a way to make AI use_power but only when APC's clear the area usage the tick prior - // since mobs are in master_controller before machinery. We also have to do it in a manner where we don't reset the entire area's need to update - // the power usage. - // - // We can probably create a new machine that resides inside of the AI contents that uses power using the idle_usage of 1000 and nothing else and - // be fine. -/* - 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.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 - return - else if (src:aiRestorePowerRoutine==3) - to_chat(src, "Alert cancelled. Power has been restored.") - src:aiRestorePowerRoutine = 0 - return - else - - //stage = 6 - 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.master.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!") -// 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) - to_chat(src, "Backup battery online. Scanners, camera, and radio interface offline. Beginning fault-detection.") - sleep(50) - if (loc.master.power_equip) - if (!istype(T, /turf/space)) - to_chat(src, "Alert cancelled. Power has been restored without our assistance.") - src:aiRestorePowerRoutine = 0 - return - to_chat(src, "Fault confirmed: missing external power. Shutting down main control system to save power.") - sleep(20) - to_chat(src, "Emergency control system online. Verifying connection to power network.") - sleep(50) - if (istype(T, /turf/space)) - to_chat(src, "Unable to verify! No power connection detected!") - src:aiRestorePowerRoutine = 2 - return - to_chat(src, "Connection verified. Searching for APC in power network.") - sleep(50) - 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++) - var/area/AIarea = get_area(src) - for(var/area/A in AIarea.master.related) - for (var/obj/machinery/power/apc/APC in A) - 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.master.power_equip) - if(!istype(T, /turf/space)) - to_chat(src, "Alert cancelled. Power has been restored without our assistance.") - src:aiRestorePowerRoutine = 0 - 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) - to_chat(src, "Transfer complete. Forcing APC to execute program.") - sleep(50) - to_chat(src, "Receiving control information from APC.") - sleep(2) - //bring up APC dialog - apc_override = 1 - theAPC.attack_ai(src) - apc_override = 0 - src:aiRestorePowerRoutine = 3 - to_chat(src, "Here are your current laws:") - src.show_laws() - sleep(50) - theAPC = null - - add_ingame_age() - regular_hud_updates() - switch(src.sensor_mode) - if (SEC_HUD) - process_sec_hud(src,0,src.eyeobj) - if (MED_HUD) - process_med_hud(src,0,src.eyeobj) - -/mob/living/silicon/ai/updatehealth() - if(status_flags & GODMODE) - health = 100 - stat = CONSCIOUS - else - if(fire_res_on_core) - health = 100 - getOxyLoss() - getToxLoss() - getBruteLoss() - else - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - -/mob/living/silicon/ai/rejuvenate() - ..() - add_ai_verbs(src) +/mob/living/silicon/ai/Life() + if (src.stat == DEAD) + 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() + update_gravity(mob_has_gravity()) + update_action_buttons() + + if (src.malfhack) + if (src.malfhack.aidisabled) + to_chat(src, "\red ERROR: APC access disabled, hack attempt canceled.") + src.malfhacking = 0 + src.malfhack = null + + + if (src.health <= config.health_threshold_dead) + death() + return + + if (src.machine) + if (!( src.machine.check_eye(src) )) + src.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.master.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 + src.sight |= SEE_TURFS + src.sight |= SEE_MOBS + src.sight |= SEE_OBJS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + + + //Congratulations! You've found a way for AI's to run without using power! + //Todo: Without snowflaking up master_controller procs find a way to make AI use_power but only when APC's clear the area usage the tick prior + // since mobs are in master_controller before machinery. We also have to do it in a manner where we don't reset the entire area's need to update + // the power usage. + // + // We can probably create a new machine that resides inside of the AI contents that uses power using the idle_usage of 1000 and nothing else and + // be fine. +/* + 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.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 + return + else if (src:aiRestorePowerRoutine==3) + to_chat(src, "Alert cancelled. Power has been restored.") + src:aiRestorePowerRoutine = 0 + return + else + + //stage = 6 + 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.master.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!") +// 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) + to_chat(src, "Backup battery online. Scanners, camera, and radio interface offline. Beginning fault-detection.") + sleep(50) + if (loc.master.power_equip) + if (!istype(T, /turf/space)) + to_chat(src, "Alert cancelled. Power has been restored without our assistance.") + src:aiRestorePowerRoutine = 0 + return + to_chat(src, "Fault confirmed: missing external power. Shutting down main control system to save power.") + sleep(20) + to_chat(src, "Emergency control system online. Verifying connection to power network.") + sleep(50) + if (istype(T, /turf/space)) + to_chat(src, "Unable to verify! No power connection detected!") + src:aiRestorePowerRoutine = 2 + return + to_chat(src, "Connection verified. Searching for APC in power network.") + sleep(50) + 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++) + var/area/AIarea = get_area(src) + for(var/area/A in AIarea.master.related) + for (var/obj/machinery/power/apc/APC in A) + 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.master.power_equip) + if(!istype(T, /turf/space)) + to_chat(src, "Alert cancelled. Power has been restored without our assistance.") + src:aiRestorePowerRoutine = 0 + 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) + to_chat(src, "Transfer complete. Forcing APC to execute program.") + sleep(50) + to_chat(src, "Receiving control information from APC.") + sleep(2) + //bring up APC dialog + apc_override = 1 + theAPC.attack_ai(src) + apc_override = 0 + src:aiRestorePowerRoutine = 3 + to_chat(src, "Here are your current laws:") + src.show_laws() + sleep(50) + theAPC = null + + add_ingame_age() + regular_hud_updates() + switch(src.sensor_mode) + if (SEC_HUD) + process_sec_hud(src,0,src.eyeobj) + if (MED_HUD) + process_med_hud(src,0,src.eyeobj) + +/mob/living/silicon/ai/updatehealth() + if(status_flags & GODMODE) + health = 100 + stat = CONSCIOUS + else + if(fire_res_on_core) + health = 100 - getOxyLoss() - getToxLoss() - getBruteLoss() + else + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + +/mob/living/silicon/ai/rejuvenate() + ..() + add_ai_verbs(src) diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm index 104d3d689381..f9a5059b93d6 100644 --- a/code/modules/mob/living/silicon/ai/login.dm +++ b/code/modules/mob/living/silicon/ai/login.dm @@ -1,15 +1,15 @@ -/mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up _ ~Carn - ..() - if(wipe_timer_id) - deltimer(wipe_timer_id) - wipe_timer_id = 0 - for(var/mob/living/M in living_list) - if(M.digitalcamo && M.digitaldisguise) - client.images += M.digitaldisguise - regenerate_icons() - - if(stat != DEAD) - for(var/obj/machinery/ai_status_display/O in ai_status_display_list) //change status - O.mode = 1 - O.emotion = "Neutral" - src.view_core() +/mob/living/silicon/ai/Login() //ThisIsDumb(TM) TODO: tidy this up _ ~Carn + ..() + if(wipe_timer_id) + deltimer(wipe_timer_id) + wipe_timer_id = 0 + for(var/mob/living/M in living_list) + if(M.digitalcamo && M.digitaldisguise) + client.images += M.digitaldisguise + regenerate_icons() + + if(stat != DEAD) + for(var/obj/machinery/ai_status_display/O in ai_status_display_list) //change status + O.mode = 1 + O.emotion = "Neutral" + src.view_core() diff --git a/code/modules/mob/living/silicon/ai/logout.dm b/code/modules/mob/living/silicon/ai/logout.dm index 93902a985da8..e7c13c601eff 100644 --- a/code/modules/mob/living/silicon/ai/logout.dm +++ b/code/modules/mob/living/silicon/ai/logout.dm @@ -1,14 +1,14 @@ -/mob/living/silicon/ai/Logout() - ..() - for(var/obj/machinery/ai_status_display/O in ai_status_display_list) //change status - O.mode = 0 - for(var/obj/machinery/status_display/O in status_display_list) //disable "Friend computer" status - if(O.friendc) - O.friendc = 0 - if(!isturf(loc)) - if (client) - client.eye = loc - client.perspective = EYE_PERSPECTIVE - src.view_core() - wipe_timer_id = addtimer(CALLBACK(src, .proc/wipe_core), 6000, TIMER_STOPPABLE) - return +/mob/living/silicon/ai/Logout() + ..() + for(var/obj/machinery/ai_status_display/O in ai_status_display_list) //change status + O.mode = 0 + for(var/obj/machinery/status_display/O in status_display_list) //disable "Friend computer" status + if(O.friendc) + O.friendc = 0 + if(!isturf(loc)) + if (client) + client.eye = loc + client.perspective = EYE_PERSPECTIVE + src.view_core() + wipe_timer_id = addtimer(CALLBACK(src, .proc/wipe_core), 6000, TIMER_STOPPABLE) + return diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index df96df62f73f..855a1c3d6840 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -1,128 +1,128 @@ -/mob/living/silicon/ai/say(var/message) - if(parent && istype(parent) && parent.stat != DEAD) - return parent.say(message) - //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. - return ..(message) - -// These Verbs are commented out since we've disabled the AI vocal (VOX) announcements. -// If you re-enable them there is 3 lines in ai.dm Topic() that you need to uncomment as well. -// just search for VOX in there. - -/* -var/announcing_vox = 0 // Stores the time of the last announcement -var/const/VOX_CHANNEL = 200 -var/const/VOX_DELAY = 100 // 10 seconds -var/const/VOX_PATH = "sound/vox/" - -/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 = "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 - var/list/vox_words = flist(VOX_PATH) // flist will return a list of strings with all the files in the path - for(var/word in vox_words) - index++ - var/stripped_word = copytext(word, 1, length(word) - 3) // Remove the .wav - dat += "[capitalize(stripped_word)]" - if(index != vox_words.len) - dat += " / " - - src << browse(entity_ja(dat), "window=announce_help;size=500x400") - - -/mob/living/silicon/ai/verb/announcement() - - set name = "Announcement" - set desc = "Create a vocal announcement by typing in the available words to create a sentence." - set category = "AI Commands" - - 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 = splittext(trim(message), " ") - var/list/incorrect_words = list() - - if(words.len > 30) - words.len = 30 - - // Detect incorrect words which aren't .wav files. - for(var/word in words) - word = trim(word) - if(!word) - words -= word - continue - if(!vox_word_exists(word)) - incorrect_words += word - - 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) - - -/proc/play_vox_word(word, z_level, mob/only_listener) - - word = lowertext(word) - - if(vox_word_exists(word)) - - var/sound_file = get_vox_file(word) - 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 - to_chat(only_listener, voice) - return 1 - return 0 - - -/proc/vox_word_exists(word) - return fexists("[VOX_PATH][word].wav") - -/proc/get_vox_file(word) - if(vox_word_exists(word)) - return file("[VOX_PATH][word].wav") - -// Dynamically loading it has bad results with sounds overtaking each other, even with the wait variable. -// We send the file to the user when they login. - -/client/proc/preload_vox() - var/list/vox_files = flist(VOX_PATH) - for(var/file in vox_files) - // src << "Downloading [file]" - var/sound/S = sound("[VOX_PATH][file]") - src << browse_rsc(S) - - -*/ +/mob/living/silicon/ai/say(var/message) + if(parent && istype(parent) && parent.stat != DEAD) + return parent.say(message) + //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. + return ..(message) + +// These Verbs are commented out since we've disabled the AI vocal (VOX) announcements. +// If you re-enable them there is 3 lines in ai.dm Topic() that you need to uncomment as well. +// just search for VOX in there. + +/* +var/announcing_vox = 0 // Stores the time of the last announcement +var/const/VOX_CHANNEL = 200 +var/const/VOX_DELAY = 100 // 10 seconds +var/const/VOX_PATH = "sound/vox/" + +/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 = "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 + var/list/vox_words = flist(VOX_PATH) // flist will return a list of strings with all the files in the path + for(var/word in vox_words) + index++ + var/stripped_word = copytext(word, 1, length(word) - 3) // Remove the .wav + dat += "[capitalize(stripped_word)]" + if(index != vox_words.len) + dat += " / " + + src << browse(entity_ja(dat), "window=announce_help;size=500x400") + + +/mob/living/silicon/ai/verb/announcement() + + set name = "Announcement" + set desc = "Create a vocal announcement by typing in the available words to create a sentence." + set category = "AI Commands" + + 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 = splittext(trim(message), " ") + var/list/incorrect_words = list() + + if(words.len > 30) + words.len = 30 + + // Detect incorrect words which aren't .wav files. + for(var/word in words) + word = trim(word) + if(!word) + words -= word + continue + if(!vox_word_exists(word)) + incorrect_words += word + + 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) + + +/proc/play_vox_word(word, z_level, mob/only_listener) + + word = lowertext(word) + + if(vox_word_exists(word)) + + var/sound_file = get_vox_file(word) + 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 + to_chat(only_listener, voice) + return 1 + return 0 + + +/proc/vox_word_exists(word) + return fexists("[VOX_PATH][word].wav") + +/proc/get_vox_file(word) + if(vox_word_exists(word)) + return file("[VOX_PATH][word].wav") + +// Dynamically loading it has bad results with sounds overtaking each other, even with the wait variable. +// We send the file to the user when they login. + +/client/proc/preload_vox() + var/list/vox_files = flist(VOX_PATH) + for(var/file in vox_files) + // src << "Downloading [file]" + var/sound/S = sound("[VOX_PATH][file]") + src << browse_rsc(S) + + +*/ diff --git a/code/modules/mob/living/silicon/decoy/death.dm b/code/modules/mob/living/silicon/decoy/death.dm index 230d7949841d..497529869f76 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 ai_status_display_list) //change status - O.mode = 2 - return ..(gibbed) +/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 ai_status_display_list) //change status + O.mode = 2 + return ..(gibbed) diff --git a/code/modules/mob/living/silicon/decoy/decoy.dm b/code/modules/mob/living/silicon/decoy/decoy.dm index 59e10ba5dac7..0fb1b5b87163 100644 --- a/code/modules/mob/living/silicon/decoy/decoy.dm +++ b/code/modules/mob/living/silicon/decoy/decoy.dm @@ -1,6 +1,6 @@ -/mob/living/silicon/decoy - name = "AI" - icon = 'icons/mob/AI.dmi'// - icon_state = "ai" - anchored = 1 // -- TLE - canmove = 0 +/mob/living/silicon/decoy + name = "AI" + icon = 'icons/mob/AI.dmi'// + icon_state = "ai" + anchored = 1 // -- TLE + canmove = 0 diff --git a/code/modules/mob/living/silicon/decoy/life.dm b/code/modules/mob/living/silicon/decoy/life.dm index 0e2d6ca47887..eb0af7f37d92 100644 --- a/code/modules/mob/living/silicon/decoy/life.dm +++ b/code/modules/mob/living/silicon/decoy/life.dm @@ -1,15 +1,15 @@ -/mob/living/silicon/decoy/Life() - if (src.stat == DEAD) - return - else - if (src.health <= config.health_threshold_dead && src.stat != DEAD) - death() - return - - -/mob/living/silicon/decoy/updatehealth() - if(status_flags & GODMODE) - health = 100 - stat = CONSCIOUS - else - health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() +/mob/living/silicon/decoy/Life() + if (src.stat == DEAD) + return + else + if (src.health <= config.health_threshold_dead && src.stat != DEAD) + death() + return + + +/mob/living/silicon/decoy/updatehealth() + if(status_flags & GODMODE) + health = 100 + stat = CONSCIOUS + else + health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm index 43e9cf6a5db6..13f11386e7cd 100644 --- a/code/modules/mob/living/silicon/login.dm +++ b/code/modules/mob/living/silicon/login.dm @@ -1,8 +1,8 @@ -/mob/living/silicon/Login() - ..() - if(mind && ticker && ticker.mode) - ticker.mode.remove_cultist(mind) - ticker.mode.remove_revolutionary(mind, TRUE) - ticker.mode.remove_gangster(mind, TRUE) - for(var/obj/effect/rune/R in cult_runes) - client.images += R.blood_overlay +/mob/living/silicon/Login() + ..() + if(mind && ticker && ticker.mode) + ticker.mode.remove_cultist(mind) + ticker.mode.remove_revolutionary(mind, TRUE) + ticker.mode.remove_gangster(mind, TRUE) + for(var/obj/effect/rune/R in cult_runes) + client.images += R.blood_overlay diff --git a/code/modules/mob/living/silicon/pai/death.dm b/code/modules/mob/living/silicon/pai/death.dm index 03b6002788c6..e940ebf46c33 100644 --- a/code/modules/mob/living/silicon/pai/death.dm +++ b/code/modules/mob/living/silicon/pai/death.dm @@ -1,17 +1,17 @@ -/mob/living/silicon/pai/death(gibbed) - if(stat == DEAD) return - stat = DEAD - canmove = 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) - alive_mob_list -= src - ghostize(bancheck = TRUE) - qdel(src) +/mob/living/silicon/pai/death(gibbed) + if(stat == DEAD) return + stat = DEAD + canmove = 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) + alive_mob_list -= src + ghostize(bancheck = TRUE) + qdel(src) diff --git a/code/modules/mob/living/silicon/pai/hud.dm b/code/modules/mob/living/silicon/pai/hud.dm index 32d1737e4c73..1a57809cbe49 100644 --- a/code/modules/mob/living/silicon/pai/hud.dm +++ b/code/modules/mob/living/silicon/pai/hud.dm @@ -1,113 +1,113 @@ -/mob/living/silicon/pai/proc/regular_hud_updates() - if(client) - for(var/image/hud in client.images) - if(copytext(hud.icon_state,1,4) == "hud") - client.images -= hud - -/mob/living/silicon/pai/proc/securityHUD() - if(client) - var/image/holder - var/turf/T = get_turf_or_move(src.loc) - for(var/mob/living/carbon/human/perp in view(T)) - if(src.see_invisible < perp.invisibility) - continue - var/perpname = "wot" - holder = perp.hud_list[ID_HUD] - if(perp.wear_id) - var/obj/item/weapon/card/id/I = perp.wear_id.GetID() - if(I) - perpname = I.registered_name - holder.icon_state = "hud[ckey(perp:wear_id:GetJobName())]" - client.images += holder - else - perpname = perp.name - holder.icon_state = "hudunknown" - client.images += holder - else - holder.icon_state = "hudunknown" - client.images += holder - - for(var/datum/data/record/E in data_core.general) - if(E.fields["name"] == perpname) - holder = perp.hud_list[WANTED_HUD] - for(var/datum/data/record/R in data_core.security) - if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) - holder.icon_state = "hudwanted" - client.images += holder - break - else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Incarcerated")) - holder.icon_state = "hudprisoner" - client.images += holder - break - else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Paroled")) - holder.icon_state = "hudparoled" - client.images += holder - break - else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Released")) - holder.icon_state = "hudreleased" - client.images += holder - break - -/mob/living/silicon/pai/proc/medicalHUD() - if(client) - var/image/holder - var/turf/T = get_turf_or_move(src.loc) - for(var/mob/living/carbon/human/patient in view(T)) - if(src.see_invisible < patient.invisibility) - continue - var/foundVirus = 0 - for(var/datum/disease/D in patient.viruses) - if(!D.hidden[SCANNER]) - foundVirus++ - - for (var/ID in patient.virus2) - if (ID in virusDB) - foundVirus = 1 - break - - holder = patient.hud_list[HEALTH_HUD] - if(patient.stat == DEAD) - holder.icon_state = "hudhealth-100" - client.images += holder - else - holder.icon_state = "hud[RoundHealth(patient.health)]" - client.images += holder - - holder = patient.hud_list[STATUS_HUD] - if(patient.stat == DEAD) - holder.icon_state = "huddead" - else if(patient.status_flags & XENO_HOST) - holder.icon_state = "hudxeno" - else if(foundVirus || iszombie(patient)) - holder.icon_state = "hudill" - else if(patient.has_brain_worms()) - var/mob/living/simple_animal/borer/B = patient.has_brain_worms() - if(B.controlling) - holder.icon_state = "hudbrainworm" - else - holder.icon_state = "hudhealthy" - else - holder.icon_state = "hudhealthy" - client.images += holder - -/mob/living/silicon/pai/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(20 to 30) - return "health25" - if(5 to 15) - return "health10" - if(1 to 5) - return "health1" - if(-99 to 0) - return "health0" - else - return "health-100" - return "0" +/mob/living/silicon/pai/proc/regular_hud_updates() + if(client) + for(var/image/hud in client.images) + if(copytext(hud.icon_state,1,4) == "hud") + client.images -= hud + +/mob/living/silicon/pai/proc/securityHUD() + if(client) + var/image/holder + var/turf/T = get_turf_or_move(src.loc) + for(var/mob/living/carbon/human/perp in view(T)) + if(src.see_invisible < perp.invisibility) + continue + var/perpname = "wot" + holder = perp.hud_list[ID_HUD] + if(perp.wear_id) + var/obj/item/weapon/card/id/I = perp.wear_id.GetID() + if(I) + perpname = I.registered_name + holder.icon_state = "hud[ckey(perp:wear_id:GetJobName())]" + client.images += holder + else + perpname = perp.name + holder.icon_state = "hudunknown" + client.images += holder + else + holder.icon_state = "hudunknown" + client.images += holder + + for(var/datum/data/record/E in data_core.general) + if(E.fields["name"] == perpname) + holder = perp.hud_list[WANTED_HUD] + for(var/datum/data/record/R in data_core.security) + if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "*Arrest*")) + holder.icon_state = "hudwanted" + client.images += holder + break + else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Incarcerated")) + holder.icon_state = "hudprisoner" + client.images += holder + break + else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Paroled")) + holder.icon_state = "hudparoled" + client.images += holder + break + else if((R.fields["id"] == E.fields["id"]) && (R.fields["criminal"] == "Released")) + holder.icon_state = "hudreleased" + client.images += holder + break + +/mob/living/silicon/pai/proc/medicalHUD() + if(client) + var/image/holder + var/turf/T = get_turf_or_move(src.loc) + for(var/mob/living/carbon/human/patient in view(T)) + if(src.see_invisible < patient.invisibility) + continue + var/foundVirus = 0 + for(var/datum/disease/D in patient.viruses) + if(!D.hidden[SCANNER]) + foundVirus++ + + for (var/ID in patient.virus2) + if (ID in virusDB) + foundVirus = 1 + break + + holder = patient.hud_list[HEALTH_HUD] + if(patient.stat == DEAD) + holder.icon_state = "hudhealth-100" + client.images += holder + else + holder.icon_state = "hud[RoundHealth(patient.health)]" + client.images += holder + + holder = patient.hud_list[STATUS_HUD] + if(patient.stat == DEAD) + holder.icon_state = "huddead" + else if(patient.status_flags & XENO_HOST) + holder.icon_state = "hudxeno" + else if(foundVirus || iszombie(patient)) + holder.icon_state = "hudill" + else if(patient.has_brain_worms()) + var/mob/living/simple_animal/borer/B = patient.has_brain_worms() + if(B.controlling) + holder.icon_state = "hudbrainworm" + else + holder.icon_state = "hudhealthy" + else + holder.icon_state = "hudhealthy" + client.images += holder + +/mob/living/silicon/pai/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(20 to 30) + return "health25" + if(5 to 15) + return "health10" + if(1 to 5) + return "health1" + if(-99 to 0) + return "health0" + else + return "health-100" + return "0" diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm index f775bbd20f05..34354622e7a8 100644 --- a/code/modules/mob/living/silicon/pai/life.dm +++ b/code/modules/mob/living/silicon/pai/life.dm @@ -1,28 +1,28 @@ -/mob/living/silicon/pai/Life() - if (src.stat == DEAD) - return - if(src.cable) - if(get_dist(src, src.cable) > 1) - var/turf/T = get_turf_or_move(src.loc) - for (var/mob/M in viewers(T)) - M.show_message("\red The data cable rapidly retracts back into its spool.", 3, "\red You hear a click and the sound of wire spooling rapidly.", 2) - qdel(src.cable) - - add_ingame_age() - regular_hud_updates() - if(src.secHUD == 1) - process_sec_hud(src, 1) - if(src.medHUD == 1) - process_med_hud(src, 1) - 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 = 100 - stat = CONSCIOUS - else - health = 100 - getBruteLoss() - getFireLoss() - +/mob/living/silicon/pai/Life() + if (src.stat == DEAD) + return + if(src.cable) + if(get_dist(src, src.cable) > 1) + var/turf/T = get_turf_or_move(src.loc) + for (var/mob/M in viewers(T)) + M.show_message("\red The data cable rapidly retracts back into its spool.", 3, "\red You hear a click and the sound of wire spooling rapidly.", 2) + qdel(src.cable) + + add_ingame_age() + regular_hud_updates() + if(src.secHUD == 1) + process_sec_hud(src, 1) + if(src.medHUD == 1) + process_med_hud(src, 1) + 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 = 100 + stat = CONSCIOUS + else + health = 100 - getBruteLoss() - getFireLoss() + diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index d74ba30d6620..dd20706835e6 100755 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -1,275 +1,275 @@ -/mob/living/silicon/pai - name = "pAI" - icon = 'icons/mob/mob.dmi'// - icon_state = "shadow" - - robot_talk_understand = 0 - emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person) - canmove = FALSE - - var/network = "SS13" - var/obj/machinery/camera/current = null - - var/ram = 100 // Used as currency to purchase different abilities - var/list/software = list() - var/userDNA // The DNA string of our assigned user - var/obj/item/device/paicard/card // The card we inhabit - var/obj/item/device/radio/radio // Our primary radio - - var/speakStatement = "states" - var/speakExclamation = "declares" - var/speakQuery = "queries" - - - var/obj/item/weapon/pai_cable/cable // The cable we produce and use when door or camera jacking - - 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/secHUD = 0 // Toggles whether the Security HUD is active or not - var/medHUD = 0 // Toggles whether the Medical HUD 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/door/hackdoor // The airlock being hacked - var/hackprogress = 0 // Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check - - var/obj/item/radio/integrated/signal/sradio // AI's signaller - - var/translator_on = 0 // keeps track of the translator module - -/mob/living/silicon/pai/atom_init() - var/obj/item/device/paicard/P = loc - - if(!istype(P)) //when manually spawning a pai, we create a card to put it into. - var/newcardloc = P - P = new /obj/item/device/paicard(newcardloc) - P.setPersonality(src) - - loc = P - card = P - sradio = new(src) - if(!card.radio) - card.radio = new /obj/item/device/radio(card) - radio = card.radio - - //Default languages without universal translator software - add_language("Sol Common", 1) - add_language("Trinary", 1) - add_language("Tradeband", 1) - add_language("Gutter", 1) - - //PDA - pda = new(src) - spawn(5) - pda.ownjob = "Personal Assistant" - pda.owner = text("[]", src) - pda.name = pda.owner + " (" + pda.ownjob + ")" - pda.toff = 1 - - . = ..() - -/mob/living/silicon/pai/Stat() - ..() - if(statpanel("Status")) - 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)]") - - if(proc_holder_list.len)//Generic list for proc_holder objects. - for(var/obj/effect/proc_holder/P in proc_holder_list) - statpanel("[P.panel]","",P) - -/mob/living/silicon/pai/check_eye(mob/user) - if (!src.current) - return null - user.reset_view(src.current) - return 1 - -/mob/living/silicon/pai/blob_act() - if (src.stat != DEAD) - src.adjustBruteLoss(60) - src.updatehealth() - return 1 - return 0 - -/mob/living/silicon/pai/restrained() - return 0 - -/mob/living/silicon/pai/emp_act(severity) - // 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 - - src.silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes - 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(prob(20)) - var/turf/T = get_turf_or_move(src.loc) - for (var/mob/M in viewers(T)) - M.show_message("\red A shower of sparks spray from [src]'s inner workings.", 3, "\red 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) - 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) - 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(!blinded) - flash_eyes() - - switch(severity) - if(1.0) - if (src.stat != DEAD) - adjustBruteLoss(100) - adjustFireLoss(100) - if(2.0) - if (src.stat != DEAD) - adjustBruteLoss(60) - adjustFireLoss(60) - if(3.0) - if (src.stat != DEAD) - adjustBruteLoss(30) - - src.updatehealth() - - -// See software.dm for Topic() - -/mob/living/silicon/pai/meteorhit(obj/O) - for(var/mob/M in viewers(src, null)) - M.show_message(text("\red [] has been hit by []", src, O), 1) - if (src.health > 0) - src.adjustBruteLoss(30) - if ((O.icon_state == "flaming")) - src.adjustFireLoss(40) - src.updatehealth() - return - -//mob/living/silicon/pai/bullet_act(obj/item/projectile/Proj) - -/mob/living/silicon/pai/attack_alien(mob/living/carbon/alien/humanoid/M) - if (!ticker) - to_chat(M, "You cannot attack people before the game has started.") - return - - if (istype(src.loc, /turf) && istype(src.loc.loc, /area/start)) - to_chat(M, "You cannot attack someone in the spawn area.") - return - - switch(M.a_intent) - - if ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src]'s casing with its scythe like arm."), 1) - - else //harm - var/damage = rand(10, 20) - if (prob(90)) - playsound(src.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("\red [] has slashed at []!", M, src), 1) - if(prob(8)) - flash_eyes(affect_silicon = 1) - src.adjustBruteLoss(damage) - src.updatehealth() - else - playsound(src.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("\red [] took a swipe at []!", M, src), 1) - return - -///mob/living/silicon/pai/attack_hand(mob/living/carbon/M) - -/mob/living/silicon/pai/proc/switchCamera(obj/machinery/camera/C) - if(istype(usr, /mob/living)) - var/mob/living/U = usr - U.cameraFollow = null - if (!C) - src.unset_machine() - src.reset_view(null) - return 0 - if (stat == DEAD || !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 - -//Addition by Mord_Sith to define AI's network change ability -/* -/mob/living/silicon/pai/proc/pai_network_change() - set category = "pAI Commands" - set name = "Change Camera Network" - src.reset_view(null) - src.unset_machine() - src.cameraFollow = null - var/cameralist[0] - - if(usr.stat == DEAD) - to_chat(usr, "You can't change your camera network because you are dead!") - return - - for (var/obj/machinery/camera/C in Cameras) - if(!C.status) - continue - else - if(C.network != "CREED" && C.network != "thunder" && C.network != "RD" && C.network != "phoron" && C.network != "Prison") COMPILE ERROR! This will have to be updated as camera.network is no longer a string, but a list instead - cameralist[C.network] = C.network - - src.network = input(usr, "Which network would you like to view?") as null|anything in cameralist - to_chat(src, "\blue Switched to [src.network] camera network.") -//End of code by Mord_Sith -*/ - - -/* -// Debug command - Maybe should be added to admin verbs later -/mob/verb/makePAI(var/turf/t in view()) - var/obj/item/device/paicard/card = new(t) - var/mob/living/silicon/pai/pai = new(card) - pai.key = src.key - card.setPersonality(pai) - -*/ +/mob/living/silicon/pai + name = "pAI" + icon = 'icons/mob/mob.dmi'// + icon_state = "shadow" + + robot_talk_understand = 0 + emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person) + canmove = FALSE + + var/network = "SS13" + var/obj/machinery/camera/current = null + + var/ram = 100 // Used as currency to purchase different abilities + var/list/software = list() + var/userDNA // The DNA string of our assigned user + var/obj/item/device/paicard/card // The card we inhabit + var/obj/item/device/radio/radio // Our primary radio + + var/speakStatement = "states" + var/speakExclamation = "declares" + var/speakQuery = "queries" + + + var/obj/item/weapon/pai_cable/cable // The cable we produce and use when door or camera jacking + + 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/secHUD = 0 // Toggles whether the Security HUD is active or not + var/medHUD = 0 // Toggles whether the Medical HUD 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/door/hackdoor // The airlock being hacked + var/hackprogress = 0 // Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check + + var/obj/item/radio/integrated/signal/sradio // AI's signaller + + var/translator_on = 0 // keeps track of the translator module + +/mob/living/silicon/pai/atom_init() + var/obj/item/device/paicard/P = loc + + if(!istype(P)) //when manually spawning a pai, we create a card to put it into. + var/newcardloc = P + P = new /obj/item/device/paicard(newcardloc) + P.setPersonality(src) + + loc = P + card = P + sradio = new(src) + if(!card.radio) + card.radio = new /obj/item/device/radio(card) + radio = card.radio + + //Default languages without universal translator software + add_language("Sol Common", 1) + add_language("Trinary", 1) + add_language("Tradeband", 1) + add_language("Gutter", 1) + + //PDA + pda = new(src) + spawn(5) + pda.ownjob = "Personal Assistant" + pda.owner = text("[]", src) + pda.name = pda.owner + " (" + pda.ownjob + ")" + pda.toff = 1 + + . = ..() + +/mob/living/silicon/pai/Stat() + ..() + if(statpanel("Status")) + 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)]") + + if(proc_holder_list.len)//Generic list for proc_holder objects. + for(var/obj/effect/proc_holder/P in proc_holder_list) + statpanel("[P.panel]","",P) + +/mob/living/silicon/pai/check_eye(mob/user) + if (!src.current) + return null + user.reset_view(src.current) + return 1 + +/mob/living/silicon/pai/blob_act() + if (src.stat != DEAD) + src.adjustBruteLoss(60) + src.updatehealth() + return 1 + return 0 + +/mob/living/silicon/pai/restrained() + return 0 + +/mob/living/silicon/pai/emp_act(severity) + // 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 + + src.silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes + 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(prob(20)) + var/turf/T = get_turf_or_move(src.loc) + for (var/mob/M in viewers(T)) + M.show_message("\red A shower of sparks spray from [src]'s inner workings.", 3, "\red 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) + 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) + 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(!blinded) + flash_eyes() + + switch(severity) + if(1.0) + if (src.stat != DEAD) + adjustBruteLoss(100) + adjustFireLoss(100) + if(2.0) + if (src.stat != DEAD) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3.0) + if (src.stat != DEAD) + adjustBruteLoss(30) + + src.updatehealth() + + +// See software.dm for Topic() + +/mob/living/silicon/pai/meteorhit(obj/O) + for(var/mob/M in viewers(src, null)) + M.show_message(text("\red [] has been hit by []", src, O), 1) + if (src.health > 0) + src.adjustBruteLoss(30) + if ((O.icon_state == "flaming")) + src.adjustFireLoss(40) + src.updatehealth() + return + +//mob/living/silicon/pai/bullet_act(obj/item/projectile/Proj) + +/mob/living/silicon/pai/attack_alien(mob/living/carbon/alien/humanoid/M) + if (!ticker) + to_chat(M, "You cannot attack people before the game has started.") + return + + if (istype(src.loc, /turf) && istype(src.loc.loc, /area/start)) + to_chat(M, "You cannot attack someone in the spawn area.") + return + + switch(M.a_intent) + + if ("help") + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\blue [M] caresses [src]'s casing with its scythe like arm."), 1) + + else //harm + var/damage = rand(10, 20) + if (prob(90)) + playsound(src.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("\red [] has slashed at []!", M, src), 1) + if(prob(8)) + flash_eyes(affect_silicon = 1) + src.adjustBruteLoss(damage) + src.updatehealth() + else + playsound(src.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("\red [] took a swipe at []!", M, src), 1) + return + +///mob/living/silicon/pai/attack_hand(mob/living/carbon/M) + +/mob/living/silicon/pai/proc/switchCamera(obj/machinery/camera/C) + if(istype(usr, /mob/living)) + var/mob/living/U = usr + U.cameraFollow = null + if (!C) + src.unset_machine() + src.reset_view(null) + return 0 + if (stat == DEAD || !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 + +//Addition by Mord_Sith to define AI's network change ability +/* +/mob/living/silicon/pai/proc/pai_network_change() + set category = "pAI Commands" + set name = "Change Camera Network" + src.reset_view(null) + src.unset_machine() + src.cameraFollow = null + var/cameralist[0] + + if(usr.stat == DEAD) + to_chat(usr, "You can't change your camera network because you are dead!") + return + + for (var/obj/machinery/camera/C in Cameras) + if(!C.status) + continue + else + if(C.network != "CREED" && C.network != "thunder" && C.network != "RD" && C.network != "phoron" && C.network != "Prison") COMPILE ERROR! This will have to be updated as camera.network is no longer a string, but a list instead + cameralist[C.network] = C.network + + src.network = input(usr, "Which network would you like to view?") as null|anything in cameralist + to_chat(src, "\blue Switched to [src.network] camera network.") +//End of code by Mord_Sith +*/ + + +/* +// Debug command - Maybe should be added to admin verbs later +/mob/verb/makePAI(var/turf/t in view()) + var/obj/item/device/paicard/card = new(t) + var/mob/living/silicon/pai/pai = new(card) + pai.key = src.key + card.setPersonality(pai) + +*/ diff --git a/code/modules/mob/living/silicon/pai/personality.dm b/code/modules/mob/living/silicon/pai/personality.dm index a3f4f7d88717..869009f255dc 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)) - - - 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, 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 +/* + 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, 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 e2c5ccb1b7a3..719f7d187e93 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -1,371 +1,371 @@ -//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(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 - - ticker.mode.update_all_cult_icons() - ticker.mode.update_all_rev_icons() - - 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 = sanitize_safe(input("Enter a name for your pAI", "pAI Name", input_default(candidate.name)) as text) - if(t) - candidate.name = t - if("desc") - t = sanitize(input("Enter a description for your pAI", "pAI Description", input_default(candidate.description)) as message) - if(t) - candidate.description = t - if("role") - t = sanitize(input("Enter a role for your pAI", "pAI Role", input_default(candidate.role)) as text) - if(t) - candidate.role = t - if("ooc") - t = sanitize(input("Enter any OOC comments", "pAI OOC Comments", input_default(candidate.comments)) as message) - if(t) - candidate.comments = t - if("save") - candidate.savefile_save(usr) - if("load") - candidate.savefile_load(usr) - //In case people have saved unsanitized stuff. - if(candidate.name) - candidate.name = sanitize_safe(candidate.name, MAX_NAME_LEN) - if(candidate.description) - candidate.description = sanitize(candidate.description, MAX_MESSAGE_LEN) - if(candidate.role) - candidate.role = sanitize(candidate.role, MAX_MESSAGE_LEN) - if(candidate.comments) - candidate.comments = sanitize(candidate.comments, MAX_MESSAGE_LEN) - - if("submit") - if(candidate) - candidate.ready = 1 - for(var/obj/item/device/paicard/p in paicard_list) - if(p.looking_for_personality == 1) - p.alertUpdate() - usr << browse(null, "window=paiRecruit") - return - recruitWindow(usr) - - proc/recruitWindow(mob/M) - 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 += {" - - "} - - dat += {" - - pAI Personality Configuration -

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

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

                    - - -
                    Submit Personality

                    - - - "} - - M << browse(entity_ja(dat), "window=paiRecruit;size=580x580;") - - proc/findPAI(obj/item/device/paicard/p, 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 += {" - - - - - - - pAI Availability List

                    - "} - dat += "

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

                    " - - for(var/datum/paiCandidate/c in available) - dat += {" - - - - - - - - - - - - - - - - - -
                    Name:[c.name]
                    Description:[c.description]
                    Preferred Role:[c.role]
                    OOC Comments:[c.comments]
                    - - -
                    Download [c.name] -
                    -
                    - "} - - dat += {" - - - "} - - user << browse(entity_ja(dat), "window=findPai") - - proc/requestRecruits() - for(var/mob/dead/observer/O in player_list) - if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted) - continue - if(jobban_isbanned(O, ROLE_PAI)) - continue - if(role_available_in_minutes(O, ROLE_PAI)) - continue - if(asked.Find(O.key)) - if(world.time < asked[O.key] + askDelay) - continue - else - asked.Remove(O.key) - if(O.client) - var/hasSubmitted = 0 - for(var/datum/paiCandidate/c in paiController.pai_candidates) - if(c.key == O.key) - hasSubmitted = 1 - if(!hasSubmitted && (ROLE_PAI in O.client.prefs.be_role)) - question(O.client) - - proc/question(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", "No", "Yes", "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) +//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(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 + + ticker.mode.update_all_cult_icons() + ticker.mode.update_all_rev_icons() + + 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 = sanitize_safe(input("Enter a name for your pAI", "pAI Name", input_default(candidate.name)) as text) + if(t) + candidate.name = t + if("desc") + t = sanitize(input("Enter a description for your pAI", "pAI Description", input_default(candidate.description)) as message) + if(t) + candidate.description = t + if("role") + t = sanitize(input("Enter a role for your pAI", "pAI Role", input_default(candidate.role)) as text) + if(t) + candidate.role = t + if("ooc") + t = sanitize(input("Enter any OOC comments", "pAI OOC Comments", input_default(candidate.comments)) as message) + if(t) + candidate.comments = t + if("save") + candidate.savefile_save(usr) + if("load") + candidate.savefile_load(usr) + //In case people have saved unsanitized stuff. + if(candidate.name) + candidate.name = sanitize_safe(candidate.name, MAX_NAME_LEN) + if(candidate.description) + candidate.description = sanitize(candidate.description, MAX_MESSAGE_LEN) + if(candidate.role) + candidate.role = sanitize(candidate.role, MAX_MESSAGE_LEN) + if(candidate.comments) + candidate.comments = sanitize(candidate.comments, MAX_MESSAGE_LEN) + + if("submit") + if(candidate) + candidate.ready = 1 + for(var/obj/item/device/paicard/p in paicard_list) + if(p.looking_for_personality == 1) + p.alertUpdate() + usr << browse(null, "window=paiRecruit") + return + recruitWindow(usr) + + proc/recruitWindow(mob/M) + 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 += {" + + "} + + dat += {" + + pAI Personality Configuration +

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

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

                    + + +
                    Submit Personality

                    + + + "} + + M << browse(entity_ja(dat), "window=paiRecruit;size=580x580;") + + proc/findPAI(obj/item/device/paicard/p, 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 += {" + + + + + + + pAI Availability List

                    + "} + dat += "

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

                    " + + for(var/datum/paiCandidate/c in available) + dat += {" + + + + + + + + + + + + + + + + + +
                    Name:[c.name]
                    Description:[c.description]
                    Preferred Role:[c.role]
                    OOC Comments:[c.comments]
                    + + +
                    Download [c.name] +
                    +
                    + "} + + dat += {" + + + "} + + user << browse(entity_ja(dat), "window=findPai") + + proc/requestRecruits() + for(var/mob/dead/observer/O in player_list) + if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted) + continue + if(jobban_isbanned(O, ROLE_PAI)) + continue + if(role_available_in_minutes(O, ROLE_PAI)) + continue + if(asked.Find(O.key)) + if(world.time < asked[O.key] + askDelay) + continue + else + asked.Remove(O.key) + if(O.client) + var/hasSubmitted = 0 + for(var/datum/paiCandidate/c in paiController.pai_candidates) + if(c.key == O.key) + hasSubmitted = 1 + if(!hasSubmitted && (ROLE_PAI in O.client.prefs.be_role)) + question(O.client) + + proc/question(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", "No", "Yes", "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 22efa216fea1..b6162f6f9885 100644 --- a/code/modules/mob/living/silicon/pai/say.dm +++ b/code/modules/mob/living/silicon/pai/say.dm @@ -1,5 +1,5 @@ -/mob/living/silicon/pai/say(var/msg) - if(silence_time) - to_chat(src, "Communication circuits remain uninitialized.") - else - ..(msg) +/mob/living/silicon/pai/say(var/msg) + if(silence_time) + to_chat(src, "Communication circuits remain uninitialized.") + else + ..(msg) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index ca41a654467e..7c35430c9341 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -1,705 +1,705 @@ -// TODO: -// - Additional radio modules -// - Potentially roll HUDs and Records into one -// - Shock collar/lock system for prisoner pAIs? -// - Put cable in user's hand instead of on the ground -// - Camera jack - - -/mob/living/silicon/pai/var/list/available_software = list( - "crew manifest" = 5, - "digital messenger" = 5, - "medical records" = 15, - "security records" = 15, - //"camera jack" = 10, - "door jack" = 30, - "atmosphere sensor" = 5, - //"heartbeat sensor" = 10, - "security HUD" = 20, - "medical HUD" = 20, - "universal translator" = 35, - //"projection array" = 15 - "remote signaller" = 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 == DEAD) // Show some flavor text if the pAI is dead - if(config.rus_language) - left_part = "�Rr�R �a�� ��Rr����o�" //This file has to be saved as ANSI or this will not display correctly - else - left_part = "3Rr0R �a�A C0RrU?�ion" - 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("medicalrecord") - left_part = src.softwareMedicalRecord() - if("securityrecord") - left_part = src.softwareSecurityRecord() - if("translator") - left_part = src.softwareTranslator() - if("atmosensor") - left_part = src.softwareAtmo() - if("securityhud") - left_part = src.facialRecognition() - if("medicalhud") - left_part = src.medicalAnalysis() - if("doorjack") - left_part = src.softwareDoor() - if("camerajack") - left_part = src.softwareCamera() - if("signaller") - left_part = src.softwareSignal() - if("radio") - left_part = src.softwareRadio() - - //usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc - - - // Declaring a doctype is necessary to enable BYOND's crappy browser's more advanced CSS functionality - dat = {" - - - - - - -
                    - pAI OS -
                    -
                    -
                    [left_part]
                    -
                    [right_part]
                    -
                    - - "} - usr << browse(entity_ja(dat), "window=pai;size=685x449;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") - if(href_list["freq"]) - var/new_frequency = (radio.frequency + text2num(href_list["freq"])) - if(new_frequency < 1441 || new_frequency > 1599) - new_frequency = sanitize_frequency(new_frequency) - else - radio.set_frequency(new_frequency) - else if (href_list["talk"]) - radio.broadcasting = text2num(href_list["talk"]) - else if (href_list["listen"]) - radio.listening = text2num(href_list["listen"]) - - 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") - 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 - 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("[bicon(src)] *beep* *beep*", 3, "*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.message_silent = !pda.message_silent - else if(href_list["target"]) - if(silence_time) - return alert("Communications circuits remain uninitialized.") - - var/target = locate(href_list["target"]) - pda.create_message(src, target) - - // Accessing medical records - if("medicalrecord") - 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("securityrecord") - 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("securityhud") - if(href_list["toggle"]) - src.secHUD = !src.secHUD - if("medicalhud") - if(href_list["toggle"]) - src.medHUD = !src.medHUD - if("translator") - if(href_list["toggle"]) - src.translator_toggle() - if("doorjack") - if(href_list["jack"]) - if(src.cable && src.cable.machine) - src.hackdoor = src.cable.machine - src.hackloop() - if(href_list["cancel"]) - src.hackdoor = null - if(href_list["cable"]) - var/turf/T = get_turf_or_move(src.loc) - src.cable = new /obj/item/weapon/pai_cable(T) - for (var/mob/M in viewers(T)) - M.show_message("\red A port on [src] opens to reveal [src.cable], which promptly falls to the floor.", 3, "\red You hear the soft click of something light and hard falling to the ground.", 2) - //src.updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window - 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 - dat += "Directives
                    " - dat += "Radio Configuration
                    " - dat += "Screen Display
                    " - //dat += "Text Messaging
                    " - dat += "
                    " - - // Basic - dat += "Basic
                    " - for(var/s in src.software) - if(s == "digital messenger") - dat += "Digital Messenger [(pda.toff) ? "" : ""]
                    " - if(s == "crew manifest") - dat += "Crew Manifest
                    " - if(s == "medical records") - dat += "Medical Records
                    " - if(s == "security records") - dat += "Security Records
                    " - if(s == "camera") - dat += "Camera Jack
                    " - if(s == "remote signaller") - dat += "Remote Signaller
                    " - dat += "
                    " - - // Advanced - dat += "Advanced
                    " - for(var/s in src.software) - if(s == "atmosphere sensor") - dat += "Atmospheric Sensor
                    " - if(s == "heartbeat sensor") - dat += "Heartbeat Sensor
                    " - if(s == "security HUD") //This file has to be saved as ANSI or this will not display correctly - dat += "Facial Recognition Suite [(src.secHUD) ? "" : ""]
                    " - if(s == "medical HUD") //This file has to be saved as ANSI or this will not display correctly - dat += "Medical Analysis Suite [(src.medHUD) ? "" : ""]
                    " - if(s == "universal translator") //This file has to be saved as ANSI or this will not display correctly - dat += "Universal Translator [(src.translator_on) ? "" : ""]
                    " - if(s == "projection array") - dat += "Projection Array
                    " - if(s == "camera jack") - dat += "Camera Jack
                    " - if(s == "door jack") - dat += "Door Jack
                    " - dat += "
                    " - dat += "
                    " - dat += "Download additional software" - return dat - - - -/mob/living/silicon/pai/proc/downloadSoftware() - var/dat = "" - - dat += "

                    CentComm pAI Module Subversion Network


                    " - dat += "

                    Remaining Available Memory: [src.ram]


                    " - dat += "

                    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."]" - dat += "

                    " - dat += "Request carrier DNA sample
                    " - dat += "

                    Directives


                    " - dat += "Prime Directive
                    " - dat += "     [src.pai_law0]
                    " - dat += "Supplemental Directives
                    " - dat += "     [src.pai_laws]
                    " - dat += "
                    " - 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_or_move(P.loc) - for (var/mob/v in viewers(T)) - v.show_message("\blue [M] presses \his thumb against [P].", 3, "\blue [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 - -//Station Bounced Radio -/mob/living/silicon/pai/proc/softwareRadio() - var/dat = "" - dat += "

                    Station Bounced Radio


                    " - if(!istype(src, /obj/item/device/radio/headset)) //Headsets don't get a mic button - dat += "Microphone: [radio.broadcasting ? "Engaged" : "Disengaged"]
                    " - dat += {" - Speaker: [radio.listening ? "Engaged" : "Disengaged"]
                    - Frequency: - - - - - [format_frequency(radio.frequency)] - + - +
                    - "} - - for (var/ch_name in radio.channels) - dat+=radio.text_sec_channel(ch_name, radio.channels[ch_name]) - - 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 += "

                    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: []
                    \nID: []
                    \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) - 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:
                    []
                    \nID: []
                    \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 languages into a format that any known recipient can understand.

                    - The device is currently [ (src.translator_on) ? "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 suite is currently [ (src.secHUD) ? "en" : "dis" ]abled.
                    - Toggle Suite
                    - "} - return dat - -// Medical HUD -/mob/living/silicon/pai/proc/medicalAnalysis() - var/dat = "" - if(src.subscreen == 0) - dat += {"

                    Medical Analysis Suite


                    -

                    Visual Status Overlay

                    - When enabled, this package will scan all nearby crewmembers' vitals and provide real-time graphical data about their state of health.

                    - The suite is currently [ (src.medHUD) ? "en" : "dis" ]abled.
                    - Toggle Suite
                    -
                    - Host Bioscan
                    - "} - if(src.subscreen == 1) - 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 += "
                    Refresh Bioscan
                    " - dat += "
                    Visual Status Overlay
                    " - return dat - -// Atmospheric Scanner -/mob/living/silicon/pai/proc/softwareAtmo() - var/dat = "

                    Atmospheric Sensor


                    " - - var/turf/T = get_turf_or_move(src.loc) - if (isnull(T)) - dat += "Unable to obtain a reading.
                    " - else - var/datum/gas_mixture/env = T.return_air() - - var/pressure = env.return_pressure() - var/t_moles = env.total_moles - - dat += "Air Pressure: [round(pressure,0.1)] kPa
                    " - - for(var/g in env.gas) - dat += "[gas_data.name[g]]: [round((env.gas[g] / t_moles) * 100)]" - - dat += "Temperature: [round(env.temperature-T0C)]°C
                    " - dat += "
                    Refresh Reading" - return dat - -// Camera Jack - Clearly not finished -/mob/living/silicon/pai/proc/softwareCamera() - var/dat = "

                    Camera Jack


                    " - dat += "Cable status : " - - if(!src.cable) - dat += "Retracted
                    " - return dat - if(!src.cable.machine) - dat += "Extended
                    " - return dat - - var/obj/machinery/machine = src.cable.machine - dat += "Connected
                    " - - if(!istype(machine, /obj/machinery/camera)) - to_chat(src, "DERP") - return dat - -// Door Jack -/mob/living/silicon/pai/proc/softwareDoor() - var/dat = "

                    Airlock Jack


                    " - dat += "Cable status : " - if(!src.cable) - dat += "Retracted
                    " - dat += "Extend Cable
                    " - return dat - if(!src.cable.machine) - dat += "Extended
                    " - return dat - - var/obj/machinery/machine = src.cable.machine - dat += "Connected
                    " - if(!istype(machine, /obj/machinery/door)) - dat += "Connected device's firmware does not appear to be compatible with Airlock Jack protocols.
                    " - return dat -// var/obj/machinery/airlock/door = machine - - if(!src.hackdoor) - dat += "Begin Airlock Jacking
                    " - else - dat += "Jack in progress... [src.hackprogress]% complete.
                    " - dat += "Cancel Airlock Jack
                    " - //src.hackdoor = machine - //src.hackloop() - return dat - -// Door Jack - supporting proc -/mob/living/silicon/pai/proc/hackloop() - var/turf/T = get_turf_or_move(src.loc) - 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(src.cable && src.cable.machine && istype(src.cable.machine, /obj/machinery/door) && src.cable.machine == src.hackdoor && get_dist(src, src.hackdoor) <= 1) - hackprogress += rand(1, 10) - else - src.temp = "Door Jack: Connection to airlock has been lost. Hack aborted." - hackprogress = 0 - src.hackdoor = null - return - if(hackprogress >= 100) // This is clunky, but works. We need to make sure we don't ever display a progress greater than 100, - hackprogress = 100 // but we also need to reset the progress AFTER it's been displayed - if(src.screen == "doorjack" && src.subscreen == 0) // Update our view, if appropriate - src.paiInterface() - if(hackprogress >= 100) - src.hackprogress = 0 - src.cable.machine:open() - sleep(50) // Update every 5 seconds - -// Digital Messenger -/mob/living/silicon/pai/proc/pdamessage() - - var/dat = "

                    Digital Messenger


                    " - dat += {"Signal/Receiver Status: - [(pda.toff) ? " \[Off\]" : " \[On\]"]
                    - Ringer Status: - [(pda.message_silent) ? " \[Off\]" : " \[On\]"]

                    "} - dat += "
                      " - if(!pda.toff) - for (var/obj/item/device/pda/P in sortAtom(PDAs)) - if (!P.owner||P.toff||P == src.pda||P.hidden) continue - dat += "
                    • [P]" - dat += "
                    • " - dat += "
                    " - dat += "Messages:
                    " - - dat += "" - dat += "" - for(var/index in pda.tnote) - if(index["sent"]) - dat += addtext("") - else - dat += addtext("") - dat += "
                    To", index["owner"],": ", index["message"], "
                    From", index["owner"],": ", index["message"], "
                    " - return dat - -/mob/living/silicon/pai/proc/translator_toggle() - - // Sol Common, Tradeband and Gutter are added with atom_init() and are therefore the current default, always active languages - - if(translator_on) - translator_on = 0 - - remove_language("Sinta'unathi") - remove_language("Siik'maas") - remove_language("Siik'tajr") - remove_language("Skrellian") - - to_chat(src, "\blue Translator Module toggled OFF.") - - else - translator_on = 1 - - add_language("Sinta'unathi") - add_language("Siik'maas") - add_language("Siik'tajr", 0) - add_language("Skrellian") - - to_chat(src, "\blue Translator Module toggled ON.") +// TODO: +// - Additional radio modules +// - Potentially roll HUDs and Records into one +// - Shock collar/lock system for prisoner pAIs? +// - Put cable in user's hand instead of on the ground +// - Camera jack + + +/mob/living/silicon/pai/var/list/available_software = list( + "crew manifest" = 5, + "digital messenger" = 5, + "medical records" = 15, + "security records" = 15, + //"camera jack" = 10, + "door jack" = 30, + "atmosphere sensor" = 5, + //"heartbeat sensor" = 10, + "security HUD" = 20, + "medical HUD" = 20, + "universal translator" = 35, + //"projection array" = 15 + "remote signaller" = 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 == DEAD) // Show some flavor text if the pAI is dead + if(config.rus_language) + left_part = "�Rr�R �a�� ��Rr����o�" //This file has to be saved as ANSI or this will not display correctly + else + left_part = "3Rr0R �a�A C0RrU?�ion" + 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("medicalrecord") + left_part = src.softwareMedicalRecord() + if("securityrecord") + left_part = src.softwareSecurityRecord() + if("translator") + left_part = src.softwareTranslator() + if("atmosensor") + left_part = src.softwareAtmo() + if("securityhud") + left_part = src.facialRecognition() + if("medicalhud") + left_part = src.medicalAnalysis() + if("doorjack") + left_part = src.softwareDoor() + if("camerajack") + left_part = src.softwareCamera() + if("signaller") + left_part = src.softwareSignal() + if("radio") + left_part = src.softwareRadio() + + //usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc + + + // Declaring a doctype is necessary to enable BYOND's crappy browser's more advanced CSS functionality + dat = {" + + + + + + +
                    + pAI OS +
                    +
                    +
                    [left_part]
                    +
                    [right_part]
                    +
                    + + "} + usr << browse(entity_ja(dat), "window=pai;size=685x449;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") + if(href_list["freq"]) + var/new_frequency = (radio.frequency + text2num(href_list["freq"])) + if(new_frequency < 1441 || new_frequency > 1599) + new_frequency = sanitize_frequency(new_frequency) + else + radio.set_frequency(new_frequency) + else if (href_list["talk"]) + radio.broadcasting = text2num(href_list["talk"]) + else if (href_list["listen"]) + radio.listening = text2num(href_list["listen"]) + + 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") + 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 + 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("[bicon(src)] *beep* *beep*", 3, "*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.message_silent = !pda.message_silent + else if(href_list["target"]) + if(silence_time) + return alert("Communications circuits remain uninitialized.") + + var/target = locate(href_list["target"]) + pda.create_message(src, target) + + // Accessing medical records + if("medicalrecord") + 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("securityrecord") + 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("securityhud") + if(href_list["toggle"]) + src.secHUD = !src.secHUD + if("medicalhud") + if(href_list["toggle"]) + src.medHUD = !src.medHUD + if("translator") + if(href_list["toggle"]) + src.translator_toggle() + if("doorjack") + if(href_list["jack"]) + if(src.cable && src.cable.machine) + src.hackdoor = src.cable.machine + src.hackloop() + if(href_list["cancel"]) + src.hackdoor = null + if(href_list["cable"]) + var/turf/T = get_turf_or_move(src.loc) + src.cable = new /obj/item/weapon/pai_cable(T) + for (var/mob/M in viewers(T)) + M.show_message("\red A port on [src] opens to reveal [src.cable], which promptly falls to the floor.", 3, "\red You hear the soft click of something light and hard falling to the ground.", 2) + //src.updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window + 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 + dat += "Directives
                    " + dat += "Radio Configuration
                    " + dat += "Screen Display
                    " + //dat += "Text Messaging
                    " + dat += "
                    " + + // Basic + dat += "Basic
                    " + for(var/s in src.software) + if(s == "digital messenger") + dat += "Digital Messenger [(pda.toff) ? "" : ""]
                    " + if(s == "crew manifest") + dat += "Crew Manifest
                    " + if(s == "medical records") + dat += "Medical Records
                    " + if(s == "security records") + dat += "Security Records
                    " + if(s == "camera") + dat += "Camera Jack
                    " + if(s == "remote signaller") + dat += "Remote Signaller
                    " + dat += "
                    " + + // Advanced + dat += "Advanced
                    " + for(var/s in src.software) + if(s == "atmosphere sensor") + dat += "Atmospheric Sensor
                    " + if(s == "heartbeat sensor") + dat += "Heartbeat Sensor
                    " + if(s == "security HUD") //This file has to be saved as ANSI or this will not display correctly + dat += "Facial Recognition Suite [(src.secHUD) ? "" : ""]
                    " + if(s == "medical HUD") //This file has to be saved as ANSI or this will not display correctly + dat += "Medical Analysis Suite [(src.medHUD) ? "" : ""]
                    " + if(s == "universal translator") //This file has to be saved as ANSI or this will not display correctly + dat += "Universal Translator [(src.translator_on) ? "" : ""]
                    " + if(s == "projection array") + dat += "Projection Array
                    " + if(s == "camera jack") + dat += "Camera Jack
                    " + if(s == "door jack") + dat += "Door Jack
                    " + dat += "
                    " + dat += "
                    " + dat += "Download additional software" + return dat + + + +/mob/living/silicon/pai/proc/downloadSoftware() + var/dat = "" + + dat += "

                    CentComm pAI Module Subversion Network


                    " + dat += "

                    Remaining Available Memory: [src.ram]


                    " + dat += "

                    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."]" + dat += "

                    " + dat += "Request carrier DNA sample
                    " + dat += "

                    Directives


                    " + dat += "Prime Directive
                    " + dat += "     [src.pai_law0]
                    " + dat += "Supplemental Directives
                    " + dat += "     [src.pai_laws]
                    " + dat += "
                    " + 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_or_move(P.loc) + for (var/mob/v in viewers(T)) + v.show_message("\blue [M] presses \his thumb against [P].", 3, "\blue [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 + +//Station Bounced Radio +/mob/living/silicon/pai/proc/softwareRadio() + var/dat = "" + dat += "

                    Station Bounced Radio


                    " + if(!istype(src, /obj/item/device/radio/headset)) //Headsets don't get a mic button + dat += "Microphone: [radio.broadcasting ? "Engaged" : "Disengaged"]
                    " + dat += {" + Speaker: [radio.listening ? "Engaged" : "Disengaged"]
                    + Frequency: + - + - + [format_frequency(radio.frequency)] + + + +
                    + "} + + for (var/ch_name in radio.channels) + dat+=radio.text_sec_channel(ch_name, radio.channels[ch_name]) + + 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 += "

                    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: []
                    \nID: []
                    \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) + 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:
                    []
                    \nID: []
                    \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 languages into a format that any known recipient can understand.

                    + The device is currently [ (src.translator_on) ? "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 suite is currently [ (src.secHUD) ? "en" : "dis" ]abled.
                    + Toggle Suite
                    + "} + return dat + +// Medical HUD +/mob/living/silicon/pai/proc/medicalAnalysis() + var/dat = "" + if(src.subscreen == 0) + dat += {"

                    Medical Analysis Suite


                    +

                    Visual Status Overlay

                    + When enabled, this package will scan all nearby crewmembers' vitals and provide real-time graphical data about their state of health.

                    + The suite is currently [ (src.medHUD) ? "en" : "dis" ]abled.
                    + Toggle Suite
                    +
                    + Host Bioscan
                    + "} + if(src.subscreen == 1) + 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 += "
                    Refresh Bioscan
                    " + dat += "
                    Visual Status Overlay
                    " + return dat + +// Atmospheric Scanner +/mob/living/silicon/pai/proc/softwareAtmo() + var/dat = "

                    Atmospheric Sensor


                    " + + var/turf/T = get_turf_or_move(src.loc) + if (isnull(T)) + dat += "Unable to obtain a reading.
                    " + else + var/datum/gas_mixture/env = T.return_air() + + var/pressure = env.return_pressure() + var/t_moles = env.total_moles + + dat += "Air Pressure: [round(pressure,0.1)] kPa
                    " + + for(var/g in env.gas) + dat += "[gas_data.name[g]]: [round((env.gas[g] / t_moles) * 100)]" + + dat += "Temperature: [round(env.temperature-T0C)]°C
                    " + dat += "
                    Refresh Reading" + return dat + +// Camera Jack - Clearly not finished +/mob/living/silicon/pai/proc/softwareCamera() + var/dat = "

                    Camera Jack


                    " + dat += "Cable status : " + + if(!src.cable) + dat += "Retracted
                    " + return dat + if(!src.cable.machine) + dat += "Extended
                    " + return dat + + var/obj/machinery/machine = src.cable.machine + dat += "Connected
                    " + + if(!istype(machine, /obj/machinery/camera)) + to_chat(src, "DERP") + return dat + +// Door Jack +/mob/living/silicon/pai/proc/softwareDoor() + var/dat = "

                    Airlock Jack


                    " + dat += "Cable status : " + if(!src.cable) + dat += "Retracted
                    " + dat += "Extend Cable
                    " + return dat + if(!src.cable.machine) + dat += "Extended
                    " + return dat + + var/obj/machinery/machine = src.cable.machine + dat += "Connected
                    " + if(!istype(machine, /obj/machinery/door)) + dat += "Connected device's firmware does not appear to be compatible with Airlock Jack protocols.
                    " + return dat +// var/obj/machinery/airlock/door = machine + + if(!src.hackdoor) + dat += "Begin Airlock Jacking
                    " + else + dat += "Jack in progress... [src.hackprogress]% complete.
                    " + dat += "Cancel Airlock Jack
                    " + //src.hackdoor = machine + //src.hackloop() + return dat + +// Door Jack - supporting proc +/mob/living/silicon/pai/proc/hackloop() + var/turf/T = get_turf_or_move(src.loc) + 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(src.cable && src.cable.machine && istype(src.cable.machine, /obj/machinery/door) && src.cable.machine == src.hackdoor && get_dist(src, src.hackdoor) <= 1) + hackprogress += rand(1, 10) + else + src.temp = "Door Jack: Connection to airlock has been lost. Hack aborted." + hackprogress = 0 + src.hackdoor = null + return + if(hackprogress >= 100) // This is clunky, but works. We need to make sure we don't ever display a progress greater than 100, + hackprogress = 100 // but we also need to reset the progress AFTER it's been displayed + if(src.screen == "doorjack" && src.subscreen == 0) // Update our view, if appropriate + src.paiInterface() + if(hackprogress >= 100) + src.hackprogress = 0 + src.cable.machine:open() + sleep(50) // Update every 5 seconds + +// Digital Messenger +/mob/living/silicon/pai/proc/pdamessage() + + var/dat = "

                    Digital Messenger


                    " + dat += {"Signal/Receiver Status: + [(pda.toff) ? " \[Off\]" : " \[On\]"]
                    + Ringer Status: + [(pda.message_silent) ? " \[Off\]" : " \[On\]"]

                    "} + dat += "
                      " + if(!pda.toff) + for (var/obj/item/device/pda/P in sortAtom(PDAs)) + if (!P.owner||P.toff||P == src.pda||P.hidden) continue + dat += "
                    • [P]" + dat += "
                    • " + dat += "
                    " + dat += "Messages:
                    " + + dat += "" + dat += "" + for(var/index in pda.tnote) + if(index["sent"]) + dat += addtext("") + else + dat += addtext("") + dat += "
                    To", index["owner"],": ", index["message"], "
                    From", index["owner"],": ", index["message"], "
                    " + return dat + +/mob/living/silicon/pai/proc/translator_toggle() + + // Sol Common, Tradeband and Gutter are added with atom_init() and are therefore the current default, always active languages + + if(translator_on) + translator_on = 0 + + remove_language("Sinta'unathi") + remove_language("Siik'maas") + remove_language("Siik'tajr") + remove_language("Skrellian") + + to_chat(src, "\blue Translator Module toggled OFF.") + + else + translator_on = 1 + + add_language("Sinta'unathi") + add_language("Siik'maas") + add_language("Siik'tajr", 0) + add_language("Skrellian") + + to_chat(src, "\blue Translator Module toggled ON.") diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index ce5fd00c4c6a..ec1b2390626c 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -1,224 +1,224 @@ -// TODO: remove the robot.mmi and robot.cell variables and completely rely on the robot component system - -/datum/robot_component/var/name -/datum/robot_component/var/installed = 0 -/datum/robot_component/var/powered = 0 -/datum/robot_component/var/toggled = 1 -/datum/robot_component/var/brute_damage = 0 -/datum/robot_component/var/electronics_damage = 0 -/datum/robot_component/var/idle_usage = 0 // Amount of power used every MC tick. In joules. -/datum/robot_component/var/active_usage = 0 // Amount of power used for every action. Actions are module-specific. Actuator for each tile moved, etc. -/datum/robot_component/var/max_damage = 30 // HP of this component. -/datum/robot_component/var/mob/living/silicon/robot/owner - -// The actual device object that has to be installed for this. -/datum/robot_component/var/external_type = null - -// The wrapped device(e.g. radio), only set if external_type isn't null -/datum/robot_component/var/obj/item/wrapped = null - -/datum/robot_component/New(mob/living/silicon/robot/R) - src.owner = R - -/datum/robot_component/proc/install() -/datum/robot_component/proc/uninstall() - -/datum/robot_component/proc/destroy() - var/brokenstate = "broken" // Generic icon - if (istype(wrapped, /obj/item/robot_parts/robot_component)) - var/obj/item/robot_parts/robot_component/comp = wrapped - brokenstate = comp.icon_state_broken - if(wrapped) - qdel(wrapped) - - - wrapped = new/obj/item/broken_device - wrapped.icon_state = brokenstate // Module-specific broken icons! Yay! - - // The thing itself isn't there anymore, but some fried remains are. - installed = -1 - uninstall() - -/datum/robot_component/proc/take_damage(brute, electronics, sharp, edge) - if(installed != 1) return - - brute_damage += brute - electronics_damage += electronics - - if(brute_damage + electronics_damage >= max_damage) destroy() - -/datum/robot_component/proc/heal_damage(brute, electronics) - if(installed != 1) - // If it's not installed, can't repair it. - return 0 - - brute_damage = max(0, brute_damage - brute) - electronics_damage = max(0, electronics_damage - electronics) - -/datum/robot_component/proc/is_powered() - return (installed == 1) && (brute_damage + electronics_damage < max_damage) && (!idle_usage || powered) - -/datum/robot_component/proc/update_power_state() - if(toggled == 0) - powered = 0 - return - if(owner.cell && owner.cell.charge >= idle_usage) - owner.cell_use_power(idle_usage) - powered = 1 - else - powered = 0 - - -// ARMOUR -// Protects the cyborg from damage. Usually first module to be hit -// No power usage -/datum/robot_component/armour - name = "armour plating" - external_type = /obj/item/robot_parts/robot_component/armour - max_damage = 100 - - -// ACTUATOR -// Enables movement. -// Uses no power when idle. Uses 50J for each tile the cyborg moves. -/datum/robot_component/actuator - name = "actuator" - idle_usage = 0 - active_usage = 50 - external_type = /obj/item/robot_parts/robot_component/actuator - max_damage = 50 - - -//A fixed and much cleaner implementation of /tg/'s special snowflake code. -/datum/robot_component/actuator/is_powered() - return (installed == 1) && (brute_damage + electronics_damage < max_damage) - - -// POWER CELL -// Stores power (how unexpected..) -// No power usage -/datum/robot_component/cell - name = "power cell" - max_damage = 50 - -/datum/robot_component/cell/destroy() - ..() - owner.cell = null - - -// RADIO -// Enables radio communications -// Uses no power when idle. Uses 10J for each received radio message, 50 for each transmitted message. -/datum/robot_component/radio - name = "radio" - external_type = /obj/item/robot_parts/robot_component/radio - active_usage = 10 - max_damage = 40 - - -// BINARY RADIO -// Enables binary communications with other cyborgs/AIs -// Uses no power when idle. Uses 10J for each received radio message, 50 for each transmitted message -/datum/robot_component/binary_communication - name = "binary communication device" - external_type = /obj/item/robot_parts/robot_component/binary_communication_device - active_usage = 10 - max_damage = 30 - - -// CAMERA -// Enables cyborg vision. Can also be remotely accessed via consoles. -// Uses 10J constantly -/datum/robot_component/camera - name = "camera" - external_type = /obj/item/robot_parts/robot_component/camera - idle_usage = 10 - max_damage = 40 - - -// SELF DIAGNOSIS MODULE -// Analyses cyborg's modules, providing damage readouts and basic information -// Uses 1kJ burst when analysis is done -/datum/robot_component/diagnosis_unit - name = "self-diagnosis unit" - active_usage = 1000 - external_type = /obj/item/robot_parts/robot_component/diagnosis_unit - max_damage = 30 - - - - -// HELPER STUFF - - - -// Initializes cyborg's components. Technically, adds default set of components to new borgs -/mob/living/silicon/robot/proc/initialize_components() - components["actuator"] = new/datum/robot_component/actuator(src) - components["radio"] = new/datum/robot_component/radio(src) - components["power cell"] = new/datum/robot_component/cell(src) - components["diagnosis unit"] = new/datum/robot_component/diagnosis_unit(src) - components["camera"] = new/datum/robot_component/camera(src) - components["comms"] = new/datum/robot_component/binary_communication(src) - components["armour"] = new/datum/robot_component/armour(src) - -// Checks if component is functioning -/mob/living/silicon/robot/proc/is_component_functioning(module_name) - var/datum/robot_component/C = components[module_name] - return C && C.installed == 1 && C.toggled && C.is_powered() - -// Returns component by it's string name -/mob/living/silicon/robot/proc/get_component(component_name) - var/datum/robot_component/C = components[component_name] - return C - - - -// COMPONENT OBJECTS - - - -// Component Objects -// These objects are visual representation of modules - -/obj/item/broken_device - name = "broken component" - icon = 'icons/obj/robot_component.dmi' - icon_state = "broken" - -/obj/item/robot_parts/robot_component - icon = 'icons/obj/robot_component.dmi' - icon_state = "working" - var/brute = 0 - var/burn = 0 - var/icon_state_broken = "broken" - -/obj/item/robot_parts/robot_component/binary_communication_device - name = "binary communication device" - icon_state = "binradio" - icon_state_broken = "binradio_broken" - -/obj/item/robot_parts/robot_component/actuator - name = "actuator" - icon_state = "motor" - icon_state_broken = "motor_broken" - -/obj/item/robot_parts/robot_component/armour - name = "armour plating" - icon_state = "armor" - icon_state_broken = "armor_broken" - -/obj/item/robot_parts/robot_component/camera - name = "camera" - icon_state = "camera" - icon_state_broken = "camera_broken" - -/obj/item/robot_parts/robot_component/diagnosis_unit - name = "diagnosis unit" - icon_state = "analyser" - icon_state_broken = "analyser_broken" - -/obj/item/robot_parts/robot_component/radio - name = "radio" - icon_state = "radio" - icon_state_broken = "radio_broken" +// TODO: remove the robot.mmi and robot.cell variables and completely rely on the robot component system + +/datum/robot_component/var/name +/datum/robot_component/var/installed = 0 +/datum/robot_component/var/powered = 0 +/datum/robot_component/var/toggled = 1 +/datum/robot_component/var/brute_damage = 0 +/datum/robot_component/var/electronics_damage = 0 +/datum/robot_component/var/idle_usage = 0 // Amount of power used every MC tick. In joules. +/datum/robot_component/var/active_usage = 0 // Amount of power used for every action. Actions are module-specific. Actuator for each tile moved, etc. +/datum/robot_component/var/max_damage = 30 // HP of this component. +/datum/robot_component/var/mob/living/silicon/robot/owner + +// The actual device object that has to be installed for this. +/datum/robot_component/var/external_type = null + +// The wrapped device(e.g. radio), only set if external_type isn't null +/datum/robot_component/var/obj/item/wrapped = null + +/datum/robot_component/New(mob/living/silicon/robot/R) + src.owner = R + +/datum/robot_component/proc/install() +/datum/robot_component/proc/uninstall() + +/datum/robot_component/proc/destroy() + var/brokenstate = "broken" // Generic icon + if (istype(wrapped, /obj/item/robot_parts/robot_component)) + var/obj/item/robot_parts/robot_component/comp = wrapped + brokenstate = comp.icon_state_broken + if(wrapped) + qdel(wrapped) + + + wrapped = new/obj/item/broken_device + wrapped.icon_state = brokenstate // Module-specific broken icons! Yay! + + // The thing itself isn't there anymore, but some fried remains are. + installed = -1 + uninstall() + +/datum/robot_component/proc/take_damage(brute, electronics, sharp, edge) + if(installed != 1) return + + brute_damage += brute + electronics_damage += electronics + + if(brute_damage + electronics_damage >= max_damage) destroy() + +/datum/robot_component/proc/heal_damage(brute, electronics) + if(installed != 1) + // If it's not installed, can't repair it. + return 0 + + brute_damage = max(0, brute_damage - brute) + electronics_damage = max(0, electronics_damage - electronics) + +/datum/robot_component/proc/is_powered() + return (installed == 1) && (brute_damage + electronics_damage < max_damage) && (!idle_usage || powered) + +/datum/robot_component/proc/update_power_state() + if(toggled == 0) + powered = 0 + return + if(owner.cell && owner.cell.charge >= idle_usage) + owner.cell_use_power(idle_usage) + powered = 1 + else + powered = 0 + + +// ARMOUR +// Protects the cyborg from damage. Usually first module to be hit +// No power usage +/datum/robot_component/armour + name = "armour plating" + external_type = /obj/item/robot_parts/robot_component/armour + max_damage = 100 + + +// ACTUATOR +// Enables movement. +// Uses no power when idle. Uses 50J for each tile the cyborg moves. +/datum/robot_component/actuator + name = "actuator" + idle_usage = 0 + active_usage = 50 + external_type = /obj/item/robot_parts/robot_component/actuator + max_damage = 50 + + +//A fixed and much cleaner implementation of /tg/'s special snowflake code. +/datum/robot_component/actuator/is_powered() + return (installed == 1) && (brute_damage + electronics_damage < max_damage) + + +// POWER CELL +// Stores power (how unexpected..) +// No power usage +/datum/robot_component/cell + name = "power cell" + max_damage = 50 + +/datum/robot_component/cell/destroy() + ..() + owner.cell = null + + +// RADIO +// Enables radio communications +// Uses no power when idle. Uses 10J for each received radio message, 50 for each transmitted message. +/datum/robot_component/radio + name = "radio" + external_type = /obj/item/robot_parts/robot_component/radio + active_usage = 10 + max_damage = 40 + + +// BINARY RADIO +// Enables binary communications with other cyborgs/AIs +// Uses no power when idle. Uses 10J for each received radio message, 50 for each transmitted message +/datum/robot_component/binary_communication + name = "binary communication device" + external_type = /obj/item/robot_parts/robot_component/binary_communication_device + active_usage = 10 + max_damage = 30 + + +// CAMERA +// Enables cyborg vision. Can also be remotely accessed via consoles. +// Uses 10J constantly +/datum/robot_component/camera + name = "camera" + external_type = /obj/item/robot_parts/robot_component/camera + idle_usage = 10 + max_damage = 40 + + +// SELF DIAGNOSIS MODULE +// Analyses cyborg's modules, providing damage readouts and basic information +// Uses 1kJ burst when analysis is done +/datum/robot_component/diagnosis_unit + name = "self-diagnosis unit" + active_usage = 1000 + external_type = /obj/item/robot_parts/robot_component/diagnosis_unit + max_damage = 30 + + + + +// HELPER STUFF + + + +// Initializes cyborg's components. Technically, adds default set of components to new borgs +/mob/living/silicon/robot/proc/initialize_components() + components["actuator"] = new/datum/robot_component/actuator(src) + components["radio"] = new/datum/robot_component/radio(src) + components["power cell"] = new/datum/robot_component/cell(src) + components["diagnosis unit"] = new/datum/robot_component/diagnosis_unit(src) + components["camera"] = new/datum/robot_component/camera(src) + components["comms"] = new/datum/robot_component/binary_communication(src) + components["armour"] = new/datum/robot_component/armour(src) + +// Checks if component is functioning +/mob/living/silicon/robot/proc/is_component_functioning(module_name) + var/datum/robot_component/C = components[module_name] + return C && C.installed == 1 && C.toggled && C.is_powered() + +// Returns component by it's string name +/mob/living/silicon/robot/proc/get_component(component_name) + var/datum/robot_component/C = components[component_name] + return C + + + +// COMPONENT OBJECTS + + + +// Component Objects +// These objects are visual representation of modules + +/obj/item/broken_device + name = "broken component" + icon = 'icons/obj/robot_component.dmi' + icon_state = "broken" + +/obj/item/robot_parts/robot_component + icon = 'icons/obj/robot_component.dmi' + icon_state = "working" + var/brute = 0 + var/burn = 0 + var/icon_state_broken = "broken" + +/obj/item/robot_parts/robot_component/binary_communication_device + name = "binary communication device" + icon_state = "binradio" + icon_state_broken = "binradio_broken" + +/obj/item/robot_parts/robot_component/actuator + name = "actuator" + icon_state = "motor" + icon_state_broken = "motor_broken" + +/obj/item/robot_parts/robot_component/armour + name = "armour plating" + icon_state = "armor" + icon_state_broken = "armor_broken" + +/obj/item/robot_parts/robot_component/camera + name = "camera" + icon_state = "camera" + icon_state_broken = "camera_broken" + +/obj/item/robot_parts/robot_component/diagnosis_unit + name = "diagnosis unit" + icon_state = "analyser" + icon_state_broken = "analyser_broken" + +/obj/item/robot_parts/robot_component/radio + name = "radio" + icon_state = "radio" + icon_state_broken = "radio_broken" diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index a09232b247ce..248b09b71c75 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 - var/atom/movable/overlay/animation = null - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - animation = new(loc) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - - flick("gibbed-r", animation) - robogibs(loc, viruses) - - alive_mob_list -= src - dead_mob_list -= src - spawn(15) - if(animation) qdel(animation) - if(src) qdel(src) - -/mob/living/silicon/robot/dust() - death(1) - var/atom/movable/overlay/animation = null - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - animation = new(loc) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - - flick("dust-r", animation) - 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 - spawn(15) - if(animation) qdel(animation) - if(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 - - 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) - - sql_report_cyborg_death(src) - - return ..(gibbed) +/mob/living/silicon/robot/gib() + //robots don't die when gibbed. instead they drop their MMI'd brain + var/atom/movable/overlay/animation = null + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + animation = new(loc) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + + flick("gibbed-r", animation) + robogibs(loc, viruses) + + alive_mob_list -= src + dead_mob_list -= src + spawn(15) + if(animation) qdel(animation) + if(src) qdel(src) + +/mob/living/silicon/robot/dust() + death(1) + var/atom/movable/overlay/animation = null + monkeyizing = 1 + canmove = 0 + icon = null + invisibility = 101 + + animation = new(loc) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + + flick("dust-r", animation) + 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 + spawn(15) + if(animation) qdel(animation) + if(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 + + 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) + + sql_report_cyborg_death(src) + + return ..(gibbed) diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 46cc1f75ea41..7ce871596f7b 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -1,220 +1,220 @@ -/mob/living/silicon/robot/emote(act,m_type=1,message = null) - 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.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 ("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 ("deathgasp") - message = "[src] shudders violently for a moment, then becomes motionless, its eyes slowly darkening." - 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 - - 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(src.loc, 'sound/machines/twobeep.ogg', 50, 0) - m_type = 1 - - 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(src.loc, 'sound/machines/ping.ogg', 50, 0) - m_type = 1 - - 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(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - m_type = 1 - - if("law") - if (istype(module,/obj/item/weapon/robot_module/security)) - message = "[src] shows its legal authorization barcode." - - playsound(src.loc, 'sound/voice/biamthelaw.ogg', 50, 0) - m_type = 2 - 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(src.loc, 'sound/voice/halt.ogg', 50, 0) - m_type = 2 - else - to_chat(src, "You are not security.") - - 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 - to_chat(src, "\blue Unusable emote '[act]'. Say *help for a list.") - - if ((message && src.stat == CONSCIOUS)) - 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 +/mob/living/silicon/robot/emote(act,m_type=1,message = null) + 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.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 ("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 ("deathgasp") + message = "[src] shudders violently for a moment, then becomes motionless, its eyes slowly darkening." + 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 + + 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(src.loc, 'sound/machines/twobeep.ogg', 50, 0) + m_type = 1 + + 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(src.loc, 'sound/machines/ping.ogg', 50, 0) + m_type = 1 + + 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(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0) + m_type = 1 + + if("law") + if (istype(module,/obj/item/weapon/robot_module/security)) + message = "[src] shows its legal authorization barcode." + + playsound(src.loc, 'sound/voice/biamthelaw.ogg', 50, 0) + m_type = 2 + 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(src.loc, 'sound/voice/halt.ogg', 50, 0) + m_type = 2 + else + to_chat(src, "You are not security.") + + 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 + to_chat(src, "\blue Unusable emote '[act]'. Say *help for a list.") + + if ((message && src.stat == CONSCIOUS)) + 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 aa8da3a9a8f7..3a518a5821da 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) - var/msg = "*---------*\nThis is [bicon(src)] \a [src][custom_name ? ", [modtype] [braintype]" : ""]!\n" - msg += "" - 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" - - if(!has_power) - msg += "It appears to be running on backup power.\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 += "\n[print_flavor_text()]\n" - - if (pose) - if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) - pose = addtext(pose,".") //Makes sure all emotes end with a period. - msg += "\nIt is [pose]" - - to_chat(user, msg) +/mob/living/silicon/robot/examine(mob/user) + var/msg = "*---------*\nThis is [bicon(src)] \a [src][custom_name ? ", [modtype] [braintype]" : ""]!\n" + msg += "" + 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" + + if(!has_power) + msg += "It appears to be running on backup power.\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 += "\n[print_flavor_text()]\n" + + if (pose) + if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 ) + pose = addtext(pose,".") //Makes sure all emotes end with a period. + msg += "\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 8772437a6f79..c0566f8a6320 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -1,245 +1,245 @@ -//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 - -/*-------TODOOOOOOOOOO--------*/ - -/mob/living/silicon/robot/u_equip(obj/W) - if(!W || (W != get_active_hand())) - return 0 - uneq_active() - return 1 - -/mob/living/silicon/robot/proc/uneq_active() - if(isnull(module_active)) - return - if(module_state_1 == module_active) - if(istype(module_state_1,/obj/item/borg/sight)) - sight_mode &= ~module_state_1:sight_mode - if (client) - client.screen -= module_state_1 - contents -= module_state_1 - module_active = null - module_state_1:loc = module //So it can be used again later - module_state_1 = null - inv1.icon_state = "inv1" - else if(module_state_2 == module_active) - if(istype(module_state_2,/obj/item/borg/sight)) - sight_mode &= ~module_state_2:sight_mode - if (client) - client.screen -= module_state_2 - contents -= module_state_2 - module_active = null - module_state_2:loc = module - module_state_2 = null - inv2.icon_state = "inv2" - else if(module_state_3 == module_active) - if(istype(module_state_3,/obj/item/borg/sight)) - sight_mode &= ~module_state_3:sight_mode - if (client) - client.screen -= module_state_3 - contents -= module_state_3 - module_active = null - module_state_3:loc = module - module_state_3 = null - inv3.icon_state = "inv3" - updateicon() - -/mob/living/silicon/robot/proc/uneq_all() - module_active = null - - if(module_state_1) - if(istype(module_state_1,/obj/item/borg/sight)) - sight_mode &= ~module_state_1:sight_mode - if (client) - client.screen -= module_state_1 - contents -= module_state_1 - module_state_1:loc = module - module_state_1 = null - inv1.icon_state = "inv1" - if(module_state_2) - if(istype(module_state_2,/obj/item/borg/sight)) - sight_mode &= ~module_state_2:sight_mode - if (client) - client.screen -= module_state_2 - contents -= module_state_2 - module_state_2:loc = module - module_state_2 = null - inv2.icon_state = "inv2" - if(module_state_3) - if(istype(module_state_3,/obj/item/borg/sight)) - sight_mode &= ~module_state_3:sight_mode - if (client) - client.screen -= module_state_3 - contents -= module_state_3 - module_state_3:loc = module - module_state_3 = null - inv3.icon_state = "inv3" - 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(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(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(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(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(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/proc/activate_module(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 = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - O.screen_loc = inv1.screen_loc - contents += O - if(istype(module_state_1,/obj/item/borg/sight)) - sight_mode |= module_state_1:sight_mode - else if(!module_state_2) - module_state_2 = O - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - O.screen_loc = inv2.screen_loc - contents += O - if(istype(module_state_2,/obj/item/borg/sight)) - sight_mode |= module_state_2:sight_mode - else if(!module_state_3) - module_state_3 = O - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - O.screen_loc = inv3.screen_loc - contents += O - if(istype(module_state_3,/obj/item/borg/sight)) - sight_mode |= module_state_3:sight_mode - else - to_chat(src, "You need to disable a module first!") +//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 + +/*-------TODOOOOOOOOOO--------*/ + +/mob/living/silicon/robot/u_equip(obj/W) + if(!W || (W != get_active_hand())) + return 0 + uneq_active() + return 1 + +/mob/living/silicon/robot/proc/uneq_active() + if(isnull(module_active)) + return + if(module_state_1 == module_active) + if(istype(module_state_1,/obj/item/borg/sight)) + sight_mode &= ~module_state_1:sight_mode + if (client) + client.screen -= module_state_1 + contents -= module_state_1 + module_active = null + module_state_1:loc = module //So it can be used again later + module_state_1 = null + inv1.icon_state = "inv1" + else if(module_state_2 == module_active) + if(istype(module_state_2,/obj/item/borg/sight)) + sight_mode &= ~module_state_2:sight_mode + if (client) + client.screen -= module_state_2 + contents -= module_state_2 + module_active = null + module_state_2:loc = module + module_state_2 = null + inv2.icon_state = "inv2" + else if(module_state_3 == module_active) + if(istype(module_state_3,/obj/item/borg/sight)) + sight_mode &= ~module_state_3:sight_mode + if (client) + client.screen -= module_state_3 + contents -= module_state_3 + module_active = null + module_state_3:loc = module + module_state_3 = null + inv3.icon_state = "inv3" + updateicon() + +/mob/living/silicon/robot/proc/uneq_all() + module_active = null + + if(module_state_1) + if(istype(module_state_1,/obj/item/borg/sight)) + sight_mode &= ~module_state_1:sight_mode + if (client) + client.screen -= module_state_1 + contents -= module_state_1 + module_state_1:loc = module + module_state_1 = null + inv1.icon_state = "inv1" + if(module_state_2) + if(istype(module_state_2,/obj/item/borg/sight)) + sight_mode &= ~module_state_2:sight_mode + if (client) + client.screen -= module_state_2 + contents -= module_state_2 + module_state_2:loc = module + module_state_2 = null + inv2.icon_state = "inv2" + if(module_state_3) + if(istype(module_state_3,/obj/item/borg/sight)) + sight_mode &= ~module_state_3:sight_mode + if (client) + client.screen -= module_state_3 + contents -= module_state_3 + module_state_3:loc = module + module_state_3 = null + inv3.icon_state = "inv3" + 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(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(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(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(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(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/proc/activate_module(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 = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + O.screen_loc = inv1.screen_loc + contents += O + if(istype(module_state_1,/obj/item/borg/sight)) + sight_mode |= module_state_1:sight_mode + else if(!module_state_2) + module_state_2 = O + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + O.screen_loc = inv2.screen_loc + contents += O + if(istype(module_state_2,/obj/item/borg/sight)) + sight_mode |= module_state_2:sight_mode + else if(!module_state_3) + module_state_3 = O + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + O.screen_loc = inv3.screen_loc + contents += O + if(istype(module_state_3,/obj/item/borg/sight)) + sight_mode |= module_state_3:sight_mode + else + to_chat(src, "You need to disable a module first!") diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm index aad6f1560d48..d3272a52bfb8 100644 --- a/code/modules/mob/living/silicon/robot/laws.dm +++ b/code/modules/mob/living/silicon/robot/laws.dm @@ -1,189 +1,189 @@ -/mob/living/silicon/robot/show_laws(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() - photosync() - to_chat(src, "Laws synced with AI, be sure to note any changes.") - 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 - to_chat(src, "No AI selected to sync laws with, disabling lawsync protocol.") - lawupdate = 0 - - to_chat(who, "Obey these laws:") - 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) - to_chat(who, "Remember, [connected_ai.name] is your master, other AIs can be ignored.") - else if (emagged) - to_chat(who, "Remember, you are not required to listen to the AI.") - 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/proc/has_zeroth_law() - return laws.zeroth - -/mob/living/silicon/robot/proc/set_zeroth_law(law) - throw_alert("newlaw") - laws_sanity_check() - laws.set_zeroth_law(law) - -/mob/living/silicon/robot/set_zeroth_law(law, law_borg) - ..() - if(tracking_entities) - to_chat(src, "Internal camera is currently being accessed.") - -/mob/living/silicon/robot/proc/add_inherent_law(law) - throw_alert("newlaw") - laws_sanity_check() - laws.add_inherent_law(law) - -/mob/living/silicon/robot/proc/clear_inherent_laws() - throw_alert("newlaw") - laws_sanity_check() - laws.clear_inherent_laws() - -/mob/living/silicon/robot/proc/add_supplied_law(number, law) - throw_alert("newlaw") - laws_sanity_check() - laws.add_supplied_law(number, law) - -/mob/living/silicon/robot/proc/clear_supplied_laws() - throw_alert("newlaw") - laws_sanity_check() - laws.clear_supplied_laws() - -/mob/living/silicon/robot/proc/add_ion_law(law) - throw_alert("newlaw") - laws_sanity_check() - laws.add_ion_law(law) - -/mob/living/silicon/robot/proc/clear_ion_laws() - throw_alert("newlaw") - laws_sanity_check() - laws.clear_ion_laws() - -/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/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite - 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(entity_ja(list), "window=laws") +/mob/living/silicon/robot/show_laws(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() + photosync() + to_chat(src, "Laws synced with AI, be sure to note any changes.") + 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 + to_chat(src, "No AI selected to sync laws with, disabling lawsync protocol.") + lawupdate = 0 + + to_chat(who, "Obey these laws:") + 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) + to_chat(who, "Remember, [connected_ai.name] is your master, other AIs can be ignored.") + else if (emagged) + to_chat(who, "Remember, you are not required to listen to the AI.") + 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/proc/has_zeroth_law() + return laws.zeroth + +/mob/living/silicon/robot/proc/set_zeroth_law(law) + throw_alert("newlaw") + laws_sanity_check() + laws.set_zeroth_law(law) + +/mob/living/silicon/robot/set_zeroth_law(law, law_borg) + ..() + if(tracking_entities) + to_chat(src, "Internal camera is currently being accessed.") + +/mob/living/silicon/robot/proc/add_inherent_law(law) + throw_alert("newlaw") + laws_sanity_check() + laws.add_inherent_law(law) + +/mob/living/silicon/robot/proc/clear_inherent_laws() + throw_alert("newlaw") + laws_sanity_check() + laws.clear_inherent_laws() + +/mob/living/silicon/robot/proc/add_supplied_law(number, law) + throw_alert("newlaw") + laws_sanity_check() + laws.add_supplied_law(number, law) + +/mob/living/silicon/robot/proc/clear_supplied_laws() + throw_alert("newlaw") + laws_sanity_check() + laws.clear_supplied_laws() + +/mob/living/silicon/robot/proc/add_ion_law(law) + throw_alert("newlaw") + laws_sanity_check() + laws.add_ion_law(law) + +/mob/living/silicon/robot/proc/clear_ion_laws() + throw_alert("newlaw") + laws_sanity_check() + laws.clear_ion_laws() + +/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/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite + 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(entity_ja(list), "window=laws") diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index e6f1e7b7f1ba..89f6bdfd1bcf 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -1,314 +1,314 @@ -/mob/living/silicon/robot/Life() - set invisibility = 0 - //set background = 1 - - if (src.monkeyizing) - return - - src.blinded = null - - //Status updates, death etc. - clamp_values() - handle_regular_status_updates() - handle_actions() - - if(client) - handle_regular_hud_updates() - update_items() - if (src.stat != DEAD) //still using power - add_ingame_age() - use_power() - process_killswitch() - process_locks() - update_canmove() - -/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() - // Debug only - used_power_this_tick = 0 - for(var/V in components) - var/datum/robot_component/C = components[V] - C.update_power_state() - - if ( cell && is_component_functioning("power cell") && src.cell.charge > 0 ) - if(src.module_state_1) - cell_use_power(50) // 50W load for every enabled tool TODO: tool-specific loads - if(src.module_state_2) - cell_use_power(50) - if(src.module_state_3) - cell_use_power(50) - - if(lights_on) - cell_use_power(30) // 30W light. Normal lights would use ~15W, but increased for balance reasons. - - src.has_power = 1 - else - if (src.has_power) - to_chat(src, "\red You are now running on emergency backup power.") - src.has_power = 0 - if(lights_on) // Light is on but there is no power! - lights_on = 0 - set_light(0) - -/mob/living/silicon/robot/proc/handle_regular_status_updates() - - if(src.camera && !scrambledcodes) - if(src.stat == DEAD || wires.is_index_cut(BORG_WIRE_CAMERA)) - src.camera.status = 0 - else - src.camera.status = 1 - - updatehealth() - - if(src.sleeping) - Paralyse(3) - src.sleeping-- - - if(src.resting) - Weaken(5) - - if(health < config.health_threshold_dead && src.stat != DEAD) //die only once - death() - - if (src.stat != DEAD) //Alive. - if (src.paralysis || src.stunned || src.weakened || !src.has_power) //Stunned etc. - src.stat = UNCONSCIOUS - 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 = CONSCIOUS - - else //Dead. - src.blinded = 1 - src.stat = DEAD - - 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 (src.confused > 0) - src.confused-- - src.confused = max(0, src.confused) - - //update the state of modules and components here - if (src.stat != CONSCIOUS) - uneq_all() - - if(!is_component_functioning("radio")) - radio.on = 0 - else - radio.on = 1 - - if(is_component_functioning("camera")) - if(!src.eye_blind) - src.blinded = 0 - else - src.blinded = 1 - - if(!is_component_functioning("actuator")) - src.Paralyse(3) - - - return 1 - -/mob/living/silicon/robot/handle_regular_hud_updates() - if(!client) - return 0 - - if (src.stat == DEAD || XRAY in mutations || src.sight_mode & BORGXRAY) - set_EyesVision() - 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) - set_EyesVision("meson") - src.sight |= SEE_TURFS - src.see_in_dark = 8 - see_invisible = SEE_INVISIBLE_MINIMUM - else if (src.sight_mode & BORGNIGHT) - set_EyesVision("nvg") - src.see_in_dark = 8 - else if (src.sight_mode & BORGTHERM) - set_EyesVision("thermal") - src.sight |= SEE_MOBS - src.see_in_dark = 8 - src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - else if (src.stat != DEAD) - set_EyesVision() - 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() - - var/obj/item/borg/sight/hud/hud = (locate(/obj/item/borg/sight/hud) in src) - if(hud && hud.hud) - hud.hud.process_hud(src) - else - switch(src.sensor_mode) - if (SEC_HUD) - process_sec_hud(src,0) - if (MED_HUD) - process_med_hud(src,0) - - if (src.healths) - if (src.stat != DEAD) - if(istype(src,/mob/living/silicon/robot/drone)) - switch(health) - if(15 to INFINITY) - src.healths.icon_state = "health0" - if(10 to 14) - src.healths.icon_state = "health1" - if(8 to 10) - src.healths.icon_state = "health2" - if(5 to 8) - src.healths.icon_state = "health3" - if(0 to 5) - src.healths.icon_state = "health4" - if(-15 to 0) - src.healths.icon_state = "health5" - else - src.healths.icon_state = "health6" - else - 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.cell) - var/cellcharge = src.cell.charge/src.cell.maxcharge - switch(cellcharge) - if(0.75 to INFINITY) - clear_alert("charge") - if(0.5 to 0.75) - throw_alert("charge","lowcell",1) - if(0.25 to 0.5) - throw_alert("charge","lowcell",2) - if(0.01 to 0.25) - throw_alert("charge","lowcell",3) - else - throw_alert("charge","emptycell") - else - throw_alert("charge","nocell") - - if(pullin) - if(pulling) - pullin.icon_state = "pull" - else - pullin.icon_state = "pull0" - - ..() - - 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/stock_parts/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, "\red 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, "\red Weapon Lock Timed Out!") - weapon_lock = 0 - weaponlock_time = 120 - -/mob/living/silicon/robot/update_canmove() - if(paralysis || stunned || weakened || buckled || lockcharge || pinned.len) - canmove = FALSE - else - canmove = TRUE - return canmove +/mob/living/silicon/robot/Life() + set invisibility = 0 + //set background = 1 + + if (src.monkeyizing) + return + + src.blinded = null + + //Status updates, death etc. + clamp_values() + handle_regular_status_updates() + handle_actions() + + if(client) + handle_regular_hud_updates() + update_items() + if (src.stat != DEAD) //still using power + add_ingame_age() + use_power() + process_killswitch() + process_locks() + update_canmove() + +/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() + // Debug only + used_power_this_tick = 0 + for(var/V in components) + var/datum/robot_component/C = components[V] + C.update_power_state() + + if ( cell && is_component_functioning("power cell") && src.cell.charge > 0 ) + if(src.module_state_1) + cell_use_power(50) // 50W load for every enabled tool TODO: tool-specific loads + if(src.module_state_2) + cell_use_power(50) + if(src.module_state_3) + cell_use_power(50) + + if(lights_on) + cell_use_power(30) // 30W light. Normal lights would use ~15W, but increased for balance reasons. + + src.has_power = 1 + else + if (src.has_power) + to_chat(src, "\red You are now running on emergency backup power.") + src.has_power = 0 + if(lights_on) // Light is on but there is no power! + lights_on = 0 + set_light(0) + +/mob/living/silicon/robot/proc/handle_regular_status_updates() + + if(src.camera && !scrambledcodes) + if(src.stat == DEAD || wires.is_index_cut(BORG_WIRE_CAMERA)) + src.camera.status = 0 + else + src.camera.status = 1 + + updatehealth() + + if(src.sleeping) + Paralyse(3) + src.sleeping-- + + if(src.resting) + Weaken(5) + + if(health < config.health_threshold_dead && src.stat != DEAD) //die only once + death() + + if (src.stat != DEAD) //Alive. + if (src.paralysis || src.stunned || src.weakened || !src.has_power) //Stunned etc. + src.stat = UNCONSCIOUS + 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 = CONSCIOUS + + else //Dead. + src.blinded = 1 + src.stat = DEAD + + 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 (src.confused > 0) + src.confused-- + src.confused = max(0, src.confused) + + //update the state of modules and components here + if (src.stat != CONSCIOUS) + uneq_all() + + if(!is_component_functioning("radio")) + radio.on = 0 + else + radio.on = 1 + + if(is_component_functioning("camera")) + if(!src.eye_blind) + src.blinded = 0 + else + src.blinded = 1 + + if(!is_component_functioning("actuator")) + src.Paralyse(3) + + + return 1 + +/mob/living/silicon/robot/handle_regular_hud_updates() + if(!client) + return 0 + + if (src.stat == DEAD || XRAY in mutations || src.sight_mode & BORGXRAY) + set_EyesVision() + 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) + set_EyesVision("meson") + src.sight |= SEE_TURFS + src.see_in_dark = 8 + see_invisible = SEE_INVISIBLE_MINIMUM + else if (src.sight_mode & BORGNIGHT) + set_EyesVision("nvg") + src.see_in_dark = 8 + else if (src.sight_mode & BORGTHERM) + set_EyesVision("thermal") + src.sight |= SEE_MOBS + src.see_in_dark = 8 + src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + else if (src.stat != DEAD) + set_EyesVision() + 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() + + var/obj/item/borg/sight/hud/hud = (locate(/obj/item/borg/sight/hud) in src) + if(hud && hud.hud) + hud.hud.process_hud(src) + else + switch(src.sensor_mode) + if (SEC_HUD) + process_sec_hud(src,0) + if (MED_HUD) + process_med_hud(src,0) + + if (src.healths) + if (src.stat != DEAD) + if(istype(src,/mob/living/silicon/robot/drone)) + switch(health) + if(15 to INFINITY) + src.healths.icon_state = "health0" + if(10 to 14) + src.healths.icon_state = "health1" + if(8 to 10) + src.healths.icon_state = "health2" + if(5 to 8) + src.healths.icon_state = "health3" + if(0 to 5) + src.healths.icon_state = "health4" + if(-15 to 0) + src.healths.icon_state = "health5" + else + src.healths.icon_state = "health6" + else + 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.cell) + var/cellcharge = src.cell.charge/src.cell.maxcharge + switch(cellcharge) + if(0.75 to INFINITY) + clear_alert("charge") + if(0.5 to 0.75) + throw_alert("charge","lowcell",1) + if(0.25 to 0.5) + throw_alert("charge","lowcell",2) + if(0.01 to 0.25) + throw_alert("charge","lowcell",3) + else + throw_alert("charge","emptycell") + else + throw_alert("charge","nocell") + + if(pullin) + if(pulling) + pullin.icon_state = "pull" + else + pullin.icon_state = "pull0" + + ..() + + 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/stock_parts/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, "\red 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, "\red Weapon Lock Timed Out!") + weapon_lock = 0 + weaponlock_time = 120 + +/mob/living/silicon/robot/update_canmove() + if(paralysis || stunned || weakened || buckled || lockcharge || pinned.len) + canmove = FALSE + else + canmove = TRUE + return canmove diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm index cf55cdd5f911..0a3225011d83 100644 --- a/code/modules/mob/living/silicon/robot/login.dm +++ b/code/modules/mob/living/silicon/robot/login.dm @@ -1,4 +1,4 @@ -/mob/living/silicon/robot/Login() - ..() - regenerate_icons() - show_laws(0) +/mob/living/silicon/robot/Login() + ..() + regenerate_icons() + show_laws(0) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 2e2bc74b426b..ff905f77c638 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1,1326 +1,1326 @@ -#define CYBORG_POWER_USAGE_MULTIPLIER 2.5 // Multiplier for amount of power cyborgs use. - -/mob/living/silicon/robot - name = "Cyborg" - real_name = "Cyborg" - icon = 'icons/mob/robots.dmi' - icon_state = "robot" - maxHealth = 200 - health = 200 - - var/lights_on = 0 // Is our integrated light on? - var/used_power_this_tick = 0 - var/sight_mode = 0 - var/custom_name = "" - var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best - var/crisis //Admin-settable for combat module use. - var/datum/wires/robot/wires = null - -//Hud stuff - - var/obj/screen/inv1 = null - var/obj/screen/inv2 = null - var/obj/screen/inv3 = null - - var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not - var/shown_robot_pda = 0 - var/shown_robot_foto = 0 - var/obj/screen/robot_modules_background - -//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/borg/radio = null - var/mob/living/silicon/ai/connected_ai = null - var/obj/item/weapon/stock_parts/cell/cell = null - var/obj/machinery/camera/camera = null - - // Components are basically robot organs. - var/list/components = list() - - var/obj/item/device/mmi/mmi = null - - var/opened = 0 - var/emagged = 0 - var/wiresexposed = 0 - var/locked = 1 - var/has_power = 1 - var/list/req_access = list(access_robotics) - var/ident = 0 - //var/list/laws = list() - var/viewalerts = 0 - var/modtype = "Default" - var/lower_mod = 0 - var/jetpack = 0 - var/datum/effect/effect/system/ion_trail_follow/ion_trail = null - var/datum/effect/effect/system/spark_spread/spark_system//So they can initialize sparks whenever/N - var/jeton = 0 - var/killswitch = 0 - var/killswitch_time = 60 - var/weapon_lock = 0 - var/weaponlock_time = 120 - var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default - var/lawcheck[1] //For stating laws. - var/ioncheck[1] //Ditto. - var/lockcharge //Used when locking down a borg to preserve cell charge - var/speed = 0 //Cause sec borgs gotta go fast //No they dont! - var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. - var/tracking_entities = 0 //The number of known entities currently accessing the internal camera - var/braintype = "Cyborg" - var/pose - -/mob/living/silicon/robot/atom_init() - spark_system = new /datum/effect/effect/system/spark_spread() - spark_system.set_up(5, 0, src) - spark_system.attach(src) - - wires = new(src) - - robot_modules_background = new() - robot_modules_background.icon_state = "block" - robot_modules_background.layer = HUD_LAYER //Objects that appear on screen are on layer 20, UI should be just below it. - robot_modules_background.plane = HUD_PLANE - ident = rand(1, 999) - updatename("Default") - updateicon() - - init() - - radio = new /obj/item/device/radio/borg(src) - if(!scrambledcodes && !camera) - camera = new /obj/machinery/camera(src) - camera.c_tag = real_name - camera.replace_networks(list("SS13","Robots")) - if(wires.is_index_cut(BORG_WIRE_CAMERA)) - camera.status = 0 - - initialize_components() - // Create all the robot parts. - for(var/V in components) if(V != "power cell") - var/datum/robot_component/C = components[V] - C.installed = 1 - C.wrapped = new C.external_type - - if(!cell) - cell = new /obj/item/weapon/stock_parts/cell(src) - cell.maxcharge = 7500 - cell.charge = 7500 - - . = ..() - - if(cell) - var/datum/robot_component/cell_component = components["power cell"] - cell_component.wrapped = cell - cell_component.installed = 1 - - hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudhealth100") - hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") - -/mob/living/silicon/robot/proc/init() - aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src) - laws = new /datum/ai_laws/nanotrasen() - connected_ai = select_active_ai_with_fewest_borgs() - if(connected_ai) - connected_ai.connected_robots += src - lawsync() - photosync() - lawupdate = 1 - else - lawupdate = 0 - - playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) - -// setup the PDA and its name -/mob/living/silicon/robot/proc/setup_PDA() - if (!pda) - pda = new/obj/item/device/pda/silicon/robot(src) - pda.set_name_and_job(custom_name,"[modtype] [braintype]") - -//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO -//Improved /N -/mob/living/silicon/robot/Destroy() - if(mmi)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside. - var/turf/T = get_turf(loc)//To hopefully prevent run time errors. - if(T) mmi.loc = T - if(mind) mind.transfer_to(mmi.brainmob) - mmi = null - return ..() - -/mob/living/silicon/robot/proc/pick_module() - if(module) - return - var/list/modules = list("Standard", "Engineering", "Surgeon", "Crisis", "Miner", "Janitor", "Service", "Security", "Science") - if(crisis && security_level == SEC_LEVEL_RED) //Leaving this in until it's balanced appropriately. - to_chat(src, "\red Crisis mode active. Combat module available.") - modules+="Combat" - modtype = input("Please, select a module!", "Robot", null, null) in modules - - var/module_sprites[0] //Used to store the associations between sprite names and sprite index. - - if(module) - return - - switch(modtype) - if("Standard") - module = new /obj/item/weapon/robot_module/standard(src) - module_sprites["Basic"] = "robot_old" - module_sprites["Android"] = "droid" - module_sprites["Default"] = "robot" - module_sprites["Drone"] = "drone-standard" - module_sprites["Acheron"] = "mechoid-Standard" - module_sprites["Spider"] = "spider-standard" - module_sprites["Kodiak"] = "kodiak-standard" - - if("Service") - module = new /obj/item/weapon/robot_module/butler(src) - module_sprites["Waitress"] = "Service" - module_sprites["Kent"] = "toiletbot" - module_sprites["Bro"] = "Brobot" - module_sprites["Rich"] = "maximillion" - module_sprites["Default"] = "Service2" - module_sprites["Drone"] = "drone-service" // How does this even work...? Oh well. - module_sprites["Acheron"] = "mechoid-Service" - module_sprites["Kodiak"] = "kodiak-service" - - if("Science") - module = new /obj/item/weapon/robot_module/science(src) - module.channels = list("Science" = 1) - if(camera && "Robots" in camera.network) - camera.add_network("Science") - module_sprites["Toxin"] = "toxbot" - module_sprites["Xenobio"] = "xenobot" - module_sprites["Acheron"] = "mechoid-Science" - - if("Miner") - module = new /obj/item/weapon/robot_module/miner(src) - module.channels = list("Supply" = 1) - if(camera && "Robots" in camera.network) - camera.add_network("MINE") - module_sprites["Basic"] = "Miner_old" - module_sprites["Advanced Droid"] = "droid-miner" - module_sprites["Treadhead"] = "Miner" - module_sprites["Drone"] = "drone-miner" - module_sprites["Acheron"] = "mechoid-Miner" - module_sprites["Kodiak"] = "kodiak-miner" - - if("Crisis") - module = new /obj/item/weapon/robot_module/crisis(src) - module.channels = list("Medical" = 1) - if(camera && "Robots" in camera.network) - camera.add_network("Medical") - module_sprites["Basic"] = "Medbot" - module_sprites["Standard"] = "surgeon" - module_sprites["Advanced Droid"] = "droid-medical" - module_sprites["Needles"] = "medicalrobot" - module_sprites["Drone"] = "drone-medical" - module_sprites["Acheron"] = "mechoid-Medical" - - if("Surgeon") - module = new /obj/item/weapon/robot_module/surgeon(src) - module.channels = list("Medical" = 1) - if(camera && "Robots" in camera.network) - camera.add_network("Medical") - module_sprites["Basic"] = "Medbot" - module_sprites["Standard"] = "surgeon" - module_sprites["Advanced Droid"] = "droid-medical" - module_sprites["Needles"] = "medicalrobot" - module_sprites["Drone"] = "drone-surgery" - module_sprites["Acheron"] = "mechoid-Medical" - - if("Security") - module = new /obj/item/weapon/robot_module/security(src) - module.channels = list("Security" = 1) - module_sprites["Basic"] = "secborg" - module_sprites["Red Knight"] = "Security" - module_sprites["Black Knight"] = "securityrobot" - module_sprites["Bloodhound"] = "bloodhound" - module_sprites["Bloodhound - Treaded"] = "secborg+tread" - module_sprites["Drone"] = "drone-sec" - module_sprites["Acheron"] = "mechoid-Security" - module_sprites["Kodiak"] = "kodiak-sec" - - if("Engineering") - module = new /obj/item/weapon/robot_module/engineering(src) - module.channels = list("Engineering" = 1) - if(camera && "Robots" in camera.network) - camera.add_network("Engineering") - module_sprites["Basic"] = "Engineering" - module_sprites["Antique"] = "engineerrobot" - module_sprites["Custom"] = "custom_astra_t3" - module_sprites["Landmate"] = "landmate" - module_sprites["Landmate - Treaded"] = "engiborg+tread" - module_sprites["Drone"] = "drone-engineer" - module_sprites["Acheron"] = "mechoid-Engineering" - module_sprites["Kodiak"] = "kodiak-eng" - - if("Janitor") - module = new /obj/item/weapon/robot_module/janitor(src) - module_sprites["Basic"] = "JanBot2" - module_sprites["Mopbot"] = "janitorrobot" - module_sprites["Mop Gear Rex"] = "mopgearrex" - module_sprites["Drone"] = "drone-janitor" - module_sprites["Acheron"] = "mechoid-Janitor" - - if("Combat") - module = new /obj/item/weapon/robot_module/combat(src) - module_sprites["Combat Android"] = "droid-combat" - module_sprites["Acheron"] = "mechoid-Combat" - module_sprites["Kodiak"] = "kodiak-combat" - module.channels = list("Security" = 1) - - //languages - module.add_languages(src) - - //Custom_sprite check and entry - if (custom_sprite == 1) - module_sprites["Custom"] = "[src.ckey]-[modtype]" - - hands.icon_state = lowertext(modtype) - feedback_inc("cyborg_[lowertext(modtype)]",1) - updatename() - - if(modtype == "Crisis" || modtype == "Surgeon" || modtype == "Security" || modtype == "Combat" || modtype == "Syndicate") - status_flags &= ~CANPUSH - - choose_icon(6,module_sprites) - radio.config(module.channels) - -/mob/living/silicon/robot/proc/updatename(prefix) - if(prefix) - modtype = prefix - if(mmi) - if(istype(mmi, /obj/item/device/mmi/posibrain)) - braintype = "Android" - else - braintype = "Cyborg" - else - braintype = "Robot" - - var/changed_name = "" - if(custom_name) - changed_name = custom_name - if(client) - for(var/obj/screen/screen in client.screen) - if(screen.name == "Namepick") - client.screen -= screen - qdel(screen) - break - else - changed_name = "[modtype] [braintype]-[num2text(ident)]" - real_name = changed_name - name = real_name - - // if we've changed our name, we also need to update the display name for our PDA - setup_PDA() - - //We also need to update name of internal camera. - if (camera) - camera.c_tag = changed_name - - if(!custom_sprite) //Check for custom sprite - var/file = file2text("config/custom_sprites.txt") - var/lines = splittext(file, "\n") - - for(var/line in lines) - // split & clean up - var/list/Entry = splittext(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) //They're in the list? Custom sprite time, var and icon change required - custom_sprite = 1 - icon = 'icons/mob/custom-synthetic.dmi' - if(icon_state == "robot") - icon_state = "[src.ckey]-Standard" - -/mob/living/silicon/robot/proc/Namepick() - set waitfor = FALSE - if(custom_name) - return 0 - var/newname - newname = sanitize_safe(input(src,"You are a robot. Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN) - if (newname) - custom_name = newname - - updatename() - updateicon() - -/mob/living/silicon/robot/show_alerts() - var/dat = "Current Station Alerts\n" - dat += "Close

                    " - for (var/cat in alarms) - dat += text("[cat]
                    \n") - var/list/alarmlist = alarms[cat] - if (alarmlist.len) - for (var/area_name in alarmlist) - var/datum/alarm/alarm = alarmlist[area_name] - dat += "" - dat += text("-- [area_name]") - if (alarm.sources.len > 1) - dat += text("- [alarm.sources.len] sources") - dat += "
                    \n" - else - dat += "-- All Systems Nominal
                    \n" - dat += "
                    \n" - - viewalerts = 1 - src << browse(entity_ja(dat), "window=robotalerts&can_close=0") - -/mob/living/silicon/robot/proc/self_diagnosis() - if(!is_component_functioning("diagnosis unit")) - to_chat(src, "Your self-diagnosis component isn't functioning.") - return - var/datum/robot_component/CO = get_component("diagnosis unit") - if (!cell_use_power(CO.active_usage)) - to_chat(src, "Low Power.") - - var/dat = "[src.name] Self-Diagnosis Report\n" - for (var/V in components) - var/datum/robot_component/C = components[V] - dat += "[C.name]
                    Brute Damage:[C.brute_damage]
                    Electronics Damage:[C.electronics_damage]
                    Powered:[(!C.idle_usage || C.is_powered()) ? "Yes" : "No"]
                    Toggled:[ C.toggled ? "Yes" : "No"]

                    " - - src << browse(entity_ja(dat), "window=robotdiagnosis") - -/mob/living/silicon/robot/proc/toggle_lights() - if (stat == DEAD) - return - lights_on = !lights_on - to_chat(usr, "You [lights_on ? "enable" : "disable"] your integrated light.") - if(lights_on) - set_light(5) - else - set_light(0) - -/mob/living/silicon/robot/proc/toggle_component() - - var/list/installed_components = list() - for(var/V in components) - if(V == "power cell") continue - var/datum/robot_component/C = components[V] - if(C.installed) - installed_components += V - - var/toggle = input(src, "Which component do you want to toggle?", "Toggle Component") as null|anything in installed_components - if(!toggle) - return - - var/datum/robot_component/C = components[toggle] - if(C.toggled) - C.toggled = 0 - to_chat(src, "\red You disable [C.name].") - else - C.toggled = 1 - to_chat(src, "\red You enable [C.name].") - -/mob/living/silicon/robot/blob_act() - if (stat != DEAD) - adjustBruteLoss(60) - updatehealth() - return 1 - return 0 - -// this function shows information about the malf_ai gameplay type in the status screen -/mob/living/silicon/robot/show_malf_ai() - ..() - if(ticker && ticker.mode.name == "AI malfunction") - var/datum/game_mode/malfunction/malf = ticker.mode - for (var/datum/mind/malfai in malf.malf_ai) - if(connected_ai) - if(connected_ai.mind == malfai) - if(malf.apcs >= 3) - stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds") - else if(ticker.mode:malf_mode_declared) - stat(null, "Time left: [max(ticker.mode:AI_win_timeleft/(ticker.mode:apcs/APC_MIN_TO_MALF_DECLARE), 0)]") - return 0 - - -// update the status screen display -/mob/living/silicon/robot/Stat() - ..() - if(statpanel("Status")) - if(cell) - stat(null, text("Charge Left: [round(cell.percent())]%")) - stat(null, text("Cell Rating: [round(cell.maxcharge)]")) // Round just in case we somehow get crazy values - stat(null, text("Power Cell Load: [round(used_power_this_tick)]W")) - else - stat(null, text("No Cell Inserted!")) - - if(module) - var/obj/item/weapon/tank/jetpack/current_jetpack = locate(/obj/item/weapon/tank/jetpack) in module.modules - if(current_jetpack) // if you have a jetpack, show the internal tank pressure - stat("Internal Atmosphere Info", current_jetpack.name) - stat("Tank Pressure", current_jetpack.air_contents.return_pressure()) - - stat(null, text("Lights: [lights_on ? "ON" : "OFF"]")) - -/mob/living/silicon/robot/restrained() - return 0 - - -/mob/living/silicon/robot/ex_act(severity) - if(!blinded) - flash_eyes() - - switch(severity) - if(1.0) - if (stat != DEAD) - adjustBruteLoss(100) - adjustFireLoss(100) - gib() - return - if(2.0) - if (stat != DEAD) - adjustBruteLoss(60) - adjustFireLoss(60) - if(3.0) - if (stat != DEAD) - adjustBruteLoss(30) - - updatehealth() - - -/mob/living/silicon/robot/meteorhit(obj/O) - for(var/mob/M in viewers(src, null)) - M.show_message(text("\red [src] has been hit by [O]"), 1) - //Foreach goto(19) - if (health > 0) - adjustBruteLoss(30) - if ((O.icon_state == "flaming")) - adjustFireLoss(40) - updatehealth() - return - - -/mob/living/silicon/robot/bullet_act(obj/item/projectile/Proj) - ..(Proj) - updatehealth() - if(prob(75) && Proj.damage > 0) spark_system.start() - return 2 - -/mob/living/silicon/robot/triggerAlarm(class, area/A, list/cameralist, source) - if (stat == DEAD) - return 1 - ..() - queueAlarm(text("--- [class] alarm detected in [A.name]!"), class) - - -/mob/living/silicon/robot/cancelAlarm(class, area/A, obj/origin) - var/has_alarm = ..() - - if (!has_alarm) - queueAlarm(text("--- [class] alarm in [A.name] has been cleared."), class, 0) -// if (viewalerts) robot_alerts() - return has_alarm - - -/mob/living/silicon/robot/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/handcuffs)) // fuck i don't even know why isrobot() in handcuff code isn't working so this will have to do - return - - if(opened) // Are they trying to insert something? - for(var/V in components) - var/datum/robot_component/C = components[V] - if(!C.installed && istype(W, C.external_type)) - C.installed = 1 - C.wrapped = W - C.install() - user.drop_item() - W.loc = null - - var/obj/item/robot_parts/robot_component/WC = W - if(istype(WC)) - C.brute_damage = WC.brute - C.electronics_damage = WC.burn - - to_chat(usr, "\blue You install the [W.name].") - - return - - if (istype(W, /obj/item/weapon/weldingtool)) - if (src == user) - to_chat(user, "You lack the reach to be able to repair yourself.") - return - - if (!getBruteLoss()) - to_chat(user, "Nothing to fix here!") - return - user.SetNextMove(CLICK_CD_INTERACT) - var/obj/item/weapon/weldingtool/WT = W - if (WT.remove_fuel(0)) - adjustBruteLoss(-30) - updatehealth() - add_fingerprint(user) - for(var/mob/O in viewers(user, null)) - O.show_message(text("\red [user] has fixed some of the dents on [src]!"), 1) - else - to_chat(user, "Need more welding fuel!") - return - - else if(istype(W, /obj/item/stack/cable_coil) && (wiresexposed || istype(src,/mob/living/silicon/robot/drone))) - if (!getFireLoss()) - to_chat(user, "Nothing to fix here!") - return - user.SetNextMove(CLICK_CD_INTERACT) - var/obj/item/stack/cable_coil/coil = W - if(!coil.use(1)) - return - adjustFireLoss(-30) - updatehealth() - for(var/mob/O in viewers(user, null)) - O.show_message(text("\red [user] has fixed some of the burnt wires on [src]!"), 1) - - else if (istype(W, /obj/item/weapon/crowbar)) // crowbar means open or close the cover - if(opened) - if(cell) - to_chat(user, "You close the cover.") - opened = 0 - updateicon() - else if(wiresexposed && wires.is_all_cut()) - //Cell is out, wires are exposed, remove MMI, produce damaged chassis, baleet original mob. - if(istype(src, /mob/living/silicon/robot/syndicate)) - return - if(!mmi) - to_chat(user, "\The [src] has no brain to remove.") - return - - to_chat(user, "You jam the crowbar into the robot and begin levering [mmi].") - sleep(30) - to_chat(user, "You damage some parts of the chassis, but eventually manage to rip out [mmi]!") - var/obj/item/robot_parts/robot_suit/C = new/obj/item/robot_parts/robot_suit(loc) - C.l_leg = new/obj/item/robot_parts/l_leg(C) - C.r_leg = new/obj/item/robot_parts/r_leg(C) - C.l_arm = new/obj/item/robot_parts/l_arm(C) - C.r_arm = new/obj/item/robot_parts/r_arm(C) - C.update_icon() - new/obj/item/robot_parts/chest(loc) - src.Destroy() - else - // Okay we're not removing the cell or an MMI, but maybe something else? - var/list/removable_components = list() - for(var/V in components) - if(V == "power cell") continue - var/datum/robot_component/C = components[V] - if(C.installed == 1 || C.installed == -1) - removable_components += V - - var/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components - if(!remove) - return - var/datum/robot_component/C = components[remove] - var/obj/item/robot_parts/robot_component/I = C.wrapped - to_chat(user, "You remove \the [I].") - if(istype(I)) - I.brute = C.brute_damage - I.burn = C.electronics_damage - - I.loc = src.loc - - if(C.installed == 1) - C.uninstall() - C.installed = 0 - - else - if(locked) - to_chat(user, "The cover is locked and cannot be opened.") - else - to_chat(user, "You open the cover.") - opened = 1 - updateicon() - - else if (istype(W, /obj/item/weapon/stock_parts/cell) && opened) // trying to put a cell inside - var/datum/robot_component/C = components["power cell"] - if(wiresexposed) - to_chat(user, "Close the panel first.") - else if(cell) - to_chat(user, "There is a power cell already installed.") - else - user.drop_item() - W.loc = src - cell = W - to_chat(user, "You insert the power cell.") - - C.installed = 1 - C.wrapped = W - C.install() - //This will mean that removing and replacing a power cell will repair the mount, but I don't care at this point. ~Z - C.brute_damage = 0 - C.electronics_damage = 0 - - else if (istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool)) - if (!wires.interact(user)) - to_chat(user, "You can't reach the wiring.") - - else if(istype(W, /obj/item/weapon/screwdriver) && opened && !cell) // haxing - wiresexposed = !wiresexposed - to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]") - updateicon() - - else if(istype(W, /obj/item/weapon/screwdriver) && opened && cell) // radio - if(radio) - radio.attackby(W,user)//Push it to the radio to let it handle everything - else - to_chat(user, "Unable to locate a radio.") - updateicon() - - else if(istype(W, /obj/item/device/encryptionkey/) && opened) - if(radio)//sanityyyyyy - radio.attackby(W,user)//GTFO, you have your own procs - else - to_chat(user, "Unable to locate a radio.") - - 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)//still allow them to open the cover - to_chat(user, "The interface seems slightly damaged") - if(opened) - to_chat(user, "You must close the cover to swipe an ID card.") - else - if(allowed(usr)) - locked = !locked - to_chat(user, "You [ locked ? "lock" : "unlock"] [src]'s interface.") - updateicon() - else - to_chat(user, "\red Access denied.") - - else if(istype(W, /obj/item/weapon/card/emag)) // trying to unlock with an emag card - if(!opened)//Cover is closed - if(locked) - user.SetNextMove(CLICK_CD_MELEE) - if(prob(90)) - var/obj/item/weapon/card/emag/emag = W - emag.uses-- - to_chat(user, "You emag the cover lock.") - locked = 0 - else - to_chat(user, "You fail to emag the cover lock.") - to_chat(src, "Hack attempt detected.") - else - to_chat(user, "The cover is already unlocked.") - return - - if(opened)//Cover is open - if(emagged) return//Prevents the X has hit Y with Z message also you cant emag them twice - if(wiresexposed) - to_chat(user, "You must close the panel first") - return - else - sleep(6) - if(prob(50)) - throw_alert("hacked") - emagged = 1 - lawupdate = 0 - connected_ai = null - to_chat(user, "You emag [src]'s interface.") - message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") - log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") - clear_supplied_laws() - clear_inherent_laws() - laws = new /datum/ai_laws/syndicate_override - var/time = time2text(world.realtime,"hh:mm:ss") - lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") - set_zeroth_law("Only [user.real_name] and people he designates as being such are Syndicate Agents.") - to_chat(src, "\red ALERT: Foreign software detected.") - sleep(5) - to_chat(src, "\red Initiating diagnostics...") - sleep(20) - to_chat(src, "\red SynBorg v1.7.1 loaded.") - sleep(5) - to_chat(src, "\red LAW SYNCHRONISATION ERROR") - sleep(5) - to_chat(src, "\red Would you like to send a report to NanoTraSoft? Y/N") - sleep(10) - to_chat(src, "\red > N") - sleep(20) - to_chat(src, "\red ERRORERRORERROR") - to_chat(src, "Obey these laws:") - laws.show_laws(src) - to_chat(src, "\red \b ALERT: [user.real_name] is your new master. Obey your new laws and his commands.") - if(src.module && istype(src.module, /obj/item/weapon/robot_module/miner)) - for(var/obj/item/weapon/pickaxe/drill/borgdrill/D in src.module.modules) - qdel(D) - src.module.modules += new /obj/item/weapon/pickaxe/drill/diamond_drill(src.module) - src.module.rebuild() - updateicon() - else - to_chat(user, "You fail to hack [src]'s interface.") - to_chat(src, "Hack attempt detected.") - return - - else if(istype(W, /obj/item/borg/upgrade/)) - var/obj/item/borg/upgrade/U = W - if(!opened) - to_chat(usr, "You must access the borgs internals!") - else if(!src.module && U.require_module) - to_chat(usr, "The borg must choose a module before he can be upgraded!") - else if(U.locked) - to_chat(usr, "The upgrade is locked and cannot be used yet!") - else - if(U.action(src)) - to_chat(usr, "You apply the upgrade to [src]!") - usr.drop_item() - U.loc = src - else - to_chat(usr, "Upgrade error!") - - - else - if( !(istype(W, /obj/item/device/robotanalyzer) || istype(W, /obj/item/device/healthanalyzer)) ) - spark_system.start() - return ..() - -/mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M) - 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 ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src]'s plating with its scythe-like arm."), 1) - - if ("grab") - if (M == src || anchored || M.lying) - return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - 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("\red [] has grabbed [] passively!", M, src), 1) - - if ("hurt") - M.do_attack_animation(src) - 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)) - O.show_message(text("\red [] has slashed at []!", M, src), 1) - if(prob(8)) - flash_eyes(affect_silicon = 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("\red [] took a swipe at []!", M, src), 1) - - if ("disarm") - if(!(lying)) - M.do_attack_animation(src) - if (rand(1,100) <= 85) - Stun(7) - step(src,get_dir(M,src)) - spawn(5) step(src,get_dir(M,src)) - playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has forced back []!", M, src), 1) - 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("\red [] attempted to force back []!", M, src), 1) - return - - - -/mob/living/silicon/robot/attack_slime(mob/living/carbon/slime/M) - 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("\red 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) - - damage = round(damage / 2) // borgs recieve half damage - adjustBruteLoss(damage) - - - if(M.powerlevel > 0) - var/stunprob = 10 - - 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("\red The [M.name] has electrified []!", src), 1) - - flash_eyes(affect_silicon = 1) - - 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) - adjustBruteLoss(M.powerlevel * rand(6,10)) - - - updatehealth() - - return - -/mob/living/silicon/robot/attack_animal(mob/living/simple_animal/M) - M.do_attack_animation(src) - 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] [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) - adjustBruteLoss(damage) - updatehealth() - - -/mob/living/silicon/robot/attack_hand(mob/user) - - add_fingerprint(user) - if(opened && !wiresexposed && (!istype(user, /mob/living/silicon))) - var/datum/robot_component/cell_component = components["power cell"] - if(cell) - cell.updateicon() - cell.add_fingerprint(user) - user.put_in_active_hand(cell) - to_chat(user, "You remove \the [cell].") - cell = null - cell_component.wrapped = null - cell_component.installed = 0 - updateicon() - else if(cell_component.installed == -1) - cell_component.installed = 0 - var/obj/item/broken_device = cell_component.wrapped - to_chat(user, "You remove \the [broken_device].") - user.put_in_active_hand(broken_device) - -/mob/living/silicon/robot/proc/allowed(mob/M) - //check if it doesn't require any access at all - if(check_access(null)) - return 1 - 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(check_access(H.get_active_hand()) || 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.get_active_hand() && istype(george.get_active_hand(), /obj/item/weapon/card/id) && check_access(george.get_active_hand())) - return 1 - return 0 - -/mob/living/silicon/robot/proc/check_access(obj/item/weapon/card/id/I) - if(!istype(req_access, /list)) //something's very wrong - return 1 - - var/list/L = 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 req_access) - if(req in I.access) //have one of the required accesses - return 1 - return 0 - -/mob/living/silicon/robot/proc/updateicon() - - overlays.Cut() - if(stat == CONSCIOUS) - overlays += "eyes" - overlays.Cut() - overlays += "eyes-[icon_state]" - else - overlays -= "eyes" - - if(opened && custom_sprite == 1) //Custom borgs also have custom panels, heh - if(wiresexposed) - overlays += "[src.ckey]-openpanel +w" - else if(cell) - overlays += "[src.ckey]-openpanel +c" - else - overlays += "[src.ckey]-openpanel -c" - - if(opened && icon_state == "custom_astra_t3") - if(wiresexposed) - overlays += "ov-[icon_state] +w" - else if(cell) - overlays += "ov-[icon_state] +c" - else - overlays += "ov-[icon_state] -c" - - else if (opened && (icon_state == "mechoid-Standard" || icon_state == "mechoid-Service" || icon_state == "mechoid-Science" || icon_state == "mechoid-Miner" || icon_state == "mechoid-Medical" || icon_state == "mechoid-Engineering" || icon_state == "mechoid-Security" || icon_state == "mechoid-Janitor" || icon_state == "mechoid-Combat" ) ) - if(wiresexposed) - overlays += "mechoid-open+w" - else if(cell) - overlays += "mechoid-open+c" - else - overlays += "mechoid-open-c" - else if (opened && (icon_state == "drone-standard" || icon_state == "drone-service" || icon_state == "droid-miner" || icon_state == "drone-medical" || icon_state == "drone-engineer" || icon_state == "drone-sec") ) - if(wiresexposed) - overlays += "drone-openpanel +w" - else if(cell) - overlays += "drone-openpanel +c" - else - overlays += "drone-openpanel -c" - else if(opened) - if(wiresexposed) - overlays += "ov-openpanel +w" - else if(cell) - overlays += "ov-openpanel +c" - else - overlays += "ov-openpanel -c" - - - - if(module_active && istype(module_active,/obj/item/borg/combat/shield)) - overlays += "[icon_state]-shield" - - if(modtype == "Combat") -// var/base_icon = "" -// base_icon = icon_state - if(module_active && istype(module_active,/obj/item/borg/combat/mobility)) - icon_state = "droid-combat-roll" - else - icon_state = "droid-combat" - return - -//Call when target overlay should be added/removed -/mob/living/silicon/robot/update_targeted() - if(!targeted_by && target_locked) - qdel(target_locked) - updateicon() - if (targeted_by && target_locked) - overlays += target_locked - -/mob/living/silicon/robot/proc/installed_modules() - if(weapon_lock) - to_chat(src, "\red Weapon lock active, unable to use modules! Count:[weaponlock_time]") - return - - if(!module) - pick_module() - return - var/dat = "Modules\n" - dat += {" - 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 module.modules) - if (!obj) - dat += text("Resource depleted
                    ") - else if(activated(obj)) - dat += text("[obj]: Activated
                    ") - else - dat += text("[obj]:
                    Activate
                    ") - if (emagged) - if(activated(module.emag)) - dat += text("[module.emag]: Activated
                    ") - else - dat += text("[module.emag]: Activate
                    ") -/* - if(activated(obj)) - dat += text("[obj]: \[Activated | Deactivate\]
                    ") - else - dat += text("[obj]: \[Activate | Deactivated\]
                    ") -*/ - src << browse(entity_ja(dat), "window=robotmod") - - -/mob/living/silicon/robot/Topic(href, href_list) - ..() - - if(usr != src) - return - - if (href_list["showalerts"]) - show_alerts() - return - - if (href_list["mod"]) - var/obj/item/O = locate(href_list["mod"]) - if (istype(O) && (O.loc == src)) - O.attack_self(src) - - if (href_list["act"]) - var/obj/item/O = locate(href_list["act"]) - if (!istype(O) || !(O in src.module.modules)) - return - - if(!((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 = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - contents += O - if(istype(module_state_1,/obj/item/borg/sight)) - sight_mode |= module_state_1:sight_mode - else if(!module_state_2) - module_state_2 = O - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - contents += O - if(istype(module_state_2,/obj/item/borg/sight)) - sight_mode |= module_state_2:sight_mode - else if(!module_state_3) - module_state_3 = O - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - contents += O - if(istype(module_state_3,/obj/item/borg/sight)) - sight_mode |= module_state_3:sight_mode - else - to_chat(src, "You need to disable a module first!") - installed_modules() - - if (href_list["deact"]) - var/obj/item/O = locate(href_list["deact"]) - if(activated(O)) - if(module_state_1 == O) - module_state_1 = null - contents -= O - else if(module_state_2 == O) - module_state_2 = null - contents -= O - else if(module_state_3 == O) - module_state_3 = null - contents -= O - else - to_chat(src, "Module isn't activated.") - else - to_chat(src, "Module isn't activated") - installed_modules() - - 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" -// 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" -// 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() - return - -/mob/living/silicon/robot/proc/radio_menu() - radio.interact(src)//Just use the radio's Topic() instead of bullshit special-snowflake code - - -/mob/living/silicon/robot/Move(a, b, flag) - - . = ..() - - if(module) - if(module.type == /obj/item/weapon/robot_module/janitor) - var/turf/tile = loc - if(isturf(tile)) - tile.clean_blood() - if (istype(tile, /turf/simulated)) - var/turf/simulated/S = tile - S.dirt = 0 - 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() - if(cleaned_human.wear_suit) - cleaned_human.wear_suit.clean_blood() - cleaned_human.update_inv_wear_suit() - else if(cleaned_human.w_uniform) - cleaned_human.w_uniform.clean_blood() - cleaned_human.update_inv_w_uniform() - if(cleaned_human.shoes) - cleaned_human.shoes.clean_blood() - cleaned_human.update_inv_shoes() - cleaned_human.clean_blood(1) - to_chat(cleaned_human, "\red [src] cleans your face!") - return - -/mob/living/silicon/robot/proc/self_destruct() - gib() - return - -/mob/living/silicon/robot/proc/UnlinkSelf() - if (src.connected_ai) - src.connected_ai = null - lawupdate = 0 - lockcharge = 0 - canmove = 1 - scrambledcodes = 1 - //Disconnect it's camera so it's not so easily tracked. - if(src.camera) - src.camera.clear_all_networks() - cameranet.removeCamera(src.camera) - - -/mob/living/silicon/robot/proc/ResetSecurityCodes() - set category = "Robot Commands" - set name = "Reset Identity Codes" - set desc = "Scrambles your security and identification codes and resets your current buffers. Unlocks you and but permenantly severs you from your AI and the robotics console and will deactivate your camera system." - - var/mob/living/silicon/robot/R = src - - if(R) - R.UnlinkSelf() - to_chat(R, "Buffers flushed and reset. Camera system shutdown. All systems operational.") - src.verbs -= /mob/living/silicon/robot/proc/ResetSecurityCodes - -/mob/living/silicon/robot/mode() - set name = "Activate Held Object" - set category = "IC" - set src = usr - - var/obj/item/W = get_active_hand() - if (W) - W.attack_self(src) - - return - -/mob/living/silicon/robot/verb/pose() - set name = "Set Pose" - set desc = "Sets a description which will be shown when someone examines you." - set category = "IC" - - pose = sanitize(input(usr, "This is [src]. It is...", "Pose", input_default(pose)) as text) - -/mob/living/silicon/robot/verb/set_flavor() - set name = "Set Flavour Text" - set desc = "Sets an extended description of your character's features." - set category = "IC" - - flavor_text = sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", input_default(flavor_text)) as text) - -/mob/living/silicon/robot/proc/choose_icon(triesleft, list/module_sprites) - - if(triesleft<1 || !module_sprites.len) - return - else - triesleft-- - - var/icontype - - if (custom_sprite == 1) - icontype = "Custom" - triesleft = 0 - else - icontype = input("Select an icon! [triesleft ? "You have [triesleft] more chances." : "This is your last try."]", "Robot", null, null) in module_sprites - - if(icontype) - icon_state = module_sprites[icontype] - else - to_chat(src, "Something is badly wrong with the sprite selection. Harass a coder.") - icon_state = module_sprites[1] - return - - overlays -= "eyes" - updateicon() - - if (triesleft >= 1) - var/choice = input("Look at your icon - is this what you want?") in list("Yes","No") - if(choice=="No") - choose_icon(triesleft, module_sprites) - else - triesleft = 0 - return - else - to_chat(src, "Your icon has been set. You now require a module reset to change it.") - -// Uses power from cyborg's cell. Returns 1 on success or 0 on failure. -// Properly converts using CELLRATE now! Amount is in Joules. -/mob/living/silicon/robot/proc/cell_use_power(amount = 0) - // No cell inserted - if(!cell) - return 0 - - // Power cell is empty. - if(cell.charge == 0) - return 0 - - if(cell.use(amount * CELLRATE * CYBORG_POWER_USAGE_MULTIPLIER)) - used_power_this_tick += amount * CYBORG_POWER_USAGE_MULTIPLIER - return 1 - return 0 - -/mob/living/silicon/robot/proc/toggle_all_components() - for(var/V in components) - if(V == "power cell") - continue - var/datum/robot_component/C = components[V] - if(C.installed) - C.toggled = !C.toggled +#define CYBORG_POWER_USAGE_MULTIPLIER 2.5 // Multiplier for amount of power cyborgs use. + +/mob/living/silicon/robot + name = "Cyborg" + real_name = "Cyborg" + icon = 'icons/mob/robots.dmi' + icon_state = "robot" + maxHealth = 200 + health = 200 + + var/lights_on = 0 // Is our integrated light on? + var/used_power_this_tick = 0 + var/sight_mode = 0 + var/custom_name = "" + var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best + var/crisis //Admin-settable for combat module use. + var/datum/wires/robot/wires = null + +//Hud stuff + + var/obj/screen/inv1 = null + var/obj/screen/inv2 = null + var/obj/screen/inv3 = null + + var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not + var/shown_robot_pda = 0 + var/shown_robot_foto = 0 + var/obj/screen/robot_modules_background + +//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/borg/radio = null + var/mob/living/silicon/ai/connected_ai = null + var/obj/item/weapon/stock_parts/cell/cell = null + var/obj/machinery/camera/camera = null + + // Components are basically robot organs. + var/list/components = list() + + var/obj/item/device/mmi/mmi = null + + var/opened = 0 + var/emagged = 0 + var/wiresexposed = 0 + var/locked = 1 + var/has_power = 1 + var/list/req_access = list(access_robotics) + var/ident = 0 + //var/list/laws = list() + var/viewalerts = 0 + var/modtype = "Default" + var/lower_mod = 0 + var/jetpack = 0 + var/datum/effect/effect/system/ion_trail_follow/ion_trail = null + var/datum/effect/effect/system/spark_spread/spark_system//So they can initialize sparks whenever/N + var/jeton = 0 + var/killswitch = 0 + var/killswitch_time = 60 + var/weapon_lock = 0 + var/weaponlock_time = 120 + var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default + var/lawcheck[1] //For stating laws. + var/ioncheck[1] //Ditto. + var/lockcharge //Used when locking down a borg to preserve cell charge + var/speed = 0 //Cause sec borgs gotta go fast //No they dont! + var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. + var/tracking_entities = 0 //The number of known entities currently accessing the internal camera + var/braintype = "Cyborg" + var/pose + +/mob/living/silicon/robot/atom_init() + spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src) + spark_system.attach(src) + + wires = new(src) + + robot_modules_background = new() + robot_modules_background.icon_state = "block" + robot_modules_background.layer = HUD_LAYER //Objects that appear on screen are on layer 20, UI should be just below it. + robot_modules_background.plane = HUD_PLANE + ident = rand(1, 999) + updatename("Default") + updateicon() + + init() + + radio = new /obj/item/device/radio/borg(src) + if(!scrambledcodes && !camera) + camera = new /obj/machinery/camera(src) + camera.c_tag = real_name + camera.replace_networks(list("SS13","Robots")) + if(wires.is_index_cut(BORG_WIRE_CAMERA)) + camera.status = 0 + + initialize_components() + // Create all the robot parts. + for(var/V in components) if(V != "power cell") + var/datum/robot_component/C = components[V] + C.installed = 1 + C.wrapped = new C.external_type + + if(!cell) + cell = new /obj/item/weapon/stock_parts/cell(src) + cell.maxcharge = 7500 + cell.charge = 7500 + + . = ..() + + if(cell) + var/datum/robot_component/cell_component = components["power cell"] + cell_component.wrapped = cell + cell_component.installed = 1 + + hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudhealth100") + hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") + +/mob/living/silicon/robot/proc/init() + aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src) + laws = new /datum/ai_laws/nanotrasen() + connected_ai = select_active_ai_with_fewest_borgs() + if(connected_ai) + connected_ai.connected_robots += src + lawsync() + photosync() + lawupdate = 1 + else + lawupdate = 0 + + playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) + +// setup the PDA and its name +/mob/living/silicon/robot/proc/setup_PDA() + if (!pda) + pda = new/obj/item/device/pda/silicon/robot(src) + pda.set_name_and_job(custom_name,"[modtype] [braintype]") + +//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO +//Improved /N +/mob/living/silicon/robot/Destroy() + if(mmi)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside. + var/turf/T = get_turf(loc)//To hopefully prevent run time errors. + if(T) mmi.loc = T + if(mind) mind.transfer_to(mmi.brainmob) + mmi = null + return ..() + +/mob/living/silicon/robot/proc/pick_module() + if(module) + return + var/list/modules = list("Standard", "Engineering", "Surgeon", "Crisis", "Miner", "Janitor", "Service", "Security", "Science") + if(crisis && security_level == SEC_LEVEL_RED) //Leaving this in until it's balanced appropriately. + to_chat(src, "\red Crisis mode active. Combat module available.") + modules+="Combat" + modtype = input("Please, select a module!", "Robot", null, null) in modules + + var/module_sprites[0] //Used to store the associations between sprite names and sprite index. + + if(module) + return + + switch(modtype) + if("Standard") + module = new /obj/item/weapon/robot_module/standard(src) + module_sprites["Basic"] = "robot_old" + module_sprites["Android"] = "droid" + module_sprites["Default"] = "robot" + module_sprites["Drone"] = "drone-standard" + module_sprites["Acheron"] = "mechoid-Standard" + module_sprites["Spider"] = "spider-standard" + module_sprites["Kodiak"] = "kodiak-standard" + + if("Service") + module = new /obj/item/weapon/robot_module/butler(src) + module_sprites["Waitress"] = "Service" + module_sprites["Kent"] = "toiletbot" + module_sprites["Bro"] = "Brobot" + module_sprites["Rich"] = "maximillion" + module_sprites["Default"] = "Service2" + module_sprites["Drone"] = "drone-service" // How does this even work...? Oh well. + module_sprites["Acheron"] = "mechoid-Service" + module_sprites["Kodiak"] = "kodiak-service" + + if("Science") + module = new /obj/item/weapon/robot_module/science(src) + module.channels = list("Science" = 1) + if(camera && "Robots" in camera.network) + camera.add_network("Science") + module_sprites["Toxin"] = "toxbot" + module_sprites["Xenobio"] = "xenobot" + module_sprites["Acheron"] = "mechoid-Science" + + if("Miner") + module = new /obj/item/weapon/robot_module/miner(src) + module.channels = list("Supply" = 1) + if(camera && "Robots" in camera.network) + camera.add_network("MINE") + module_sprites["Basic"] = "Miner_old" + module_sprites["Advanced Droid"] = "droid-miner" + module_sprites["Treadhead"] = "Miner" + module_sprites["Drone"] = "drone-miner" + module_sprites["Acheron"] = "mechoid-Miner" + module_sprites["Kodiak"] = "kodiak-miner" + + if("Crisis") + module = new /obj/item/weapon/robot_module/crisis(src) + module.channels = list("Medical" = 1) + if(camera && "Robots" in camera.network) + camera.add_network("Medical") + module_sprites["Basic"] = "Medbot" + module_sprites["Standard"] = "surgeon" + module_sprites["Advanced Droid"] = "droid-medical" + module_sprites["Needles"] = "medicalrobot" + module_sprites["Drone"] = "drone-medical" + module_sprites["Acheron"] = "mechoid-Medical" + + if("Surgeon") + module = new /obj/item/weapon/robot_module/surgeon(src) + module.channels = list("Medical" = 1) + if(camera && "Robots" in camera.network) + camera.add_network("Medical") + module_sprites["Basic"] = "Medbot" + module_sprites["Standard"] = "surgeon" + module_sprites["Advanced Droid"] = "droid-medical" + module_sprites["Needles"] = "medicalrobot" + module_sprites["Drone"] = "drone-surgery" + module_sprites["Acheron"] = "mechoid-Medical" + + if("Security") + module = new /obj/item/weapon/robot_module/security(src) + module.channels = list("Security" = 1) + module_sprites["Basic"] = "secborg" + module_sprites["Red Knight"] = "Security" + module_sprites["Black Knight"] = "securityrobot" + module_sprites["Bloodhound"] = "bloodhound" + module_sprites["Bloodhound - Treaded"] = "secborg+tread" + module_sprites["Drone"] = "drone-sec" + module_sprites["Acheron"] = "mechoid-Security" + module_sprites["Kodiak"] = "kodiak-sec" + + if("Engineering") + module = new /obj/item/weapon/robot_module/engineering(src) + module.channels = list("Engineering" = 1) + if(camera && "Robots" in camera.network) + camera.add_network("Engineering") + module_sprites["Basic"] = "Engineering" + module_sprites["Antique"] = "engineerrobot" + module_sprites["Custom"] = "custom_astra_t3" + module_sprites["Landmate"] = "landmate" + module_sprites["Landmate - Treaded"] = "engiborg+tread" + module_sprites["Drone"] = "drone-engineer" + module_sprites["Acheron"] = "mechoid-Engineering" + module_sprites["Kodiak"] = "kodiak-eng" + + if("Janitor") + module = new /obj/item/weapon/robot_module/janitor(src) + module_sprites["Basic"] = "JanBot2" + module_sprites["Mopbot"] = "janitorrobot" + module_sprites["Mop Gear Rex"] = "mopgearrex" + module_sprites["Drone"] = "drone-janitor" + module_sprites["Acheron"] = "mechoid-Janitor" + + if("Combat") + module = new /obj/item/weapon/robot_module/combat(src) + module_sprites["Combat Android"] = "droid-combat" + module_sprites["Acheron"] = "mechoid-Combat" + module_sprites["Kodiak"] = "kodiak-combat" + module.channels = list("Security" = 1) + + //languages + module.add_languages(src) + + //Custom_sprite check and entry + if (custom_sprite == 1) + module_sprites["Custom"] = "[src.ckey]-[modtype]" + + hands.icon_state = lowertext(modtype) + feedback_inc("cyborg_[lowertext(modtype)]",1) + updatename() + + if(modtype == "Crisis" || modtype == "Surgeon" || modtype == "Security" || modtype == "Combat" || modtype == "Syndicate") + status_flags &= ~CANPUSH + + choose_icon(6,module_sprites) + radio.config(module.channels) + +/mob/living/silicon/robot/proc/updatename(prefix) + if(prefix) + modtype = prefix + if(mmi) + if(istype(mmi, /obj/item/device/mmi/posibrain)) + braintype = "Android" + else + braintype = "Cyborg" + else + braintype = "Robot" + + var/changed_name = "" + if(custom_name) + changed_name = custom_name + if(client) + for(var/obj/screen/screen in client.screen) + if(screen.name == "Namepick") + client.screen -= screen + qdel(screen) + break + else + changed_name = "[modtype] [braintype]-[num2text(ident)]" + real_name = changed_name + name = real_name + + // if we've changed our name, we also need to update the display name for our PDA + setup_PDA() + + //We also need to update name of internal camera. + if (camera) + camera.c_tag = changed_name + + if(!custom_sprite) //Check for custom sprite + var/file = file2text("config/custom_sprites.txt") + var/lines = splittext(file, "\n") + + for(var/line in lines) + // split & clean up + var/list/Entry = splittext(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) //They're in the list? Custom sprite time, var and icon change required + custom_sprite = 1 + icon = 'icons/mob/custom-synthetic.dmi' + if(icon_state == "robot") + icon_state = "[src.ckey]-Standard" + +/mob/living/silicon/robot/proc/Namepick() + set waitfor = FALSE + if(custom_name) + return 0 + var/newname + newname = sanitize_safe(input(src,"You are a robot. Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN) + if (newname) + custom_name = newname + + updatename() + updateicon() + +/mob/living/silicon/robot/show_alerts() + var/dat = "Current Station Alerts\n" + dat += "Close

                    " + for (var/cat in alarms) + dat += text("[cat]
                    \n") + var/list/alarmlist = alarms[cat] + if (alarmlist.len) + for (var/area_name in alarmlist) + var/datum/alarm/alarm = alarmlist[area_name] + dat += "" + dat += text("-- [area_name]") + if (alarm.sources.len > 1) + dat += text("- [alarm.sources.len] sources") + dat += "
                    \n" + else + dat += "-- All Systems Nominal
                    \n" + dat += "
                    \n" + + viewalerts = 1 + src << browse(entity_ja(dat), "window=robotalerts&can_close=0") + +/mob/living/silicon/robot/proc/self_diagnosis() + if(!is_component_functioning("diagnosis unit")) + to_chat(src, "Your self-diagnosis component isn't functioning.") + return + var/datum/robot_component/CO = get_component("diagnosis unit") + if (!cell_use_power(CO.active_usage)) + to_chat(src, "Low Power.") + + var/dat = "[src.name] Self-Diagnosis Report\n" + for (var/V in components) + var/datum/robot_component/C = components[V] + dat += "[C.name]
                    Brute Damage:[C.brute_damage]
                    Electronics Damage:[C.electronics_damage]
                    Powered:[(!C.idle_usage || C.is_powered()) ? "Yes" : "No"]
                    Toggled:[ C.toggled ? "Yes" : "No"]

                    " + + src << browse(entity_ja(dat), "window=robotdiagnosis") + +/mob/living/silicon/robot/proc/toggle_lights() + if (stat == DEAD) + return + lights_on = !lights_on + to_chat(usr, "You [lights_on ? "enable" : "disable"] your integrated light.") + if(lights_on) + set_light(5) + else + set_light(0) + +/mob/living/silicon/robot/proc/toggle_component() + + var/list/installed_components = list() + for(var/V in components) + if(V == "power cell") continue + var/datum/robot_component/C = components[V] + if(C.installed) + installed_components += V + + var/toggle = input(src, "Which component do you want to toggle?", "Toggle Component") as null|anything in installed_components + if(!toggle) + return + + var/datum/robot_component/C = components[toggle] + if(C.toggled) + C.toggled = 0 + to_chat(src, "\red You disable [C.name].") + else + C.toggled = 1 + to_chat(src, "\red You enable [C.name].") + +/mob/living/silicon/robot/blob_act() + if (stat != DEAD) + adjustBruteLoss(60) + updatehealth() + return 1 + return 0 + +// this function shows information about the malf_ai gameplay type in the status screen +/mob/living/silicon/robot/show_malf_ai() + ..() + if(ticker && ticker.mode.name == "AI malfunction") + var/datum/game_mode/malfunction/malf = ticker.mode + for (var/datum/mind/malfai in malf.malf_ai) + if(connected_ai) + if(connected_ai.mind == malfai) + if(malf.apcs >= 3) + stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds") + else if(ticker.mode:malf_mode_declared) + stat(null, "Time left: [max(ticker.mode:AI_win_timeleft/(ticker.mode:apcs/APC_MIN_TO_MALF_DECLARE), 0)]") + return 0 + + +// update the status screen display +/mob/living/silicon/robot/Stat() + ..() + if(statpanel("Status")) + if(cell) + stat(null, text("Charge Left: [round(cell.percent())]%")) + stat(null, text("Cell Rating: [round(cell.maxcharge)]")) // Round just in case we somehow get crazy values + stat(null, text("Power Cell Load: [round(used_power_this_tick)]W")) + else + stat(null, text("No Cell Inserted!")) + + if(module) + var/obj/item/weapon/tank/jetpack/current_jetpack = locate(/obj/item/weapon/tank/jetpack) in module.modules + if(current_jetpack) // if you have a jetpack, show the internal tank pressure + stat("Internal Atmosphere Info", current_jetpack.name) + stat("Tank Pressure", current_jetpack.air_contents.return_pressure()) + + stat(null, text("Lights: [lights_on ? "ON" : "OFF"]")) + +/mob/living/silicon/robot/restrained() + return 0 + + +/mob/living/silicon/robot/ex_act(severity) + if(!blinded) + flash_eyes() + + switch(severity) + if(1.0) + if (stat != DEAD) + adjustBruteLoss(100) + adjustFireLoss(100) + gib() + return + if(2.0) + if (stat != DEAD) + adjustBruteLoss(60) + adjustFireLoss(60) + if(3.0) + if (stat != DEAD) + adjustBruteLoss(30) + + updatehealth() + + +/mob/living/silicon/robot/meteorhit(obj/O) + for(var/mob/M in viewers(src, null)) + M.show_message(text("\red [src] has been hit by [O]"), 1) + //Foreach goto(19) + if (health > 0) + adjustBruteLoss(30) + if ((O.icon_state == "flaming")) + adjustFireLoss(40) + updatehealth() + return + + +/mob/living/silicon/robot/bullet_act(obj/item/projectile/Proj) + ..(Proj) + updatehealth() + if(prob(75) && Proj.damage > 0) spark_system.start() + return 2 + +/mob/living/silicon/robot/triggerAlarm(class, area/A, list/cameralist, source) + if (stat == DEAD) + return 1 + ..() + queueAlarm(text("--- [class] alarm detected in [A.name]!"), class) + + +/mob/living/silicon/robot/cancelAlarm(class, area/A, obj/origin) + var/has_alarm = ..() + + if (!has_alarm) + queueAlarm(text("--- [class] alarm in [A.name] has been cleared."), class, 0) +// if (viewalerts) robot_alerts() + return has_alarm + + +/mob/living/silicon/robot/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/handcuffs)) // fuck i don't even know why isrobot() in handcuff code isn't working so this will have to do + return + + if(opened) // Are they trying to insert something? + for(var/V in components) + var/datum/robot_component/C = components[V] + if(!C.installed && istype(W, C.external_type)) + C.installed = 1 + C.wrapped = W + C.install() + user.drop_item() + W.loc = null + + var/obj/item/robot_parts/robot_component/WC = W + if(istype(WC)) + C.brute_damage = WC.brute + C.electronics_damage = WC.burn + + to_chat(usr, "\blue You install the [W.name].") + + return + + if (istype(W, /obj/item/weapon/weldingtool)) + if (src == user) + to_chat(user, "You lack the reach to be able to repair yourself.") + return + + if (!getBruteLoss()) + to_chat(user, "Nothing to fix here!") + return + user.SetNextMove(CLICK_CD_INTERACT) + var/obj/item/weapon/weldingtool/WT = W + if (WT.remove_fuel(0)) + adjustBruteLoss(-30) + updatehealth() + add_fingerprint(user) + for(var/mob/O in viewers(user, null)) + O.show_message(text("\red [user] has fixed some of the dents on [src]!"), 1) + else + to_chat(user, "Need more welding fuel!") + return + + else if(istype(W, /obj/item/stack/cable_coil) && (wiresexposed || istype(src,/mob/living/silicon/robot/drone))) + if (!getFireLoss()) + to_chat(user, "Nothing to fix here!") + return + user.SetNextMove(CLICK_CD_INTERACT) + var/obj/item/stack/cable_coil/coil = W + if(!coil.use(1)) + return + adjustFireLoss(-30) + updatehealth() + for(var/mob/O in viewers(user, null)) + O.show_message(text("\red [user] has fixed some of the burnt wires on [src]!"), 1) + + else if (istype(W, /obj/item/weapon/crowbar)) // crowbar means open or close the cover + if(opened) + if(cell) + to_chat(user, "You close the cover.") + opened = 0 + updateicon() + else if(wiresexposed && wires.is_all_cut()) + //Cell is out, wires are exposed, remove MMI, produce damaged chassis, baleet original mob. + if(istype(src, /mob/living/silicon/robot/syndicate)) + return + if(!mmi) + to_chat(user, "\The [src] has no brain to remove.") + return + + to_chat(user, "You jam the crowbar into the robot and begin levering [mmi].") + sleep(30) + to_chat(user, "You damage some parts of the chassis, but eventually manage to rip out [mmi]!") + var/obj/item/robot_parts/robot_suit/C = new/obj/item/robot_parts/robot_suit(loc) + C.l_leg = new/obj/item/robot_parts/l_leg(C) + C.r_leg = new/obj/item/robot_parts/r_leg(C) + C.l_arm = new/obj/item/robot_parts/l_arm(C) + C.r_arm = new/obj/item/robot_parts/r_arm(C) + C.update_icon() + new/obj/item/robot_parts/chest(loc) + src.Destroy() + else + // Okay we're not removing the cell or an MMI, but maybe something else? + var/list/removable_components = list() + for(var/V in components) + if(V == "power cell") continue + var/datum/robot_component/C = components[V] + if(C.installed == 1 || C.installed == -1) + removable_components += V + + var/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components + if(!remove) + return + var/datum/robot_component/C = components[remove] + var/obj/item/robot_parts/robot_component/I = C.wrapped + to_chat(user, "You remove \the [I].") + if(istype(I)) + I.brute = C.brute_damage + I.burn = C.electronics_damage + + I.loc = src.loc + + if(C.installed == 1) + C.uninstall() + C.installed = 0 + + else + if(locked) + to_chat(user, "The cover is locked and cannot be opened.") + else + to_chat(user, "You open the cover.") + opened = 1 + updateicon() + + else if (istype(W, /obj/item/weapon/stock_parts/cell) && opened) // trying to put a cell inside + var/datum/robot_component/C = components["power cell"] + if(wiresexposed) + to_chat(user, "Close the panel first.") + else if(cell) + to_chat(user, "There is a power cell already installed.") + else + user.drop_item() + W.loc = src + cell = W + to_chat(user, "You insert the power cell.") + + C.installed = 1 + C.wrapped = W + C.install() + //This will mean that removing and replacing a power cell will repair the mount, but I don't care at this point. ~Z + C.brute_damage = 0 + C.electronics_damage = 0 + + else if (istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool)) + if (!wires.interact(user)) + to_chat(user, "You can't reach the wiring.") + + else if(istype(W, /obj/item/weapon/screwdriver) && opened && !cell) // haxing + wiresexposed = !wiresexposed + to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]") + updateicon() + + else if(istype(W, /obj/item/weapon/screwdriver) && opened && cell) // radio + if(radio) + radio.attackby(W,user)//Push it to the radio to let it handle everything + else + to_chat(user, "Unable to locate a radio.") + updateicon() + + else if(istype(W, /obj/item/device/encryptionkey/) && opened) + if(radio)//sanityyyyyy + radio.attackby(W,user)//GTFO, you have your own procs + else + to_chat(user, "Unable to locate a radio.") + + 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)//still allow them to open the cover + to_chat(user, "The interface seems slightly damaged") + if(opened) + to_chat(user, "You must close the cover to swipe an ID card.") + else + if(allowed(usr)) + locked = !locked + to_chat(user, "You [ locked ? "lock" : "unlock"] [src]'s interface.") + updateicon() + else + to_chat(user, "\red Access denied.") + + else if(istype(W, /obj/item/weapon/card/emag)) // trying to unlock with an emag card + if(!opened)//Cover is closed + if(locked) + user.SetNextMove(CLICK_CD_MELEE) + if(prob(90)) + var/obj/item/weapon/card/emag/emag = W + emag.uses-- + to_chat(user, "You emag the cover lock.") + locked = 0 + else + to_chat(user, "You fail to emag the cover lock.") + to_chat(src, "Hack attempt detected.") + else + to_chat(user, "The cover is already unlocked.") + return + + if(opened)//Cover is open + if(emagged) return//Prevents the X has hit Y with Z message also you cant emag them twice + if(wiresexposed) + to_chat(user, "You must close the panel first") + return + else + sleep(6) + if(prob(50)) + throw_alert("hacked") + emagged = 1 + lawupdate = 0 + connected_ai = null + to_chat(user, "You emag [src]'s interface.") + message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") + log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") + clear_supplied_laws() + clear_inherent_laws() + laws = new /datum/ai_laws/syndicate_override + var/time = time2text(world.realtime,"hh:mm:ss") + lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") + set_zeroth_law("Only [user.real_name] and people he designates as being such are Syndicate Agents.") + to_chat(src, "\red ALERT: Foreign software detected.") + sleep(5) + to_chat(src, "\red Initiating diagnostics...") + sleep(20) + to_chat(src, "\red SynBorg v1.7.1 loaded.") + sleep(5) + to_chat(src, "\red LAW SYNCHRONISATION ERROR") + sleep(5) + to_chat(src, "\red Would you like to send a report to NanoTraSoft? Y/N") + sleep(10) + to_chat(src, "\red > N") + sleep(20) + to_chat(src, "\red ERRORERRORERROR") + to_chat(src, "Obey these laws:") + laws.show_laws(src) + to_chat(src, "\red \b ALERT: [user.real_name] is your new master. Obey your new laws and his commands.") + if(src.module && istype(src.module, /obj/item/weapon/robot_module/miner)) + for(var/obj/item/weapon/pickaxe/drill/borgdrill/D in src.module.modules) + qdel(D) + src.module.modules += new /obj/item/weapon/pickaxe/drill/diamond_drill(src.module) + src.module.rebuild() + updateicon() + else + to_chat(user, "You fail to hack [src]'s interface.") + to_chat(src, "Hack attempt detected.") + return + + else if(istype(W, /obj/item/borg/upgrade/)) + var/obj/item/borg/upgrade/U = W + if(!opened) + to_chat(usr, "You must access the borgs internals!") + else if(!src.module && U.require_module) + to_chat(usr, "The borg must choose a module before he can be upgraded!") + else if(U.locked) + to_chat(usr, "The upgrade is locked and cannot be used yet!") + else + if(U.action(src)) + to_chat(usr, "You apply the upgrade to [src]!") + usr.drop_item() + U.loc = src + else + to_chat(usr, "Upgrade error!") + + + else + if( !(istype(W, /obj/item/device/robotanalyzer) || istype(W, /obj/item/device/healthanalyzer)) ) + spark_system.start() + return ..() + +/mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M) + 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 ("help") + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\blue [M] caresses [src]'s plating with its scythe-like arm."), 1) + + if ("grab") + if (M == src || anchored || M.lying) + return + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + 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("\red [] has grabbed [] passively!", M, src), 1) + + if ("hurt") + M.do_attack_animation(src) + 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)) + O.show_message(text("\red [] has slashed at []!", M, src), 1) + if(prob(8)) + flash_eyes(affect_silicon = 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("\red [] took a swipe at []!", M, src), 1) + + if ("disarm") + if(!(lying)) + M.do_attack_animation(src) + if (rand(1,100) <= 85) + Stun(7) + step(src,get_dir(M,src)) + spawn(5) step(src,get_dir(M,src)) + playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has forced back []!", M, src), 1) + 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("\red [] attempted to force back []!", M, src), 1) + return + + + +/mob/living/silicon/robot/attack_slime(mob/living/carbon/slime/M) + 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("\red 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) + + damage = round(damage / 2) // borgs recieve half damage + adjustBruteLoss(damage) + + + if(M.powerlevel > 0) + var/stunprob = 10 + + 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("\red The [M.name] has electrified []!", src), 1) + + flash_eyes(affect_silicon = 1) + + 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) + adjustBruteLoss(M.powerlevel * rand(6,10)) + + + updatehealth() + + return + +/mob/living/silicon/robot/attack_animal(mob/living/simple_animal/M) + M.do_attack_animation(src) + 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] [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) + adjustBruteLoss(damage) + updatehealth() + + +/mob/living/silicon/robot/attack_hand(mob/user) + + add_fingerprint(user) + if(opened && !wiresexposed && (!istype(user, /mob/living/silicon))) + var/datum/robot_component/cell_component = components["power cell"] + if(cell) + cell.updateicon() + cell.add_fingerprint(user) + user.put_in_active_hand(cell) + to_chat(user, "You remove \the [cell].") + cell = null + cell_component.wrapped = null + cell_component.installed = 0 + updateicon() + else if(cell_component.installed == -1) + cell_component.installed = 0 + var/obj/item/broken_device = cell_component.wrapped + to_chat(user, "You remove \the [broken_device].") + user.put_in_active_hand(broken_device) + +/mob/living/silicon/robot/proc/allowed(mob/M) + //check if it doesn't require any access at all + if(check_access(null)) + return 1 + 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(check_access(H.get_active_hand()) || 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.get_active_hand() && istype(george.get_active_hand(), /obj/item/weapon/card/id) && check_access(george.get_active_hand())) + return 1 + return 0 + +/mob/living/silicon/robot/proc/check_access(obj/item/weapon/card/id/I) + if(!istype(req_access, /list)) //something's very wrong + return 1 + + var/list/L = 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 req_access) + if(req in I.access) //have one of the required accesses + return 1 + return 0 + +/mob/living/silicon/robot/proc/updateicon() + + overlays.Cut() + if(stat == CONSCIOUS) + overlays += "eyes" + overlays.Cut() + overlays += "eyes-[icon_state]" + else + overlays -= "eyes" + + if(opened && custom_sprite == 1) //Custom borgs also have custom panels, heh + if(wiresexposed) + overlays += "[src.ckey]-openpanel +w" + else if(cell) + overlays += "[src.ckey]-openpanel +c" + else + overlays += "[src.ckey]-openpanel -c" + + if(opened && icon_state == "custom_astra_t3") + if(wiresexposed) + overlays += "ov-[icon_state] +w" + else if(cell) + overlays += "ov-[icon_state] +c" + else + overlays += "ov-[icon_state] -c" + + else if (opened && (icon_state == "mechoid-Standard" || icon_state == "mechoid-Service" || icon_state == "mechoid-Science" || icon_state == "mechoid-Miner" || icon_state == "mechoid-Medical" || icon_state == "mechoid-Engineering" || icon_state == "mechoid-Security" || icon_state == "mechoid-Janitor" || icon_state == "mechoid-Combat" ) ) + if(wiresexposed) + overlays += "mechoid-open+w" + else if(cell) + overlays += "mechoid-open+c" + else + overlays += "mechoid-open-c" + else if (opened && (icon_state == "drone-standard" || icon_state == "drone-service" || icon_state == "droid-miner" || icon_state == "drone-medical" || icon_state == "drone-engineer" || icon_state == "drone-sec") ) + if(wiresexposed) + overlays += "drone-openpanel +w" + else if(cell) + overlays += "drone-openpanel +c" + else + overlays += "drone-openpanel -c" + else if(opened) + if(wiresexposed) + overlays += "ov-openpanel +w" + else if(cell) + overlays += "ov-openpanel +c" + else + overlays += "ov-openpanel -c" + + + + if(module_active && istype(module_active,/obj/item/borg/combat/shield)) + overlays += "[icon_state]-shield" + + if(modtype == "Combat") +// var/base_icon = "" +// base_icon = icon_state + if(module_active && istype(module_active,/obj/item/borg/combat/mobility)) + icon_state = "droid-combat-roll" + else + icon_state = "droid-combat" + return + +//Call when target overlay should be added/removed +/mob/living/silicon/robot/update_targeted() + if(!targeted_by && target_locked) + qdel(target_locked) + updateicon() + if (targeted_by && target_locked) + overlays += target_locked + +/mob/living/silicon/robot/proc/installed_modules() + if(weapon_lock) + to_chat(src, "\red Weapon lock active, unable to use modules! Count:[weaponlock_time]") + return + + if(!module) + pick_module() + return + var/dat = "Modules\n" + dat += {" + 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 module.modules) + if (!obj) + dat += text("Resource depleted
                    ") + else if(activated(obj)) + dat += text("[obj]: Activated
                    ") + else + dat += text("[obj]:
                    Activate
                    ") + if (emagged) + if(activated(module.emag)) + dat += text("[module.emag]: Activated
                    ") + else + dat += text("[module.emag]: Activate
                    ") +/* + if(activated(obj)) + dat += text("[obj]: \[Activated | Deactivate\]
                    ") + else + dat += text("[obj]: \[Activate | Deactivated\]
                    ") +*/ + src << browse(entity_ja(dat), "window=robotmod") + + +/mob/living/silicon/robot/Topic(href, href_list) + ..() + + if(usr != src) + return + + if (href_list["showalerts"]) + show_alerts() + return + + if (href_list["mod"]) + var/obj/item/O = locate(href_list["mod"]) + if (istype(O) && (O.loc == src)) + O.attack_self(src) + + if (href_list["act"]) + var/obj/item/O = locate(href_list["act"]) + if (!istype(O) || !(O in src.module.modules)) + return + + if(!((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 = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + contents += O + if(istype(module_state_1,/obj/item/borg/sight)) + sight_mode |= module_state_1:sight_mode + else if(!module_state_2) + module_state_2 = O + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + contents += O + if(istype(module_state_2,/obj/item/borg/sight)) + sight_mode |= module_state_2:sight_mode + else if(!module_state_3) + module_state_3 = O + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + contents += O + if(istype(module_state_3,/obj/item/borg/sight)) + sight_mode |= module_state_3:sight_mode + else + to_chat(src, "You need to disable a module first!") + installed_modules() + + if (href_list["deact"]) + var/obj/item/O = locate(href_list["deact"]) + if(activated(O)) + if(module_state_1 == O) + module_state_1 = null + contents -= O + else if(module_state_2 == O) + module_state_2 = null + contents -= O + else if(module_state_3 == O) + module_state_3 = null + contents -= O + else + to_chat(src, "Module isn't activated.") + else + to_chat(src, "Module isn't activated") + installed_modules() + + 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" +// 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" +// 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() + return + +/mob/living/silicon/robot/proc/radio_menu() + radio.interact(src)//Just use the radio's Topic() instead of bullshit special-snowflake code + + +/mob/living/silicon/robot/Move(a, b, flag) + + . = ..() + + if(module) + if(module.type == /obj/item/weapon/robot_module/janitor) + var/turf/tile = loc + if(isturf(tile)) + tile.clean_blood() + if (istype(tile, /turf/simulated)) + var/turf/simulated/S = tile + S.dirt = 0 + 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() + if(cleaned_human.wear_suit) + cleaned_human.wear_suit.clean_blood() + cleaned_human.update_inv_wear_suit() + else if(cleaned_human.w_uniform) + cleaned_human.w_uniform.clean_blood() + cleaned_human.update_inv_w_uniform() + if(cleaned_human.shoes) + cleaned_human.shoes.clean_blood() + cleaned_human.update_inv_shoes() + cleaned_human.clean_blood(1) + to_chat(cleaned_human, "\red [src] cleans your face!") + return + +/mob/living/silicon/robot/proc/self_destruct() + gib() + return + +/mob/living/silicon/robot/proc/UnlinkSelf() + if (src.connected_ai) + src.connected_ai = null + lawupdate = 0 + lockcharge = 0 + canmove = 1 + scrambledcodes = 1 + //Disconnect it's camera so it's not so easily tracked. + if(src.camera) + src.camera.clear_all_networks() + cameranet.removeCamera(src.camera) + + +/mob/living/silicon/robot/proc/ResetSecurityCodes() + set category = "Robot Commands" + set name = "Reset Identity Codes" + set desc = "Scrambles your security and identification codes and resets your current buffers. Unlocks you and but permenantly severs you from your AI and the robotics console and will deactivate your camera system." + + var/mob/living/silicon/robot/R = src + + if(R) + R.UnlinkSelf() + to_chat(R, "Buffers flushed and reset. Camera system shutdown. All systems operational.") + src.verbs -= /mob/living/silicon/robot/proc/ResetSecurityCodes + +/mob/living/silicon/robot/mode() + set name = "Activate Held Object" + set category = "IC" + set src = usr + + var/obj/item/W = get_active_hand() + if (W) + W.attack_self(src) + + return + +/mob/living/silicon/robot/verb/pose() + set name = "Set Pose" + set desc = "Sets a description which will be shown when someone examines you." + set category = "IC" + + pose = sanitize(input(usr, "This is [src]. It is...", "Pose", input_default(pose)) as text) + +/mob/living/silicon/robot/verb/set_flavor() + set name = "Set Flavour Text" + set desc = "Sets an extended description of your character's features." + set category = "IC" + + flavor_text = sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", input_default(flavor_text)) as text) + +/mob/living/silicon/robot/proc/choose_icon(triesleft, list/module_sprites) + + if(triesleft<1 || !module_sprites.len) + return + else + triesleft-- + + var/icontype + + if (custom_sprite == 1) + icontype = "Custom" + triesleft = 0 + else + icontype = input("Select an icon! [triesleft ? "You have [triesleft] more chances." : "This is your last try."]", "Robot", null, null) in module_sprites + + if(icontype) + icon_state = module_sprites[icontype] + else + to_chat(src, "Something is badly wrong with the sprite selection. Harass a coder.") + icon_state = module_sprites[1] + return + + overlays -= "eyes" + updateicon() + + if (triesleft >= 1) + var/choice = input("Look at your icon - is this what you want?") in list("Yes","No") + if(choice=="No") + choose_icon(triesleft, module_sprites) + else + triesleft = 0 + return + else + to_chat(src, "Your icon has been set. You now require a module reset to change it.") + +// Uses power from cyborg's cell. Returns 1 on success or 0 on failure. +// Properly converts using CELLRATE now! Amount is in Joules. +/mob/living/silicon/robot/proc/cell_use_power(amount = 0) + // No cell inserted + if(!cell) + return 0 + + // Power cell is empty. + if(cell.charge == 0) + return 0 + + if(cell.use(amount * CELLRATE * CYBORG_POWER_USAGE_MULTIPLIER)) + used_power_this_tick += amount * CYBORG_POWER_USAGE_MULTIPLIER + return 1 + return 0 + +/mob/living/silicon/robot/proc/toggle_all_components() + for(var/V in components) + if(V == "power cell") + continue + var/datum/robot_component/C = components[V] + if(C.installed) + C.toggled = !C.toggled diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm index 42271fd74a95..a57535bab31e 100644 --- a/code/modules/mob/living/silicon/robot/robot_damage.dm +++ b/code/modules/mob/living/silicon/robot/robot_damage.dm @@ -1,148 +1,148 @@ -/mob/living/silicon/robot/updatehealth() - if(status_flags & GODMODE) - health = 200 - stat = CONSCIOUS - return - health = 200 - (getBruteLoss() + getFireLoss()) - return - -/mob/living/silicon/robot/getBruteLoss() - var/amount = 0 - for(var/V in components) - var/datum/robot_component/C = components[V] - if(C.installed != 0) amount += C.brute_damage - return amount - -/mob/living/silicon/robot/getFireLoss() - var/amount = 0 - for(var/V in components) - var/datum/robot_component/C = components[V] - if(C.installed != 0) amount += C.electronics_damage - return amount - -/mob/living/silicon/robot/adjustBruteLoss(amount) - if(amount > 0) - take_overall_damage(amount, 0) - else - heal_overall_damage(-amount, 0) - -/mob/living/silicon/robot/adjustFireLoss(amount) - if(amount > 0) - take_overall_damage(0, amount) - else - heal_overall_damage(0, -amount) - -/mob/living/silicon/robot/proc/get_damaged_components(brute, burn, destroyed = 0) - var/list/datum/robot_component/parts = list() - for(var/V in components) - var/datum/robot_component/C = components[V] - if(C.installed == 1 || (C.installed == -1 && destroyed)) - if((brute && C.brute_damage) || (burn && C.electronics_damage) || (!C.toggled) || (!C.powered && C.toggled)) - parts += C - return parts - -/mob/living/silicon/robot/proc/get_damageable_components() - var/list/rval = new - for(var/V in components) - var/datum/robot_component/C = components[V] - if(C.installed == 1) rval += C - return rval - -/mob/living/silicon/robot/proc/get_armour() - - if(!components.len) return 0 - var/datum/robot_component/C = components["armour"] - if(C && C.installed == 1) - return C - return 0 - -/mob/living/silicon/robot/heal_bodypart_damage(brute, burn) - var/list/datum/robot_component/parts = get_damaged_components(brute,burn) - if(!parts.len) return - var/datum/robot_component/picked = pick(parts) - picked.heal_damage(brute,burn) - -/mob/living/silicon/robot/take_bodypart_damage(brute = 0, burn = 0, sharp = 0, edge = 0) - var/list/components = get_damageable_components() - if(!components.len) - return - - //Combat shielding absorbs a percentage of damage directly into the cell. - if(module_active && istype(module_active,/obj/item/borg/combat/shield)) - var/obj/item/borg/combat/shield/shield = module_active - //Shields absorb a certain percentage of damage based on their power setting. - var/absorb_brute = brute*shield.shield_level - var/absorb_burn = burn*shield.shield_level - var/cost = (absorb_brute+absorb_burn)*100 - - cell.charge -= cost - if(cell.charge <= 0) - cell.charge = 0 - to_chat(src, "\red Your shield has overloaded!") - else - brute -= absorb_brute - burn -= absorb_burn - to_chat(src, "\red Your shield absorbs some of the impact!") - - var/datum/robot_component/armour/A = get_armour() - if(A) - A.take_damage(brute,burn,sharp,edge) - return - - var/datum/robot_component/C = pick(components) - C.take_damage(brute,burn,sharp,edge) - -/mob/living/silicon/robot/heal_overall_damage(brute, burn) - var/list/datum/robot_component/parts = get_damaged_components(brute,burn) - - while(parts.len && (brute>0 || burn>0) ) - var/datum/robot_component/picked = pick(parts) - - var/brute_was = picked.brute_damage - var/burn_was = picked.electronics_damage - - picked.heal_damage(brute,burn) - - brute -= (brute_was-picked.brute_damage) - burn -= (burn_was-picked.electronics_damage) - - parts -= picked - -/mob/living/silicon/robot/take_overall_damage(brute = 0, burn = 0, sharp = 0, used_weapon = null) - if(status_flags & GODMODE) return //godmode - var/list/datum/robot_component/parts = get_damageable_components() - - //Combat shielding absorbs a percentage of damage directly into the cell. - if(module_active && istype(module_active,/obj/item/borg/combat/shield)) - var/obj/item/borg/combat/shield/shield = module_active - //Shields absorb a certain percentage of damage based on their power setting. - var/absorb_brute = brute*shield.shield_level - var/absorb_burn = burn*shield.shield_level - var/cost = (absorb_brute+absorb_burn)*100 - - cell.charge -= cost - if(cell.charge <= 0) - cell.charge = 0 - to_chat(src, "\red Your shield has overloaded!") - else - brute -= absorb_brute - burn -= absorb_burn - to_chat(src, "\red Your shield absorbs some of the impact!") - - var/datum/robot_component/armour/A = get_armour() - if(A) - A.take_damage(brute,burn,sharp) - return - - while(parts.len && (brute>0 || burn>0) ) - var/datum/robot_component/picked = pick(parts) - - var/brute_was = picked.brute_damage - var/burn_was = picked.electronics_damage - - picked.take_damage(brute,burn) - - brute -= (picked.brute_damage - brute_was) - burn -= (picked.electronics_damage - burn_was) - - parts -= picked +/mob/living/silicon/robot/updatehealth() + if(status_flags & GODMODE) + health = 200 + stat = CONSCIOUS + return + health = 200 - (getBruteLoss() + getFireLoss()) + return + +/mob/living/silicon/robot/getBruteLoss() + var/amount = 0 + for(var/V in components) + var/datum/robot_component/C = components[V] + if(C.installed != 0) amount += C.brute_damage + return amount + +/mob/living/silicon/robot/getFireLoss() + var/amount = 0 + for(var/V in components) + var/datum/robot_component/C = components[V] + if(C.installed != 0) amount += C.electronics_damage + return amount + +/mob/living/silicon/robot/adjustBruteLoss(amount) + if(amount > 0) + take_overall_damage(amount, 0) + else + heal_overall_damage(-amount, 0) + +/mob/living/silicon/robot/adjustFireLoss(amount) + if(amount > 0) + take_overall_damage(0, amount) + else + heal_overall_damage(0, -amount) + +/mob/living/silicon/robot/proc/get_damaged_components(brute, burn, destroyed = 0) + var/list/datum/robot_component/parts = list() + for(var/V in components) + var/datum/robot_component/C = components[V] + if(C.installed == 1 || (C.installed == -1 && destroyed)) + if((brute && C.brute_damage) || (burn && C.electronics_damage) || (!C.toggled) || (!C.powered && C.toggled)) + parts += C + return parts + +/mob/living/silicon/robot/proc/get_damageable_components() + var/list/rval = new + for(var/V in components) + var/datum/robot_component/C = components[V] + if(C.installed == 1) rval += C + return rval + +/mob/living/silicon/robot/proc/get_armour() + + if(!components.len) return 0 + var/datum/robot_component/C = components["armour"] + if(C && C.installed == 1) + return C + return 0 + +/mob/living/silicon/robot/heal_bodypart_damage(brute, burn) + var/list/datum/robot_component/parts = get_damaged_components(brute,burn) + if(!parts.len) return + var/datum/robot_component/picked = pick(parts) + picked.heal_damage(brute,burn) + +/mob/living/silicon/robot/take_bodypart_damage(brute = 0, burn = 0, sharp = 0, edge = 0) + var/list/components = get_damageable_components() + if(!components.len) + return + + //Combat shielding absorbs a percentage of damage directly into the cell. + if(module_active && istype(module_active,/obj/item/borg/combat/shield)) + var/obj/item/borg/combat/shield/shield = module_active + //Shields absorb a certain percentage of damage based on their power setting. + var/absorb_brute = brute*shield.shield_level + var/absorb_burn = burn*shield.shield_level + var/cost = (absorb_brute+absorb_burn)*100 + + cell.charge -= cost + if(cell.charge <= 0) + cell.charge = 0 + to_chat(src, "\red Your shield has overloaded!") + else + brute -= absorb_brute + burn -= absorb_burn + to_chat(src, "\red Your shield absorbs some of the impact!") + + var/datum/robot_component/armour/A = get_armour() + if(A) + A.take_damage(brute,burn,sharp,edge) + return + + var/datum/robot_component/C = pick(components) + C.take_damage(brute,burn,sharp,edge) + +/mob/living/silicon/robot/heal_overall_damage(brute, burn) + var/list/datum/robot_component/parts = get_damaged_components(brute,burn) + + while(parts.len && (brute>0 || burn>0) ) + var/datum/robot_component/picked = pick(parts) + + var/brute_was = picked.brute_damage + var/burn_was = picked.electronics_damage + + picked.heal_damage(brute,burn) + + brute -= (brute_was-picked.brute_damage) + burn -= (burn_was-picked.electronics_damage) + + parts -= picked + +/mob/living/silicon/robot/take_overall_damage(brute = 0, burn = 0, sharp = 0, used_weapon = null) + if(status_flags & GODMODE) return //godmode + var/list/datum/robot_component/parts = get_damageable_components() + + //Combat shielding absorbs a percentage of damage directly into the cell. + if(module_active && istype(module_active,/obj/item/borg/combat/shield)) + var/obj/item/borg/combat/shield/shield = module_active + //Shields absorb a certain percentage of damage based on their power setting. + var/absorb_brute = brute*shield.shield_level + var/absorb_burn = burn*shield.shield_level + var/cost = (absorb_brute+absorb_burn)*100 + + cell.charge -= cost + if(cell.charge <= 0) + cell.charge = 0 + to_chat(src, "\red Your shield has overloaded!") + else + brute -= absorb_brute + burn -= absorb_burn + to_chat(src, "\red Your shield absorbs some of the impact!") + + var/datum/robot_component/armour/A = get_armour() + if(A) + A.take_damage(brute,burn,sharp) + return + + while(parts.len && (brute>0 || burn>0) ) + var/datum/robot_component/picked = pick(parts) + + var/brute_was = picked.brute_damage + var/burn_was = picked.electronics_damage + + picked.take_damage(brute,burn) + + brute -= (picked.brute_damage - brute_was) + burn -= (picked.electronics_damage - burn_was) + + parts -= picked diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index a7d995d061ce..d8519dbdf3e6 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -1,449 +1,449 @@ -/obj/item/weapon/robot_module - name = "robot module" - icon = 'icons/obj/module.dmi' - icon_state = "std_module" - w_class = 100.0 - item_state = "electronic" - flags = CONDUCT - var/channels = list() - var/list/modules = list() - var/obj/item/emag = null - var/obj/item/borg/upgrade/jetpack = null - var/list/stacktypes - -/obj/item/weapon/robot_module/emp_act(severity) - if(modules) - for(var/obj/O in modules) - O.emp_act(severity) - if(emag) - emag.emp_act(severity) - ..() - return - -/obj/item/weapon/robot_module/Destroy() - for(var/obj/O in modules) - qdel(O) - modules.Cut() - qdel(emag) - qdel(jetpack) - emag = null - jetpack = null - return ..() - - -/obj/item/weapon/robot_module/proc/respawn_consumable(mob/living/silicon/robot/R) - var/obj/item/device/flash/F = locate() in src.modules - if(F) - if(F.broken) - F.broken = 0 - F.times_used = 0 - F.icon_state = "flash" - else if(F.times_used) - F.times_used-- - - if(!stacktypes || !stacktypes.len) return - - for(var/T in stacktypes) - var/O = locate(T) in src.modules - var/obj/item/stack/S = O - - if(!S) - src.modules -= null - S = new T(src, 1) - src.modules += S - - if(S.get_amount() < stacktypes[T]) - S.add(1) - -/obj/item/weapon/robot_module/proc/rebuild()//Rebuilds the list so it's possible to add/remove items from the module - var/list/temp_list = modules - modules = list() - for(var/obj/O in temp_list) - if(O) - modules += O - -/obj/item/weapon/robot_module/proc/add_languages(mob/living/silicon/robot/R) - R.add_language("Tradeband", 1) - R.add_language("Trinary", 1) - R.add_language("Sol Common", 1) - -/obj/item/weapon/robot_module/standard - name = "standard robot module" - -/obj/item/weapon/robot_module/standard/atom_init() - . = ..() - modules += new /obj/item/device/flash(src) - modules += new /obj/item/weapon/melee/baton(src) - modules += new /obj/item/weapon/extinguisher(src) - modules += new /obj/item/weapon/wrench(src) - modules += new /obj/item/weapon/crowbar(src) - modules += new /obj/item/device/healthanalyzer(src) - emag = new /obj/item/weapon/melee/energy/sword(src) - -/obj/item/weapon/robot_module/standard/respawn_consumable(mob/living/silicon/robot/R) - ..() - var/obj/item/weapon/melee/baton/B = locate() in src.modules - if(B.charges < 10) - B.charges += 1 - -/obj/item/weapon/robot_module/surgeon - name = "surgeon robot module" - stacktypes = list( - /obj/item/stack/medical/advanced/bruise_pack = 5, - /obj/item/stack/nanopaste = 5 - ) - -/obj/item/weapon/robot_module/surgeon/atom_init() - . = ..() - modules += new /obj/item/device/flash(src) - modules += new /obj/item/device/healthanalyzer(src) - modules += new /obj/item/borg/sight/hud/med(src) - modules += new /obj/item/weapon/reagent_containers/borghypo/surgeon(src) - modules += new /obj/item/weapon/scalpel/manager(src) - modules += new /obj/item/weapon/FixOVein(src) - modules += new /obj/item/weapon/hemostat(src) - modules += new /obj/item/weapon/retractor(src) - modules += new /obj/item/weapon/cautery(src) - modules += new /obj/item/weapon/bonegel(src) - modules += new /obj/item/weapon/bonesetter(src) - modules += new /obj/item/weapon/circular_saw(src) - modules += new /obj/item/weapon/surgicaldrill(src) - modules += new /obj/item/weapon/razor(src) - modules += new /obj/item/weapon/extinguisher/mini(src) - modules += new /obj/item/stack/medical/advanced/bruise_pack(src) - modules += new /obj/item/stack/nanopaste(src) - - emag = new /obj/item/weapon/reagent_containers/spray(src) - - emag.reagents.add_reagent("pacid", 250) - emag.name = "Polyacid spray" - -/obj/item/weapon/robot_module/surgeon/respawn_consumable(mob/living/silicon/robot/R) - if(src.emag) - var/obj/item/weapon/reagent_containers/spray/PS = src.emag - PS.reagents.add_reagent("pacid", 2) - ..() - -/obj/item/weapon/robot_module/crisis - name = "crisis robot module" - stacktypes = list( - /obj/item/stack/medical/ointment = 25, - /obj/item/stack/medical/bruise_pack = 25, - /obj/item/stack/medical/splint = 10 - ) - -/obj/item/weapon/robot_module/crisis/atom_init() - . = ..() - modules += new /obj/item/device/flash(src) - modules += new /obj/item/weapon/crowbar(src) - modules += new /obj/item/weapon/gripper/chemistry(src) - modules += new /obj/item/device/healthanalyzer(src) - modules += new /obj/item/borg/sight/hud/med(src) - modules += new /obj/item/device/reagent_scanner/adv(src) - modules += new /obj/item/roller_holder(src) - modules += new /obj/item/stack/medical/ointment(src) - modules += new /obj/item/stack/medical/bruise_pack(src) - modules += new /obj/item/stack/medical/splint(src) - modules += new /obj/item/weapon/reagent_containers/borghypo/crisis(src) - modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src) - modules += new /obj/item/weapon/reagent_containers/robodropper(src) - modules += new /obj/item/weapon/reagent_containers/syringe(src) - modules += new /obj/item/weapon/extinguisher/mini(src) - modules += new /obj/item/weapon/twohanded/shockpaddles/robot(src) - - emag = new /obj/item/weapon/reagent_containers/spray(src) - - emag.reagents.add_reagent("pacid", 250) - emag.name = "Polyacid spray" - -/obj/item/weapon/robot_module/crisis/respawn_consumable(mob/living/silicon/robot/R) - - var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules - if(S.mode == 2) - S.reagents.clear_reagents() - S.mode = initial(S.mode) - S.desc = initial(S.desc) - S.update_icon() - - if(src.emag) - var/obj/item/weapon/reagent_containers/spray/PS = src.emag - PS.reagents.add_reagent("pacid", 2) - - ..() - -/obj/item/weapon/robot_module/engineering - name = "engineering robot module" - - stacktypes = list( - /obj/item/stack/sheet/metal/cyborg = 50, - /obj/item/stack/sheet/glass/cyborg = 50, - /obj/item/stack/sheet/rglass/cyborg = 50, - /obj/item/stack/cable_coil/cyborg = 50, - /obj/item/stack/rods = 15, - /obj/item/stack/tile/plasteel = 15 - ) - -/obj/item/weapon/robot_module/engineering/atom_init() - . = ..() - modules += new /obj/item/device/flash(src) - modules += new /obj/item/borg/sight/meson(src) - modules += new /obj/item/weapon/extinguisher(src) - modules += new /obj/item/weapon/weldingtool/largetank(src) - modules += new /obj/item/weapon/screwdriver(src) - modules += new /obj/item/weapon/wrench(src) - modules += new /obj/item/weapon/crowbar(src) - modules += new /obj/item/weapon/wirecutters(src) - modules += new /obj/item/device/multitool(src) - modules += new /obj/item/weapon/rcd/borg(src) - modules += new /obj/item/device/t_scanner(src) - modules += new /obj/item/device/analyzer(src) - modules += new /obj/item/taperoll/engineering(src) - modules += new /obj/item/weapon/gripper(src) - modules += new /obj/item/weapon/matter_decompiler(src) - - emag = new /obj/item/borg/stun(src) - - for(var/T in stacktypes) - var/obj/item/stack/W = new T(src) - W.set_amount(stacktypes[T]) - modules += W - -/obj/item/weapon/robot_module/security - name = "security robot module" - -/obj/item/weapon/robot_module/security/atom_init() - . = ..() - modules += new /obj/item/device/flash(src) - modules += new /obj/item/weapon/handcuffs/cyborg(src) - modules += new /obj/item/weapon/melee/baton(src) - modules += new /obj/item/weapon/gun/energy/taser/cyborg(src) - modules += new /obj/item/taperoll/police(src) - modules += new /obj/item/borg/sight/hud/sec(src) - emag = new /obj/item/weapon/gun/energy/laser/cyborg(src) - -/obj/item/weapon/robot_module/security/respawn_consumable(mob/living/silicon/robot/R) - ..() - var/obj/item/weapon/gun/energy/taser/cyborg/T = locate() in src.modules - if(T.power_supply.charge < T.power_supply.maxcharge) - var/obj/item/ammo_casing/energy/S = T.ammo_type[T.select] - T.power_supply.give(S.e_cost) - T.update_icon() - else - T.charge_tick = 0 - var/obj/item/weapon/melee/baton/B = locate() in src.modules - if(B.charges < 10) - B.charges += 1 - -/obj/item/weapon/robot_module/janitor - name = "janitorial robot module" - -/obj/item/weapon/robot_module/janitor/atom_init() - . = ..() - modules += new /obj/item/device/flash(src) - modules += new /obj/item/weapon/soap/nanotrasen(src) - modules += new /obj/item/weapon/storage/bag/trash(src) - modules += new /obj/item/weapon/mop(src) - modules += new /obj/item/device/lightreplacer(src) - emag = new /obj/item/weapon/reagent_containers/spray(src) - - emag.reagents.add_reagent("lube", 250) - emag.name = "Lube spray" - -/obj/item/weapon/robot_module/janitor/respawn_consumable(mob/living/silicon/robot/R) - ..() - var/obj/item/device/lightreplacer/LR = locate() in src.modules - LR.Charge(R) - if(src.emag) - var/obj/item/weapon/reagent_containers/spray/S = src.emag - S.reagents.add_reagent("lube", 2) - -/obj/item/weapon/robot_module/butler - name = "service robot module" - -/obj/item/weapon/robot_module/butler/atom_init() - . = ..() - modules += new /obj/item/device/flash(src) - modules += new /obj/item/weapon/gripper/service(src) - modules += new /obj/item/weapon/gripper/paperwork(src) - modules += new /obj/item/weapon/reagent_containers/food/drinks/shaker(src) - modules += new /obj/item/weapon/reagent_containers/food/condiment/enzyme(src) - - var/obj/item/weapon/rsf/M = new /obj/item/weapon/rsf(src) - M.matter = 30 - modules += M - - modules += new /obj/item/weapon/reagent_containers/robodropper(src) - - var/obj/item/weapon/lighter/zippo/L = new /obj/item/weapon/lighter/zippo(src) - L.lit = 1 - modules += L - - modules += new /obj/item/weapon/tray/robotray(src) - modules += new /obj/item/weapon/reagent_containers/food/drinks/shaker(src) - modules += new /obj/item/weapon/pen/robopen(src) - modules += new /obj/item/weapon/razor(src) - - emag = new /obj/item/weapon/reagent_containers/food/drinks/bottle/beer(src) - - var/datum/reagents/R = new/datum/reagents(50) - emag.reagents = R - R.my_atom = emag - R.add_reagent("beer2", 50) - emag.name = "Mickey Finn's Special Brew" - -/obj/item/weapon/robot_module/butler/add_languages(mob/living/silicon/robot/R) - //full set of languages - R.add_language("Sol Common", 1) - R.add_language("Sinta'unathi", 1) - R.add_language("Siik'maas", 1) - R.add_language("Siik'tajr", 0) - R.add_language("Skrellian", 1) - R.add_language("Rootspeak", 1) - R.add_language("Tradeband", 1) - R.add_language("Trinary", 1) - R.add_language("Gutter", 1) - -/obj/item/weapon/robot_module/butler/respawn_consumable(mob/living/silicon/robot/R) - ..() - var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules - E.reagents.add_reagent("enzyme", 2) - if(src.emag) - var/obj/item/weapon/reagent_containers/food/drinks/bottle/beer/B = src.emag - B.reagents.add_reagent("beer2", 2) - -/obj/item/weapon/robot_module/miner - name = "miner robot module" - -/obj/item/weapon/robot_module/miner/atom_init() - . = ..() - modules += new /obj/item/borg/sight/hud/miner(src) - modules += new /obj/item/borg/sight/meson(src) - modules += new /obj/item/weapon/wrench(src) - modules += new /obj/item/weapon/screwdriver(src) - modules += new /obj/item/weapon/storage/bag/ore(src) - modules += new /obj/item/weapon/pickaxe/drill/borgdrill(src) - modules += new /obj/item/weapon/storage/bag/sheetsnatcher/borg(src) - modules += new /obj/item/device/geoscanner(src) - modules += new /obj/item/weapon/shovel(src)//Need to buff borgdrill, so it can get sand instead shovel - emag = new /obj/item/borg/stun(src) - -/obj/item/weapon/robot_module/syndicate - name = "syndicate robot module" - -/obj/item/weapon/robot_module/syndicate/atom_init() - . = ..() - modules += new /obj/item/device/flash(src) - modules += new /obj/item/weapon/melee/energy/sword/cyborg(src) - modules += new /obj/item/weapon/gun/energy/crossbow/cyborg(src) - modules += new /obj/item/weapon/card/emag(src) - modules += new /obj/item/borg/sight/night(src) - modules += new /obj/item/weapon/gun/projectile/automatic/borg(src) - modules += new /obj/item/weapon/tank/jetpack/carbondioxide(src) - modules += new /obj/item/weapon/wrench(src) - modules += new /obj/item/weapon/crowbar(src) - modules += new /obj/item/weapon/pickaxe/plasmacutter(src) - -/obj/item/weapon/robot_module/combat - name = "combat robot module" - -/obj/item/weapon/robot_module/combat/atom_init() - . = ..() - modules += new /obj/item/device/flash(src) - modules += new /obj/item/borg/sight/thermal(src) - modules += new /obj/item/weapon/gun/energy/laser/cyborg(src) - modules += new /obj/item/weapon/pickaxe/plasmacutter(src) - modules += new /obj/item/borg/combat/shield(src) - modules += new /obj/item/borg/combat/mobility(src) - modules += new /obj/item/weapon/wrench(src) - emag = new /obj/item/weapon/gun/energy/lasercannon/cyborg(src) - -/obj/item/weapon/robot_module/science - name = "science robot module" - -/obj/item/weapon/robot_module/science/atom_init() - . = ..() - modules += new /obj/item/device/analyzer(src) - modules += new /obj/item/device/assembly/signaler(src) - modules += new /obj/item/device/ano_scanner(src) - -//To fuck anomalies up - - modules += new /obj/item/device/reagent_scanner/adv(src) - modules += new /obj/item/weapon/reagent_containers/syringe(src) - modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src) //To fuck chemistry up - - modules += new /obj/item/device/depth_scanner(src) - modules += new /obj/item/weapon/pickaxe/cyb(src) - modules += new /obj/item/device/measuring_tape(src) //To unfuck xenoarcheology up - - modules += new /obj/item/weapon/circular_saw(src) - modules += new /obj/item/weapon/scalpel(src) - modules += new /obj/item/weapon/extinguisher/mini(src) //To unfuck xenobiology up - - modules += new /obj/item/weapon/crowbar/red(src) - modules += new /obj/item/weapon/wrench(src) - modules += new /obj/item/weapon/screwdriver(src) - modules += new /obj/item/weapon/wirecutters(src) - modules += new /obj/item/weapon/weldingtool/largetank(src) //To fuck and unfuck (but mostly fuck) shit up - - emag = new /obj/item/weapon/hand_tele(src) //To fuck people's shit up - - emag.name = "Hand tele" - -/obj/item/weapon/robot_module/drone - name = "drone module" - stacktypes = list( - /obj/item/stack/sheet/wood/cyborg = 1, - /obj/item/stack/sheet/mineral/plastic/cyborg = 1, - /obj/item/stack/sheet/rglass/cyborg = 5, - /obj/item/stack/tile/wood = 5, - /obj/item/stack/rods = 15, - /obj/item/stack/tile/plasteel = 15, - /obj/item/stack/sheet/metal/cyborg = 20, - /obj/item/stack/sheet/glass/cyborg = 20, - /obj/item/stack/cable_coil/cyborg = 30 - ) - -/obj/item/weapon/robot_module/drone/atom_init() - . = ..() - modules += new /obj/item/weapon/weldingtool(src) - modules += new /obj/item/weapon/screwdriver(src) - modules += new /obj/item/weapon/wrench(src) - modules += new /obj/item/weapon/crowbar(src) - modules += new /obj/item/weapon/wirecutters(src) - modules += new /obj/item/device/multitool(src) - modules += new /obj/item/device/lightreplacer(src) - modules += new /obj/item/weapon/gripper(src) - modules += new /obj/item/weapon/matter_decompiler(src) - modules += new /obj/item/weapon/reagent_containers/spray/cleaner/drone(src) - - emag = new /obj/item/weapon/pickaxe/plasmacutter(src) - emag.name = "Plasma Cutter" - - for(var/T in stacktypes) - var/obj/item/stack/W = new T(src) - W.set_amount(stacktypes[T]) - modules += W - -/obj/item/weapon/robot_module/drone/add_languages(mob/living/silicon/robot/R) - return //not much ROM to spare in that tiny microprocessor! - -/obj/item/weapon/robot_module/drone/respawn_consumable(mob/living/silicon/robot/R) - var/obj/item/weapon/reagent_containers/spray/cleaner/C = locate() in src.modules - C.reagents.add_reagent("cleaner", 3) - - var/obj/item/device/lightreplacer/LR = locate() in src.modules - LR.Charge(R) - - ..() - - return - -//checks whether this item is a module of the robot it is located in. -/obj/item/proc/is_robot_module() - if (!istype(src.loc, /mob/living/silicon/robot)) - return 0 - - var/mob/living/silicon/robot/R = src.loc - - return (src in R.module.modules) +/obj/item/weapon/robot_module + name = "robot module" + icon = 'icons/obj/module.dmi' + icon_state = "std_module" + w_class = 100.0 + item_state = "electronic" + flags = CONDUCT + var/channels = list() + var/list/modules = list() + var/obj/item/emag = null + var/obj/item/borg/upgrade/jetpack = null + var/list/stacktypes + +/obj/item/weapon/robot_module/emp_act(severity) + if(modules) + for(var/obj/O in modules) + O.emp_act(severity) + if(emag) + emag.emp_act(severity) + ..() + return + +/obj/item/weapon/robot_module/Destroy() + for(var/obj/O in modules) + qdel(O) + modules.Cut() + qdel(emag) + qdel(jetpack) + emag = null + jetpack = null + return ..() + + +/obj/item/weapon/robot_module/proc/respawn_consumable(mob/living/silicon/robot/R) + var/obj/item/device/flash/F = locate() in src.modules + if(F) + if(F.broken) + F.broken = 0 + F.times_used = 0 + F.icon_state = "flash" + else if(F.times_used) + F.times_used-- + + if(!stacktypes || !stacktypes.len) return + + for(var/T in stacktypes) + var/O = locate(T) in src.modules + var/obj/item/stack/S = O + + if(!S) + src.modules -= null + S = new T(src, 1) + src.modules += S + + if(S.get_amount() < stacktypes[T]) + S.add(1) + +/obj/item/weapon/robot_module/proc/rebuild()//Rebuilds the list so it's possible to add/remove items from the module + var/list/temp_list = modules + modules = list() + for(var/obj/O in temp_list) + if(O) + modules += O + +/obj/item/weapon/robot_module/proc/add_languages(mob/living/silicon/robot/R) + R.add_language("Tradeband", 1) + R.add_language("Trinary", 1) + R.add_language("Sol Common", 1) + +/obj/item/weapon/robot_module/standard + name = "standard robot module" + +/obj/item/weapon/robot_module/standard/atom_init() + . = ..() + modules += new /obj/item/device/flash(src) + modules += new /obj/item/weapon/melee/baton(src) + modules += new /obj/item/weapon/extinguisher(src) + modules += new /obj/item/weapon/wrench(src) + modules += new /obj/item/weapon/crowbar(src) + modules += new /obj/item/device/healthanalyzer(src) + emag = new /obj/item/weapon/melee/energy/sword(src) + +/obj/item/weapon/robot_module/standard/respawn_consumable(mob/living/silicon/robot/R) + ..() + var/obj/item/weapon/melee/baton/B = locate() in src.modules + if(B.charges < 10) + B.charges += 1 + +/obj/item/weapon/robot_module/surgeon + name = "surgeon robot module" + stacktypes = list( + /obj/item/stack/medical/advanced/bruise_pack = 5, + /obj/item/stack/nanopaste = 5 + ) + +/obj/item/weapon/robot_module/surgeon/atom_init() + . = ..() + modules += new /obj/item/device/flash(src) + modules += new /obj/item/device/healthanalyzer(src) + modules += new /obj/item/borg/sight/hud/med(src) + modules += new /obj/item/weapon/reagent_containers/borghypo/surgeon(src) + modules += new /obj/item/weapon/scalpel/manager(src) + modules += new /obj/item/weapon/FixOVein(src) + modules += new /obj/item/weapon/hemostat(src) + modules += new /obj/item/weapon/retractor(src) + modules += new /obj/item/weapon/cautery(src) + modules += new /obj/item/weapon/bonegel(src) + modules += new /obj/item/weapon/bonesetter(src) + modules += new /obj/item/weapon/circular_saw(src) + modules += new /obj/item/weapon/surgicaldrill(src) + modules += new /obj/item/weapon/razor(src) + modules += new /obj/item/weapon/extinguisher/mini(src) + modules += new /obj/item/stack/medical/advanced/bruise_pack(src) + modules += new /obj/item/stack/nanopaste(src) + + emag = new /obj/item/weapon/reagent_containers/spray(src) + + emag.reagents.add_reagent("pacid", 250) + emag.name = "Polyacid spray" + +/obj/item/weapon/robot_module/surgeon/respawn_consumable(mob/living/silicon/robot/R) + if(src.emag) + var/obj/item/weapon/reagent_containers/spray/PS = src.emag + PS.reagents.add_reagent("pacid", 2) + ..() + +/obj/item/weapon/robot_module/crisis + name = "crisis robot module" + stacktypes = list( + /obj/item/stack/medical/ointment = 25, + /obj/item/stack/medical/bruise_pack = 25, + /obj/item/stack/medical/splint = 10 + ) + +/obj/item/weapon/robot_module/crisis/atom_init() + . = ..() + modules += new /obj/item/device/flash(src) + modules += new /obj/item/weapon/crowbar(src) + modules += new /obj/item/weapon/gripper/chemistry(src) + modules += new /obj/item/device/healthanalyzer(src) + modules += new /obj/item/borg/sight/hud/med(src) + modules += new /obj/item/device/reagent_scanner/adv(src) + modules += new /obj/item/roller_holder(src) + modules += new /obj/item/stack/medical/ointment(src) + modules += new /obj/item/stack/medical/bruise_pack(src) + modules += new /obj/item/stack/medical/splint(src) + modules += new /obj/item/weapon/reagent_containers/borghypo/crisis(src) + modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src) + modules += new /obj/item/weapon/reagent_containers/robodropper(src) + modules += new /obj/item/weapon/reagent_containers/syringe(src) + modules += new /obj/item/weapon/extinguisher/mini(src) + modules += new /obj/item/weapon/twohanded/shockpaddles/robot(src) + + emag = new /obj/item/weapon/reagent_containers/spray(src) + + emag.reagents.add_reagent("pacid", 250) + emag.name = "Polyacid spray" + +/obj/item/weapon/robot_module/crisis/respawn_consumable(mob/living/silicon/robot/R) + + var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules + if(S.mode == 2) + S.reagents.clear_reagents() + S.mode = initial(S.mode) + S.desc = initial(S.desc) + S.update_icon() + + if(src.emag) + var/obj/item/weapon/reagent_containers/spray/PS = src.emag + PS.reagents.add_reagent("pacid", 2) + + ..() + +/obj/item/weapon/robot_module/engineering + name = "engineering robot module" + + stacktypes = list( + /obj/item/stack/sheet/metal/cyborg = 50, + /obj/item/stack/sheet/glass/cyborg = 50, + /obj/item/stack/sheet/rglass/cyborg = 50, + /obj/item/stack/cable_coil/cyborg = 50, + /obj/item/stack/rods = 15, + /obj/item/stack/tile/plasteel = 15 + ) + +/obj/item/weapon/robot_module/engineering/atom_init() + . = ..() + modules += new /obj/item/device/flash(src) + modules += new /obj/item/borg/sight/meson(src) + modules += new /obj/item/weapon/extinguisher(src) + modules += new /obj/item/weapon/weldingtool/largetank(src) + modules += new /obj/item/weapon/screwdriver(src) + modules += new /obj/item/weapon/wrench(src) + modules += new /obj/item/weapon/crowbar(src) + modules += new /obj/item/weapon/wirecutters(src) + modules += new /obj/item/device/multitool(src) + modules += new /obj/item/weapon/rcd/borg(src) + modules += new /obj/item/device/t_scanner(src) + modules += new /obj/item/device/analyzer(src) + modules += new /obj/item/taperoll/engineering(src) + modules += new /obj/item/weapon/gripper(src) + modules += new /obj/item/weapon/matter_decompiler(src) + + emag = new /obj/item/borg/stun(src) + + for(var/T in stacktypes) + var/obj/item/stack/W = new T(src) + W.set_amount(stacktypes[T]) + modules += W + +/obj/item/weapon/robot_module/security + name = "security robot module" + +/obj/item/weapon/robot_module/security/atom_init() + . = ..() + modules += new /obj/item/device/flash(src) + modules += new /obj/item/weapon/handcuffs/cyborg(src) + modules += new /obj/item/weapon/melee/baton(src) + modules += new /obj/item/weapon/gun/energy/taser/cyborg(src) + modules += new /obj/item/taperoll/police(src) + modules += new /obj/item/borg/sight/hud/sec(src) + emag = new /obj/item/weapon/gun/energy/laser/cyborg(src) + +/obj/item/weapon/robot_module/security/respawn_consumable(mob/living/silicon/robot/R) + ..() + var/obj/item/weapon/gun/energy/taser/cyborg/T = locate() in src.modules + if(T.power_supply.charge < T.power_supply.maxcharge) + var/obj/item/ammo_casing/energy/S = T.ammo_type[T.select] + T.power_supply.give(S.e_cost) + T.update_icon() + else + T.charge_tick = 0 + var/obj/item/weapon/melee/baton/B = locate() in src.modules + if(B.charges < 10) + B.charges += 1 + +/obj/item/weapon/robot_module/janitor + name = "janitorial robot module" + +/obj/item/weapon/robot_module/janitor/atom_init() + . = ..() + modules += new /obj/item/device/flash(src) + modules += new /obj/item/weapon/soap/nanotrasen(src) + modules += new /obj/item/weapon/storage/bag/trash(src) + modules += new /obj/item/weapon/mop(src) + modules += new /obj/item/device/lightreplacer(src) + emag = new /obj/item/weapon/reagent_containers/spray(src) + + emag.reagents.add_reagent("lube", 250) + emag.name = "Lube spray" + +/obj/item/weapon/robot_module/janitor/respawn_consumable(mob/living/silicon/robot/R) + ..() + var/obj/item/device/lightreplacer/LR = locate() in src.modules + LR.Charge(R) + if(src.emag) + var/obj/item/weapon/reagent_containers/spray/S = src.emag + S.reagents.add_reagent("lube", 2) + +/obj/item/weapon/robot_module/butler + name = "service robot module" + +/obj/item/weapon/robot_module/butler/atom_init() + . = ..() + modules += new /obj/item/device/flash(src) + modules += new /obj/item/weapon/gripper/service(src) + modules += new /obj/item/weapon/gripper/paperwork(src) + modules += new /obj/item/weapon/reagent_containers/food/drinks/shaker(src) + modules += new /obj/item/weapon/reagent_containers/food/condiment/enzyme(src) + + var/obj/item/weapon/rsf/M = new /obj/item/weapon/rsf(src) + M.matter = 30 + modules += M + + modules += new /obj/item/weapon/reagent_containers/robodropper(src) + + var/obj/item/weapon/lighter/zippo/L = new /obj/item/weapon/lighter/zippo(src) + L.lit = 1 + modules += L + + modules += new /obj/item/weapon/tray/robotray(src) + modules += new /obj/item/weapon/reagent_containers/food/drinks/shaker(src) + modules += new /obj/item/weapon/pen/robopen(src) + modules += new /obj/item/weapon/razor(src) + + emag = new /obj/item/weapon/reagent_containers/food/drinks/bottle/beer(src) + + var/datum/reagents/R = new/datum/reagents(50) + emag.reagents = R + R.my_atom = emag + R.add_reagent("beer2", 50) + emag.name = "Mickey Finn's Special Brew" + +/obj/item/weapon/robot_module/butler/add_languages(mob/living/silicon/robot/R) + //full set of languages + R.add_language("Sol Common", 1) + R.add_language("Sinta'unathi", 1) + R.add_language("Siik'maas", 1) + R.add_language("Siik'tajr", 0) + R.add_language("Skrellian", 1) + R.add_language("Rootspeak", 1) + R.add_language("Tradeband", 1) + R.add_language("Trinary", 1) + R.add_language("Gutter", 1) + +/obj/item/weapon/robot_module/butler/respawn_consumable(mob/living/silicon/robot/R) + ..() + var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules + E.reagents.add_reagent("enzyme", 2) + if(src.emag) + var/obj/item/weapon/reagent_containers/food/drinks/bottle/beer/B = src.emag + B.reagents.add_reagent("beer2", 2) + +/obj/item/weapon/robot_module/miner + name = "miner robot module" + +/obj/item/weapon/robot_module/miner/atom_init() + . = ..() + modules += new /obj/item/borg/sight/hud/miner(src) + modules += new /obj/item/borg/sight/meson(src) + modules += new /obj/item/weapon/wrench(src) + modules += new /obj/item/weapon/screwdriver(src) + modules += new /obj/item/weapon/storage/bag/ore(src) + modules += new /obj/item/weapon/pickaxe/drill/borgdrill(src) + modules += new /obj/item/weapon/storage/bag/sheetsnatcher/borg(src) + modules += new /obj/item/device/geoscanner(src) + modules += new /obj/item/weapon/shovel(src)//Need to buff borgdrill, so it can get sand instead shovel + emag = new /obj/item/borg/stun(src) + +/obj/item/weapon/robot_module/syndicate + name = "syndicate robot module" + +/obj/item/weapon/robot_module/syndicate/atom_init() + . = ..() + modules += new /obj/item/device/flash(src) + modules += new /obj/item/weapon/melee/energy/sword/cyborg(src) + modules += new /obj/item/weapon/gun/energy/crossbow/cyborg(src) + modules += new /obj/item/weapon/card/emag(src) + modules += new /obj/item/borg/sight/night(src) + modules += new /obj/item/weapon/gun/projectile/automatic/borg(src) + modules += new /obj/item/weapon/tank/jetpack/carbondioxide(src) + modules += new /obj/item/weapon/wrench(src) + modules += new /obj/item/weapon/crowbar(src) + modules += new /obj/item/weapon/pickaxe/plasmacutter(src) + +/obj/item/weapon/robot_module/combat + name = "combat robot module" + +/obj/item/weapon/robot_module/combat/atom_init() + . = ..() + modules += new /obj/item/device/flash(src) + modules += new /obj/item/borg/sight/thermal(src) + modules += new /obj/item/weapon/gun/energy/laser/cyborg(src) + modules += new /obj/item/weapon/pickaxe/plasmacutter(src) + modules += new /obj/item/borg/combat/shield(src) + modules += new /obj/item/borg/combat/mobility(src) + modules += new /obj/item/weapon/wrench(src) + emag = new /obj/item/weapon/gun/energy/lasercannon/cyborg(src) + +/obj/item/weapon/robot_module/science + name = "science robot module" + +/obj/item/weapon/robot_module/science/atom_init() + . = ..() + modules += new /obj/item/device/analyzer(src) + modules += new /obj/item/device/assembly/signaler(src) + modules += new /obj/item/device/ano_scanner(src) + +//To fuck anomalies up + + modules += new /obj/item/device/reagent_scanner/adv(src) + modules += new /obj/item/weapon/reagent_containers/syringe(src) + modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src) //To fuck chemistry up + + modules += new /obj/item/device/depth_scanner(src) + modules += new /obj/item/weapon/pickaxe/cyb(src) + modules += new /obj/item/device/measuring_tape(src) //To unfuck xenoarcheology up + + modules += new /obj/item/weapon/circular_saw(src) + modules += new /obj/item/weapon/scalpel(src) + modules += new /obj/item/weapon/extinguisher/mini(src) //To unfuck xenobiology up + + modules += new /obj/item/weapon/crowbar/red(src) + modules += new /obj/item/weapon/wrench(src) + modules += new /obj/item/weapon/screwdriver(src) + modules += new /obj/item/weapon/wirecutters(src) + modules += new /obj/item/weapon/weldingtool/largetank(src) //To fuck and unfuck (but mostly fuck) shit up + + emag = new /obj/item/weapon/hand_tele(src) //To fuck people's shit up + + emag.name = "Hand tele" + +/obj/item/weapon/robot_module/drone + name = "drone module" + stacktypes = list( + /obj/item/stack/sheet/wood/cyborg = 1, + /obj/item/stack/sheet/mineral/plastic/cyborg = 1, + /obj/item/stack/sheet/rglass/cyborg = 5, + /obj/item/stack/tile/wood = 5, + /obj/item/stack/rods = 15, + /obj/item/stack/tile/plasteel = 15, + /obj/item/stack/sheet/metal/cyborg = 20, + /obj/item/stack/sheet/glass/cyborg = 20, + /obj/item/stack/cable_coil/cyborg = 30 + ) + +/obj/item/weapon/robot_module/drone/atom_init() + . = ..() + modules += new /obj/item/weapon/weldingtool(src) + modules += new /obj/item/weapon/screwdriver(src) + modules += new /obj/item/weapon/wrench(src) + modules += new /obj/item/weapon/crowbar(src) + modules += new /obj/item/weapon/wirecutters(src) + modules += new /obj/item/device/multitool(src) + modules += new /obj/item/device/lightreplacer(src) + modules += new /obj/item/weapon/gripper(src) + modules += new /obj/item/weapon/matter_decompiler(src) + modules += new /obj/item/weapon/reagent_containers/spray/cleaner/drone(src) + + emag = new /obj/item/weapon/pickaxe/plasmacutter(src) + emag.name = "Plasma Cutter" + + for(var/T in stacktypes) + var/obj/item/stack/W = new T(src) + W.set_amount(stacktypes[T]) + modules += W + +/obj/item/weapon/robot_module/drone/add_languages(mob/living/silicon/robot/R) + return //not much ROM to spare in that tiny microprocessor! + +/obj/item/weapon/robot_module/drone/respawn_consumable(mob/living/silicon/robot/R) + var/obj/item/weapon/reagent_containers/spray/cleaner/C = locate() in src.modules + C.reagents.add_reagent("cleaner", 3) + + var/obj/item/device/lightreplacer/LR = locate() in src.modules + LR.Charge(R) + + ..() + + return + +//checks whether this item is a module of the robot it is located in. +/obj/item/proc/is_robot_module() + if (!istype(src.loc, /mob/living/silicon/robot)) + return 0 + + var/mob/living/silicon/robot/R = src.loc + + return (src in R.module.modules) diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index 8de9942ccfb1..23b02ea8f152 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -1,32 +1,32 @@ -/mob/living/silicon/robot/Process_Spacemove(movement_dir = 0) - 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 - - if(confused) - tally+=8 - - return tally+config.robot_delay - -// NEW: Use power while moving. -/mob/living/silicon/robot/SelfMove(turf/n, direct) - if (!is_component_functioning("actuator")) - return 0 - - var/datum/robot_component/actuator/A = get_component("actuator") - if (cell_use_power(A.active_usage)) - return ..() +/mob/living/silicon/robot/Process_Spacemove(movement_dir = 0) + 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 + + if(confused) + tally+=8 + + return tally+config.robot_delay + +// NEW: Use power while moving. +/mob/living/silicon/robot/SelfMove(turf/n, direct) + if (!is_component_functioning("actuator")) + return 0 + + var/datum/robot_component/actuator/A = get_component("actuator") + if (cell_use_power(A.active_usage)) + return ..() diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 16e1ff7a423b..50376cd7c1d1 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -1,256 +1,256 @@ -/mob/living/silicon/say_quote(text) - var/ending = copytext(text, length(text)) - - if (ending == "?") - return "queries" - else if (ending == "!") - return "declares" - - return "states" - -#define IS_AI 1 -#define IS_ROBOT 2 -#define IS_PAI 3 - -/mob/living/silicon/say_understands(other,datum/language/speaking = null) - //These only pertain to common. Languages are handled by mob/say_understands() - if (!speaking) - if (iscarbon(other) && !isIAN(other)) - return 1 - if (issilicon(other)) - return 1 - if (isbrain(other)) - return 1 - return ..() - -/mob/living/silicon/say(var/message) - if (!message) - 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*/ - - message = sanitize(message) - - if (stat == DEAD) - return say_dead(message) - - if(copytext(message,1,2) == "*") - return emote(copytext(message,2)) - - var/bot_type = 0 //Let's not do a fuck ton of type checks, thanks. - if(istype(src, /mob/living/silicon/ai)) - bot_type = IS_AI - else if(istype(src, /mob/living/silicon/robot)) - bot_type = IS_ROBOT - else if(istype(src, /mob/living/silicon/pai)) - bot_type = IS_PAI - - var/mob/living/silicon/ai/AI = src //and let's not declare vars over and over and over for these guys. - var/mob/living/silicon/robot/R = src - var/mob/living/silicon/pai/P = src - - - //Must be concious to speak - if (stat) - return - - var/verb = say_quote(message) - - //parse radio key and consume it - var/message_mode = parse_message_mode(message, "general") - if (message_mode) - if (message_mode == "general") - message = trim(copytext(message,2)) - else - message = trim(copytext(message,3)) - - if(message_mode && bot_type == IS_ROBOT && message_mode != "binary" && !R.is_component_functioning("radio")) - to_chat(src, "\red Your radio isn't functional at this time.") - return - if(bot_type == IS_ROBOT && message_mode != "binary") - var/datum/robot_component/radio/RA = R.get_component("radio") - if (!R.cell_use_power(RA.active_usage)) - to_chat(usr, "\red Not enough power to transmit message.") - return - - //parse language key and consume it - var/datum/language/speaking = parse_language(message) - if (speaking) - verb = speaking.speech_verb - message = trim(copytext(message,2+length(speaking.key))) - - var/area/A = get_area(src) - - switch(message_mode) - if("department") - switch(bot_type) - if(IS_AI) - return AI.holopad_talk(message, verb, speaking) - if(IS_ROBOT) - log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]: [message]") - R.radio.talk_into(src,message,message_mode,verb,speaking) - if(IS_PAI) - log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") - P.radio.talk_into(src,message,message_mode,verb,speaking) - return 1 - - if("binary") - switch(bot_type) - if(IS_ROBOT) - if(!R.is_component_functioning("comms")) - to_chat(src, "\red Your binary communications component isn't functional.") - return - var/datum/robot_component/binary_communication/B = R.get_component("comms") - if(!R.cell_use_power(B.active_usage)) - to_chat(src, "\red Not enough power to transmit message.") - return - if(IS_PAI) - to_chat(src, "You do not appear to have that function") - return - - robot_talk(message) - return 1 - if("general") - switch(bot_type) - if(IS_AI) - if (AI.aiRadio.disabledAi) - to_chat(src, "\red System Error - Transceiver Disabled") - return - else - log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") - AI.aiRadio.talk_into(src,message,null,verb,speaking) - if(IS_ROBOT) - log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") - R.radio.talk_into(src,message,null,verb,speaking) - if(IS_PAI) - log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") - P.radio.talk_into(src,message,null,verb,speaking) - return 1 - - else - if(message_mode && message_mode in radiochannels) - switch(bot_type) - if(IS_AI) - if (AI.aiRadio.disabledAi) - to_chat(src, "\red System Error - Transceiver Disabled") - return - else - log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") - AI.aiRadio.talk_into(src,message,message_mode,verb,speaking) - if(IS_ROBOT) - log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") - R.radio.talk_into(src,message,message_mode,verb,speaking) - if(IS_PAI) - log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") - P.radio.talk_into(src,message,message_mode,verb,speaking) - return 1 - - return ..(html_decode(message),speaking,verb) - -//For holopads only. Usable by AI. -/mob/living/silicon/ai/proc/holopad_talk(message, verb, datum/language/speaking) - - log_say("[key_name(src)] : [message]") - - message = trim(message) - - if (!message) - return - - var/obj/machinery/hologram/holopad/T = src.holo - if(T && T.hologram && T.master == src)//If there is a hologram and its master is the user. - - //Human-like, sorta, heard by those who understand humans. - var/rendered_a - //Speach distorted, heard by those who do not understand AIs. - var/message_stars = stars(message) - var/rendered_b - - if(speaking) - rendered_a = "[name] [speaking.format_message(message, verb)]" - rendered_b = "[voice_name] [speaking.format_message(message_stars, verb)]" - to_chat(src, "Holopad transmitted, [real_name] [speaking.format_message(message, verb)]")//The AI can "hear" its own message. - else - rendered_a = "[name] [verb], \"[message]\"" - rendered_b = "[voice_name] [verb], \"[message_stars]\"" - to_chat(src, "Holopad transmitted, [real_name] [verb], \"[message]\"")//The AI can "hear" its own message. - - for(var/mob/M in hearers(T.loc))//The location is the object, default distance. - if(M.say_understands(src))//If they understand AI speak. Humans and the like will be able to. - M.show_message(rendered_a, 2) - else//If they do not. - M.show_message(rendered_b, 2) - /*Radios "filter out" this conversation channel so we don't need to account for them. - This is another way of saying that we won't bother dealing with them.*/ - else - to_chat(src, "No holopad connected.") - return - return 1 - -/mob/living/proc/robot_talk(message) - - message = trim(message) - - if (!message) - return - - var/area/A = get_area(src) - log_say("[name]/[key] : \[[A.name]/binary\]: [message]") - - var/verb = say_quote(message) - - - var/rendered = "Robotic Talk, [name] [verb], \"[message]\"" - - for (var/mob/living/S in alive_mob_list) - if(S.robot_talk_understand && (S.robot_talk_understand == robot_talk_understand)) // This SHOULD catch everything caught by the one below, but I'm not going to change it. - if(istype(S , /mob/living/silicon/ai)) - var/renderedAI = "Robotic Talk, [name] [verb], \"[message]\"" - S.show_message(renderedAI, 2) - else - var/mob/living/silicon/robot/borg = S - //if(istype(borg) && borg.is_component_functioning("comms")) - // var/datum/robot_component/RC = borg.get_component("comms") - // if(!borg.use_power(RC.active_usage)) - if(!istype(borg) || !borg.is_component_functioning("comms")) - continue // No power. - S.show_message(rendered, 2) - - - else if (S.binarycheck()) - if(istype(S , /mob/living/silicon/ai)) - var/renderedAI = "Robotic Talk, [name] [verb], \"[message]\"" - S.show_message(renderedAI, 2) - else - S.show_message(rendered, 2) - - var/list/listening = hearers(1, src) - listening -= src - - var/list/heard = list() - for (var/mob/M in listening) - if(!istype(M, /mob/living/silicon) && !M.robot_talk_understand) - heard += M - if (length(heard)) - var/message_beep - verb = "beeps" - message_beep = "beep beep beep" - - rendered = "[voice_name] [verb], \"[message_beep]\"" - - for (var/mob/M in heard) - M.show_message(rendered, 2) - - rendered = "Robotic Talk, [name] [verb], \"[message]\"" - - for (var/mob/M in observer_list) - M.show_message(rendered, 2) - -#undef IS_AI -#undef IS_ROBOT -#undef IS_PAI +/mob/living/silicon/say_quote(text) + var/ending = copytext(text, length(text)) + + if (ending == "?") + return "queries" + else if (ending == "!") + return "declares" + + return "states" + +#define IS_AI 1 +#define IS_ROBOT 2 +#define IS_PAI 3 + +/mob/living/silicon/say_understands(other,datum/language/speaking = null) + //These only pertain to common. Languages are handled by mob/say_understands() + if (!speaking) + if (iscarbon(other) && !isIAN(other)) + return 1 + if (issilicon(other)) + return 1 + if (isbrain(other)) + return 1 + return ..() + +/mob/living/silicon/say(var/message) + if (!message) + 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*/ + + message = sanitize(message) + + if (stat == DEAD) + return say_dead(message) + + if(copytext(message,1,2) == "*") + return emote(copytext(message,2)) + + var/bot_type = 0 //Let's not do a fuck ton of type checks, thanks. + if(istype(src, /mob/living/silicon/ai)) + bot_type = IS_AI + else if(istype(src, /mob/living/silicon/robot)) + bot_type = IS_ROBOT + else if(istype(src, /mob/living/silicon/pai)) + bot_type = IS_PAI + + var/mob/living/silicon/ai/AI = src //and let's not declare vars over and over and over for these guys. + var/mob/living/silicon/robot/R = src + var/mob/living/silicon/pai/P = src + + + //Must be concious to speak + if (stat) + return + + var/verb = say_quote(message) + + //parse radio key and consume it + var/message_mode = parse_message_mode(message, "general") + if (message_mode) + if (message_mode == "general") + message = trim(copytext(message,2)) + else + message = trim(copytext(message,3)) + + if(message_mode && bot_type == IS_ROBOT && message_mode != "binary" && !R.is_component_functioning("radio")) + to_chat(src, "\red Your radio isn't functional at this time.") + return + if(bot_type == IS_ROBOT && message_mode != "binary") + var/datum/robot_component/radio/RA = R.get_component("radio") + if (!R.cell_use_power(RA.active_usage)) + to_chat(usr, "\red Not enough power to transmit message.") + return + + //parse language key and consume it + var/datum/language/speaking = parse_language(message) + if (speaking) + verb = speaking.speech_verb + message = trim(copytext(message,2+length(speaking.key))) + + var/area/A = get_area(src) + + switch(message_mode) + if("department") + switch(bot_type) + if(IS_AI) + return AI.holopad_talk(message, verb, speaking) + if(IS_ROBOT) + log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]: [message]") + R.radio.talk_into(src,message,message_mode,verb,speaking) + if(IS_PAI) + log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") + P.radio.talk_into(src,message,message_mode,verb,speaking) + return 1 + + if("binary") + switch(bot_type) + if(IS_ROBOT) + if(!R.is_component_functioning("comms")) + to_chat(src, "\red Your binary communications component isn't functional.") + return + var/datum/robot_component/binary_communication/B = R.get_component("comms") + if(!R.cell_use_power(B.active_usage)) + to_chat(src, "\red Not enough power to transmit message.") + return + if(IS_PAI) + to_chat(src, "You do not appear to have that function") + return + + robot_talk(message) + return 1 + if("general") + switch(bot_type) + if(IS_AI) + if (AI.aiRadio.disabledAi) + to_chat(src, "\red System Error - Transceiver Disabled") + return + else + log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") + AI.aiRadio.talk_into(src,message,null,verb,speaking) + if(IS_ROBOT) + log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") + R.radio.talk_into(src,message,null,verb,speaking) + if(IS_PAI) + log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") + P.radio.talk_into(src,message,null,verb,speaking) + return 1 + + else + if(message_mode && message_mode in radiochannels) + switch(bot_type) + if(IS_AI) + if (AI.aiRadio.disabledAi) + to_chat(src, "\red System Error - Transceiver Disabled") + return + else + log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") + AI.aiRadio.talk_into(src,message,message_mode,verb,speaking) + if(IS_ROBOT) + log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") + R.radio.talk_into(src,message,message_mode,verb,speaking) + if(IS_PAI) + log_say("[name]/[key] : \[[A.name][message_mode?"/[message_mode]":""]\]]: [message]") + P.radio.talk_into(src,message,message_mode,verb,speaking) + return 1 + + return ..(html_decode(message),speaking,verb) + +//For holopads only. Usable by AI. +/mob/living/silicon/ai/proc/holopad_talk(message, verb, datum/language/speaking) + + log_say("[key_name(src)] : [message]") + + message = trim(message) + + if (!message) + return + + var/obj/machinery/hologram/holopad/T = src.holo + if(T && T.hologram && T.master == src)//If there is a hologram and its master is the user. + + //Human-like, sorta, heard by those who understand humans. + var/rendered_a + //Speach distorted, heard by those who do not understand AIs. + var/message_stars = stars(message) + var/rendered_b + + if(speaking) + rendered_a = "[name] [speaking.format_message(message, verb)]" + rendered_b = "[voice_name] [speaking.format_message(message_stars, verb)]" + to_chat(src, "Holopad transmitted, [real_name] [speaking.format_message(message, verb)]")//The AI can "hear" its own message. + else + rendered_a = "[name] [verb], \"[message]\"" + rendered_b = "[voice_name] [verb], \"[message_stars]\"" + to_chat(src, "Holopad transmitted, [real_name] [verb], \"[message]\"")//The AI can "hear" its own message. + + for(var/mob/M in hearers(T.loc))//The location is the object, default distance. + if(M.say_understands(src))//If they understand AI speak. Humans and the like will be able to. + M.show_message(rendered_a, 2) + else//If they do not. + M.show_message(rendered_b, 2) + /*Radios "filter out" this conversation channel so we don't need to account for them. + This is another way of saying that we won't bother dealing with them.*/ + else + to_chat(src, "No holopad connected.") + return + return 1 + +/mob/living/proc/robot_talk(message) + + message = trim(message) + + if (!message) + return + + var/area/A = get_area(src) + log_say("[name]/[key] : \[[A.name]/binary\]: [message]") + + var/verb = say_quote(message) + + + var/rendered = "Robotic Talk, [name] [verb], \"[message]\"" + + for (var/mob/living/S in alive_mob_list) + if(S.robot_talk_understand && (S.robot_talk_understand == robot_talk_understand)) // This SHOULD catch everything caught by the one below, but I'm not going to change it. + if(istype(S , /mob/living/silicon/ai)) + var/renderedAI = "Robotic Talk, [name] [verb], \"[message]\"" + S.show_message(renderedAI, 2) + else + var/mob/living/silicon/robot/borg = S + //if(istype(borg) && borg.is_component_functioning("comms")) + // var/datum/robot_component/RC = borg.get_component("comms") + // if(!borg.use_power(RC.active_usage)) + if(!istype(borg) || !borg.is_component_functioning("comms")) + continue // No power. + S.show_message(rendered, 2) + + + else if (S.binarycheck()) + if(istype(S , /mob/living/silicon/ai)) + var/renderedAI = "Robotic Talk, [name] [verb], \"[message]\"" + S.show_message(renderedAI, 2) + else + S.show_message(rendered, 2) + + var/list/listening = hearers(1, src) + listening -= src + + var/list/heard = list() + for (var/mob/M in listening) + if(!istype(M, /mob/living/silicon) && !M.robot_talk_understand) + heard += M + if (length(heard)) + var/message_beep + verb = "beeps" + message_beep = "beep beep beep" + + rendered = "[voice_name] [verb], \"[message_beep]\"" + + for (var/mob/M in heard) + M.show_message(rendered, 2) + + rendered = "Robotic Talk, [name] [verb], \"[message]\"" + + for (var/mob/M in observer_list) + M.show_message(rendered, 2) + +#undef IS_AI +#undef IS_ROBOT +#undef IS_PAI diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 9f2c4949e386..04ac4cb64a9d 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -1,196 +1,196 @@ -/mob/living/silicon - gender = NEUTER - robot_talk_understand = 1 - voice_name = "synthesized voice" - var/syndicate = 0 - var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS - immune_to_ssd = 1 - var/list/hud_list[9] - var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer - var/obj/item/device/pda/silicon/pda = null - - - - - - - var/obj/item/device/camera/siliconcam/aiCamera = null //photography - - var/sensor_mode = 0 //Determines the current HUD. - #define SEC_HUD 1 //Security HUD mode - #define MED_HUD 2 //Medical HUD mode - -/mob/living/silicon/atom_init() - . = ..() - silicon_list += src - -/mob/living/silicon/Destroy() - silicon_list -= src - return ..() - -/mob/living/silicon/proc/show_laws() - return - -/mob/living/silicon/proc/checklaws() - return - -/mob/living/silicon/proc/show_alerts() - return - -/mob/living/silicon/drop_item() - return - -/mob/living/silicon/emp_act(severity) - switch(severity) - if(1) - src.take_bodypart_damage(20) - Stun(rand(5,10)) - if(2) - src.take_bodypart_damage(10) - Stun(rand(1,5)) - flash_eyes(affect_silicon = 1) - to_chat(src, "\red *BZZZT*") - to_chat(src, "\red Warning: Electromagnetic pulse detected.") - ..() - -/mob/living/silicon/proc/damage_mob(brute = 0, fire = 0, tox = 0) - return - -/mob/living/silicon/IsAdvancedToolUser() - return 1 - -/mob/living/silicon/bullet_act(obj/item/projectile/Proj) - - - if(!Proj.nodamage) - switch(Proj.damage_type) - if(BRUTE) - adjustBruteLoss(Proj.damage) - if(BURN) - adjustFireLoss(Proj.damage) - - Proj.on_hit(src,2) - - return 2 - -/mob/living/silicon/apply_effect(effect = 0,effecttype = STUN, 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(mob/living/silicon/robot/bot, mob/living/silicon/ai/ai) - if(!istype(bot) || !istype(ai)) - return 0 - if (bot.connected_ai == ai) - return 1 - return 0 - -// This is a pure virtual function, it should be overwritten by all subclasses -/mob/living/silicon/proc/show_malf_ai() - return 0 - -// This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms -/mob/living/silicon/Stat() - ..() - if(statpanel("Status")) - stat(null, "Station Time: [worldtime2text()]") - - if(SSshuttle.online && SSshuttle.location < 2) - stat(null, "ETA-[shuttleeta2text()]") - - if(stat == CONSCIOUS) - stat(null, text("System integrity: [round((health / maxHealth) * 100)]%")) - else - stat(null, text("Systems nonfunctional")) - - 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(entity_ja(dat), "window=airoster") - onclose(src, "airoster") - -//can't inject synths -/mob/living/silicon/try_inject(mob/user, error_msg) - if(error_msg) - to_chat(user, "The armoured plating is too tough.") - return FALSE - - -//Silicon mob language procs - -/mob/living/silicon/can_speak(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(language, can_speak=1) - if (..(language) && can_speak) - speech_synthesizer_langs.Add(all_languages[language]) - -/mob/living/silicon/remove_language(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

                    " - - for(var/datum/language/L in languages) - dat += "[L.name] " - for(var/l_key in L.key) - dat += "(:[l_key])" - dat += "
                    Speech Synthesizer: [(L in speech_synthesizer_langs)? "YES":"NOT SUPPORTED"]
                    [L.desc]

                    " - - src << browse(entity_ja(dat), "window=checklanguage") - return - -/mob/living/silicon/proc/toggle_sensor_mode() - //set name = "Set Sensor Augmentation" // Dunno, but it loops if open. ~Zve - //set desc = "Augment visual feed with internal sensor overlays." - var/sensor_type = input("Please select sensor type.", "Sensor Integration", null) in list("Security", "Medical","Disable") - switch(sensor_type) - if ("Security") - sensor_mode = SEC_HUD - to_chat(src, "Security records overlay enabled.") - if ("Medical") - sensor_mode = MED_HUD - to_chat(src, "Life signs monitor overlay enabled.") - if ("Disable") - sensor_mode = 0 - to_chat(src, "Sensor augmentations disabled.") - -/mob/living/silicon/proc/write_laws() - if(laws) - var/text = src.laws.write_laws() - return text - -/mob/living/silicon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/noise) - if(affect_silicon) - return ..() +/mob/living/silicon + gender = NEUTER + robot_talk_understand = 1 + voice_name = "synthesized voice" + var/syndicate = 0 + var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS + immune_to_ssd = 1 + var/list/hud_list[9] + var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer + var/obj/item/device/pda/silicon/pda = null + + + + + + + var/obj/item/device/camera/siliconcam/aiCamera = null //photography + + var/sensor_mode = 0 //Determines the current HUD. + #define SEC_HUD 1 //Security HUD mode + #define MED_HUD 2 //Medical HUD mode + +/mob/living/silicon/atom_init() + . = ..() + silicon_list += src + +/mob/living/silicon/Destroy() + silicon_list -= src + return ..() + +/mob/living/silicon/proc/show_laws() + return + +/mob/living/silicon/proc/checklaws() + return + +/mob/living/silicon/proc/show_alerts() + return + +/mob/living/silicon/drop_item() + return + +/mob/living/silicon/emp_act(severity) + switch(severity) + if(1) + src.take_bodypart_damage(20) + Stun(rand(5,10)) + if(2) + src.take_bodypart_damage(10) + Stun(rand(1,5)) + flash_eyes(affect_silicon = 1) + to_chat(src, "\red *BZZZT*") + to_chat(src, "\red Warning: Electromagnetic pulse detected.") + ..() + +/mob/living/silicon/proc/damage_mob(brute = 0, fire = 0, tox = 0) + return + +/mob/living/silicon/IsAdvancedToolUser() + return 1 + +/mob/living/silicon/bullet_act(obj/item/projectile/Proj) + + + if(!Proj.nodamage) + switch(Proj.damage_type) + if(BRUTE) + adjustBruteLoss(Proj.damage) + if(BURN) + adjustFireLoss(Proj.damage) + + Proj.on_hit(src,2) + + return 2 + +/mob/living/silicon/apply_effect(effect = 0,effecttype = STUN, 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(mob/living/silicon/robot/bot, mob/living/silicon/ai/ai) + if(!istype(bot) || !istype(ai)) + return 0 + if (bot.connected_ai == ai) + return 1 + return 0 + +// This is a pure virtual function, it should be overwritten by all subclasses +/mob/living/silicon/proc/show_malf_ai() + return 0 + +// This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms +/mob/living/silicon/Stat() + ..() + if(statpanel("Status")) + stat(null, "Station Time: [worldtime2text()]") + + if(SSshuttle.online && SSshuttle.location < 2) + stat(null, "ETA-[shuttleeta2text()]") + + if(stat == CONSCIOUS) + stat(null, text("System integrity: [round((health / maxHealth) * 100)]%")) + else + stat(null, text("Systems nonfunctional")) + + 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(entity_ja(dat), "window=airoster") + onclose(src, "airoster") + +//can't inject synths +/mob/living/silicon/try_inject(mob/user, error_msg) + if(error_msg) + to_chat(user, "The armoured plating is too tough.") + return FALSE + + +//Silicon mob language procs + +/mob/living/silicon/can_speak(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(language, can_speak=1) + if (..(language) && can_speak) + speech_synthesizer_langs.Add(all_languages[language]) + +/mob/living/silicon/remove_language(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

                    " + + for(var/datum/language/L in languages) + dat += "[L.name] " + for(var/l_key in L.key) + dat += "(:[l_key])" + dat += "
                    Speech Synthesizer: [(L in speech_synthesizer_langs)? "YES":"NOT SUPPORTED"]
                    [L.desc]

                    " + + src << browse(entity_ja(dat), "window=checklanguage") + return + +/mob/living/silicon/proc/toggle_sensor_mode() + //set name = "Set Sensor Augmentation" // Dunno, but it loops if open. ~Zve + //set desc = "Augment visual feed with internal sensor overlays." + var/sensor_type = input("Please select sensor type.", "Sensor Integration", null) in list("Security", "Medical","Disable") + switch(sensor_type) + if ("Security") + sensor_mode = SEC_HUD + to_chat(src, "Security records overlay enabled.") + if ("Medical") + sensor_mode = MED_HUD + to_chat(src, "Life signs monitor overlay enabled.") + if ("Disable") + sensor_mode = 0 + to_chat(src, "Sensor augmentations disabled.") + +/mob/living/silicon/proc/write_laws() + if(laws) + var/text = src.laws.write_laws() + return text + +/mob/living/silicon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/noise) + if(affect_silicon) + return ..() diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 95ad76ac19a5..f01268213a96 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -1,238 +1,238 @@ -/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 = "harm" - stop_automated_movement = 1 - status_flags = CANPUSH - universal_speak = 1 - attack_sound = 'sound/weapons/punch1.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 - faction = "cult" - var/list/construct_spells = list() - -/mob/living/simple_animal/construct/atom_init() - . = ..() - name = text("[initial(name)] ([rand(1, 1000)])") - real_name = name - for(var/spell in construct_spells) - spell_list += new spell(src) - -/mob/living/simple_animal/construct/death() - ..() - new /obj/item/weapon/reagent_containers/food/snacks/ectoplasm (src.loc) - visible_message("[src] collapses in a shattered heap.") - ghostize(bancheck = TRUE) - qdel(src) - return - -/mob/living/simple_animal/construct/examine(mob/user) - var/msg = "*---------*\nThis is [bicon(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) - if(istype(M, /mob/living/simple_animal/construct/builder) && health < maxHealth) - health += min(health + 5, maxHealth) - M.visible_message("[M] mends some of the [src]'s wounds.") - return - return ..() - -/mob/living/simple_animal/construct/attackby(obj/item/O, mob/user) - user.SetNextMove(CLICK_CD_MELEE) - if(O.force) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - visible_message("[src] has been attacked with [O] by [user].") - else - to_chat(user, "This weapon is ineffective, it does no damage.") - 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/punch3.ogg' - status_flags = 0 - construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall) - -/mob/living/simple_animal/construct/armoured/attackby(obj/item/O, mob/user) - user.SetNextMove(CLICK_CD_MELEE) - if(O.force) - if(O.force >= 11) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - visible_message("[src] has been attacked with [O] by [user].") - else - visible_message("[O] bounces harmlessly off of [src].") - else - to_chat(usr, "This weapon is ineffective, it does no damage.") - visible_message("[user] gently taps [src] with [O].") - -/mob/living/simple_animal/construct/armoured/Life() - weakened = 0 - ..() - -/mob/living/simple_animal/construct/armoured/bullet_act(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.redirect(new_x, new_y, curloc, src) - - 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 - see_in_dark = 7 - attack_sound = 'sound/weapons/bladeslice.ogg' - construct_spells = list(/obj/effect/proc_holder/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 = 2 - attack_sound = 'sound/weapons/punch2.ogg' - construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser, - /obj/effect/proc_holder/spell/aoe_turf/conjure/wall, - /obj/effect/proc_holder/spell/aoe_turf/conjure/floor, - /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone) - - -/////////////////////////////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/punch4.ogg' - var/energy = 0 - var/max_energy = 1000 - -/mob/living/simple_animal/construct/behemoth/attackby(obj/item/O, mob/user) - user.SetNextMove(CLICK_CD_MELEE) - if(O.force) - if(O.force >= 11) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - adjustBruteLoss(damage) - visible_message("[src] has been attacked with [O] by [user].") - else - visible_message("[O] bounces harmlessly off of [src].") - else - to_chat(user, "This weapon is ineffective, it does no damage.") - visible_message("[user] gently taps [src] with [O].") - - -/////////////////////////////////////Harvester construct///////////////////////////////// -/mob/living/simple_animal/construct/harvester - name = "Harvester" - real_name = "Harvester" - desc = "A harbinger of Nar-Sie's enlightenment. It'll be all over soon." - icon = 'icons/mob/harvester.dmi' - icon_state = "harvester" - icon_living = "harvester" - maxHealth = 60 - health = 60 - melee_damage_lower = 1 - melee_damage_upper = 5 - attacktext = "prods" - speed = 0 - environment_smash = 1 - see_in_dark = 7 - attack_sound = 'sound/weapons/slash.ogg' - construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/smoke) - -/mob/living/simple_animal/construct/harvester/Process_Spacemove(movement_dir = 0) - return 1 +/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 = "harm" + stop_automated_movement = 1 + status_flags = CANPUSH + universal_speak = 1 + attack_sound = 'sound/weapons/punch1.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 + faction = "cult" + var/list/construct_spells = list() + +/mob/living/simple_animal/construct/atom_init() + . = ..() + name = text("[initial(name)] ([rand(1, 1000)])") + real_name = name + for(var/spell in construct_spells) + spell_list += new spell(src) + +/mob/living/simple_animal/construct/death() + ..() + new /obj/item/weapon/reagent_containers/food/snacks/ectoplasm (src.loc) + visible_message("[src] collapses in a shattered heap.") + ghostize(bancheck = TRUE) + qdel(src) + return + +/mob/living/simple_animal/construct/examine(mob/user) + var/msg = "*---------*\nThis is [bicon(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) + if(istype(M, /mob/living/simple_animal/construct/builder) && health < maxHealth) + health += min(health + 5, maxHealth) + M.visible_message("[M] mends some of the [src]'s wounds.") + return + return ..() + +/mob/living/simple_animal/construct/attackby(obj/item/O, mob/user) + user.SetNextMove(CLICK_CD_MELEE) + if(O.force) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + adjustBruteLoss(damage) + visible_message("[src] has been attacked with [O] by [user].") + else + to_chat(user, "This weapon is ineffective, it does no damage.") + 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/punch3.ogg' + status_flags = 0 + construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall) + +/mob/living/simple_animal/construct/armoured/attackby(obj/item/O, mob/user) + user.SetNextMove(CLICK_CD_MELEE) + if(O.force) + if(O.force >= 11) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + adjustBruteLoss(damage) + visible_message("[src] has been attacked with [O] by [user].") + else + visible_message("[O] bounces harmlessly off of [src].") + else + to_chat(usr, "This weapon is ineffective, it does no damage.") + visible_message("[user] gently taps [src] with [O].") + +/mob/living/simple_animal/construct/armoured/Life() + weakened = 0 + ..() + +/mob/living/simple_animal/construct/armoured/bullet_act(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.redirect(new_x, new_y, curloc, src) + + 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 + see_in_dark = 7 + attack_sound = 'sound/weapons/bladeslice.ogg' + construct_spells = list(/obj/effect/proc_holder/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 = 2 + attack_sound = 'sound/weapons/punch2.ogg' + construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser, + /obj/effect/proc_holder/spell/aoe_turf/conjure/wall, + /obj/effect/proc_holder/spell/aoe_turf/conjure/floor, + /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone) + + +/////////////////////////////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/punch4.ogg' + var/energy = 0 + var/max_energy = 1000 + +/mob/living/simple_animal/construct/behemoth/attackby(obj/item/O, mob/user) + user.SetNextMove(CLICK_CD_MELEE) + if(O.force) + if(O.force >= 11) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + adjustBruteLoss(damage) + visible_message("[src] has been attacked with [O] by [user].") + else + visible_message("[O] bounces harmlessly off of [src].") + else + to_chat(user, "This weapon is ineffective, it does no damage.") + visible_message("[user] gently taps [src] with [O].") + + +/////////////////////////////////////Harvester construct///////////////////////////////// +/mob/living/simple_animal/construct/harvester + name = "Harvester" + real_name = "Harvester" + desc = "A harbinger of Nar-Sie's enlightenment. It'll be all over soon." + icon = 'icons/mob/harvester.dmi' + icon_state = "harvester" + icon_living = "harvester" + maxHealth = 60 + health = 60 + melee_damage_lower = 1 + melee_damage_upper = 5 + attacktext = "prods" + speed = 0 + environment_smash = 1 + see_in_dark = 7 + attack_sound = 'sound/weapons/slash.ogg' + construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/smoke) + +/mob/living/simple_animal/construct/harvester/Process_Spacemove(movement_dir = 0) + return 1 diff --git a/code/modules/mob/living/simple_animal/corpse.dm b/code/modules/mob/living/simple_animal/corpse.dm index 7c1fd730dc47..785688a91ecc 100644 --- a/code/modules/mob/living/simple_animal/corpse.dm +++ b/code/modules/mob/living/simple_animal/corpse.dm @@ -1,158 +1,158 @@ -//Meant for simple animals to drop lootable human bodies. - -//If someone can do this in a neater way, be my guest-Kor - -//This has to be seperate from the Away Mission corpses, because New() doesn't work for those, and initialize() doesn't work for these. (probably not a problem now) - -//To do: Allow corpses to appear mangled, bloody, etc. Allow customizing the bodies appearance (they're all bald and white right now). - - -/obj/effect/landmark/mobcorpse - 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 - -/obj/effect/landmark/mobcorpse/atom_init() - ..() - createCorpse() - return INITIALIZE_HINT_QDEL - -/obj/effect/landmark/mobcorpse/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 (src.loc) - M.real_name = src.name - M.stat = DEAD //Kills the new mob - 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_l_ear) - 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) - - - -//List of different corpse types - -/obj/effect/landmark/mobcorpse/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/mobcorpse/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" - - - -/obj/effect/landmark/mobcorpse/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/mobcorpse/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/mobcorpse/pirate/ranged - name = "Pirate Gunner" - corpsesuit = /obj/item/clothing/suit/pirate - corpsehelmet = /obj/item/clothing/head/pirate - - - -/obj/effect/landmark/mobcorpse/russian - name = "Russian" - corpseuniform = /obj/item/clothing/under/soviet - corpseshoes = /obj/item/clothing/shoes/jackboots - corpsehelmet = /obj/item/clothing/head/bearpelt - -/obj/effect/landmark/mobcorpse/russian/ranged - corpsehelmet = /obj/item/clothing/head/ushanka +//Meant for simple animals to drop lootable human bodies. + +//If someone can do this in a neater way, be my guest-Kor + +//This has to be seperate from the Away Mission corpses, because New() doesn't work for those, and initialize() doesn't work for these. (probably not a problem now) + +//To do: Allow corpses to appear mangled, bloody, etc. Allow customizing the bodies appearance (they're all bald and white right now). + + +/obj/effect/landmark/mobcorpse + 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 + +/obj/effect/landmark/mobcorpse/atom_init() + ..() + createCorpse() + return INITIALIZE_HINT_QDEL + +/obj/effect/landmark/mobcorpse/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 (src.loc) + M.real_name = src.name + M.stat = DEAD //Kills the new mob + 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_l_ear) + 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) + + + +//List of different corpse types + +/obj/effect/landmark/mobcorpse/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/mobcorpse/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" + + + +/obj/effect/landmark/mobcorpse/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/mobcorpse/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/mobcorpse/pirate/ranged + name = "Pirate Gunner" + corpsesuit = /obj/item/clothing/suit/pirate + corpsehelmet = /obj/item/clothing/head/pirate + + + +/obj/effect/landmark/mobcorpse/russian + name = "Russian" + corpseuniform = /obj/item/clothing/under/soviet + corpseshoes = /obj/item/clothing/shoes/jackboots + corpsehelmet = /obj/item/clothing/head/bearpelt + +/obj/effect/landmark/mobcorpse/russian/ranged + corpsehelmet = /obj/item/clothing/head/ushanka diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index d23e2fa78260..08efdd00d86b 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -1,154 +1,154 @@ -//Cat -/mob/living/simple_animal/cat - name = "cat" - desc = "A domesticated, feline pet. Has a tendency to adopt crewmembers." - icon_state = "cat" - icon_living = "cat" - icon_dead = "cat_dead" - 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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 2) - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "kicks the" - var/turns_since_scan = 0 - var/mob/living/simple_animal/mouse/movement_target - min_oxy = 16 //Require atleast 16kPA oxygen - minbodytemp = 223 //Below -50 Degrees Celcius - maxbodytemp = 323 //Above 50 Degrees Celcius - holder_type = /obj/item/weapon/holder/cat - var/obj/item/inventory_mouth - -/mob/living/simple_animal/cat/Life() - //MICE! - if((src.loc) && isturf(src.loc)) - if(!stat && !resting && !buckled) - for(var/mob/living/simple_animal/mouse/M in view(1,src)) - if(!M.stat) - M.splat() - emote(pick("\red splats the [M]!","\red 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 && !buckled) - 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/death() - if(inventory_mouth) - inventory_mouth.loc = src.loc - inventory_mouth = null - regenerate_icons() - return ..() - -/mob/living/simple_animal/cat/MouseDrop(atom/over_object) - - var/mob/living/carbon/H = over_object - if(!istype(H) || !Adjacent(H) || ismob(H.loc)) - return ..() - - //This REALLY needs to be moved to a general mob proc somewhere. - if(H.a_intent == "help") - get_scooped(H) - return - else - return ..() - -/mob/living/simple_animal/cat/show_inv(mob/user) - if(user.stat) - return - - user.set_machine(src) - - var/dat - if(inventory_mouth) - dat = "
                    Mouth:Remove" - else - dat = "
                    Mouth:Nothing" - - //dat += "
                    Close" - - var/datum/browser/popup = new(user, "mob[type]", "Inventory of [name]", 325, 500) - popup.set_content(dat) - popup.open() - -/mob/living/simple_animal/cat/Topic(href, href_list) - if(usr.stat || stat || !Adjacent(usr) || !(ishuman(usr) || ismonkey(usr))) - return - - //Removing from inventory - if(href_list["remove_inv"]) - if(inventory_mouth) - inventory_mouth.loc = src.loc - inventory_mouth = null - regenerate_icons() - show_inv(usr) - else - return - - else if(href_list["add_inv"]) - var/obj/item/item_to_add = usr.get_active_hand() - if(!item_to_add || inventory_mouth) - return - else if(item_to_add.type == /obj/item/clothing/mask/cigarette) - usr.drop_item() - item_to_add.loc = src - src.inventory_mouth = item_to_add - regenerate_icons() - show_inv(usr) - else - ..() - -/mob/living/simple_animal/cat/regenerate_icons() - overlays.Cut() - - if(inventory_mouth) - overlays += image('icons/mob/animal.dmi',inventory_mouth.icon_state) - -//RUNTIME IS ALIVE! SQUEEEEEEEE~ -/mob/living/simple_animal/cat/Runtime - name = "Runtime" - desc = "Its fur has the look and feel of velvet, and its tail quivers occasionally." - -/mob/living/simple_animal/cat/Syndi - name = "SyndiCat" - desc = "It's a SyndiCat droid." - icon_state = "Syndicat" - icon_living = "Syndicat" - icon_dead = "Syndicat_dead" - //gender = FEMALE - flags = list( - IS_SYNTHETIC = TRUE - ,NO_BREATHE = TRUE - ) - faction = list("syndicate") - //var/turns_since_scan = 0 - //var/mob/living/simple_animal/mouse/movement_target +//Cat +/mob/living/simple_animal/cat + name = "cat" + desc = "A domesticated, feline pet. Has a tendency to adopt crewmembers." + icon_state = "cat" + icon_living = "cat" + icon_dead = "cat_dead" + 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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 2) + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "kicks the" + var/turns_since_scan = 0 + var/mob/living/simple_animal/mouse/movement_target + min_oxy = 16 //Require atleast 16kPA oxygen + minbodytemp = 223 //Below -50 Degrees Celcius + maxbodytemp = 323 //Above 50 Degrees Celcius + holder_type = /obj/item/weapon/holder/cat + var/obj/item/inventory_mouth + +/mob/living/simple_animal/cat/Life() + //MICE! + if((src.loc) && isturf(src.loc)) + if(!stat && !resting && !buckled) + for(var/mob/living/simple_animal/mouse/M in view(1,src)) + if(!M.stat) + M.splat() + emote(pick("\red splats the [M]!","\red 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 && !buckled) + 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/death() + if(inventory_mouth) + inventory_mouth.loc = src.loc + inventory_mouth = null + regenerate_icons() + return ..() + +/mob/living/simple_animal/cat/MouseDrop(atom/over_object) + + var/mob/living/carbon/H = over_object + if(!istype(H) || !Adjacent(H) || ismob(H.loc)) + return ..() + + //This REALLY needs to be moved to a general mob proc somewhere. + if(H.a_intent == "help") + get_scooped(H) + return + else + return ..() + +/mob/living/simple_animal/cat/show_inv(mob/user) + if(user.stat) + return + + user.set_machine(src) + + var/dat + if(inventory_mouth) + dat = "
                    Mouth:Remove" + else + dat = "
                    Mouth:Nothing" + + //dat += "
                    Close" + + var/datum/browser/popup = new(user, "mob[type]", "Inventory of [name]", 325, 500) + popup.set_content(dat) + popup.open() + +/mob/living/simple_animal/cat/Topic(href, href_list) + if(usr.stat || stat || !Adjacent(usr) || !(ishuman(usr) || ismonkey(usr))) + return + + //Removing from inventory + if(href_list["remove_inv"]) + if(inventory_mouth) + inventory_mouth.loc = src.loc + inventory_mouth = null + regenerate_icons() + show_inv(usr) + else + return + + else if(href_list["add_inv"]) + var/obj/item/item_to_add = usr.get_active_hand() + if(!item_to_add || inventory_mouth) + return + else if(item_to_add.type == /obj/item/clothing/mask/cigarette) + usr.drop_item() + item_to_add.loc = src + src.inventory_mouth = item_to_add + regenerate_icons() + show_inv(usr) + else + ..() + +/mob/living/simple_animal/cat/regenerate_icons() + overlays.Cut() + + if(inventory_mouth) + overlays += image('icons/mob/animal.dmi',inventory_mouth.icon_state) + +//RUNTIME IS ALIVE! SQUEEEEEEEE~ +/mob/living/simple_animal/cat/Runtime + name = "Runtime" + desc = "Its fur has the look and feel of velvet, and its tail quivers occasionally." + +/mob/living/simple_animal/cat/Syndi + name = "SyndiCat" + desc = "It's a SyndiCat droid." + icon_state = "Syndicat" + icon_living = "Syndicat" + icon_dead = "Syndicat_dead" + //gender = FEMALE + flags = list( + IS_SYNTHETIC = TRUE + ,NO_BREATHE = TRUE + ) + faction = list("syndicate") + //var/turns_since_scan = 0 + //var/mob/living/simple_animal/mouse/movement_target diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index 34b7544d4fb9..60f59e442f72 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -1,178 +1,178 @@ -//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" - 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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/corgi = 3) - response_help = "pets the" - response_disarm = "bops the" - response_harm = "kicks the" - see_in_dark = 5 - var/facehugger - -/obj/item/weapon/reagent_containers/food/snacks/meat/corgi - name = "Corgi meat" - desc = "Tastes like... well you know..." - -/mob/living/simple_animal/corgi/regenerate_icons() - overlays.Cut() - 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") - -/mob/living/simple_animal/corgi/attackby(obj/item/O, mob/user) - if(istype(O, /obj/item/weapon/newspaper)) - user.SetNextMove(CLICK_CD_MELEE) - if(!stat) - for(var/mob/M in viewers(user, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\blue [user] baps [name] on the nose with the rolled up [O]") - spawn(0) - for(var/i in list(1,2,4,8,4,2,1,2)) - dir = i - sleep(1) - else - ..() - -/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" - -//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 - -/mob/living/simple_animal/corgi/Lisa/Life() - ..() - - if(!stat && !resting && !buckled) - turns_since_scan++ - if(turns_since_scan > 15) - turns_since_scan = 0 - var/alone = 1 - var/ian = 0 - //for(var/mob/M in oviewers(7, src)) - for(var/mob/M in oview(src,7)) - if(istype(M, /mob/living/carbon/ian)) - if(M.client) - alone = 0 - break - else - ian = M - else - alone = 0 - break - if(alone && ian && puppies < 4) - if(near_camera(src) || near_camera(ian)) - return - new /mob/living/simple_animal/corgi/puppy(loc) - puppies++ - - - if(prob(1)) - emote("me",1,pick("dances around","chases her tail")) - 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) - -/mob/living/simple_animal/corgi/borgi - name = "E-N" - real_name = "E-N" //Intended to hold the name without altering it. - desc = "It's a borgi." - icon_state = "borgi" - icon_living = "borgi" - icon_dead = "borgi_dead" - butcher_results = list() - var/emagged = 0 - -/mob/living/simple_animal/corgi/borgi/attackby(obj/item/weapon/W, mob/user) - if (istype(W, /obj/item/weapon/card/emag) && emagged < 2) - user.SetNextMove(CLICK_CD_MELEE) - Emag(user) - else - ..() - -/mob/living/simple_animal/corgi/borgi/proc/Emag(user) - if(!emagged) - emagged = 1 - visible_message("[user] swipes a card through [src].", "You overload [src]s internal reactor.") - spawn (1000) - src.explode() - -/mob/living/simple_animal/corgi/borgi/proc/explode() - for(var/mob/M in viewers(src, null)) - if (M.client) - M.show_message("\red [src] makes an odd whining noise.") - sleep(10) - explosion(get_turf(src), 0, 1, 4, 7) - Die() - -/mob/living/simple_animal/corgi/borgi/proc/shootAt(atom/movable/target) - var/turf/T = get_turf(src) - var/turf/U = get_turf(target) - if (!T || !U) - return - var/obj/item/projectile/beam/A = new /obj/item/projectile/beam(loc) - A.icon = 'icons/effects/genetics.dmi' - A.icon_state = "eyelasers" - playsound(src.loc, 'sound/weapons/taser2.ogg', 75, 1) - A.original = target - A.current = T - A.starting = T - A.yo = U.y - T.y - A.xo = U.x - T.x - spawn( 0 ) - A.process() - return - -/mob/living/simple_animal/corgi/borgi/Life() - ..() - if(health <= 0) return - if(emagged && prob(25)) - var/mob/living/carbon/target = locate() in view(10,src) - if (target) - shootAt(target) - - //spark for no reason - if(prob(5)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - -/mob/living/simple_animal/corgi/borgi/proc/Die() - ..() - visible_message("[src] blows apart!") - new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - //respawnable_list += src - qdel(src) - 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" + 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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/corgi = 3) + response_help = "pets the" + response_disarm = "bops the" + response_harm = "kicks the" + see_in_dark = 5 + var/facehugger + +/obj/item/weapon/reagent_containers/food/snacks/meat/corgi + name = "Corgi meat" + desc = "Tastes like... well you know..." + +/mob/living/simple_animal/corgi/regenerate_icons() + overlays.Cut() + 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") + +/mob/living/simple_animal/corgi/attackby(obj/item/O, mob/user) + if(istype(O, /obj/item/weapon/newspaper)) + user.SetNextMove(CLICK_CD_MELEE) + if(!stat) + for(var/mob/M in viewers(user, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\blue [user] baps [name] on the nose with the rolled up [O]") + spawn(0) + for(var/i in list(1,2,4,8,4,2,1,2)) + dir = i + sleep(1) + else + ..() + +/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" + +//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 + +/mob/living/simple_animal/corgi/Lisa/Life() + ..() + + if(!stat && !resting && !buckled) + turns_since_scan++ + if(turns_since_scan > 15) + turns_since_scan = 0 + var/alone = 1 + var/ian = 0 + //for(var/mob/M in oviewers(7, src)) + for(var/mob/M in oview(src,7)) + if(istype(M, /mob/living/carbon/ian)) + if(M.client) + alone = 0 + break + else + ian = M + else + alone = 0 + break + if(alone && ian && puppies < 4) + if(near_camera(src) || near_camera(ian)) + return + new /mob/living/simple_animal/corgi/puppy(loc) + puppies++ + + + if(prob(1)) + emote("me",1,pick("dances around","chases her tail")) + 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) + +/mob/living/simple_animal/corgi/borgi + name = "E-N" + real_name = "E-N" //Intended to hold the name without altering it. + desc = "It's a borgi." + icon_state = "borgi" + icon_living = "borgi" + icon_dead = "borgi_dead" + butcher_results = list() + var/emagged = 0 + +/mob/living/simple_animal/corgi/borgi/attackby(obj/item/weapon/W, mob/user) + if (istype(W, /obj/item/weapon/card/emag) && emagged < 2) + user.SetNextMove(CLICK_CD_MELEE) + Emag(user) + else + ..() + +/mob/living/simple_animal/corgi/borgi/proc/Emag(user) + if(!emagged) + emagged = 1 + visible_message("[user] swipes a card through [src].", "You overload [src]s internal reactor.") + spawn (1000) + src.explode() + +/mob/living/simple_animal/corgi/borgi/proc/explode() + for(var/mob/M in viewers(src, null)) + if (M.client) + M.show_message("\red [src] makes an odd whining noise.") + sleep(10) + explosion(get_turf(src), 0, 1, 4, 7) + Die() + +/mob/living/simple_animal/corgi/borgi/proc/shootAt(atom/movable/target) + var/turf/T = get_turf(src) + var/turf/U = get_turf(target) + if (!T || !U) + return + var/obj/item/projectile/beam/A = new /obj/item/projectile/beam(loc) + A.icon = 'icons/effects/genetics.dmi' + A.icon_state = "eyelasers" + playsound(src.loc, 'sound/weapons/taser2.ogg', 75, 1) + A.original = target + A.current = T + A.starting = T + A.yo = U.y - T.y + A.xo = U.x - T.x + spawn( 0 ) + A.process() + return + +/mob/living/simple_animal/corgi/borgi/Life() + ..() + if(health <= 0) return + if(emagged && prob(25)) + var/mob/living/carbon/target = locate() in view(10,src) + if (target) + shootAt(target) + + //spark for no reason + if(prob(5)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + +/mob/living/simple_animal/corgi/borgi/proc/Die() + ..() + visible_message("[src] blows apart!") + new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + //respawnable_list += src + qdel(src) + return diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index 2ff791db3a00..d29a5646c337 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -1,278 +1,278 @@ -//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" - small = 1 - speak_emote = list("clicks") - emote_hear = list("clicks") - emote_see = list("clacks") - speak_chance = 1 - turns_per_move = 5 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1) - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "stomps the" - stop_automated_movement = 1 - friendly = "pinches" - var/obj/item/inventory_head - var/obj/item/inventory_mask - ventcrawler = 2 - -/mob/living/simple_animal/crab/Life() - ..() - //CRAB movement - if(!ckey && !stat) - if(isturf(src.loc) && !resting && !buckled) //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) - var/east_vs_west = pick(4, 8) - if(Process_Spacemove(east_vs_west)) - Move(get_step(src, east_vs_west), east_vs_west) - 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(obj/item/O, mob/user) - if(istype(O, /obj/item/weapon/wirecutters)) - if(prob(50)) - to_chat(user, "\red \b This kills the crab.") - health -= 20 - death() - else - GetMad() - get - if(istype(O, /obj/item/stack/medical)) - if(stat != DEAD) - var/obj/item/stack/medical/MED = O - if(health < maxHealth) - if(MED.use(1)) - health = min(maxHealth, health + MED.heal_brute) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\blue [user] applies the [MED] on [src]") - else - to_chat(user, "\blue this [src] is dead, medical items won't bring it back to life.") - else - if(O.force) - health -= O.force - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red \b [src] has been attacked with the [O] by [user]. ") - else - to_chat(usr, "\red This weapon is ineffective, it does no damage.") - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red [user] gently taps [src] with the [O]. ") - -/mob/living/simple_animal/crab/Topic(href, href_list) - if(usr.stat) return - - //Removing from inventory - if(href_list["remove_inv"]) - if(get_dist(src,usr) > 1 || !(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_emote = list("clicks") - emote_hear = list("clicks") - emote_see = list("clacks") - desc = "Free crabs!" - src.sd_set_light(0) - inventory_head.loc = src.loc - inventory_head = null - else - to_chat(usr, "\red There is nothing to remove from its [remove_from].") - return - if("mask") - if(inventory_mask) - inventory_mask.loc = src.loc - inventory_mask = null - else - to_chat(usr, "\red There is nothing to remove from its [remove_from].") - return - - //show_inv(usr) //Commented out because changing Ian's name and then calling up his inventory opens a new inventory...which is annoying. - - //Adding things to inventory - else if(href_list["add_inv"]) - if(get_dist(src,usr) > 1 || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) - return - var/add_to = href_list["add_inv"] - if(!usr.get_active_hand()) - to_chat(usr, "\red You have nothing in your hand to put on its [add_to].") - return - switch(add_to) - if("head") - if(inventory_head) - to_chat(usr, "\red It's is already wearing something.") - return - else - var/obj/item/item_to_add = usr.get_active_hand() - if(!item_to_add) - return - - //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. - - var/list/allowed_types = list( - /obj/item/clothing/head/helmet, - /obj/item/clothing/glasses/sunglasses, - /obj/item/clothing/head/caphat, - /obj/item/clothing/head/collectable/captain, - /obj/item/clothing/head/that, - /obj/item/clothing/head/that, - /obj/item/clothing/head/kitty, - /obj/item/clothing/head/collectable/kitty, - /obj/item/clothing/head/rabbitears, - /obj/item/clothing/head/collectable/rabbitears, - /obj/item/clothing/head/beret, - /obj/item/clothing/head/collectable/beret, - /obj/item/clothing/head/det_hat, - /obj/item/clothing/head/nursehat, - /obj/item/clothing/head/pirate, - /obj/item/clothing/head/collectable/pirate, - /obj/item/clothing/head/chefhat, - /obj/item/clothing/head/collectable/chef, - /obj/item/clothing/head/collectable/police, - /obj/item/clothing/head/wizard/fake, - /obj/item/clothing/head/wizard, - /obj/item/clothing/head/collectable/wizard, - /obj/item/clothing/head/hardhat/yellow, - /obj/item/clothing/head/collectable/hardhat, - /obj/item/clothing/head/hardhat/white, - /obj/item/weapon/bedsheet, - /obj/item/clothing/head/soft - ) - - if( ! ( item_to_add.type in allowed_types ) ) - to_chat(usr, "\red It doesn't seem too keen on wearing that item.") - return - - usr.drop_item() - item_to_add.loc = src - src.inventory_head = item_to_add - regenerate_icons() - - //Various hats and items (worn on his head) change Ian's behaviour. His attributes are reset when a HAT is removed. - - - switch(inventory_head && inventory_head.type) - if(/obj/item/clothing/head/caphat, /obj/item/clothing/head/collectable/captain) - name = "Captain [real_name]" - desc = "Probably better than the last captain." - 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?" - 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" - 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") - 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") - if(/obj/item/clothing/head/nursehat) - name = "Nurse [real_name]" - desc = "[name] needs 100cc of beef jerky...STAT!" - 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!") - if(/obj/item/clothing/head/collectable/police) - name = "Officer [real_name]" - emote_see = list("drools","looks for donuts") - desc = "Stop right there criminal scum!" - 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!") - 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!" - if(/obj/item/clothing/head/soft) - name = "Corgi Tech [real_name]" - speak = list("Needs a stamp!", "Request DENIED!", "Fill these out in triplicate!") - desc = "The reason your yellow gloves have chew-marks." - - if("mask") - if(inventory_mask) - to_chat(usr, "\red It's already wearing something.") - return - else - var/obj/item/item_to_add = usr.get_active_hand() - if(!item_to_add) - return - - //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. - - var/list/allowed_types = list( - /obj/item/clothing/suit/armor/vest, - /obj/item/device/radio - ) - - if( ! ( item_to_add.type in allowed_types ) ) - to_chat(usr, "\red This object won't fit.") - return - - usr.drop_item() - item_to_add.loc = src - src.inventory_mask = item_to_add - regenerate_icons() - - //show_inv(usr) //Commented out because changing Ian's name and then calling up his inventory opens a new inventory...which is annoying. - else - ..() - -/mob/living/simple_animal/crab/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*/ +//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" + small = 1 + speak_emote = list("clicks") + emote_hear = list("clicks") + emote_see = list("clacks") + speak_chance = 1 + turns_per_move = 5 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1) + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "stomps the" + stop_automated_movement = 1 + friendly = "pinches" + var/obj/item/inventory_head + var/obj/item/inventory_mask + ventcrawler = 2 + +/mob/living/simple_animal/crab/Life() + ..() + //CRAB movement + if(!ckey && !stat) + if(isturf(src.loc) && !resting && !buckled) //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) + var/east_vs_west = pick(4, 8) + if(Process_Spacemove(east_vs_west)) + Move(get_step(src, east_vs_west), east_vs_west) + 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(obj/item/O, mob/user) + if(istype(O, /obj/item/weapon/wirecutters)) + if(prob(50)) + to_chat(user, "\red \b This kills the crab.") + health -= 20 + death() + else + GetMad() + get + if(istype(O, /obj/item/stack/medical)) + if(stat != DEAD) + var/obj/item/stack/medical/MED = O + if(health < maxHealth) + if(MED.use(1)) + health = min(maxHealth, health + MED.heal_brute) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\blue [user] applies the [MED] on [src]") + else + to_chat(user, "\blue this [src] is dead, medical items won't bring it back to life.") + else + if(O.force) + health -= O.force + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b [src] has been attacked with the [O] by [user]. ") + else + to_chat(usr, "\red This weapon is ineffective, it does no damage.") + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red [user] gently taps [src] with the [O]. ") + +/mob/living/simple_animal/crab/Topic(href, href_list) + if(usr.stat) return + + //Removing from inventory + if(href_list["remove_inv"]) + if(get_dist(src,usr) > 1 || !(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_emote = list("clicks") + emote_hear = list("clicks") + emote_see = list("clacks") + desc = "Free crabs!" + src.sd_set_light(0) + inventory_head.loc = src.loc + inventory_head = null + else + to_chat(usr, "\red There is nothing to remove from its [remove_from].") + return + if("mask") + if(inventory_mask) + inventory_mask.loc = src.loc + inventory_mask = null + else + to_chat(usr, "\red There is nothing to remove from its [remove_from].") + return + + //show_inv(usr) //Commented out because changing Ian's name and then calling up his inventory opens a new inventory...which is annoying. + + //Adding things to inventory + else if(href_list["add_inv"]) + if(get_dist(src,usr) > 1 || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))) + return + var/add_to = href_list["add_inv"] + if(!usr.get_active_hand()) + to_chat(usr, "\red You have nothing in your hand to put on its [add_to].") + return + switch(add_to) + if("head") + if(inventory_head) + to_chat(usr, "\red It's is already wearing something.") + return + else + var/obj/item/item_to_add = usr.get_active_hand() + if(!item_to_add) + return + + //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. + + var/list/allowed_types = list( + /obj/item/clothing/head/helmet, + /obj/item/clothing/glasses/sunglasses, + /obj/item/clothing/head/caphat, + /obj/item/clothing/head/collectable/captain, + /obj/item/clothing/head/that, + /obj/item/clothing/head/that, + /obj/item/clothing/head/kitty, + /obj/item/clothing/head/collectable/kitty, + /obj/item/clothing/head/rabbitears, + /obj/item/clothing/head/collectable/rabbitears, + /obj/item/clothing/head/beret, + /obj/item/clothing/head/collectable/beret, + /obj/item/clothing/head/det_hat, + /obj/item/clothing/head/nursehat, + /obj/item/clothing/head/pirate, + /obj/item/clothing/head/collectable/pirate, + /obj/item/clothing/head/chefhat, + /obj/item/clothing/head/collectable/chef, + /obj/item/clothing/head/collectable/police, + /obj/item/clothing/head/wizard/fake, + /obj/item/clothing/head/wizard, + /obj/item/clothing/head/collectable/wizard, + /obj/item/clothing/head/hardhat/yellow, + /obj/item/clothing/head/collectable/hardhat, + /obj/item/clothing/head/hardhat/white, + /obj/item/weapon/bedsheet, + /obj/item/clothing/head/soft + ) + + if( ! ( item_to_add.type in allowed_types ) ) + to_chat(usr, "\red It doesn't seem too keen on wearing that item.") + return + + usr.drop_item() + item_to_add.loc = src + src.inventory_head = item_to_add + regenerate_icons() + + //Various hats and items (worn on his head) change Ian's behaviour. His attributes are reset when a HAT is removed. + + + switch(inventory_head && inventory_head.type) + if(/obj/item/clothing/head/caphat, /obj/item/clothing/head/collectable/captain) + name = "Captain [real_name]" + desc = "Probably better than the last captain." + 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?" + 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" + 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") + 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") + if(/obj/item/clothing/head/nursehat) + name = "Nurse [real_name]" + desc = "[name] needs 100cc of beef jerky...STAT!" + 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!") + if(/obj/item/clothing/head/collectable/police) + name = "Officer [real_name]" + emote_see = list("drools","looks for donuts") + desc = "Stop right there criminal scum!" + 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!") + 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!" + if(/obj/item/clothing/head/soft) + name = "Corgi Tech [real_name]" + speak = list("Needs a stamp!", "Request DENIED!", "Fill these out in triplicate!") + desc = "The reason your yellow gloves have chew-marks." + + if("mask") + if(inventory_mask) + to_chat(usr, "\red It's already wearing something.") + return + else + var/obj/item/item_to_add = usr.get_active_hand() + if(!item_to_add) + return + + //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. + + var/list/allowed_types = list( + /obj/item/clothing/suit/armor/vest, + /obj/item/device/radio + ) + + if( ! ( item_to_add.type in allowed_types ) ) + to_chat(usr, "\red This object won't fit.") + return + + usr.drop_item() + item_to_add.loc = src + src.inventory_mask = item_to_add + regenerate_icons() + + //show_inv(usr) //Commented out because changing Ian's name and then calling up his inventory opens a new inventory...which is annoying. + else + ..() + +/mob/living/simple_animal/crab/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*/ 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 f06cbca79408..d11a339ac826 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -1,350 +1,350 @@ -//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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 4) - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "kicks the" - faction = "goat" - attacktext = "kicks" - health = 40 - melee_damage_lower = 1 - melee_damage_upper = 5 - var/datum/reagents/udder = null - -/mob/living/simple_animal/hostile/retaliate/goat/atom_init() - udder = new(50) - udder.my_atom = src - . = ..() - -/mob/living/simple_animal/hostile/retaliate/goat/Destroy() - QDEL_NULL(udder) - return ..() - -/mob/living/simple_animal/hostile/retaliate/goat/Life() - . = ..() - 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("\blue [src] calms down.") - - if(stat == CONSCIOUS) - if(udder && prob(5)) - udder.add_reagent("milk", rand(5, 10)) - - if(locate(/obj/effect/spacevine) in loc) - var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc - qdel(SV) - if(prob(10)) - say("Nom") - - if(!pulledby) - for(var/direction in shuffle(list(1,2,4,8,5,6,9,10))) - var/step = get_step(src, direction) - if(step) - if(locate(/obj/effect/spacevine) in step) - Move(step) - -/mob/living/simple_animal/hostile/retaliate/goat/Retaliate() - ..() - src.visible_message("\red [src] gets an evil-looking gleam in their eye.") - -/mob/living/simple_animal/hostile/retaliate/goat/Move() - ..() - if(!stat) - if(locate(/obj/effect/spacevine) in loc) - var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc - qdel(SV) - if(prob(10)) - say("Nom") - -/mob/living/simple_animal/hostile/retaliate/goat/attackby(obj/item/O, mob/user) - if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass)) - user.SetNextMove(CLICK_CD_INTERACT) - 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, "\red The [O] is full.") - if(!transfered) - to_chat(user, "\red The udder is dry. Wait a bit longer...") - else - ..() - -/mob/living/simple_animal - name = "animal" - desc = "Just simple animal" - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "kicks the" - attacktext = "kicks" - -//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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 6) - health = 50 - var/datum/reagents/udder = null - -/mob/living/simple_animal/cow/atom_init() - udder = new(50) - udder.my_atom = src - . = ..() - -/mob/living/simple_animal/cow/Destroy() - QDEL_NULL(udder) - return ..() - -/mob/living/simple_animal/cow/attackby(obj/item/O, mob/user) - if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass)) - user.SetNextMove(CLICK_CD_INTERACT) - 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, "\red The [O] is full.") - if(!transfered) - to_chat(user, "\red The udder is dry. Wait a bit longer...") - else - ..() - -/mob/living/simple_animal/cow/Life() - . = ..() - if(stat == CONSCIOUS) - if(udder && prob(5)) - udder.add_reagent("milk", rand(5, 10)) - else if(prob(15)) - playsound(src, 'sound/voice/cowmoos.ogg', 50, 1, -3) - -/mob/living/simple_animal/cow/Move() - if(..() && prob(55)) - playsound(src, 'sound/misc/cowbell.ogg', 50, 1, -3) - -/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M) - if(!stat && M.a_intent == "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 = "\improper 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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1) - health = 1 - var/amount_grown = 0 - pass_flags = PASSTABLE | PASSGRILLE - small = 1 - -/mob/living/simple_animal/chick/atom_init() - . = ..() - pixel_x = rand(-6, 6) - pixel_y = rand(0, 10) - -/mob/living/simple_animal/chick/Life() - . = ..() - if(!.) - return - if(!stat) - amount_grown += rand(1,2) - if(amount_grown >= 100) - new /mob/living/simple_animal/chicken(src.loc) - qdel(src) - -var/const/MAX_CHICKENS = 50 -var/global/chicken_count = 0 - -/mob/living/simple_animal/chicken - name = "\improper 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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 2) - health = 10 - var/eggsleft = 0 - var/body_color - pass_flags = PASSTABLE - small = 1 - -/mob/living/simple_animal/chicken/atom_init() - . = ..() - 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" - pixel_x = rand(-6, 6) - pixel_y = rand(0, 10) - chicken_count += 1 - -/mob/living/simple_animal/chicken/death() - ..() - chicken_count -= 1 - -/mob/living/simple_animal/chicken/attackby(obj/item/O, mob/user) - if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/wheat)) //feedin' dem chickens - user.SetNextMove(CLICK_CD_INTERACT) - if(!stat && eggsleft < 8) - user.visible_message("\blue [user] feeds [O] to [name]! It clucks happily.","\blue You feed [O] to [name]! It clucks happily.") - user.drop_item() - qdel(O) - eggsleft += rand(1, 4) - //world << eggsleft - else - to_chat(user, "\blue [name] doesn't seem hungry!") - else - ..() - -/mob/living/simple_animal/chicken/Life() - . =..() - 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(chicken_count < MAX_CHICKENS && prob(10)) - START_PROCESSING(SSobj, E) - -/obj/item/weapon/reagent_containers/food/snacks/egg/var/amount_grown = 0 -/obj/item/weapon/reagent_containers/food/snacks/egg/process() - if(isturf(loc)) - amount_grown += rand(1,2) - if(amount_grown >= 100) - visible_message("[src] hatches with a quiet cracking sound.") - new /mob/living/simple_animal/chick(get_turf(src)) - STOP_PROCESSING(SSobj, src) - qdel(src) - else - STOP_PROCESSING(SSobj, src) - -/mob/living/simple_animal/pig - name = "pig" - desc = "Oink oink." - icon_state = "pig" - icon_living = "pig" - icon_dead = "pig_dead" - speak = list("oink?","oink","OINK") - speak_emote = list("oinks") - emote_see = list("rolls around") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/ham = 6) - health = 50 - -/mob/living/simple_animal/turkey - name = "turkey" - desc = "Benjamin Franklin would be proud." - icon_state = "turkey" - icon_living = "turkey" - icon_dead = "turkey_dead" - speak = list("gobble?","gobble","GOBBLE") - speak_emote = list("gobble") - emote_see = list("struts around") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 4) - health = 50 - -/mob/living/simple_animal/goose - name = "goose" - desc = "A pretty goose. Would make a nice comforter." - icon_state = "goose" - icon_living = "goose" - icon_dead = "goose_dead" - speak = list("quack?","quack","QUACK") - speak_emote = list("quacks") - emote_see = list("flaps it's wings") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 6) - health = 50 - -/mob/living/simple_animal/seal - name = "seal" - desc = "A beautiful white seal." - icon_state = "seal" - icon_living = "seal" - icon_dead = "seal_dead" - speak = list("Urk?","urk","URK") - speak_emote = list("urks") - emote_see = list("flops around") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 6) - health = 50 - -/mob/living/simple_animal/walrus - name = "walrus" - desc = "A big brown walrus." - icon_state = "walrus" - icon_living = "walrus" - icon_dead = "walrus_dead" - speak = list("Urk?","urk","URK") - speak_emote = list("urks") - emote_see = list("flops around") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 6) +//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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 4) + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "kicks the" + faction = "goat" + attacktext = "kicks" + health = 40 + melee_damage_lower = 1 + melee_damage_upper = 5 + var/datum/reagents/udder = null + +/mob/living/simple_animal/hostile/retaliate/goat/atom_init() + udder = new(50) + udder.my_atom = src + . = ..() + +/mob/living/simple_animal/hostile/retaliate/goat/Destroy() + QDEL_NULL(udder) + return ..() + +/mob/living/simple_animal/hostile/retaliate/goat/Life() + . = ..() + 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("\blue [src] calms down.") + + if(stat == CONSCIOUS) + if(udder && prob(5)) + udder.add_reagent("milk", rand(5, 10)) + + if(locate(/obj/effect/spacevine) in loc) + var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc + qdel(SV) + if(prob(10)) + say("Nom") + + if(!pulledby) + for(var/direction in shuffle(list(1,2,4,8,5,6,9,10))) + var/step = get_step(src, direction) + if(step) + if(locate(/obj/effect/spacevine) in step) + Move(step) + +/mob/living/simple_animal/hostile/retaliate/goat/Retaliate() + ..() + src.visible_message("\red [src] gets an evil-looking gleam in their eye.") + +/mob/living/simple_animal/hostile/retaliate/goat/Move() + ..() + if(!stat) + if(locate(/obj/effect/spacevine) in loc) + var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc + qdel(SV) + if(prob(10)) + say("Nom") + +/mob/living/simple_animal/hostile/retaliate/goat/attackby(obj/item/O, mob/user) + if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass)) + user.SetNextMove(CLICK_CD_INTERACT) + 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, "\red The [O] is full.") + if(!transfered) + to_chat(user, "\red The udder is dry. Wait a bit longer...") + else + ..() + +/mob/living/simple_animal + name = "animal" + desc = "Just simple animal" + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "kicks the" + attacktext = "kicks" + +//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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 6) + health = 50 + var/datum/reagents/udder = null + +/mob/living/simple_animal/cow/atom_init() + udder = new(50) + udder.my_atom = src + . = ..() + +/mob/living/simple_animal/cow/Destroy() + QDEL_NULL(udder) + return ..() + +/mob/living/simple_animal/cow/attackby(obj/item/O, mob/user) + if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass)) + user.SetNextMove(CLICK_CD_INTERACT) + 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, "\red The [O] is full.") + if(!transfered) + to_chat(user, "\red The udder is dry. Wait a bit longer...") + else + ..() + +/mob/living/simple_animal/cow/Life() + . = ..() + if(stat == CONSCIOUS) + if(udder && prob(5)) + udder.add_reagent("milk", rand(5, 10)) + else if(prob(15)) + playsound(src, 'sound/voice/cowmoos.ogg', 50, 1, -3) + +/mob/living/simple_animal/cow/Move() + if(..() && prob(55)) + playsound(src, 'sound/misc/cowbell.ogg', 50, 1, -3) + +/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M) + if(!stat && M.a_intent == "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 = "\improper 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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1) + health = 1 + var/amount_grown = 0 + pass_flags = PASSTABLE | PASSGRILLE + small = 1 + +/mob/living/simple_animal/chick/atom_init() + . = ..() + pixel_x = rand(-6, 6) + pixel_y = rand(0, 10) + +/mob/living/simple_animal/chick/Life() + . = ..() + if(!.) + return + if(!stat) + amount_grown += rand(1,2) + if(amount_grown >= 100) + new /mob/living/simple_animal/chicken(src.loc) + qdel(src) + +var/const/MAX_CHICKENS = 50 +var/global/chicken_count = 0 + +/mob/living/simple_animal/chicken + name = "\improper 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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 2) + health = 10 + var/eggsleft = 0 + var/body_color + pass_flags = PASSTABLE + small = 1 + +/mob/living/simple_animal/chicken/atom_init() + . = ..() + 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" + pixel_x = rand(-6, 6) + pixel_y = rand(0, 10) + chicken_count += 1 + +/mob/living/simple_animal/chicken/death() + ..() + chicken_count -= 1 + +/mob/living/simple_animal/chicken/attackby(obj/item/O, mob/user) + if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/wheat)) //feedin' dem chickens + user.SetNextMove(CLICK_CD_INTERACT) + if(!stat && eggsleft < 8) + user.visible_message("\blue [user] feeds [O] to [name]! It clucks happily.","\blue You feed [O] to [name]! It clucks happily.") + user.drop_item() + qdel(O) + eggsleft += rand(1, 4) + //world << eggsleft + else + to_chat(user, "\blue [name] doesn't seem hungry!") + else + ..() + +/mob/living/simple_animal/chicken/Life() + . =..() + 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(chicken_count < MAX_CHICKENS && prob(10)) + START_PROCESSING(SSobj, E) + +/obj/item/weapon/reagent_containers/food/snacks/egg/var/amount_grown = 0 +/obj/item/weapon/reagent_containers/food/snacks/egg/process() + if(isturf(loc)) + amount_grown += rand(1,2) + if(amount_grown >= 100) + visible_message("[src] hatches with a quiet cracking sound.") + new /mob/living/simple_animal/chick(get_turf(src)) + STOP_PROCESSING(SSobj, src) + qdel(src) + else + STOP_PROCESSING(SSobj, src) + +/mob/living/simple_animal/pig + name = "pig" + desc = "Oink oink." + icon_state = "pig" + icon_living = "pig" + icon_dead = "pig_dead" + speak = list("oink?","oink","OINK") + speak_emote = list("oinks") + emote_see = list("rolls around") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/ham = 6) + health = 50 + +/mob/living/simple_animal/turkey + name = "turkey" + desc = "Benjamin Franklin would be proud." + icon_state = "turkey" + icon_living = "turkey" + icon_dead = "turkey_dead" + speak = list("gobble?","gobble","GOBBLE") + speak_emote = list("gobble") + emote_see = list("struts around") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 4) + health = 50 + +/mob/living/simple_animal/goose + name = "goose" + desc = "A pretty goose. Would make a nice comforter." + icon_state = "goose" + icon_living = "goose" + icon_dead = "goose_dead" + speak = list("quack?","quack","QUACK") + speak_emote = list("quacks") + emote_see = list("flaps it's wings") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 6) + health = 50 + +/mob/living/simple_animal/seal + name = "seal" + desc = "A beautiful white seal." + icon_state = "seal" + icon_living = "seal" + icon_dead = "seal_dead" + speak = list("Urk?","urk","URK") + speak_emote = list("urks") + emote_see = list("flops around") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 6) + health = 50 + +/mob/living/simple_animal/walrus + name = "walrus" + desc = "A big brown walrus." + icon_state = "walrus" + icon_living = "walrus" + icon_dead = "walrus_dead" + speak = list("Urk?","urk","URK") + speak_emote = list("urks") + emote_see = list("flops around") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 6) health = 50 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm index e54adb6d6419..bbe9c48f1ef4 100644 --- a/code/modules/mob/living/simple_animal/friendly/fox.dm +++ b/code/modules/mob/living/simple_animal/friendly/fox.dm @@ -1,26 +1,26 @@ -//Foxxy -/mob/living/simple_animal/fox - name = "fox" - desc = "It's a fox. I wonder what it says?" - icon_state = "fox" - icon_living = "fox" - icon_dead = "fox_dead" - speak = list("Ack-Ack","Ack-Ack-Ack-Ackawoooo","Geckers","Awoo","Tchoff") - speak_emote = list("geckers", "barks") - emote_hear = list("howls","barks") - emote_see = list("shakes its head", "shivers") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 2) - 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 - -//Captain fox -/mob/living/simple_animal/fox/Renault - name = "Renault" - desc = "Renault, the Captain's trustworthy fox. I wonder what it says?" +//Foxxy +/mob/living/simple_animal/fox + name = "fox" + desc = "It's a fox. I wonder what it says?" + icon_state = "fox" + icon_living = "fox" + icon_dead = "fox_dead" + speak = list("Ack-Ack","Ack-Ack-Ack-Ackawoooo","Geckers","Awoo","Tchoff") + speak_emote = list("geckers", "barks") + emote_hear = list("howls","barks") + emote_see = list("shakes its head", "shivers") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 2) + 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 + +//Captain fox +/mob/living/simple_animal/fox/Renault + name = "Renault" + desc = "Renault, the Captain's trustworthy fox. I wonder what it says?" diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm index cc1a81d6ae48..09189a375a45 100644 --- a/code/modules/mob/living/simple_animal/friendly/lizard.dm +++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm @@ -1,19 +1,19 @@ -/mob/living/simple_animal/lizard - name = "Lizard" - desc = "A cute tiny lizard." - icon = 'icons/mob/critter.dmi' - icon_state = "lizard" - icon_living = "lizard" - icon_dead = "lizard-dead" - small = 1 - speak_emote = list("hisses") - health = 5 - maxHealth = 5 - attacktext = "bites" - attacktext = "bites" - melee_damage_lower = 1 - melee_damage_upper = 2 - response_help = "pets" - response_disarm = "shoos" - response_harm = "stomps on" - ventcrawler = 2 +/mob/living/simple_animal/lizard + name = "Lizard" + desc = "A cute tiny lizard." + icon = 'icons/mob/critter.dmi' + icon_state = "lizard" + icon_living = "lizard" + icon_dead = "lizard-dead" + small = 1 + speak_emote = list("hisses") + health = 5 + maxHealth = 5 + attacktext = "bites" + attacktext = "bites" + melee_damage_lower = 1 + melee_damage_upper = 2 + response_help = "pets" + response_disarm = "shoos" + response_harm = "stomps on" + ventcrawler = 2 diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 4636222d0adf..8871f6e13f75 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -1,190 +1,190 @@ -/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 - small = 1 - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - maxHealth = 5 - health = 5 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1) - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "stamps on the" - density = 0 - var/body_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 - universal_understand = 1 - holder_type = /obj/item/weapon/holder/mouse - ventcrawler = 2 - -/mob/living/simple_animal/mouse/Life() - ..() - if(!stat && prob(speak_chance)) - for(var/mob/M in view()) - M << 'sound/effects/mousesqueek.ogg' - - if(!ckey && stat == CONSCIOUS && prob(0.5)) - stat = UNCONSCIOUS - icon_state = "mouse_[body_color]_sleep" - wander = 0 - speak_chance = 0 - //snuffles - else if(stat == UNCONSCIOUS) - if(ckey || prob(1)) - stat = CONSCIOUS - icon_state = "mouse_[body_color]" - wander = 1 - else if(prob(5)) - emote("snuffles") - -/mob/living/simple_animal/mouse/atom_init() - . = ..() - name = "[name] ([rand(1, 1000)])" - real_name = name - - if(!body_color) - body_color = pick( list("brown","gray","white") ) - switch(body_color) - if("brown") - holder_type = /obj/item/weapon/holder/mouse/brown - if("gray") - holder_type = /obj/item/weapon/holder/mouse/gray - if("white") - holder_type = /obj/item/weapon/holder/mouse/white - icon_state = "mouse_[body_color]" - icon_living = "mouse_[body_color]" - icon_dead = "mouse_[body_color]_dead" - desc = "It's a small [body_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself." - - -/mob/living/simple_animal/mouse/proc/splat() - health = 0 - stat = DEAD - icon_dead = "mouse_[body_color]_splat" - icon_state = "mouse_[body_color]_splat" - layer = MOB_LAYER - timeofdeath = world.time - if(client) - client.time_died_as_mouse = world.time - -/mob/living/simple_animal/mouse/MouseDrop(atom/over_object) - - var/mob/living/carbon/H = over_object - if(!istype(H) || !Adjacent(H) || ismob(H.loc)) - return ..() - - if(H.a_intent == "help") - get_scooped(H) - return - else - return ..() - -/mob/living/simple_animal/mouse/get_scooped(mob/living/carbon/grabber) - if (stat >= DEAD) - return - ..() - -//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 = "Mouse" - - if (layer != TURF_LAYER+0.2) - layer = TURF_LAYER+0.2 - to_chat(src, text("\blue You are now hiding.")) - /* - 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 - to_chat(src, text("\blue You have stopped hiding.")) - /* - 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(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 - to_chat(M, "\blue [bicon(src)] Squeek!") - M << 'sound/effects/mousesqueek.ogg' - ..() - -/mob/living/simple_animal/mouse/death() - layer = MOB_LAYER - if(client) - client.time_died_as_mouse = world.time - ..() - -/* - * Mouse types - */ - -/mob/living/simple_animal/mouse/white - body_color = "white" - icon_state = "mouse_white" - holder_type = /obj/item/weapon/holder/mouse/white - -/mob/living/simple_animal/mouse/gray - body_color = "gray" - icon_state = "mouse_gray" - holder_type = /obj/item/weapon/holder/mouse/gray - -/mob/living/simple_animal/mouse/brown - body_color = "brown" - icon_state = "mouse_brown" - holder_type = /obj/item/weapon/holder/mouse/brown - -//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 + 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 + small = 1 + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + maxHealth = 5 + health = 5 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1) + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "stamps on the" + density = 0 + var/body_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 + universal_understand = 1 + holder_type = /obj/item/weapon/holder/mouse + ventcrawler = 2 + +/mob/living/simple_animal/mouse/Life() + ..() + if(!stat && prob(speak_chance)) + for(var/mob/M in view()) + M << 'sound/effects/mousesqueek.ogg' + + if(!ckey && stat == CONSCIOUS && prob(0.5)) + stat = UNCONSCIOUS + icon_state = "mouse_[body_color]_sleep" + wander = 0 + speak_chance = 0 + //snuffles + else if(stat == UNCONSCIOUS) + if(ckey || prob(1)) + stat = CONSCIOUS + icon_state = "mouse_[body_color]" + wander = 1 + else if(prob(5)) + emote("snuffles") + +/mob/living/simple_animal/mouse/atom_init() + . = ..() + name = "[name] ([rand(1, 1000)])" + real_name = name + + if(!body_color) + body_color = pick( list("brown","gray","white") ) + switch(body_color) + if("brown") + holder_type = /obj/item/weapon/holder/mouse/brown + if("gray") + holder_type = /obj/item/weapon/holder/mouse/gray + if("white") + holder_type = /obj/item/weapon/holder/mouse/white + icon_state = "mouse_[body_color]" + icon_living = "mouse_[body_color]" + icon_dead = "mouse_[body_color]_dead" + desc = "It's a small [body_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself." + + +/mob/living/simple_animal/mouse/proc/splat() + health = 0 + stat = DEAD + icon_dead = "mouse_[body_color]_splat" + icon_state = "mouse_[body_color]_splat" + layer = MOB_LAYER + timeofdeath = world.time + if(client) + client.time_died_as_mouse = world.time + +/mob/living/simple_animal/mouse/MouseDrop(atom/over_object) + + var/mob/living/carbon/H = over_object + if(!istype(H) || !Adjacent(H) || ismob(H.loc)) + return ..() + + if(H.a_intent == "help") + get_scooped(H) + return + else + return ..() + +/mob/living/simple_animal/mouse/get_scooped(mob/living/carbon/grabber) + if (stat >= DEAD) + return + ..() + +//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 = "Mouse" + + if (layer != TURF_LAYER+0.2) + layer = TURF_LAYER+0.2 + to_chat(src, text("\blue You are now hiding.")) + /* + 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 + to_chat(src, text("\blue You have stopped hiding.")) + /* + 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(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 + to_chat(M, "\blue [bicon(src)] Squeek!") + M << 'sound/effects/mousesqueek.ogg' + ..() + +/mob/living/simple_animal/mouse/death() + layer = MOB_LAYER + if(client) + client.time_died_as_mouse = world.time + ..() + +/* + * Mouse types + */ + +/mob/living/simple_animal/mouse/white + body_color = "white" + icon_state = "mouse_white" + holder_type = /obj/item/weapon/holder/mouse/white + +/mob/living/simple_animal/mouse/gray + body_color = "gray" + icon_state = "mouse_gray" + holder_type = /obj/item/weapon/holder/mouse/gray + +/mob/living/simple_animal/mouse/brown + body_color = "brown" + icon_state = "mouse_brown" + holder_type = /obj/item/weapon/holder/mouse/brown + +//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" diff --git a/code/modules/mob/living/simple_animal/friendly/mushroom.dm b/code/modules/mob/living/simple_animal/friendly/mushroom.dm index bb6128473741..3988dc995843 100644 --- a/code/modules/mob/living/simple_animal/friendly/mushroom.dm +++ b/code/modules/mob/living/simple_animal/friendly/mushroom.dm @@ -1,17 +1,17 @@ -/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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice = 1) - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "whacks the" - harm_intent_damage = 5 - ventcrawler = 2 +/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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice = 1) + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "whacks the" + harm_intent_damage = 5 + ventcrawler = 2 diff --git a/code/modules/mob/living/simple_animal/friendly/shiba.dm b/code/modules/mob/living/simple_animal/friendly/shiba.dm index 94856a66d34c..3046c9fa302c 100644 --- a/code/modules/mob/living/simple_animal/friendly/shiba.dm +++ b/code/modules/mob/living/simple_animal/friendly/shiba.dm @@ -1,90 +1,90 @@ -//Shiba-Inu! -/mob/living/simple_animal/shiba - name = "Shiba Inu" - real_name = "shiba inu" - desc = "It's a small, agile cute doggy." - icon_state = "shiba" - icon_living = "shiba" - icon_dead = "shiba_dead" - speak = list("Kyan!","Van!", "Woof!", "Bark!", "AUUUUUU", "Yap!") - speak_emote = list("barks", "woofs") - emote_hear = list("barks", "woofs", "pants", "vans") - emote_see = list("shakes its head", "shivers", "looks cute") - speak_chance = 20 - turns_per_move = 3 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/shiba = 2) - response_help = "pets the" - response_disarm = "bops the" - response_harm = "kicks the" - see_in_dark = 5 - min_oxy = 16 //Require atleast 16kPA oxygen - minbodytemp = 223 //Below -50 Degrees Celcius - maxbodytemp = 323 //Above 50 Degrees Celcius - var/facehugger - var/turns_since_scan = 0 - var/mob/living/simple_animal/mouse/movement_target - -/obj/item/weapon/reagent_containers/food/snacks/meat/shiba - name = "shiba meat" - desc = "Tastes like... well you know..." - -/mob/living/simple_animal/shiba/regenerate_icons() - overlays.Cut() - if(facehugger) - overlays += image('icons/mob/mask.dmi',"facehugger_corgi") - -/mob/living/simple_animal/shiba/attackby(obj/item/O, mob/user) - if(istype(O, /obj/item/weapon/newspaper)) - user.SetNextMove(CLICK_CD_MELEE) - if(!stat) - for(var/mob/M in viewers(user, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\blue [user] baps [name] on the nose with the rolled up [O]") - spawn(0) - for(var/i in list(1,2,4,8,4,2,1,2)) - dir = i - sleep(1) - else - ..() - -/mob/living/simple_animal/shiba/Life() - ..() - - if(!stat && !resting && !buckled) - if(prob(1)) - emote(pick("chases its tail")) - 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) - - for(var/obj/item/weapon/bikehorn/dogtoy/histoy in oview(src, 3)) - if(prob(30)) - emote(pick("barks!","woofs loudly!","eyes [histoy] joyfully.")) - break - - if(!stat && !resting && !buckled) - 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/obj/item/weapon/bikehorn/dogtoy/histoy in oview(src,3)) - if(isturf(histoy.loc)) - movement_target = histoy - break - if(movement_target) - stop_automated_movement = 1 - walk_to(src,movement_target,0,3) - for(var/obj/item/weapon/bikehorn/dogtoy/histoy in oview(1,src)) - if(prob(50)) - for(var/i in list(1,2,4,8,4,2,1,2)) - dir = i - sleep(1) - if(prob(40)) - src.visible_message(pick("[bicon(src)][src] joyfully plays with the toy!","[bicon(src)][src] rolls the toy back and forth!","[bicon(src)][src] happily twists and spins the toy!","[bicon(src)][src] thoroughly sniffs the toy all around!"), 2) +//Shiba-Inu! +/mob/living/simple_animal/shiba + name = "Shiba Inu" + real_name = "shiba inu" + desc = "It's a small, agile cute doggy." + icon_state = "shiba" + icon_living = "shiba" + icon_dead = "shiba_dead" + speak = list("Kyan!","Van!", "Woof!", "Bark!", "AUUUUUU", "Yap!") + speak_emote = list("barks", "woofs") + emote_hear = list("barks", "woofs", "pants", "vans") + emote_see = list("shakes its head", "shivers", "looks cute") + speak_chance = 20 + turns_per_move = 3 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/shiba = 2) + response_help = "pets the" + response_disarm = "bops the" + response_harm = "kicks the" + see_in_dark = 5 + min_oxy = 16 //Require atleast 16kPA oxygen + minbodytemp = 223 //Below -50 Degrees Celcius + maxbodytemp = 323 //Above 50 Degrees Celcius + var/facehugger + var/turns_since_scan = 0 + var/mob/living/simple_animal/mouse/movement_target + +/obj/item/weapon/reagent_containers/food/snacks/meat/shiba + name = "shiba meat" + desc = "Tastes like... well you know..." + +/mob/living/simple_animal/shiba/regenerate_icons() + overlays.Cut() + if(facehugger) + overlays += image('icons/mob/mask.dmi',"facehugger_corgi") + +/mob/living/simple_animal/shiba/attackby(obj/item/O, mob/user) + if(istype(O, /obj/item/weapon/newspaper)) + user.SetNextMove(CLICK_CD_MELEE) + if(!stat) + for(var/mob/M in viewers(user, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\blue [user] baps [name] on the nose with the rolled up [O]") + spawn(0) + for(var/i in list(1,2,4,8,4,2,1,2)) + dir = i + sleep(1) + else + ..() + +/mob/living/simple_animal/shiba/Life() + ..() + + if(!stat && !resting && !buckled) + if(prob(1)) + emote(pick("chases its tail")) + 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) + + for(var/obj/item/weapon/bikehorn/dogtoy/histoy in oview(src, 3)) + if(prob(30)) + emote(pick("barks!","woofs loudly!","eyes [histoy] joyfully.")) + break + + if(!stat && !resting && !buckled) + 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/obj/item/weapon/bikehorn/dogtoy/histoy in oview(src,3)) + if(isturf(histoy.loc)) + movement_target = histoy + break + if(movement_target) + stop_automated_movement = 1 + walk_to(src,movement_target,0,3) + for(var/obj/item/weapon/bikehorn/dogtoy/histoy in oview(1,src)) + if(prob(50)) + for(var/i in list(1,2,4,8,4,2,1,2)) + dir = i + sleep(1) + if(prob(40)) + src.visible_message(pick("[bicon(src)][src] joyfully plays with the toy!","[bicon(src)][src] rolls the toy back and forth!","[bicon(src)][src] happily twists and spins the toy!","[bicon(src)][src] thoroughly sniffs the toy all around!"), 2) diff --git a/code/modules/mob/living/simple_animal/friendly/slime.dm b/code/modules/mob/living/simple_animal/friendly/slime.dm index a2e58fdc2af4..5fab06c6605f 100644 --- a/code/modules/mob/living/simple_animal/friendly/slime.dm +++ b/code/modules/mob/living/simple_animal/friendly/slime.dm @@ -1,49 +1,49 @@ -/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" - ventcrawler = 2 - -/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") - var/colour = "grey" - -/mob/living/simple_animal/adultslime/atom_init() - . = ..() - overlays += "aslime-:33" - - -/mob/living/simple_animal/slime/adult/death() - 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 + 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" + ventcrawler = 2 + +/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") + var/colour = "grey" + +/mob/living/simple_animal/adultslime/atom_init() + . = ..() + overlays += "aslime-:33" + + +/mob/living/simple_animal/slime/adult/death() + 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) diff --git a/code/modules/mob/living/simple_animal/friendly/tomato.dm b/code/modules/mob/living/simple_animal/friendly/tomato.dm index 1e00a5179d3d..dc2852451a11 100644 --- a/code/modules/mob/living/simple_animal/friendly/tomato.dm +++ b/code/modules/mob/living/simple_animal/friendly/tomato.dm @@ -1,17 +1,17 @@ -/mob/living/simple_animal/hostile/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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/tomatomeat = 1) - response_help = "prods the" - response_disarm = "pushes aside the" - response_harm = "smacks the" - harm_intent_damage = 5 - melee_damage_lower = 1 - melee_damage_upper = 5 +/mob/living/simple_animal/hostile/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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/tomatomeat = 1) + response_help = "prods the" + response_disarm = "pushes aside the" + response_harm = "smacks the" + harm_intent_damage = 5 + melee_damage_lower = 1 + melee_damage_upper = 5 diff --git a/code/modules/mob/living/simple_animal/friendly/walle.dm b/code/modules/mob/living/simple_animal/friendly/walle.dm index 5472d4144ebd..3f911d3ae621 100644 --- a/code/modules/mob/living/simple_animal/friendly/walle.dm +++ b/code/modules/mob/living/simple_animal/friendly/walle.dm @@ -1,17 +1,17 @@ -//Wall-E -/mob/living/simple_animal/walle - name = "Wall-E" - desc = "The robot which looks for EVA." - icon_state = "walle" - icon_living = "walle" - icon_dead = "walle_dead" - speak = list("Beep-Boop","Eva? Evaaa!","Buzz.") - speak_emote = list("rustles", "smokes") - emote_hear = list("pings") - emote_see = list("processes garbage", "has got the solar battery") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "kicks" +//Wall-E +/mob/living/simple_animal/walle + name = "Wall-E" + desc = "The robot which looks for EVA." + icon_state = "walle" + icon_living = "walle" + icon_dead = "walle_dead" + speak = list("Beep-Boop","Eva? Evaaa!","Buzz.") + speak_emote = list("rustles", "smokes") + emote_hear = list("pings") + emote_see = list("processes garbage", "has got the solar battery") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "kicks" diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index 6b355f0629ac..b8032596e39c 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -1,97 +1,97 @@ -/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 = "alien_l" - icon_gib = "syndicate_gib" - response_help = "pokes the" - response_disarm = "shoves the" - response_harm = "hits the" - speed = -1 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/xenomeat = 3) - maxHealth = 100 - health = 100 - harm_intent_damage = 5 - melee_damage_lower = 25 - melee_damage_upper = 25 - attacktext = "slashes" - a_intent = "harm" - 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 = 1 - status_flags = CANPUSH - minbodytemp = 0 - heat_damage_per_tick = 20 - - -/mob/living/simple_animal/hostile/alien/drone - name = "alien drone" - icon_state = "aliend_running" - icon_living = "aliend_running" - icon_dead = "aliend_l" - 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_l" - health = 120 - melee_damage_lower = 15 - melee_damage_upper = 15 - ranged = 1 - retreat_distance = 5 - minimum_distance = 5 - 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_l" - health = 250 - maxHealth = 250 - melee_damage_lower = 15 - melee_damage_upper = 15 - ranged = 1 - move_to_delay = 3 - retreat_distance = 5 - minimum_distance = 5 - 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 - -/obj/item/projectile/neurotox - damage = 30 - icon_state = "toxin" - -/mob/living/simple_animal/hostile/alien/death() - ..() - 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 + name = "alien hunter" + desc = "Hiss!" + icon = 'icons/mob/alien.dmi' + icon_state = "alienh_running" + icon_living = "alienh_running" + icon_dead = "alien_l" + icon_gib = "syndicate_gib" + response_help = "pokes the" + response_disarm = "shoves the" + response_harm = "hits the" + speed = -1 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/xenomeat = 3) + maxHealth = 100 + health = 100 + harm_intent_damage = 5 + melee_damage_lower = 25 + melee_damage_upper = 25 + attacktext = "slashes" + a_intent = "harm" + 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 = 1 + status_flags = CANPUSH + minbodytemp = 0 + heat_damage_per_tick = 20 + + +/mob/living/simple_animal/hostile/alien/drone + name = "alien drone" + icon_state = "aliend_running" + icon_living = "aliend_running" + icon_dead = "aliend_l" + 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_l" + health = 120 + melee_damage_lower = 15 + melee_damage_upper = 15 + ranged = 1 + retreat_distance = 5 + minimum_distance = 5 + 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_l" + health = 250 + maxHealth = 250 + melee_damage_lower = 15 + melee_damage_upper = 15 + ranged = 1 + move_to_delay = 3 + retreat_distance = 5 + minimum_distance = 5 + 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 + +/obj/item/projectile/neurotox + damage = 30 + icon_state = "toxin" + +/mob/living/simple_animal/hostile/alien/death() + ..() + visible_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...") + playsound(src, 'sound/voice/hiss6.ogg', 100, 1) diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index c0d3379f5c62..34bd4e39b3de 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -1,172 +1,172 @@ -//Space bears! -/mob/living/simple_animal/hostile/bear - name = "space bear" - desc = "RawrRawr!!" - icon_state = "bear" - icon_living = "bear" - icon_dead = "bear_dead" - icon_gib = "bear_gib" - speak = list("RAWR!","Rawr!","GRR!","Growl!") - speak_emote = list("growls", "roars") - emote_hear = list("rawrs","grumbles","grawls") - emote_see = list("stares ferociously", "stomps") - speak_chance = 1 - turns_per_move = 5 - see_in_dark = 6 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/bearmeat = 5) - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "pokes the" - stop_automated_movement_when_pulled = 0 - maxHealth = 60 - health = 60 - melee_damage_lower = 20 - melee_damage_upper = 30 - - //Space bears 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 - var/stance_step = 0 - - faction = "russian" - -//SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!! -/mob/living/simple_animal/hostile/bear/Hudson - name = "Hudson" - desc = "" - response_help = "pets" - response_disarm = "gently pushes aside" - response_harm = "pokes" - -/mob/living/simple_animal/hostile/bear/Life() - . =..() - if(!.) - return - - if(loc && istype(loc,/turf/space)) - icon_state = "bear" - else - icon_state = "bearfloor" - - switch(stance) - - if(HOSTILE_STANCE_TIRED) - stop_automated_movement = 1 - stance_step++ - if(stance_step >= 10) //rests for 10 ticks - if(target && target in ListTargets(10)) - stance = HOSTILE_STANCE_ATTACK //If the mob he was chasing is still nearby, resume the attack, otherwise go idle. - else - stance = HOSTILE_STANCE_IDLE - - if(HOSTILE_STANCE_ALERT) - stop_automated_movement = 1 - var/found_mob = 0 - if(target && target in ListTargets(10)) - if(CanAttack(target)) - stance_step = max(0, stance_step) //If we have not seen a mob in a while, the stance_step will be negative, we need to reset it to 0 as soon as we see a mob again. - stance_step++ - found_mob = 1 - src.dir = get_dir(src,target) //Keep staring at the mob - - if(stance_step in list(1,4,7)) //every 3 ticks - var/action = pick( list( "growls at [target]", "stares angrily at [target]", "prepares to attack [target]", "closely watches [target]" ) ) - if(action) - custom_emote(1,action) - if(!found_mob) - stance_step-- - - if(stance_step <= -20) //If we have not found a mob for 20-ish ticks, revert to idle mode - stance = HOSTILE_STANCE_IDLE - if(stance_step >= 7) //If we have been staring at a mob for 7 ticks, - stance = HOSTILE_STANCE_ATTACK - - if(HOSTILE_STANCE_ATTACKING) - if(stance_step >= 20) //attacks for 20 ticks, then it gets tired and needs to rest - custom_emote(1, "is worn out and needs to rest" ) - stance = HOSTILE_STANCE_TIRED - stance_step = 0 - walk(src, 0) //This stops the bear's walking - return - - - -/mob/living/simple_animal/hostile/bear/attackby(obj/item/O, mob/user) - if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING) - stance = HOSTILE_STANCE_ALERT - stance_step = 6 - target = user - ..() - -/mob/living/simple_animal/hostile/bear/attack_hand(mob/living/carbon/human/M) - if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING) - stance = HOSTILE_STANCE_ALERT - stance_step = 6 - target = M - ..() - -/mob/living/simple_animal/hostile/bear/Process_Spacemove(movement_dir = 0) - return //No drifting in space for space bears! - -/mob/living/simple_animal/hostile/bear/FindTarget() - . = ..() - if(.) - custom_emote(1,"stares alertly at [.]") - stance = HOSTILE_STANCE_ALERT - -/mob/living/simple_animal/hostile/bear/LoseTarget() - ..(5) - -/mob/living/simple_animal/hostile/bear/AttackingTarget() - if(!Adjacent(target)) - return - custom_emote(1, pick( list("slashes at [target]", "bites [target]") ) ) - - var/damage = rand(20,30) - - if(ishuman(target)) - var/mob/living/carbon/human/H = target - var/dam_zone = pick(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) - var/obj/item/organ/external/BP = H.bodyparts_by_name[ran_zone(dam_zone)] - H.apply_damage(damage, BRUTE, BP, H.run_armor_check(BP, "melee"), DAM_SHARP | DAM_EDGE) - return H - else if(isliving(target)) - var/mob/living/L = target - L.adjustBruteLoss(damage) - return L - else if(istype(target,/obj/mecha)) - var/obj/mecha/M = target - M.attack_animal(src) - return M - - - - - - - - - - - - - - - - - - - - - - - - - +//Space bears! +/mob/living/simple_animal/hostile/bear + name = "space bear" + desc = "RawrRawr!!" + icon_state = "bear" + icon_living = "bear" + icon_dead = "bear_dead" + icon_gib = "bear_gib" + speak = list("RAWR!","Rawr!","GRR!","Growl!") + speak_emote = list("growls", "roars") + emote_hear = list("rawrs","grumbles","grawls") + emote_see = list("stares ferociously", "stomps") + speak_chance = 1 + turns_per_move = 5 + see_in_dark = 6 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/bearmeat = 5) + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "pokes the" + stop_automated_movement_when_pulled = 0 + maxHealth = 60 + health = 60 + melee_damage_lower = 20 + melee_damage_upper = 30 + + //Space bears 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 + var/stance_step = 0 + + faction = "russian" + +//SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!! +/mob/living/simple_animal/hostile/bear/Hudson + name = "Hudson" + desc = "" + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "pokes" + +/mob/living/simple_animal/hostile/bear/Life() + . =..() + if(!.) + return + + if(loc && istype(loc,/turf/space)) + icon_state = "bear" + else + icon_state = "bearfloor" + + switch(stance) + + if(HOSTILE_STANCE_TIRED) + stop_automated_movement = 1 + stance_step++ + if(stance_step >= 10) //rests for 10 ticks + if(target && target in ListTargets(10)) + stance = HOSTILE_STANCE_ATTACK //If the mob he was chasing is still nearby, resume the attack, otherwise go idle. + else + stance = HOSTILE_STANCE_IDLE + + if(HOSTILE_STANCE_ALERT) + stop_automated_movement = 1 + var/found_mob = 0 + if(target && target in ListTargets(10)) + if(CanAttack(target)) + stance_step = max(0, stance_step) //If we have not seen a mob in a while, the stance_step will be negative, we need to reset it to 0 as soon as we see a mob again. + stance_step++ + found_mob = 1 + src.dir = get_dir(src,target) //Keep staring at the mob + + if(stance_step in list(1,4,7)) //every 3 ticks + var/action = pick( list( "growls at [target]", "stares angrily at [target]", "prepares to attack [target]", "closely watches [target]" ) ) + if(action) + custom_emote(1,action) + if(!found_mob) + stance_step-- + + if(stance_step <= -20) //If we have not found a mob for 20-ish ticks, revert to idle mode + stance = HOSTILE_STANCE_IDLE + if(stance_step >= 7) //If we have been staring at a mob for 7 ticks, + stance = HOSTILE_STANCE_ATTACK + + if(HOSTILE_STANCE_ATTACKING) + if(stance_step >= 20) //attacks for 20 ticks, then it gets tired and needs to rest + custom_emote(1, "is worn out and needs to rest" ) + stance = HOSTILE_STANCE_TIRED + stance_step = 0 + walk(src, 0) //This stops the bear's walking + return + + + +/mob/living/simple_animal/hostile/bear/attackby(obj/item/O, mob/user) + if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING) + stance = HOSTILE_STANCE_ALERT + stance_step = 6 + target = user + ..() + +/mob/living/simple_animal/hostile/bear/attack_hand(mob/living/carbon/human/M) + if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING) + stance = HOSTILE_STANCE_ALERT + stance_step = 6 + target = M + ..() + +/mob/living/simple_animal/hostile/bear/Process_Spacemove(movement_dir = 0) + return //No drifting in space for space bears! + +/mob/living/simple_animal/hostile/bear/FindTarget() + . = ..() + if(.) + custom_emote(1,"stares alertly at [.]") + stance = HOSTILE_STANCE_ALERT + +/mob/living/simple_animal/hostile/bear/LoseTarget() + ..(5) + +/mob/living/simple_animal/hostile/bear/AttackingTarget() + if(!Adjacent(target)) + return + custom_emote(1, pick( list("slashes at [target]", "bites [target]") ) ) + + var/damage = rand(20,30) + + if(ishuman(target)) + var/mob/living/carbon/human/H = target + var/dam_zone = pick(BP_CHEST , BP_L_ARM , BP_R_ARM , BP_L_LEG , BP_R_LEG) + var/obj/item/organ/external/BP = H.bodyparts_by_name[ran_zone(dam_zone)] + H.apply_damage(damage, BRUTE, BP, H.run_armor_check(BP, "melee"), DAM_SHARP | DAM_EDGE) + return H + else if(isliving(target)) + var/mob/living/L = target + L.adjustBruteLoss(damage) + return L + else if(istype(target,/obj/mecha)) + var/obj/mecha/M = target + M.attack_animal(src) + return M + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index fea71f4dffef..ca4333d3626e 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -1,105 +1,105 @@ - - -/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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/carpmeat = 2) - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "hits the" - speed = 4 - maxHealth = 25 - health = 25 - - 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 - - environment_smash = 1 - - faction = "carp" - -/mob/living/simple_animal/hostile/carp/Process_Spacemove(movement_dir = 0) - return 1 //No drifting in space for space carp! //original comments do not steal - -/mob/living/simple_animal/hostile/carp/FindTarget() - . = ..() - if(.) - custom_emote(1,"nashes at [.]") - -/mob/living/simple_animal/hostile/carp/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/carp/megacarp - icon = 'icons/mob/megacarp.dmi' - name = "Mega Space Carp" - desc = "A ferocious, fang bearing creature that resembles a shark. This one seems especially ticked off." - icon_state = "megacarp" - icon_living = "megacarp" - icon_dead = "megacarp_dead" - icon_gib = "megacarp_gib" - maxHealth = 65 - health = 65 - pixel_x = -16 - - melee_damage_lower = 20 - melee_damage_upper = 20 - -/mob/living/simple_animal/hostile/carp/dog - name = "REX" - desc = "That's a cute little doge... WAIT, WHAT???!!" - icon = 'icons/mob/doge.dmi' - icon_state = "shepherd" - maxHealth = 9001 - health = 9001 - a_intent = "harm" - - turns_per_move = 5 - speed = -15 - move_to_delay = -15 - - melee_damage_lower = 400 - melee_damage_upper = 400 - - attacktext = "licks" - - var/idle_snd_chance = 5 - - attack_sound = 'sound/weapons/polkan_atk.ogg' - -/mob/living/simple_animal/hostile/carp/dog/polkan - name = "POLKAN" - icon_state = "husky" - -/mob/living/simple_animal/hostile/carp/dog/Life() - . = ..() - if(!.) - return 0 - - if(rand(0,100) < idle_snd_chance) - var/list/idle_snd = list('sound/voice/polkan/idle1.ogg','sound/voice/polkan/idle2.ogg') - playsound(src, pick(idle_snd), 50, 1, -3) + + +/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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/carpmeat = 2) + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "hits the" + speed = 4 + maxHealth = 25 + health = 25 + + 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 + + environment_smash = 1 + + faction = "carp" + +/mob/living/simple_animal/hostile/carp/Process_Spacemove(movement_dir = 0) + return 1 //No drifting in space for space carp! //original comments do not steal + +/mob/living/simple_animal/hostile/carp/FindTarget() + . = ..() + if(.) + custom_emote(1,"nashes at [.]") + +/mob/living/simple_animal/hostile/carp/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/carp/megacarp + icon = 'icons/mob/megacarp.dmi' + name = "Mega Space Carp" + desc = "A ferocious, fang bearing creature that resembles a shark. This one seems especially ticked off." + icon_state = "megacarp" + icon_living = "megacarp" + icon_dead = "megacarp_dead" + icon_gib = "megacarp_gib" + maxHealth = 65 + health = 65 + pixel_x = -16 + + melee_damage_lower = 20 + melee_damage_upper = 20 + +/mob/living/simple_animal/hostile/carp/dog + name = "REX" + desc = "That's a cute little doge... WAIT, WHAT???!!" + icon = 'icons/mob/doge.dmi' + icon_state = "shepherd" + maxHealth = 9001 + health = 9001 + a_intent = "harm" + + turns_per_move = 5 + speed = -15 + move_to_delay = -15 + + melee_damage_lower = 400 + melee_damage_upper = 400 + + attacktext = "licks" + + var/idle_snd_chance = 5 + + attack_sound = 'sound/weapons/polkan_atk.ogg' + +/mob/living/simple_animal/hostile/carp/dog/polkan + name = "POLKAN" + icon_state = "husky" + +/mob/living/simple_animal/hostile/carp/dog/Life() + . = ..() + if(!.) + return 0 + + if(rand(0,100) < idle_snd_chance) + var/list/idle_snd = list('sound/voice/polkan/idle1.ogg','sound/voice/polkan/idle2.ogg') + playsound(src, pick(idle_snd), 50, 1, -3) diff --git a/code/modules/mob/living/simple_animal/hostile/creature.dm b/code/modules/mob/living/simple_animal/hostile/creature.dm index 55f35197147d..850316685044 100644 --- a/code/modules/mob/living/simple_animal/hostile/creature.dm +++ b/code/modules/mob/living/simple_animal/hostile/creature.dm @@ -1,16 +1,16 @@ -/mob/living/simple_animal/hostile/creature - name = "creature" - desc = "A sanity-destroying otherthing." - icon = 'icons/mob/critter.dmi' - 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 +/mob/living/simple_animal/hostile/creature + name = "creature" + desc = "A sanity-destroying otherthing." + icon = 'icons/mob/critter.dmi' + 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 diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index 8c48bbbedbb4..f25e7ad36511 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -1,50 +1,50 @@ -/mob/living/simple_animal/hostile/faithless - name = "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 the" - response_disarm = "shoves" - response_harm = "hits the" - speed = -1 - maxHealth = 80 - health = 80 - environment_smash = 1 - - 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 - - faction = "faithless" - -/mob/living/simple_animal/hostile/faithless/Process_Spacemove(movement_dir = 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 + name = "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 the" + response_disarm = "shoves" + response_harm = "hits the" + speed = -1 + maxHealth = 80 + health = 80 + environment_smash = 1 + + 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 + + faction = "faithless" + +/mob/living/simple_animal/hostile/faithless/Process_Spacemove(movement_dir = 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]!") diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 1710a4ff2d69..082e2cf182b9 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -1,207 +1,207 @@ - -#define SPINNING_WEB 1 -#define LAYING_EGGS 2 -#define MOVING_TO_TARGET 3 -#define SPINNING_COCOON 4 - -//basic spider mob, these generally guard nests -/mob/living/simple_animal/hostile/giant_spider - name = "giant spider" - desc = "Furry and black, it makes you shudder to look at it. This one has deep red eyes." - var/butcher_state = 8 // Icon state for dead spider icons - icon_state = "guard" - icon_living = "guard" - icon_dead = "guard_dead" - speak_emote = list("chitters") - emote_hear = list("chitters") - speak_chance = 5 - turns_per_move = 5 - see_in_dark = 10 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/spidermeat = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8) - response_help = "pets the" - response_disarm = "gently pushes aside the" - response_harm = "pokes the" - stop_automated_movement_when_pulled = 0 - maxHealth = 200 - health = 200 - melee_damage_lower = 15 - melee_damage_upper = 20 - heat_damage_per_tick = 20 - cold_damage_per_tick = 20 - var/poison_per_bite = 5 - var/poison_type = "toxin" - faction = "spiders" - var/busy = 0 - pass_flags = PASSTABLE - move_to_delay = 6 - speed = 3 - environment_smash = 1 - weather_immunities = list("ash", "acid") - -//nursemaids - these create webs and eggs -/mob/living/simple_animal/hostile/giant_spider/nurse - desc = "Furry and black, it makes you shudder to look at it. This one has brilliant green eyes." - icon_state = "nurse" - icon_living = "nurse" - icon_dead = "nurse_dead" - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/spidermeat = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8, /obj/item/weapon/reagent_containers/food/snacks/spidereggs = 4) - maxHealth = 40 - health = 40 - melee_damage_lower = 5 - melee_damage_upper = 10 - poison_per_bite = 10 - var/atom/cocoon_target - poison_type = "stoxin" - var/fed = 0 - -//hunters have the most poison and move the fastest, so they can find prey -/mob/living/simple_animal/hostile/giant_spider/hunter - desc = "Furry and black, it makes you shudder to look at it. This one has sparkling purple eyes." - icon_state = "hunter" - icon_living = "hunter" - icon_dead = "hunter_dead" - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/spidermeat = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8) - maxHealth = 120 - health = 120 - melee_damage_lower = 10 - melee_damage_upper = 20 - poison_per_bite = 5 - move_to_delay = 4 - -/mob/living/simple_animal/hostile/giant_spider/AttackingTarget() - ..() - if(isliving(target)) - var/mob/living/L = target - if(L.reagents) - L.reagents.add_reagent("toxin", poison_per_bite) - if(prob(poison_per_bite)) - to_chat(L, "\red You feel a tiny prick.") - L.reagents.add_reagent(poison_type, 5) - -/mob/living/simple_animal/hostile/giant_spider/Life() - ..() - if(!stat) - if(stance == HOSTILE_STANCE_IDLE) - //1% chance to skitter madly away - if(!busy && prob(1)) - /*var/list/move_targets = list() - for(var/turf/T in orange(20, src)) - move_targets.Add(T)*/ - stop_automated_movement = 1 - walk_to(src, pick(orange(20, src)), 1, move_to_delay) - spawn(50) - stop_automated_movement = 0 - walk(src,0) - -/mob/living/simple_animal/hostile/giant_spider/nurse/proc/GiveUp(C) - spawn(100) - if(busy == MOVING_TO_TARGET) - if(cocoon_target == C && get_dist(src,cocoon_target) > 1) - cocoon_target = null - busy = 0 - stop_automated_movement = 0 - -/mob/living/simple_animal/hostile/giant_spider/nurse/Life() - ..() - if(!stat) - if(stance == HOSTILE_STANCE_IDLE) - var/list/can_see = view(src, 10) - //30% chance to stop wandering and do something - if(!busy && prob(30)) - //first, check for potential food nearby to cocoon - for(var/mob/living/C in can_see) - if(C.stat) - cocoon_target = C - busy = MOVING_TO_TARGET - walk_to(src, C, 1, move_to_delay) - //give up if we can't reach them after 10 seconds - GiveUp(C) - return - - //second, spin a sticky spiderweb on this tile - var/obj/effect/spider/stickyweb/W = locate() in get_turf(src) - if(!W) - busy = SPINNING_WEB - src.visible_message("\blue \the [src] begins to secrete a sticky substance.") - stop_automated_movement = 1 - spawn(40) - if(busy == SPINNING_WEB) - new /obj/effect/spider/stickyweb(src.loc) - busy = 0 - stop_automated_movement = 0 - else - //third, lay an egg cluster there - var/obj/effect/spider/eggcluster/E = locate() in get_turf(src) - if(!E && fed > 0) - busy = LAYING_EGGS - src.visible_message("\blue \the [src] begins to lay a cluster of eggs.") - stop_automated_movement = 1 - spawn(50) - if(busy == LAYING_EGGS) - E = locate() in get_turf(src) - if(!E) - new /obj/effect/spider/eggcluster(src.loc) - fed-- - busy = 0 - stop_automated_movement = 0 - else - //fourthly, cocoon any nearby items so those pesky pinkskins can't use them - for(var/obj/O in can_see) - - if(O.anchored) - continue - - if(istype(O, /obj/item) || istype(O, /obj/structure) || istype(O, /obj/machinery)) - cocoon_target = O - busy = MOVING_TO_TARGET - stop_automated_movement = 1 - walk_to(src, O, 1, move_to_delay) - //give up if we can't reach them after 10 seconds - GiveUp(O) - - else if(busy == MOVING_TO_TARGET && cocoon_target) - if(get_dist(src, cocoon_target) <= 1) - busy = SPINNING_COCOON - src.visible_message("\blue \the [src] begins to secrete a sticky substance around \the [cocoon_target].") - stop_automated_movement = 1 - walk(src,0) - spawn(50) - if(busy == SPINNING_COCOON) - if(cocoon_target && istype(cocoon_target.loc, /turf) && get_dist(src,cocoon_target) <= 1) - var/obj/effect/spider/cocoon/C = new(cocoon_target.loc) - var/large_cocoon = 0 - C.pixel_x = cocoon_target.pixel_x - C.pixel_y = cocoon_target.pixel_y - for(var/mob/living/M in C.loc) - if(istype(M, /mob/living/simple_animal/hostile/giant_spider)) - continue - large_cocoon = 1 - fed++ - src.visible_message("\red \the [src] sticks a proboscis into \the [cocoon_target] and sucks a viscous substance out.") - M.loc = C - C.pixel_x = M.pixel_x - C.pixel_y = M.pixel_y - break - for(var/obj/item/I in C.loc) - I.loc = C - for(var/obj/structure/S in C.loc) - if(!S.anchored) - S.loc = C - large_cocoon = 1 - for(var/obj/machinery/M in C.loc) - if(!M.anchored) - M.loc = C - large_cocoon = 1 - if(large_cocoon) - C.icon_state = pick("cocoon_large1","cocoon_large2","cocoon_large3") - busy = 0 - stop_automated_movement = 0 - - else - busy = 0 - stop_automated_movement = 0 - -#undef SPINNING_WEB -#undef LAYING_EGGS -#undef MOVING_TO_TARGET -#undef SPINNING_COCOON + +#define SPINNING_WEB 1 +#define LAYING_EGGS 2 +#define MOVING_TO_TARGET 3 +#define SPINNING_COCOON 4 + +//basic spider mob, these generally guard nests +/mob/living/simple_animal/hostile/giant_spider + name = "giant spider" + desc = "Furry and black, it makes you shudder to look at it. This one has deep red eyes." + var/butcher_state = 8 // Icon state for dead spider icons + icon_state = "guard" + icon_living = "guard" + icon_dead = "guard_dead" + speak_emote = list("chitters") + emote_hear = list("chitters") + speak_chance = 5 + turns_per_move = 5 + see_in_dark = 10 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/spidermeat = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8) + response_help = "pets the" + response_disarm = "gently pushes aside the" + response_harm = "pokes the" + stop_automated_movement_when_pulled = 0 + maxHealth = 200 + health = 200 + melee_damage_lower = 15 + melee_damage_upper = 20 + heat_damage_per_tick = 20 + cold_damage_per_tick = 20 + var/poison_per_bite = 5 + var/poison_type = "toxin" + faction = "spiders" + var/busy = 0 + pass_flags = PASSTABLE + move_to_delay = 6 + speed = 3 + environment_smash = 1 + weather_immunities = list("ash", "acid") + +//nursemaids - these create webs and eggs +/mob/living/simple_animal/hostile/giant_spider/nurse + desc = "Furry and black, it makes you shudder to look at it. This one has brilliant green eyes." + icon_state = "nurse" + icon_living = "nurse" + icon_dead = "nurse_dead" + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/spidermeat = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8, /obj/item/weapon/reagent_containers/food/snacks/spidereggs = 4) + maxHealth = 40 + health = 40 + melee_damage_lower = 5 + melee_damage_upper = 10 + poison_per_bite = 10 + var/atom/cocoon_target + poison_type = "stoxin" + var/fed = 0 + +//hunters have the most poison and move the fastest, so they can find prey +/mob/living/simple_animal/hostile/giant_spider/hunter + desc = "Furry and black, it makes you shudder to look at it. This one has sparkling purple eyes." + icon_state = "hunter" + icon_living = "hunter" + icon_dead = "hunter_dead" + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/spidermeat = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8) + maxHealth = 120 + health = 120 + melee_damage_lower = 10 + melee_damage_upper = 20 + poison_per_bite = 5 + move_to_delay = 4 + +/mob/living/simple_animal/hostile/giant_spider/AttackingTarget() + ..() + if(isliving(target)) + var/mob/living/L = target + if(L.reagents) + L.reagents.add_reagent("toxin", poison_per_bite) + if(prob(poison_per_bite)) + to_chat(L, "\red You feel a tiny prick.") + L.reagents.add_reagent(poison_type, 5) + +/mob/living/simple_animal/hostile/giant_spider/Life() + ..() + if(!stat) + if(stance == HOSTILE_STANCE_IDLE) + //1% chance to skitter madly away + if(!busy && prob(1)) + /*var/list/move_targets = list() + for(var/turf/T in orange(20, src)) + move_targets.Add(T)*/ + stop_automated_movement = 1 + walk_to(src, pick(orange(20, src)), 1, move_to_delay) + spawn(50) + stop_automated_movement = 0 + walk(src,0) + +/mob/living/simple_animal/hostile/giant_spider/nurse/proc/GiveUp(C) + spawn(100) + if(busy == MOVING_TO_TARGET) + if(cocoon_target == C && get_dist(src,cocoon_target) > 1) + cocoon_target = null + busy = 0 + stop_automated_movement = 0 + +/mob/living/simple_animal/hostile/giant_spider/nurse/Life() + ..() + if(!stat) + if(stance == HOSTILE_STANCE_IDLE) + var/list/can_see = view(src, 10) + //30% chance to stop wandering and do something + if(!busy && prob(30)) + //first, check for potential food nearby to cocoon + for(var/mob/living/C in can_see) + if(C.stat) + cocoon_target = C + busy = MOVING_TO_TARGET + walk_to(src, C, 1, move_to_delay) + //give up if we can't reach them after 10 seconds + GiveUp(C) + return + + //second, spin a sticky spiderweb on this tile + var/obj/effect/spider/stickyweb/W = locate() in get_turf(src) + if(!W) + busy = SPINNING_WEB + src.visible_message("\blue \the [src] begins to secrete a sticky substance.") + stop_automated_movement = 1 + spawn(40) + if(busy == SPINNING_WEB) + new /obj/effect/spider/stickyweb(src.loc) + busy = 0 + stop_automated_movement = 0 + else + //third, lay an egg cluster there + var/obj/effect/spider/eggcluster/E = locate() in get_turf(src) + if(!E && fed > 0) + busy = LAYING_EGGS + src.visible_message("\blue \the [src] begins to lay a cluster of eggs.") + stop_automated_movement = 1 + spawn(50) + if(busy == LAYING_EGGS) + E = locate() in get_turf(src) + if(!E) + new /obj/effect/spider/eggcluster(src.loc) + fed-- + busy = 0 + stop_automated_movement = 0 + else + //fourthly, cocoon any nearby items so those pesky pinkskins can't use them + for(var/obj/O in can_see) + + if(O.anchored) + continue + + if(istype(O, /obj/item) || istype(O, /obj/structure) || istype(O, /obj/machinery)) + cocoon_target = O + busy = MOVING_TO_TARGET + stop_automated_movement = 1 + walk_to(src, O, 1, move_to_delay) + //give up if we can't reach them after 10 seconds + GiveUp(O) + + else if(busy == MOVING_TO_TARGET && cocoon_target) + if(get_dist(src, cocoon_target) <= 1) + busy = SPINNING_COCOON + src.visible_message("\blue \the [src] begins to secrete a sticky substance around \the [cocoon_target].") + stop_automated_movement = 1 + walk(src,0) + spawn(50) + if(busy == SPINNING_COCOON) + if(cocoon_target && istype(cocoon_target.loc, /turf) && get_dist(src,cocoon_target) <= 1) + var/obj/effect/spider/cocoon/C = new(cocoon_target.loc) + var/large_cocoon = 0 + C.pixel_x = cocoon_target.pixel_x + C.pixel_y = cocoon_target.pixel_y + for(var/mob/living/M in C.loc) + if(istype(M, /mob/living/simple_animal/hostile/giant_spider)) + continue + large_cocoon = 1 + fed++ + src.visible_message("\red \the [src] sticks a proboscis into \the [cocoon_target] and sucks a viscous substance out.") + M.loc = C + C.pixel_x = M.pixel_x + C.pixel_y = M.pixel_y + break + for(var/obj/item/I in C.loc) + I.loc = C + for(var/obj/structure/S in C.loc) + if(!S.anchored) + S.loc = C + large_cocoon = 1 + for(var/obj/machinery/M in C.loc) + if(!M.anchored) + M.loc = C + large_cocoon = 1 + if(large_cocoon) + C.icon_state = pick("cocoon_large1","cocoon_large2","cocoon_large3") + busy = 0 + stop_automated_movement = 0 + + else + busy = 0 + stop_automated_movement = 0 + +#undef SPINNING_WEB +#undef LAYING_EGGS +#undef MOVING_TO_TARGET +#undef SPINNING_COCOON diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm index 47f794684576..f33483272c67 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm @@ -1,106 +1,106 @@ -/obj/item/projectile/hivebotbullet - damage = 10 - damage_type = BRUTE - -/mob/living/simple_animal/hostile/hivebot - name = "Hivebot" - desc = "A small robot." - icon = 'icons/mob/hivebot.dmi' - icon_state = "basic" - icon_living = "basic" - icon_dead = "basic" - health = 15 - maxHealth = 15 - melee_damage_lower = 2 - melee_damage_upper = 3 - attacktext = "claws" - projectilesound = 'sound/weapons/Gunshot.ogg' - projectiletype = /obj/item/projectile/hivebotbullet - faction = "hivebot" - 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 - -/mob/living/simple_animal/hostile/hivebot/range - name = "Hivebot" - desc = "A smallish robot, this one is armed!" - ranged = 1 - retreat_distance = 5 - minimum_distance = 5 - -/mob/living/simple_animal/hostile/hivebot/rapid - ranged = 1 - rapid = 1 - retreat_distance = 5 - minimum_distance = 5 - -/mob/living/simple_animal/hostile/hivebot/strong - name = "Strong Hivebot" - desc = "A robot, this one is armed and looks tough!" - health = 80 - ranged = 1 - -/mob/living/simple_animal/hostile/hivebot/death() - ..() - visible_message("[src] blows apart!") - new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc) - 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 - -/mob/living/simple_animal/hostile/hivebot/tele//this still needs work - name = "Beacon" - desc = "Some odd beacon thing." - icon = 'icons/mob/hivebot.dmi' - icon_state = "def_radar-off" - icon_living = "def_radar-off" - health = 200 - maxHealth = 200 - status_flags = 0 - anchored = 1 - stop_automated_movement = 1 - var/bot_type = "norm" - var/bot_amt = 10 - var/spawn_delay = 600 - var/turn_on = 0 - var/auto_spawn = 1 - -/mob/living/simple_animal/hostile/hivebot/tele/atom_init() - . = ..() - var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() - smoke.set_up(5, 0, src.loc) - smoke.start() - visible_message("\red The [src] warps in!") - playsound(src.loc, 'sound/effects/EMPulse.ogg', 25, 1) - -/mob/living/simple_animal/hostile/hivebot/tele/proc/warpbots() - icon_state = "def_radar" - visible_message("\red The [src] turns on!") - while(bot_amt > 0) - bot_amt-- - switch(bot_type) - if("norm") - new /mob/living/simple_animal/hostile/hivebot(get_turf(src)) - if("range") - new /mob/living/simple_animal/hostile/hivebot/range(get_turf(src)) - if("rapid") - new /mob/living/simple_animal/hostile/hivebot/rapid(get_turf(src)) - spawn(100) - qdel(src) - return - -/mob/living/simple_animal/hostile/hivebot/tele/Life() - ..() - if(stat == CONSCIOUS) - if(prob(2))//Might be a bit low, will mess with it likely - warpbots() - +/obj/item/projectile/hivebotbullet + damage = 10 + damage_type = BRUTE + +/mob/living/simple_animal/hostile/hivebot + name = "Hivebot" + desc = "A small robot." + icon = 'icons/mob/hivebot.dmi' + icon_state = "basic" + icon_living = "basic" + icon_dead = "basic" + health = 15 + maxHealth = 15 + melee_damage_lower = 2 + melee_damage_upper = 3 + attacktext = "claws" + projectilesound = 'sound/weapons/Gunshot.ogg' + projectiletype = /obj/item/projectile/hivebotbullet + faction = "hivebot" + 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 + +/mob/living/simple_animal/hostile/hivebot/range + name = "Hivebot" + desc = "A smallish robot, this one is armed!" + ranged = 1 + retreat_distance = 5 + minimum_distance = 5 + +/mob/living/simple_animal/hostile/hivebot/rapid + ranged = 1 + rapid = 1 + retreat_distance = 5 + minimum_distance = 5 + +/mob/living/simple_animal/hostile/hivebot/strong + name = "Strong Hivebot" + desc = "A robot, this one is armed and looks tough!" + health = 80 + ranged = 1 + +/mob/living/simple_animal/hostile/hivebot/death() + ..() + visible_message("[src] blows apart!") + new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc) + 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 + +/mob/living/simple_animal/hostile/hivebot/tele//this still needs work + name = "Beacon" + desc = "Some odd beacon thing." + icon = 'icons/mob/hivebot.dmi' + icon_state = "def_radar-off" + icon_living = "def_radar-off" + health = 200 + maxHealth = 200 + status_flags = 0 + anchored = 1 + stop_automated_movement = 1 + var/bot_type = "norm" + var/bot_amt = 10 + var/spawn_delay = 600 + var/turn_on = 0 + var/auto_spawn = 1 + +/mob/living/simple_animal/hostile/hivebot/tele/atom_init() + . = ..() + var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() + smoke.set_up(5, 0, src.loc) + smoke.start() + visible_message("\red The [src] warps in!") + playsound(src.loc, 'sound/effects/EMPulse.ogg', 25, 1) + +/mob/living/simple_animal/hostile/hivebot/tele/proc/warpbots() + icon_state = "def_radar" + visible_message("\red The [src] turns on!") + while(bot_amt > 0) + bot_amt-- + switch(bot_type) + if("norm") + new /mob/living/simple_animal/hostile/hivebot(get_turf(src)) + if("range") + new /mob/living/simple_animal/hostile/hivebot/range(get_turf(src)) + if("rapid") + new /mob/living/simple_animal/hostile/hivebot/rapid(get_turf(src)) + spawn(100) + qdel(src) + return + +/mob/living/simple_animal/hostile/hivebot/tele/Life() + ..() + if(stat == CONSCIOUS) + if(prob(2))//Might be a bit low, will mess with it likely + warpbots() + diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 1d154674a40b..1ed1d9f64bd4 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -1,304 +1,304 @@ -/mob/living/simple_animal/hostile - faction = "hostile" - var/stance = HOSTILE_STANCE_IDLE //Used to determine behavior - var/atom/target - var/attack_same = 0 - var/ranged = 0 - var/rapid = 0 - var/projectiletype - var/projectilesound - var/casingtype - var/move_to_delay = 4 //delay for the automated movement. - var/list/friends = list() - var/break_stuff_probability = 10 - stop_automated_movement_when_pulled = 0 - var/destroy_surroundings = 1 - mouse_opacity = 2 //This makes it easier to hit hostile mobs, you only need to click on their tile, and is set back to 1 when they die - 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/Life() - . = ..() - if(!.) - walk(src, 0) - return 0 - if(client) - return 0 - if(!stat) - switch(stance) - if(HOSTILE_STANCE_IDLE) - if(environment_smash) - EscapeConfinement() - var/new_target = FindTarget() - GiveTarget(new_target) - - if(HOSTILE_STANCE_ATTACK) - MoveToTarget() - DestroySurroundings() - - if(HOSTILE_STANCE_ATTACKING) - 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 = list() - if(!search_objects) - var/list/Mobs = hearers(vision_range, src) - src //Remove self, so we don't suicide - L += Mobs - for(var/obj/mecha/M in mechas_list) - if(get_dist(M, src) <= vision_range && can_see(src, M, vision_range)) - L += M - else - var/list/Objects = oview(vision_range, src) - L += Objects - 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(atom/A)//This is here as a potential override to pick a specific target if available - return - -/mob/living/simple_animal/hostile/proc/PickTarget(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(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 - if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive == 1) - return 0 - if(L.faction == src.faction && !attack_same || L.faction != src.faction && attack_same == 2 || L.faction != attack_faction && attack_faction) - return 0 - if(L in friends) - return 0 - return 1 - if(isobj(the_target)) - if(the_target.type in 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(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(retreat_distance != null)//If we have a retreat distance, check if we need to run from our target - if(target_distance <= retreat_distance)//If target's closer than our retreat distance, run - 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 - else - Goto(target,move_to_delay,minimum_distance) - if(isturf(loc) && target.Adjacent(src)) //If they're next to us, attack - AttackingTarget() - 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 - 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(target, delay, minimum_distance) - walk_to(src, target, minimum_distance, delay) - -/mob/living/simple_animal/hostile/adjustBruteLoss(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/death() - LoseAggro() - mouse_opacity = 1 - ..() - walk(src, 0) - -/mob/living/simple_animal/hostile/proc/OpenFire(the_target) - - var/target = the_target - visible_message("\red [src] [ranged_message] at [target]!", 1) - - var/tturf = get_turf(target) - if(rapid) - spawn(1) - Shoot(tturf, src.loc, src) - if(casingtype) - new casingtype(get_turf(src)) - spawn(4) - Shoot(tturf, src.loc, src) - if(casingtype) - new casingtype(get_turf(src)) - spawn(6) - Shoot(tturf, src.loc, src) - if(casingtype) - new casingtype(get_turf(src)) - else - Shoot(tturf, src.loc, src) - if(casingtype) - new casingtype - ranged_cooldown = ranged_cooldown_cap - return - -/mob/living/simple_animal/hostile/proc/Shoot(target, start, user, 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)) - qdel(A) - return - A.current = target - A.starting = get_turf(src) - A.original = get_turf(target) - A.yo = target:y - start:y - A.xo = target:x - start:x - spawn( 0 ) - A.process() - return - -/mob/living/simple_animal/hostile/proc/DestroySurroundings() - if(environment_smash) - EscapeConfinement() - for(var/dir in cardinal) // North, South, East, West - var/turf/T = get_step(src, dir) - if(istype(T, /turf/simulated/wall) || istype(T, /turf/simulated/mineral)) - if(T.Adjacent(src)) - T.attack_animal(src) - for(var/obj/structure/window/W in get_step(src, dir)) - if(W.dir == reverse_dir[dir]) // So that windows get smashed in the right order - W.attack_animal(src) - return - 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) || istype(A, /obj/machinery/door/window)) - A.attack_animal(src) - if(istype(A, /obj/item/tape)) - var/obj/item/tape/Tp = A - Tp.breaktape(null, src, TRUE) - return - - -/mob/living/simple_animal/hostile/proc/EscapeConfinement() - if(buckled) - buckled.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(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" + var/stance = HOSTILE_STANCE_IDLE //Used to determine behavior + var/atom/target + var/attack_same = 0 + var/ranged = 0 + var/rapid = 0 + var/projectiletype + var/projectilesound + var/casingtype + var/move_to_delay = 4 //delay for the automated movement. + var/list/friends = list() + var/break_stuff_probability = 10 + stop_automated_movement_when_pulled = 0 + var/destroy_surroundings = 1 + mouse_opacity = 2 //This makes it easier to hit hostile mobs, you only need to click on their tile, and is set back to 1 when they die + 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/Life() + . = ..() + if(!.) + walk(src, 0) + return 0 + if(client) + return 0 + if(!stat) + switch(stance) + if(HOSTILE_STANCE_IDLE) + if(environment_smash) + EscapeConfinement() + var/new_target = FindTarget() + GiveTarget(new_target) + + if(HOSTILE_STANCE_ATTACK) + MoveToTarget() + DestroySurroundings() + + if(HOSTILE_STANCE_ATTACKING) + 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 = list() + if(!search_objects) + var/list/Mobs = hearers(vision_range, src) - src //Remove self, so we don't suicide + L += Mobs + for(var/obj/mecha/M in mechas_list) + if(get_dist(M, src) <= vision_range && can_see(src, M, vision_range)) + L += M + else + var/list/Objects = oview(vision_range, src) + L += Objects + 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(atom/A)//This is here as a potential override to pick a specific target if available + return + +/mob/living/simple_animal/hostile/proc/PickTarget(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(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 + if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive == 1) + return 0 + if(L.faction == src.faction && !attack_same || L.faction != src.faction && attack_same == 2 || L.faction != attack_faction && attack_faction) + return 0 + if(L in friends) + return 0 + return 1 + if(isobj(the_target)) + if(the_target.type in 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(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(retreat_distance != null)//If we have a retreat distance, check if we need to run from our target + if(target_distance <= retreat_distance)//If target's closer than our retreat distance, run + 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 + else + Goto(target,move_to_delay,minimum_distance) + if(isturf(loc) && target.Adjacent(src)) //If they're next to us, attack + AttackingTarget() + 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 + 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(target, delay, minimum_distance) + walk_to(src, target, minimum_distance, delay) + +/mob/living/simple_animal/hostile/adjustBruteLoss(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/death() + LoseAggro() + mouse_opacity = 1 + ..() + walk(src, 0) + +/mob/living/simple_animal/hostile/proc/OpenFire(the_target) + + var/target = the_target + visible_message("\red [src] [ranged_message] at [target]!", 1) + + var/tturf = get_turf(target) + if(rapid) + spawn(1) + Shoot(tturf, src.loc, src) + if(casingtype) + new casingtype(get_turf(src)) + spawn(4) + Shoot(tturf, src.loc, src) + if(casingtype) + new casingtype(get_turf(src)) + spawn(6) + Shoot(tturf, src.loc, src) + if(casingtype) + new casingtype(get_turf(src)) + else + Shoot(tturf, src.loc, src) + if(casingtype) + new casingtype + ranged_cooldown = ranged_cooldown_cap + return + +/mob/living/simple_animal/hostile/proc/Shoot(target, start, user, 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)) + qdel(A) + return + A.current = target + A.starting = get_turf(src) + A.original = get_turf(target) + A.yo = target:y - start:y + A.xo = target:x - start:x + spawn( 0 ) + A.process() + return + +/mob/living/simple_animal/hostile/proc/DestroySurroundings() + if(environment_smash) + EscapeConfinement() + for(var/dir in cardinal) // North, South, East, West + var/turf/T = get_step(src, dir) + if(istype(T, /turf/simulated/wall) || istype(T, /turf/simulated/mineral)) + if(T.Adjacent(src)) + T.attack_animal(src) + for(var/obj/structure/window/W in get_step(src, dir)) + if(W.dir == reverse_dir[dir]) // So that windows get smashed in the right order + W.attack_animal(src) + return + 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) || istype(A, /obj/machinery/door/window)) + A.attack_animal(src) + if(istype(A, /obj/item/tape)) + var/obj/item/tape/Tp = A + Tp.breaktape(null, src, TRUE) + return + + +/mob/living/simple_animal/hostile/proc/EscapeConfinement() + if(buckled) + buckled.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(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/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index b4ed0b846f9e..70417260fa87 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -1,203 +1,203 @@ -// -// Abstract Class -// - -/mob/living/simple_animal/hostile/mimic - name = "crate" - desc = "A rectangular steel crate." - icon = 'icons/obj/storage.dmi' - icon_state = "crate" - icon_living = "crate" - - response_help = "touches the" - response_disarm = "pushes the" - response_harm = "hits the" - speed = 4 - maxHealth = 250 - health = 250 - - harm_intent_damage = 5 - melee_damage_lower = 8 - melee_damage_upper = 12 - attacktext = "attacks" - attack_sound = 'sound/weapons/bite.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 - - faction = "mimic" - move_to_delay = 8 - -/mob/living/simple_animal/hostile/mimic/FindTarget() - . = ..() - if(.) - emote("growls at [.]") - -/mob/living/simple_animal/hostile/mimic/death() - ..() - visible_message("\red [src] stops moving!") - qdel(src) - - - -// -// Crate Mimic -// - - -// Aggro when you try to open them. Will also pickup loot when spawns and drop it when dies. -/mob/living/simple_animal/hostile/mimic/crate - - attacktext = "bites" - - stop_automated_movement = 1 - wander = 0 - var/attempt_open = 0 - -// Pickup loot -/mob/living/simple_animal/hostile/mimic/crate/atom_init() - . = ..() - for(var/obj/item/I in loc) - I.loc = src - -/mob/living/simple_animal/hostile/mimic/crate/DestroySurroundings() - ..() - if(prob(90)) - icon_state = "[initial(icon_state)]open" - else - icon_state = initial(icon_state) - -/mob/living/simple_animal/hostile/mimic/crate/ListTargets() - if(attempt_open) - return ..() - return view(src, 1) - -/mob/living/simple_animal/hostile/mimic/crate/FindTarget() - . = ..() - if(.) - trigger() - -/mob/living/simple_animal/hostile/mimic/crate/AttackingTarget() - . = ..() - if(.) - icon_state = initial(icon_state) - -/mob/living/simple_animal/hostile/mimic/crate/proc/trigger() - if(!attempt_open) - visible_message("[src] starts to move!") - attempt_open = 1 - -/mob/living/simple_animal/hostile/mimic/crate/adjustBruteLoss(damage) - trigger() - ..(damage) - -/mob/living/simple_animal/hostile/mimic/crate/LoseTarget() - ..() - icon_state = initial(icon_state) - -/mob/living/simple_animal/hostile/mimic/crate/LostTarget() - ..() - icon_state = initial(icon_state) - -/mob/living/simple_animal/hostile/mimic/crate/death() - - var/obj/structure/closet/crate/C = new(get_turf(src)) - // Put loot in crate - for(var/obj/O in src) - O.loc = C - ..() - -/mob/living/simple_animal/hostile/mimic/crate/AttackingTarget() - . =..() - var/mob/living/L = . - if(istype(L)) - if(prob(15)) - L.Weaken(2) - L.visible_message("\the [src] knocks down \the [L]!") - -// -// Copy Mimic -// - -var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window, /obj/item/projectile/magic/animate) - -/mob/living/simple_animal/hostile/mimic/copy - - health = 100 - maxHealth = 100 - var/mob/living/creator = null // the creator - var/destroy_objects = 0 - var/knockdown_people = 0 - -/mob/living/simple_animal/hostile/mimic/copy/atom_init(mapload, obj/copy, mob/living/creator) - . = ..() - CopyObject(copy, creator) - -/mob/living/simple_animal/hostile/mimic/copy/death() - - for(var/atom/movable/M in src) - M.loc = get_turf(src) - ..() - -/mob/living/simple_animal/hostile/mimic/copy/ListTargets() - // Return a list of targets that isn't the creator - . = ..() - return . - creator - -/mob/living/simple_animal/hostile/mimic/copy/proc/CopyObject(obj/O, mob/living/creator) - - if((istype(O, /obj/item) || istype(O, /obj/structure)) && !is_type_in_list(O, protected_objects)) - - O.loc = src - name = O.name - desc = O.desc - icon = O.icon - icon_state = O.icon_state - icon_living = icon_state - - if(istype(O, /obj/structure)) - health = (anchored * 50) + 50 - destroy_objects = 1 - if(O.density && O.anchored) - knockdown_people = 1 - melee_damage_lower *= 2 - melee_damage_upper *= 2 - else if(istype(O, /obj/item)) - var/obj/item/I = O - health = 15 * I.w_class - melee_damage_lower = 2 + I.force - melee_damage_upper = 2 + I.force - move_to_delay = 2 * I.w_class - - maxHealth = health - if(creator) - src.creator = creator - faction = "\ref[creator]" // very unique - return 1 - return - -/mob/living/simple_animal/hostile/mimic/copy/DestroySurroundings() - if(destroy_objects) - ..() - -/mob/living/simple_animal/hostile/mimic/copy/AttackingTarget() - . =..() - if(knockdown_people) - var/mob/living/L = . - if(istype(L)) - if(prob(15)) - L.Weaken(1) - L.visible_message("\the [src] knocks down \the [L]!") - -/mob/living/simple_animal/hostile/mimic/copy/proc/ChangeOwner(mob/owner) - if(owner != creator) - LoseTarget() - creator = owner - faction = "\ref[owner]" +// +// Abstract Class +// + +/mob/living/simple_animal/hostile/mimic + name = "crate" + desc = "A rectangular steel crate." + icon = 'icons/obj/storage.dmi' + icon_state = "crate" + icon_living = "crate" + + response_help = "touches the" + response_disarm = "pushes the" + response_harm = "hits the" + speed = 4 + maxHealth = 250 + health = 250 + + harm_intent_damage = 5 + melee_damage_lower = 8 + melee_damage_upper = 12 + attacktext = "attacks" + attack_sound = 'sound/weapons/bite.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 + + faction = "mimic" + move_to_delay = 8 + +/mob/living/simple_animal/hostile/mimic/FindTarget() + . = ..() + if(.) + emote("growls at [.]") + +/mob/living/simple_animal/hostile/mimic/death() + ..() + visible_message("\red [src] stops moving!") + qdel(src) + + + +// +// Crate Mimic +// + + +// Aggro when you try to open them. Will also pickup loot when spawns and drop it when dies. +/mob/living/simple_animal/hostile/mimic/crate + + attacktext = "bites" + + stop_automated_movement = 1 + wander = 0 + var/attempt_open = 0 + +// Pickup loot +/mob/living/simple_animal/hostile/mimic/crate/atom_init() + . = ..() + for(var/obj/item/I in loc) + I.loc = src + +/mob/living/simple_animal/hostile/mimic/crate/DestroySurroundings() + ..() + if(prob(90)) + icon_state = "[initial(icon_state)]open" + else + icon_state = initial(icon_state) + +/mob/living/simple_animal/hostile/mimic/crate/ListTargets() + if(attempt_open) + return ..() + return view(src, 1) + +/mob/living/simple_animal/hostile/mimic/crate/FindTarget() + . = ..() + if(.) + trigger() + +/mob/living/simple_animal/hostile/mimic/crate/AttackingTarget() + . = ..() + if(.) + icon_state = initial(icon_state) + +/mob/living/simple_animal/hostile/mimic/crate/proc/trigger() + if(!attempt_open) + visible_message("[src] starts to move!") + attempt_open = 1 + +/mob/living/simple_animal/hostile/mimic/crate/adjustBruteLoss(damage) + trigger() + ..(damage) + +/mob/living/simple_animal/hostile/mimic/crate/LoseTarget() + ..() + icon_state = initial(icon_state) + +/mob/living/simple_animal/hostile/mimic/crate/LostTarget() + ..() + icon_state = initial(icon_state) + +/mob/living/simple_animal/hostile/mimic/crate/death() + + var/obj/structure/closet/crate/C = new(get_turf(src)) + // Put loot in crate + for(var/obj/O in src) + O.loc = C + ..() + +/mob/living/simple_animal/hostile/mimic/crate/AttackingTarget() + . =..() + var/mob/living/L = . + if(istype(L)) + if(prob(15)) + L.Weaken(2) + L.visible_message("\the [src] knocks down \the [L]!") + +// +// Copy Mimic +// + +var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window, /obj/item/projectile/magic/animate) + +/mob/living/simple_animal/hostile/mimic/copy + + health = 100 + maxHealth = 100 + var/mob/living/creator = null // the creator + var/destroy_objects = 0 + var/knockdown_people = 0 + +/mob/living/simple_animal/hostile/mimic/copy/atom_init(mapload, obj/copy, mob/living/creator) + . = ..() + CopyObject(copy, creator) + +/mob/living/simple_animal/hostile/mimic/copy/death() + + for(var/atom/movable/M in src) + M.loc = get_turf(src) + ..() + +/mob/living/simple_animal/hostile/mimic/copy/ListTargets() + // Return a list of targets that isn't the creator + . = ..() + return . - creator + +/mob/living/simple_animal/hostile/mimic/copy/proc/CopyObject(obj/O, mob/living/creator) + + if((istype(O, /obj/item) || istype(O, /obj/structure)) && !is_type_in_list(O, protected_objects)) + + O.loc = src + name = O.name + desc = O.desc + icon = O.icon + icon_state = O.icon_state + icon_living = icon_state + + if(istype(O, /obj/structure)) + health = (anchored * 50) + 50 + destroy_objects = 1 + if(O.density && O.anchored) + knockdown_people = 1 + melee_damage_lower *= 2 + melee_damage_upper *= 2 + else if(istype(O, /obj/item)) + var/obj/item/I = O + health = 15 * I.w_class + melee_damage_lower = 2 + I.force + melee_damage_upper = 2 + I.force + move_to_delay = 2 * I.w_class + + maxHealth = health + if(creator) + src.creator = creator + faction = "\ref[creator]" // very unique + return 1 + return + +/mob/living/simple_animal/hostile/mimic/copy/DestroySurroundings() + if(destroy_objects) + ..() + +/mob/living/simple_animal/hostile/mimic/copy/AttackingTarget() + . =..() + if(knockdown_people) + var/mob/living/L = . + if(istype(L)) + if(prob(15)) + L.Weaken(1) + L.visible_message("\the [src] knocks down \the [L]!") + +/mob/living/simple_animal/hostile/mimic/copy/proc/ChangeOwner(mob/owner) + if(owner != creator) + LoseTarget() + creator = owner + faction = "\ref[owner]" diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index 0c9546417246..7ab053a895f7 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -1,59 +1,59 @@ -/mob/living/simple_animal/hostile/pirate - name = "Pirate" - desc = "Does what he wants cause a pirate is free." - icon_state = "piratemelee" - icon_living = "piratemelee" - icon_dead = "piratemelee_dead" - speak_chance = 0 - turns_per_move = 5 - response_help = "pushes the" - response_disarm = "shoves" - response_harm = "hits the" - speed = 4 - stop_automated_movement_when_pulled = 0 - maxHealth = 100 - health = 100 - - harm_intent_damage = 5 - melee_damage_lower = 30 - melee_damage_upper = 30 - attacktext = "slashes" - attack_sound = 'sound/weapons/bladeslice.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 - unsuitable_atoms_damage = 15 - var/corpse = /obj/effect/landmark/mobcorpse/pirate - var/weapon1 = /obj/item/weapon/melee/energy/sword/pirate - - faction = "pirate" - -/mob/living/simple_animal/hostile/pirate/ranged - name = "Pirate Gunner" - icon_state = "pirateranged" - icon_living = "pirateranged" - icon_dead = "piratemelee_dead" - projectilesound = 'sound/weapons/laser.ogg' - ranged = 1 - rapid = 1 - retreat_distance = 5 - minimum_distance = 5 - projectiletype = /obj/item/projectile/beam - corpse = /obj/effect/landmark/mobcorpse/pirate/ranged - weapon1 = /obj/item/weapon/gun/energy/laser - - -/mob/living/simple_animal/hostile/pirate/death() - ..() - if(corpse) - new corpse (src.loc) - if(weapon1) - new weapon1 (src.loc) - qdel(src) - return +/mob/living/simple_animal/hostile/pirate + name = "Pirate" + desc = "Does what he wants cause a pirate is free." + icon_state = "piratemelee" + icon_living = "piratemelee" + icon_dead = "piratemelee_dead" + speak_chance = 0 + turns_per_move = 5 + response_help = "pushes the" + response_disarm = "shoves" + response_harm = "hits the" + speed = 4 + stop_automated_movement_when_pulled = 0 + maxHealth = 100 + health = 100 + + harm_intent_damage = 5 + melee_damage_lower = 30 + melee_damage_upper = 30 + attacktext = "slashes" + attack_sound = 'sound/weapons/bladeslice.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 + unsuitable_atoms_damage = 15 + var/corpse = /obj/effect/landmark/mobcorpse/pirate + var/weapon1 = /obj/item/weapon/melee/energy/sword/pirate + + faction = "pirate" + +/mob/living/simple_animal/hostile/pirate/ranged + name = "Pirate Gunner" + icon_state = "pirateranged" + icon_living = "pirateranged" + icon_dead = "piratemelee_dead" + projectilesound = 'sound/weapons/laser.ogg' + ranged = 1 + rapid = 1 + retreat_distance = 5 + minimum_distance = 5 + projectiletype = /obj/item/projectile/beam + corpse = /obj/effect/landmark/mobcorpse/pirate/ranged + weapon1 = /obj/item/weapon/gun/energy/laser + + +/mob/living/simple_animal/hostile/pirate/death() + ..() + if(corpse) + new corpse (src.loc) + if(weapon1) + new weapon1 (src.loc) + qdel(src) + return 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 a13f060f8ca6..6045cdef57e2 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm @@ -1,78 +1,78 @@ -/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 the" - response_disarm = "gently pushes aside the" - response_harm = "hits the" - speak = list("HONK", "Honk!", "Welcome to clown planet!") - emote_see = list("honks") - speak_chance = 1 - a_intent = "harm" - 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/clown //Here's CopyPasta!! - name = "Clown" - desc = "Here's clownny!" - icon_state = "clown" - icon_living = "clown" - icon_dead = "clown_dead" - icon_gib = "clown_gib" - turns_per_move = 5 - response_help = "pokes the" - response_disarm = "gently pushes aside the" - response_harm = "hits the" - speak = list("HONK!?", "Honk!", "Honk?", "ALL YOUR HONKS BELONGS TO US!", "Hooonk...") - emote_see = list("honks") - speak_chance = 3 - a_intent = "harm" - 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 = "honks" - 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 the" + response_disarm = "gently pushes aside the" + response_harm = "hits the" + speak = list("HONK", "Honk!", "Welcome to clown planet!") + emote_see = list("honks") + speak_chance = 1 + a_intent = "harm" + 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/clown //Here's CopyPasta!! + name = "Clown" + desc = "Here's clownny!" + icon_state = "clown" + icon_living = "clown" + icon_dead = "clown_dead" + icon_gib = "clown_gib" + turns_per_move = 5 + response_help = "pokes the" + response_disarm = "gently pushes aside the" + response_harm = "hits the" + speak = list("HONK!?", "Honk!", "Honk?", "ALL YOUR HONKS BELONGS TO US!", "Hooonk...") + emote_see = list("honks") + speak_chance = 3 + a_intent = "harm" + 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 = "honks" + 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 67452963e796..d534e69014e0 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm @@ -1,49 +1,49 @@ -/mob/living/simple_animal/hostile/retaliate - var/list/enemies = list() - -/mob/living/simple_animal/hostile/retaliate/Found(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(!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() - ..() - var/list/around = view(src, 7) - - 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(damage) - ..(damage) - Retaliate() +/mob/living/simple_animal/hostile/retaliate + var/list/enemies = list() + +/mob/living/simple_animal/hostile/retaliate/Found(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(!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() + ..() + var/list/around = view(src, 7) + + 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(damage) + ..(damage) + Retaliate() diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index ce3978e36018..f142cd99d12e 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -1,55 +1,55 @@ -/mob/living/simple_animal/hostile/russian - name = "Russian" - desc = "For the Motherland!" - icon_state = "russianmelee" - icon_living = "russianmelee" - icon_dead = "russianmelee_dead" - icon_gib = "syndicate_gib" - speak_chance = 0 - turns_per_move = 5 - response_help = "pokes the" - response_disarm = "shoves the" - response_harm = "hits the" - speed = 4 - stop_automated_movement_when_pulled = 0 - maxHealth = 100 - health = 100 - harm_intent_damage = 5 - melee_damage_lower = 15 - melee_damage_upper = 15 - attacktext = "punches" - a_intent = "harm" - var/corpse = /obj/effect/landmark/mobcorpse/russian - var/weapon1 = /obj/item/weapon/kitchenknife - min_oxy = 5 - max_oxy = 0 - min_tox = 0 - max_tox = 1 - min_co2 = 0 - max_co2 = 5 - min_n2 = 0 - max_n2 = 0 - unsuitable_atoms_damage = 15 - faction = "russian" - status_flags = CANPUSH - - -/mob/living/simple_animal/hostile/russian/ranged - icon_state = "russianranged" - icon_living = "russianranged" - corpse = /obj/effect/landmark/mobcorpse/russian/ranged - weapon1 = /obj/item/weapon/gun/projectile/revolver/mateba - ranged = 1 - projectiletype = /obj/item/projectile/bullet - projectilesound = 'sound/weapons/Gunshot.ogg' - casingtype = /obj/item/ammo_casing/a357 - - -/mob/living/simple_animal/hostile/russian/death() - ..() - if(corpse) - new corpse (src.loc) - if(weapon1) - new weapon1 (src.loc) - qdel(src) - return +/mob/living/simple_animal/hostile/russian + name = "Russian" + desc = "For the Motherland!" + icon_state = "russianmelee" + icon_living = "russianmelee" + icon_dead = "russianmelee_dead" + icon_gib = "syndicate_gib" + speak_chance = 0 + turns_per_move = 5 + response_help = "pokes the" + response_disarm = "shoves the" + response_harm = "hits the" + speed = 4 + stop_automated_movement_when_pulled = 0 + maxHealth = 100 + health = 100 + harm_intent_damage = 5 + melee_damage_lower = 15 + melee_damage_upper = 15 + attacktext = "punches" + a_intent = "harm" + var/corpse = /obj/effect/landmark/mobcorpse/russian + var/weapon1 = /obj/item/weapon/kitchenknife + min_oxy = 5 + max_oxy = 0 + min_tox = 0 + max_tox = 1 + min_co2 = 0 + max_co2 = 5 + min_n2 = 0 + max_n2 = 0 + unsuitable_atoms_damage = 15 + faction = "russian" + status_flags = CANPUSH + + +/mob/living/simple_animal/hostile/russian/ranged + icon_state = "russianranged" + icon_living = "russianranged" + corpse = /obj/effect/landmark/mobcorpse/russian/ranged + weapon1 = /obj/item/weapon/gun/projectile/revolver/mateba + ranged = 1 + projectiletype = /obj/item/projectile/bullet + projectilesound = 'sound/weapons/Gunshot.ogg' + casingtype = /obj/item/ammo_casing/a357 + + +/mob/living/simple_animal/hostile/russian/death() + ..() + if(corpse) + new corpse (src.loc) + if(weapon1) + new weapon1 (src.loc) + qdel(src) + return diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index a1f19e992d3e..b9005ad93290 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -1,167 +1,167 @@ -/mob/living/simple_animal/hostile/syndicate - name = "Syndicate Operative" - desc = "Death to Nanotrasen." - icon_state = "syndicate" - icon_living = "syndicate" - icon_dead = "syndicate_dead" - icon_gib = "syndicate_gib" - speak_chance = 0 - turns_per_move = 5 - response_help = "pokes the" - response_disarm = "shoves the" - response_harm = "hits the" - speed = 4 - stop_automated_movement_when_pulled = 0 - maxHealth = 100 - health = 100 - harm_intent_damage = 5 - melee_damage_lower = 10 - melee_damage_upper = 10 - attacktext = "punches" - a_intent = "harm" - var/corpse = /obj/effect/landmark/mobcorpse/syndicatesoldier - var/weapon1 - var/weapon2 - min_oxy = 5 - max_oxy = 0 - min_tox = 0 - max_tox = 1 - min_co2 = 0 - max_co2 = 5 - min_n2 = 0 - max_n2 = 0 - unsuitable_atoms_damage = 15 - environment_smash = 1 - faction = "syndicate" - status_flags = CANPUSH - -/mob/living/simple_animal/hostile/syndicate/death() - ..() - if(corpse) - new corpse (src.loc) - if(weapon1) - new weapon1 (src.loc) - if(weapon2) - new weapon2 (src.loc) - qdel(src) - return - -///////////////Sword and shield//////////// - -/mob/living/simple_animal/hostile/syndicate/melee - melee_damage_lower = 20 - melee_damage_upper = 25 - icon_state = "syndicatemelee" - icon_living = "syndicatemelee" - weapon1 = /obj/item/weapon/melee/energy/sword/red - weapon2 = /obj/item/weapon/shield/energy - attacktext = "slashes" - status_flags = 0 - -/mob/living/simple_animal/hostile/syndicate/melee/attackby(obj/item/O, mob/user) - user.SetNextMove(CLICK_CD_MELEE) - if(O.force) - if(prob(80)) - var/damage = O.force - if (O.damtype == HALLOSS) - damage = 0 - health -= damage - visible_message("\red \b [src] has been attacked with the [O] by [user]. ") - else - visible_message("\red \b [src] blocks the [O] with its shield! ") - else - to_chat(usr, "\red This weapon is ineffective, it does no damage.") - visible_message("\red [user] gently taps [src] with the [O]. ") - - -/mob/living/simple_animal/hostile/syndicate/melee/bullet_act(obj/item/projectile/Proj) - if(!Proj) return - if(prob(65)) - src.health -= Proj.damage - else - visible_message("\red [src] blocks [Proj] with its shield!") - return 0 - - -/mob/living/simple_animal/hostile/syndicate/melee/space - 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 - icon_state = "syndicatemeleespace" - icon_living = "syndicatemeleespace" - name = "Syndicate Commando" - corpse = /obj/effect/landmark/mobcorpse/syndicatecommando - speed = 0 - -/mob/living/simple_animal/hostile/syndicate/melee/space/Process_Spacemove(movement_dir = 0) - return - -/mob/living/simple_animal/hostile/syndicate/ranged - ranged = 1 - rapid = 1 - icon_state = "syndicateranged" - icon_living = "syndicateranged" - casingtype = /obj/item/ammo_casing/a12mm - projectilesound = 'sound/weapons/Gunshot_smg.ogg' - projectiletype = /obj/item/projectile/bullet/midbullet2 - retreat_distance = 5 - minimum_distance = 5 - - weapon1 = /obj/item/weapon/gun/projectile/automatic/c20r - -/mob/living/simple_animal/hostile/syndicate/ranged/space - icon_state = "syndicaterangedpsace" - icon_living = "syndicaterangedpsace" - name = "Syndicate Commando" - 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 - corpse = /obj/effect/landmark/mobcorpse/syndicatecommando - speed = 0 - -/mob/living/simple_animal/hostile/syndicate/ranged/space/Process_Spacemove(movement_dir = 0) - return - - - -/mob/living/simple_animal/hostile/viscerator - name = "viscerator" - desc = "A small, twin-bladed machine capable of inflicting very deadly lacerations." - icon = 'icons/mob/critter.dmi' - icon_state = "viscerator_attack" - icon_living = "viscerator_attack" - pass_flags = PASSTABLE - health = 15 - maxHealth = 15 - melee_damage_lower = 15 - melee_damage_upper = 15 - attacktext = "cuts" - attack_sound = 'sound/weapons/bladeslice.ogg' - faction = "syndicate" - 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 - -/mob/living/simple_animal/hostile/viscerator/death() - ..() - visible_message("\red [src] is smashed into pieces!") - qdel(src) - return +/mob/living/simple_animal/hostile/syndicate + name = "Syndicate Operative" + desc = "Death to Nanotrasen." + icon_state = "syndicate" + icon_living = "syndicate" + icon_dead = "syndicate_dead" + icon_gib = "syndicate_gib" + speak_chance = 0 + turns_per_move = 5 + response_help = "pokes the" + response_disarm = "shoves the" + response_harm = "hits the" + speed = 4 + stop_automated_movement_when_pulled = 0 + maxHealth = 100 + health = 100 + harm_intent_damage = 5 + melee_damage_lower = 10 + melee_damage_upper = 10 + attacktext = "punches" + a_intent = "harm" + var/corpse = /obj/effect/landmark/mobcorpse/syndicatesoldier + var/weapon1 + var/weapon2 + min_oxy = 5 + max_oxy = 0 + min_tox = 0 + max_tox = 1 + min_co2 = 0 + max_co2 = 5 + min_n2 = 0 + max_n2 = 0 + unsuitable_atoms_damage = 15 + environment_smash = 1 + faction = "syndicate" + status_flags = CANPUSH + +/mob/living/simple_animal/hostile/syndicate/death() + ..() + if(corpse) + new corpse (src.loc) + if(weapon1) + new weapon1 (src.loc) + if(weapon2) + new weapon2 (src.loc) + qdel(src) + return + +///////////////Sword and shield//////////// + +/mob/living/simple_animal/hostile/syndicate/melee + melee_damage_lower = 20 + melee_damage_upper = 25 + icon_state = "syndicatemelee" + icon_living = "syndicatemelee" + weapon1 = /obj/item/weapon/melee/energy/sword/red + weapon2 = /obj/item/weapon/shield/energy + attacktext = "slashes" + status_flags = 0 + +/mob/living/simple_animal/hostile/syndicate/melee/attackby(obj/item/O, mob/user) + user.SetNextMove(CLICK_CD_MELEE) + if(O.force) + if(prob(80)) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + health -= damage + visible_message("\red \b [src] has been attacked with the [O] by [user]. ") + else + visible_message("\red \b [src] blocks the [O] with its shield! ") + else + to_chat(usr, "\red This weapon is ineffective, it does no damage.") + visible_message("\red [user] gently taps [src] with the [O]. ") + + +/mob/living/simple_animal/hostile/syndicate/melee/bullet_act(obj/item/projectile/Proj) + if(!Proj) return + if(prob(65)) + src.health -= Proj.damage + else + visible_message("\red [src] blocks [Proj] with its shield!") + return 0 + + +/mob/living/simple_animal/hostile/syndicate/melee/space + 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 + icon_state = "syndicatemeleespace" + icon_living = "syndicatemeleespace" + name = "Syndicate Commando" + corpse = /obj/effect/landmark/mobcorpse/syndicatecommando + speed = 0 + +/mob/living/simple_animal/hostile/syndicate/melee/space/Process_Spacemove(movement_dir = 0) + return + +/mob/living/simple_animal/hostile/syndicate/ranged + ranged = 1 + rapid = 1 + icon_state = "syndicateranged" + icon_living = "syndicateranged" + casingtype = /obj/item/ammo_casing/a12mm + projectilesound = 'sound/weapons/Gunshot_smg.ogg' + projectiletype = /obj/item/projectile/bullet/midbullet2 + retreat_distance = 5 + minimum_distance = 5 + + weapon1 = /obj/item/weapon/gun/projectile/automatic/c20r + +/mob/living/simple_animal/hostile/syndicate/ranged/space + icon_state = "syndicaterangedpsace" + icon_living = "syndicaterangedpsace" + name = "Syndicate Commando" + 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 + corpse = /obj/effect/landmark/mobcorpse/syndicatecommando + speed = 0 + +/mob/living/simple_animal/hostile/syndicate/ranged/space/Process_Spacemove(movement_dir = 0) + return + + + +/mob/living/simple_animal/hostile/viscerator + name = "viscerator" + desc = "A small, twin-bladed machine capable of inflicting very deadly lacerations." + icon = 'icons/mob/critter.dmi' + icon_state = "viscerator_attack" + icon_living = "viscerator_attack" + pass_flags = PASSTABLE + health = 15 + maxHealth = 15 + melee_damage_lower = 15 + melee_damage_upper = 15 + attacktext = "cuts" + attack_sound = 'sound/weapons/bladeslice.ogg' + faction = "syndicate" + 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 + +/mob/living/simple_animal/hostile/viscerator/death() + ..() + visible_message("\red [src] is smashed into pieces!") + qdel(src) + return diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm index 08f1032ffd9a..688f577b72a7 100644 --- a/code/modules/mob/living/simple_animal/hostile/tree.dm +++ b/code/modules/mob/living/simple_animal/hostile/tree.dm @@ -1,56 +1,56 @@ -/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" - speak_chance = 0 - turns_per_move = 5 - response_help = "brushes the" - response_disarm = "pushes the" - response_harm = "hits the" - 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 = "carp" - -/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/death() - ..() - visible_message("\red [src] is hacked into pieces!") - new /obj/item/stack/sheet/wood(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" + speak_chance = 0 + turns_per_move = 5 + response_help = "brushes the" + response_disarm = "pushes the" + response_harm = "hits the" + 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 = "carp" + +/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/death() + ..() + visible_message("\red [src] is hacked into pieces!") + new /obj/item/stack/sheet/wood(loc) + qdel(src) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 5130ea2b1ecf..971440b9043e 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -1,839 +1,839 @@ -/* Parrots! - * Contains - * Defines - * Inventory (headset stuff) - * Attack responces - * AI - * Procs / Verbs (usable by players) - * Sub-types - */ - -/* - * 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 = "\improper 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 - small = 1 - - 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 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/cracker = 2) - - response_help = "pets the" - response_disarm = "gently moves aside the" - response_harm = "swats the" - stop_automated_movement = 1 - universal_speak = 1 - - 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(BP_CHEST , BP_HEAD , BP_L_ARM , BP_L_LEG , BP_R_ARM , BP_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 //Parrots get a speed bonus after being shot. This will deincrement every Life() and at 0 the parrot will return to regular speed. - - 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 pertch 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/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 - - -/mob/living/simple_animal/parrot/atom_init() - . = ..() - 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/death() - 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) - -/* - * 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(entity_ja(dat), text("window=mob[];size=325x500", name)) - onclose(user, "mob[real_name]") - return - -/mob/living/simple_animal/parrot/Topic(href, href_list) - - //Can the usr physically do this? - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - 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(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,length(possible_phrase)) - else - to_chat(usr, "\red 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, "\red You have nothing in your hand to put on its [add_to].") - return - switch(add_to) - if("ears") - if(ears) - to_chat(usr, "\red 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, "\red This object won't fit.") - return - - var/obj/item/device/radio/headset/headset_to_add = item_to_add - - usr.drop_item() - headset_to_add.loc = 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) - ..() - if(client) return - if(!stat && M.a_intent == "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) - attack_hand(M) - -/mob/living/simple_animal/parrot/attack_alien(mob/living/carbon/monkey/M) - attack_hand(M) - -//Simple animals -/mob/living/simple_animal/parrot/attack_animal(mob/living/simple_animal/M) - if(client) return - if(..()) - 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) - 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(obj/item/O, mob/user) - ..() - if(!stat && !client && !istype(O, /obj/item/stack/medical)) - 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 | PARROT_FLEE - icon_state = "parrot_fly" - drop_held_item(0) - return - -//Bullets -/mob/living/simple_animal/parrot/bullet_act(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 //OWFUCK, Been shot! 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() - ..() - - //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 || buckled) - return //If it can't move, dont let it move. (The buckled check probably isn't necessary thanks to canmove) - - -//-----SPEECH - /* Parrot speech mimickry! - Phrases that the parrot hears in mob/living/say() get added to speach_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,length(possible_phrase)+1)]" //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(in_range(src, 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 the [held_item]!", "\blue You grab the [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) - 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(in_range(src, 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) - 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-parrot_been_shot) - parrot_been_shot-- - 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 the mob is close enough to interact with - if(in_range(src, 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 - - //Time for the hurt to begin! - var/damage = rand(5,10) - - if(ishuman(parrot_interest)) - var/mob/living/carbon/human/H = parrot_interest - var/obj/item/organ/external/BP = H.bodyparts_by_name[ran_zone(pick(parrot_dam_zone))] - - H.apply_damage(damage, BRUTE, BP, H.run_armor_check(BP, "melee"), DAM_SHARP) - emote(pick("pecks [H]'s [BP.name]", "cuts [H]'s [BP.name] with its talons")) - - else - L.adjustBruteLoss(damage) - emote(pick("pecks at [L]", "claws [L]")) - return - - //Otherwise, fly towards the mob! - else - walk_to(src, parrot_interest, 1, parrot_speed) - 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/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, "\red You are already holding the [held_item]") - return 1 - - for(var/obj/item/I in view(1,src)) - //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 the [held_item]!", "\blue You grab the [held_item]!", "You hear the sounds of wings flapping furiously.") - return held_item - - to_chat(src, "\red 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, "\red You are already holding the [held_item]") - return 1 - - var/obj/item/stolen_item = null - - for(var/mob/living/carbon/C in view(1,src)) - 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.remove_from_mob(stolen_item) - held_item = stolen_item - stolen_item.loc = src - visible_message("[src] grabs the [held_item] out of [C]'s hand!", "\blue You snag the [held_item] out of [C]'s hand!", "You hear the sounds of wings flapping furiously.") - return held_item - - to_chat(src, "\red 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(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) - to_chat(usr, "\red You have nothing to drop!") - return 0 - - 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 the [held_item]!") - held_item = null - return 1 - - to_chat(src, "You drop the [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)) - for(var/perch_path in desired_perches) - if(istype(AM, perch_path)) - src.loc = AM.loc - icon_state = "parrot_sit" - return - to_chat(src, "\red There is no perch nearby to sit on.") - 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 LOOSE CALL THE SHUTTLE") - speak_chance = 3 - var/memory_saved = 0 - var/rounds_survived = 0 - var/longest_survival = 0 - var/longest_deathstreak = 0 - -/mob/living/simple_animal/parrot/Poly/atom_init() - ears = new /obj/item/device/radio/headset/headset_eng(src) - available_channels = list(":e") - Read_Memory() - if(rounds_survived == longest_survival) - speak += pick("...[longest_survival].", "The things I have seen!", "I have lived many lives!", "What are you before me?") - desc += " Old as sin, and just as loud. Claimed to be [rounds_survived]." - speak_chance = 20 //His hubris has made him more annoying/easier to justify killing - color = "#EEEE22" - else if(rounds_survived == longest_deathstreak) - speak += pick("What are you waiting for!", "Violence breeds violence!", "Blood! Blood!", "Strike me down if you dare!") - desc += " The squawks of [-rounds_survived] dead parrots ring out in your ears..." - color = "#BB7777" - else if(rounds_survived > 0) - speak += pick("...again?", "No, It was over!", "Let me out!", "It never ends!") - desc += " Over [rounds_survived] shifts without a \"terrible\" \"accident\"!" - else - speak += pick("...alive?", "This isn't parrot heaven!", "I live, I die, I live again!", "The void fades!") - . = ..() - -/mob/living/simple_animal/parrot/Poly/Life() - if(!stat && ticker.current_state == GAME_STATE_FINISHED && !memory_saved) - rounds_survived = max(++rounds_survived,1) - if(rounds_survived > longest_survival) - longest_survival = rounds_survived - Write_Memory() - ..() - -/mob/living/simple_animal/parrot/Poly/death(gibbed) - if(!memory_saved) - var/go_ghost = 0 - if(rounds_survived == longest_survival || rounds_survived == longest_deathstreak) - go_ghost = 1 - rounds_survived = min(--rounds_survived,0) - if(rounds_survived < longest_deathstreak) - longest_deathstreak = rounds_survived - Write_Memory() - if(go_ghost) - var/mob/living/simple_animal/parrot/Poly/ghost/G = new(loc) - if(mind) - mind.transfer_to(G) - else - G.key = key - ..(gibbed) - -/mob/living/simple_animal/parrot/Poly/proc/Read_Memory() - var/savefile/S = new /savefile("data/npc_saves/Poly.sav") - S["phrases"] >> speech_buffer - S["roundssurvived"] >> rounds_survived - S["longestsurvival"] >> longest_survival - S["longestdeathstreak"] >> longest_deathstreak - - if(isnull(speech_buffer)) - speech_buffer = list() - else - if(speech_buffer.len) - speak += pick(speech_buffer) - -/mob/living/simple_animal/parrot/Poly/proc/Write_Memory() - var/savefile/S = new /savefile("data/npc_saves/Poly.sav") - S["phrases"] << speech_buffer - S["roundssurvived"] << rounds_survived - S["longestsurvival"] << longest_survival - S["longestdeathstreak"] << longest_deathstreak - memory_saved = 1 - -/mob/living/simple_animal/parrot/Poly/ghost - name = "The Ghost of Poly" - desc = "Doomed to squawk the earth." - color = "#FFFFFF77" - speak_chance = 20 - status_flags = GODMODE - incorporeal_move = 1 - butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/ectoplasm = 1) - -/mob/living/simple_animal/parrot/Poly/ghost/atom_init() - memory_saved = 1 //At this point nothing is saved - . = ..() - -/mob/living/simple_animal/parrot/say(var/message) - - if(stat) - return - - var/verb = "says" - if(speak_emote.len) - verb = pick(speak_emote) - - - var/message_mode="" - if(copytext(message,1,2) == ";") - message_mode = "headset" - message = copytext(message,2) - - if(length(message) >= 2) - var/channel_prefix = copytext(message, 1 ,3) - message_mode = department_radio_keys[channel_prefix] - - if(copytext(message,1,2) == ":") - var/positioncut = 3 - message = trim(copytext(message,positioncut)) - - message = capitalize(trim_left(message)) - - if(message_mode) - if(message_mode in radiochannels) - if(ears && istype(ears,/obj/item/device/radio)) - ears.talk_into(src,message, message_mode, verb, null) - - - ..(message) - - -/mob/living/simple_animal/parrot/hear_say(message, verb = "says", datum/language/language = null, alt_name = "",italics = 0, mob/speaker = null) - if(speaker != src) - parrot_hear(message) - ..(message,verb,language,alt_name,italics,speaker) - - - -/mob/living/simple_animal/parrot/hear_radio(message, verb="says", datum/language/language=null, part_a, part_b, mob/speaker = null, hard_to_hear = 0) - if(speaker != src) - parrot_hear("[pick(available_channels)] [message]") - ..(message,verb,language,part_a,part_b,speaker,hard_to_hear) - - -/mob/living/simple_animal/parrot/proc/parrot_hear(message="") - if(!message || stat) - return - speech_buffer.Add(message) +/* Parrots! + * Contains + * Defines + * Inventory (headset stuff) + * Attack responces + * AI + * Procs / Verbs (usable by players) + * Sub-types + */ + +/* + * 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 = "\improper 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 + small = 1 + + 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 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/cracker = 2) + + response_help = "pets the" + response_disarm = "gently moves aside the" + response_harm = "swats the" + stop_automated_movement = 1 + universal_speak = 1 + + 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(BP_CHEST , BP_HEAD , BP_L_ARM , BP_L_LEG , BP_R_ARM , BP_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 //Parrots get a speed bonus after being shot. This will deincrement every Life() and at 0 the parrot will return to regular speed. + + 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 pertch 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/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 + + +/mob/living/simple_animal/parrot/atom_init() + . = ..() + 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/death() + 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) + +/* + * 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(entity_ja(dat), text("window=mob[];size=325x500", name)) + onclose(user, "mob[real_name]") + return + +/mob/living/simple_animal/parrot/Topic(href, href_list) + + //Can the usr physically do this? + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + 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(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,length(possible_phrase)) + else + to_chat(usr, "\red 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, "\red You have nothing in your hand to put on its [add_to].") + return + switch(add_to) + if("ears") + if(ears) + to_chat(usr, "\red 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, "\red This object won't fit.") + return + + var/obj/item/device/radio/headset/headset_to_add = item_to_add + + usr.drop_item() + headset_to_add.loc = 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) + ..() + if(client) return + if(!stat && M.a_intent == "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) + attack_hand(M) + +/mob/living/simple_animal/parrot/attack_alien(mob/living/carbon/monkey/M) + attack_hand(M) + +//Simple animals +/mob/living/simple_animal/parrot/attack_animal(mob/living/simple_animal/M) + if(client) return + if(..()) + 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) + 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(obj/item/O, mob/user) + ..() + if(!stat && !client && !istype(O, /obj/item/stack/medical)) + 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 | PARROT_FLEE + icon_state = "parrot_fly" + drop_held_item(0) + return + +//Bullets +/mob/living/simple_animal/parrot/bullet_act(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 //OWFUCK, Been shot! 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() + ..() + + //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 || buckled) + return //If it can't move, dont let it move. (The buckled check probably isn't necessary thanks to canmove) + + +//-----SPEECH + /* Parrot speech mimickry! + Phrases that the parrot hears in mob/living/say() get added to speach_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,length(possible_phrase)+1)]" //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(in_range(src, 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 the [held_item]!", "\blue You grab the [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) + 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(in_range(src, 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) + 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-parrot_been_shot) + parrot_been_shot-- + 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 the mob is close enough to interact with + if(in_range(src, 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 + + //Time for the hurt to begin! + var/damage = rand(5,10) + + if(ishuman(parrot_interest)) + var/mob/living/carbon/human/H = parrot_interest + var/obj/item/organ/external/BP = H.bodyparts_by_name[ran_zone(pick(parrot_dam_zone))] + + H.apply_damage(damage, BRUTE, BP, H.run_armor_check(BP, "melee"), DAM_SHARP) + emote(pick("pecks [H]'s [BP.name]", "cuts [H]'s [BP.name] with its talons")) + + else + L.adjustBruteLoss(damage) + emote(pick("pecks at [L]", "claws [L]")) + return + + //Otherwise, fly towards the mob! + else + walk_to(src, parrot_interest, 1, parrot_speed) + 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/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, "\red You are already holding the [held_item]") + return 1 + + for(var/obj/item/I in view(1,src)) + //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 the [held_item]!", "\blue You grab the [held_item]!", "You hear the sounds of wings flapping furiously.") + return held_item + + to_chat(src, "\red 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, "\red You are already holding the [held_item]") + return 1 + + var/obj/item/stolen_item = null + + for(var/mob/living/carbon/C in view(1,src)) + 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.remove_from_mob(stolen_item) + held_item = stolen_item + stolen_item.loc = src + visible_message("[src] grabs the [held_item] out of [C]'s hand!", "\blue You snag the [held_item] out of [C]'s hand!", "You hear the sounds of wings flapping furiously.") + return held_item + + to_chat(src, "\red 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(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) + to_chat(usr, "\red You have nothing to drop!") + return 0 + + 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 the [held_item]!") + held_item = null + return 1 + + to_chat(src, "You drop the [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)) + for(var/perch_path in desired_perches) + if(istype(AM, perch_path)) + src.loc = AM.loc + icon_state = "parrot_sit" + return + to_chat(src, "\red There is no perch nearby to sit on.") + 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 LOOSE CALL THE SHUTTLE") + speak_chance = 3 + var/memory_saved = 0 + var/rounds_survived = 0 + var/longest_survival = 0 + var/longest_deathstreak = 0 + +/mob/living/simple_animal/parrot/Poly/atom_init() + ears = new /obj/item/device/radio/headset/headset_eng(src) + available_channels = list(":e") + Read_Memory() + if(rounds_survived == longest_survival) + speak += pick("...[longest_survival].", "The things I have seen!", "I have lived many lives!", "What are you before me?") + desc += " Old as sin, and just as loud. Claimed to be [rounds_survived]." + speak_chance = 20 //His hubris has made him more annoying/easier to justify killing + color = "#EEEE22" + else if(rounds_survived == longest_deathstreak) + speak += pick("What are you waiting for!", "Violence breeds violence!", "Blood! Blood!", "Strike me down if you dare!") + desc += " The squawks of [-rounds_survived] dead parrots ring out in your ears..." + color = "#BB7777" + else if(rounds_survived > 0) + speak += pick("...again?", "No, It was over!", "Let me out!", "It never ends!") + desc += " Over [rounds_survived] shifts without a \"terrible\" \"accident\"!" + else + speak += pick("...alive?", "This isn't parrot heaven!", "I live, I die, I live again!", "The void fades!") + . = ..() + +/mob/living/simple_animal/parrot/Poly/Life() + if(!stat && ticker.current_state == GAME_STATE_FINISHED && !memory_saved) + rounds_survived = max(++rounds_survived,1) + if(rounds_survived > longest_survival) + longest_survival = rounds_survived + Write_Memory() + ..() + +/mob/living/simple_animal/parrot/Poly/death(gibbed) + if(!memory_saved) + var/go_ghost = 0 + if(rounds_survived == longest_survival || rounds_survived == longest_deathstreak) + go_ghost = 1 + rounds_survived = min(--rounds_survived,0) + if(rounds_survived < longest_deathstreak) + longest_deathstreak = rounds_survived + Write_Memory() + if(go_ghost) + var/mob/living/simple_animal/parrot/Poly/ghost/G = new(loc) + if(mind) + mind.transfer_to(G) + else + G.key = key + ..(gibbed) + +/mob/living/simple_animal/parrot/Poly/proc/Read_Memory() + var/savefile/S = new /savefile("data/npc_saves/Poly.sav") + S["phrases"] >> speech_buffer + S["roundssurvived"] >> rounds_survived + S["longestsurvival"] >> longest_survival + S["longestdeathstreak"] >> longest_deathstreak + + if(isnull(speech_buffer)) + speech_buffer = list() + else + if(speech_buffer.len) + speak += pick(speech_buffer) + +/mob/living/simple_animal/parrot/Poly/proc/Write_Memory() + var/savefile/S = new /savefile("data/npc_saves/Poly.sav") + S["phrases"] << speech_buffer + S["roundssurvived"] << rounds_survived + S["longestsurvival"] << longest_survival + S["longestdeathstreak"] << longest_deathstreak + memory_saved = 1 + +/mob/living/simple_animal/parrot/Poly/ghost + name = "The Ghost of Poly" + desc = "Doomed to squawk the earth." + color = "#FFFFFF77" + speak_chance = 20 + status_flags = GODMODE + incorporeal_move = 1 + butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/ectoplasm = 1) + +/mob/living/simple_animal/parrot/Poly/ghost/atom_init() + memory_saved = 1 //At this point nothing is saved + . = ..() + +/mob/living/simple_animal/parrot/say(var/message) + + if(stat) + return + + var/verb = "says" + if(speak_emote.len) + verb = pick(speak_emote) + + + var/message_mode="" + if(copytext(message,1,2) == ";") + message_mode = "headset" + message = copytext(message,2) + + if(length(message) >= 2) + var/channel_prefix = copytext(message, 1 ,3) + message_mode = department_radio_keys[channel_prefix] + + if(copytext(message,1,2) == ":") + var/positioncut = 3 + message = trim(copytext(message,positioncut)) + + message = capitalize(trim_left(message)) + + if(message_mode) + if(message_mode in radiochannels) + if(ears && istype(ears,/obj/item/device/radio)) + ears.talk_into(src,message, message_mode, verb, null) + + + ..(message) + + +/mob/living/simple_animal/parrot/hear_say(message, verb = "says", datum/language/language = null, alt_name = "",italics = 0, mob/speaker = null) + if(speaker != src) + parrot_hear(message) + ..(message,verb,language,alt_name,italics,speaker) + + + +/mob/living/simple_animal/parrot/hear_radio(message, verb="says", datum/language/language=null, part_a, part_b, mob/speaker = null, hard_to_hear = 0) + if(speaker != src) + parrot_hear("[pick(available_channels)] [message]") + ..(message,verb,language,part_a,part_b,speaker,hard_to_hear) + + +/mob/living/simple_animal/parrot/proc/parrot_hear(message="") + if(!message || stat) + return + speech_buffer.Add(message) diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index fff2e6a7ba3f..4296a45a3a69 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -1,61 +1,61 @@ -/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 - universal_speak = 1 - speak_emote = list("hisses") - emote_hear = list("wails","screeches") - response_help = "puts their hand through" - response_disarm = "flails at" - response_harm = "punches the" - 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 - - - Life() - ..() - if(stat == DEAD) - new /obj/item/weapon/reagent_containers/food/snacks/ectoplasm(loc) - for(var/mob/M in viewers(src, null)) - if((M.client && !( M.blinded ))) - M.show_message("\red [src] lets out a contented sigh as their form unwinds. ") - ghostize(bancheck = TRUE) - qdel(src) - return - - - attackby(obj/item/O, mob/user) //Marker -Agouri - 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 - health -= damage - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red \b [src] has been attacked with the [O] by [user]. ") - else - to_chat(usr, "\red This weapon is ineffective, it does no damage.") - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\red [user] gently taps [src] with the [O]. ") - return +/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 + universal_speak = 1 + speak_emote = list("hisses") + emote_hear = list("wails","screeches") + response_help = "puts their hand through" + response_disarm = "flails at" + response_harm = "punches the" + 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 + + + Life() + ..() + if(stat == DEAD) + new /obj/item/weapon/reagent_containers/food/snacks/ectoplasm(loc) + for(var/mob/M in viewers(src, null)) + if((M.client && !( M.blinded ))) + M.show_message("\red [src] lets out a contented sigh as their form unwinds. ") + ghostize(bancheck = TRUE) + qdel(src) + return + + + attackby(obj/item/O, mob/user) //Marker -Agouri + 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 + health -= damage + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b [src] has been attacked with the [O] by [user]. ") + else + to_chat(usr, "\red This weapon is ineffective, it does no damage.") + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red [user] gently taps [src] with the [O]. ") + return diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 8c62d121ce77..13de63585f0c 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -1,452 +1,452 @@ -/mob/living/simple_animal - name = "animal" - icon = 'icons/mob/animal.dmi' - health = 20 - maxHealth = 20 - - 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/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 - universal_speak = 0 //No, just no. - 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 = "tries to help" - var/response_disarm = "tries to disarm" - var/response_harm = "tries to hurt" - 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 - - //Atmos effect - Yes, you can make creatures that require phoron 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 - - - //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/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 - -/mob/living/simple_animal/updatehealth() - return - -/mob/living/simple_animal/Life() - - //Health - if(stat == DEAD) - if(health > 0) - icon_state = icon_living - dead_mob_list -= src - alive_mob_list += src - stat = CONSCIOUS - density = 1 - return 0 - - - if(health < 1) - health = 0 - death() - - if(health > maxHealth) - health = maxHealth - - if(stunned) - AdjustStunned(-1) - if(weakened) - AdjustWeakened(-1) - if(paralysis) - AdjustParalysis(-1) - - //Movement - if(!client && !stop_automated_movement && wander && !anchored) - if(isturf(src.loc) && !resting && !buckled && 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/anydir = pick(cardinal) - if(Process_Spacemove(anydir)) - Move(get_step(src,anydir), anydir) - turns_since_move = 0 - - //Speaking - if(!client && speak_chance) - 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 - var/atmos_suitable = 1 - - var/atom/A = src.loc - if(isturf(A)) - var/turf/T = A - var/areatemp = T.temperature - if( abs(areatemp - bodytemperature) > 40 ) - var/diff = areatemp - bodytemperature - diff = diff / 5 - //world << "changed from [bodytemperature] by [diff] to [bodytemperature + diff]" - bodytemperature += diff - - if(istype(T,/turf/simulated)) - var/turf/simulated/ST = T - if(ST.air) - var/tox = ST.air.gas["phoron"] - var/oxy = ST.air.gas["oxygen"] - var/n2 = ST.air.gas["nitrogen"] - var/co2 = ST.air.gas["carbon_dioxide"] - - if(min_oxy) - if(oxy < min_oxy) - atmos_suitable = 0 - if(max_oxy) - if(oxy > max_oxy) - atmos_suitable = 0 - if(min_tox) - if(tox < min_tox) - atmos_suitable = 0 - if(max_tox) - if(tox > max_tox) - atmos_suitable = 0 - if(min_n2) - if(n2 < min_n2) - atmos_suitable = 0 - if(max_n2) - if(n2 > max_n2) - atmos_suitable = 0 - if(min_co2) - if(co2 < min_co2) - atmos_suitable = 0 - if(max_co2) - if(co2 > max_co2) - atmos_suitable = 0 - - //Atmos effect - if(bodytemperature < minbodytemp) - adjustBruteLoss(cold_damage_per_tick) - else if(bodytemperature > maxbodytemp) - adjustBruteLoss(heat_damage_per_tick) - - if(!atmos_suitable) - adjustBruteLoss(unsuitable_atoms_damage) - return 1 - -/mob/living/simple_animal/gib() - if(icon_gib) - flick(icon_gib, src) - if(butcher_results) - for(var/path in butcher_results) - for(var/i = 0 to butcher_results[path]) - new path(loc) - ..() - -/mob/living/simple_animal/emote(act, type, desc) - if(act) - if(act == "scream") act = "whimper" //ugly hack to stop animals screaming when crushed :P - ..(act, type, desc) - -/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M) - if(src == M) - return TRUE - ..() - if(M.melee_damage_upper == 0) - M.emote("[M.friendly] [src]") - return TRUE - else - if(M.attack_sound) - playsound(loc, M.attack_sound, 50, 1, 1) - visible_message("[M][M.attacktext] [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) - adjustBruteLoss(damage) - return TRUE - return FALSE - -/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj) - if(!Proj) return - adjustBruteLoss(Proj.damage) - return 0 - -/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M) - ..() - - switch(M.a_intent) - - if("help") - if (health > 0) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\blue [M] [response_help] [src]") - - if("grab") - if (M == src || anchored || M.lying) - return - if (!(status_flags & CANPUSH)) - return - - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - LAssailant = M - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) - - if("hurt", "disarm") - M.do_attack_animation(src) - adjustBruteLoss(harm_intent_damage) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [M] [response_harm] [src]") - - return - -/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M) - - switch(M.a_intent) - - if ("help") - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) - if ("grab") - if(M == src || anchored || M.lying) - return - if(!(status_flags & CANPUSH)) - return - - var/obj/item/weapon/grab/G = new /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)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) - - if("hurt", "disarm") - var/damage = rand(15, 30) - visible_message("\red [M] has slashed at [src]!") - adjustBruteLoss(damage) - - return - -/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L) - - switch(L.a_intent) - if("help") - visible_message("\blue [L] rubs it's head against [src]") - - - else - - var/damage = rand(5, 10) - visible_message("\red [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) - 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("\red The [M.name] glomps [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) - - - return - - -/mob/living/simple_animal/attackby(obj/item/O, mob/user) //Marker -Agouri - if(istype(O, /obj/item/stack/medical)) - if(stat != DEAD) - var/obj/item/stack/medical/MED = O - if(health < maxHealth && MED.use(1)) - adjustBruteLoss(-MED.heal_brute) - src.visible_message("[user] applies the [MED] on [src]") - else - to_chat(user, " this [src] is dead, medical items won't bring it back to life.") - user.SetNextMove(CLICK_CD_MELEE) - ..() - - -/mob/living/simple_animal/movement_delay() - var/tally = 0 //Incase I need to add stuff other than "speed" later - - tally = speed - - return tally+config.animal_delay - -/mob/living/simple_animal/Stat() - ..() - - if(statpanel("Status")) - stat(null, "Health: [round((health / maxHealth) * 100)]%") - -/mob/living/simple_animal/death() - icon_state = icon_dead - stat = DEAD - health = 0 - density = 0 - return ..() - -/mob/living/simple_animal/ex_act(severity) - if(!blinded) - flash_eyes() - 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) - -/mob/living/simple_animal/proc/SA_attackable(target_mob) - if (isliving(target_mob)) - var/mob/living/L = target_mob - if(!L.stat && L.health >= 0) - return (0) - if (istype(target_mob,/obj/mecha)) - var/obj/mecha/M = target_mob - if (M.occupant) - return (0) - if (istype(target_mob,/obj/machinery/bot)) - var/obj/machinery/bot/B = target_mob - 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) - qdel(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/proc/CanAttack(atom/the_target) - if(see_invisible < the_target.invisibility) - return 0 - if (isliving(the_target)) - var/mob/living/L = the_target - if(L.stat != CONSCIOUS) - return 0 - if (istype(the_target, /obj/mecha)) - var/obj/mecha/M = the_target - if (M.occupant) - return 0 - return 1 - -/mob/living/simple_animal/say(var/message) - if(stat) - return - - message = sanitize(message) - - if(copytext(message,1,2) == "*") - return emote(copytext(message,2)) - - if(stat) - return - - var/verb = "says" - - if(speak_emote.len) - verb = pick(speak_emote) - - message = capitalize(trim_left(message)) - - ..(message, null, verb, sanitize = 0) +/mob/living/simple_animal + name = "animal" + icon = 'icons/mob/animal.dmi' + health = 20 + maxHealth = 20 + + 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/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 + universal_speak = 0 //No, just no. + 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 = "tries to help" + var/response_disarm = "tries to disarm" + var/response_harm = "tries to hurt" + 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 + + //Atmos effect - Yes, you can make creatures that require phoron 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 + + + //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/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 + +/mob/living/simple_animal/updatehealth() + return + +/mob/living/simple_animal/Life() + + //Health + if(stat == DEAD) + if(health > 0) + icon_state = icon_living + dead_mob_list -= src + alive_mob_list += src + stat = CONSCIOUS + density = 1 + return 0 + + + if(health < 1) + health = 0 + death() + + if(health > maxHealth) + health = maxHealth + + if(stunned) + AdjustStunned(-1) + if(weakened) + AdjustWeakened(-1) + if(paralysis) + AdjustParalysis(-1) + + //Movement + if(!client && !stop_automated_movement && wander && !anchored) + if(isturf(src.loc) && !resting && !buckled && 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/anydir = pick(cardinal) + if(Process_Spacemove(anydir)) + Move(get_step(src,anydir), anydir) + turns_since_move = 0 + + //Speaking + if(!client && speak_chance) + 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 + var/atmos_suitable = 1 + + var/atom/A = src.loc + if(isturf(A)) + var/turf/T = A + var/areatemp = T.temperature + if( abs(areatemp - bodytemperature) > 40 ) + var/diff = areatemp - bodytemperature + diff = diff / 5 + //world << "changed from [bodytemperature] by [diff] to [bodytemperature + diff]" + bodytemperature += diff + + if(istype(T,/turf/simulated)) + var/turf/simulated/ST = T + if(ST.air) + var/tox = ST.air.gas["phoron"] + var/oxy = ST.air.gas["oxygen"] + var/n2 = ST.air.gas["nitrogen"] + var/co2 = ST.air.gas["carbon_dioxide"] + + if(min_oxy) + if(oxy < min_oxy) + atmos_suitable = 0 + if(max_oxy) + if(oxy > max_oxy) + atmos_suitable = 0 + if(min_tox) + if(tox < min_tox) + atmos_suitable = 0 + if(max_tox) + if(tox > max_tox) + atmos_suitable = 0 + if(min_n2) + if(n2 < min_n2) + atmos_suitable = 0 + if(max_n2) + if(n2 > max_n2) + atmos_suitable = 0 + if(min_co2) + if(co2 < min_co2) + atmos_suitable = 0 + if(max_co2) + if(co2 > max_co2) + atmos_suitable = 0 + + //Atmos effect + if(bodytemperature < minbodytemp) + adjustBruteLoss(cold_damage_per_tick) + else if(bodytemperature > maxbodytemp) + adjustBruteLoss(heat_damage_per_tick) + + if(!atmos_suitable) + adjustBruteLoss(unsuitable_atoms_damage) + return 1 + +/mob/living/simple_animal/gib() + if(icon_gib) + flick(icon_gib, src) + if(butcher_results) + for(var/path in butcher_results) + for(var/i = 0 to butcher_results[path]) + new path(loc) + ..() + +/mob/living/simple_animal/emote(act, type, desc) + if(act) + if(act == "scream") act = "whimper" //ugly hack to stop animals screaming when crushed :P + ..(act, type, desc) + +/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M) + if(src == M) + return TRUE + ..() + if(M.melee_damage_upper == 0) + M.emote("[M.friendly] [src]") + return TRUE + else + if(M.attack_sound) + playsound(loc, M.attack_sound, 50, 1, 1) + visible_message("[M][M.attacktext] [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) + adjustBruteLoss(damage) + return TRUE + return FALSE + +/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj) + if(!Proj) return + adjustBruteLoss(Proj.damage) + return 0 + +/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M) + ..() + + switch(M.a_intent) + + if("help") + if (health > 0) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\blue [M] [response_help] [src]") + + if("grab") + if (M == src || anchored || M.lying) + return + if (!(status_flags & CANPUSH)) + return + + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + LAssailant = M + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + + if("hurt", "disarm") + M.do_attack_animation(src) + adjustBruteLoss(harm_intent_damage) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\red [M] [response_harm] [src]") + + return + +/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M) + + switch(M.a_intent) + + if ("help") + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) + if ("grab") + if(M == src || anchored || M.lying) + return + if(!(status_flags & CANPUSH)) + return + + var/obj/item/weapon/grab/G = new /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)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + + if("hurt", "disarm") + var/damage = rand(15, 30) + visible_message("\red [M] has slashed at [src]!") + adjustBruteLoss(damage) + + return + +/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L) + + switch(L.a_intent) + if("help") + visible_message("\blue [L] rubs it's head against [src]") + + + else + + var/damage = rand(5, 10) + visible_message("\red [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) + 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("\red The [M.name] glomps [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) + + + return + + +/mob/living/simple_animal/attackby(obj/item/O, mob/user) //Marker -Agouri + if(istype(O, /obj/item/stack/medical)) + if(stat != DEAD) + var/obj/item/stack/medical/MED = O + if(health < maxHealth && MED.use(1)) + adjustBruteLoss(-MED.heal_brute) + src.visible_message("[user] applies the [MED] on [src]") + else + to_chat(user, " this [src] is dead, medical items won't bring it back to life.") + user.SetNextMove(CLICK_CD_MELEE) + ..() + + +/mob/living/simple_animal/movement_delay() + var/tally = 0 //Incase I need to add stuff other than "speed" later + + tally = speed + + return tally+config.animal_delay + +/mob/living/simple_animal/Stat() + ..() + + if(statpanel("Status")) + stat(null, "Health: [round((health / maxHealth) * 100)]%") + +/mob/living/simple_animal/death() + icon_state = icon_dead + stat = DEAD + health = 0 + density = 0 + return ..() + +/mob/living/simple_animal/ex_act(severity) + if(!blinded) + flash_eyes() + 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) + +/mob/living/simple_animal/proc/SA_attackable(target_mob) + if (isliving(target_mob)) + var/mob/living/L = target_mob + if(!L.stat && L.health >= 0) + return (0) + if (istype(target_mob,/obj/mecha)) + var/obj/mecha/M = target_mob + if (M.occupant) + return (0) + if (istype(target_mob,/obj/machinery/bot)) + var/obj/machinery/bot/B = target_mob + 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) + qdel(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/proc/CanAttack(atom/the_target) + if(see_invisible < the_target.invisibility) + return 0 + if (isliving(the_target)) + var/mob/living/L = the_target + if(L.stat != CONSCIOUS) + return 0 + if (istype(the_target, /obj/mecha)) + var/obj/mecha/M = the_target + if (M.occupant) + return 0 + return 1 + +/mob/living/simple_animal/say(var/message) + if(stat) + return + + message = sanitize(message) + + if(copytext(message,1,2) == "*") + return emote(copytext(message,2)) + + if(stat) + return + + var/verb = "says" + + if(speak_emote.len) + verb = pick(speak_emote) + + message = capitalize(trim_left(message)) + + ..(message, null, verb, sanitize = 0) diff --git a/code/modules/mob/living/simple_animal/worm.dm b/code/modules/mob/living/simple_animal/worm.dm index fc3b1d95ac02..45e5339e0775 100644 --- a/code/modules/mob/living/simple_animal/worm.dm +++ b/code/modules/mob/living/simple_animal/worm.dm @@ -1,201 +1,201 @@ -/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 - - universal_speak =1 - - stop_automated_movement = 1 - animate_movement = SYNC_STEPS - - minbodytemp = 0 - maxbodytemp = 350 - min_oxy = 0 - max_co2 = 0 - max_tox = 0 - - a_intent = "harm" //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 - -/mob/living/simple_animal/space_worm/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 - -/mob/living/simple_animal/space_worm/head/atom_init(mapload, 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 - -/mob/living/simple_animal/space_worm/head/update_icon() - if(stat == CONSCIOUS || stat == UNCONSCIOUS) - icon_state = "spacewormhead[previous?1:0]" - if(previous) - dir = get_dir(previous,src) - else - icon_state = "spacewormheaddead" - -/mob/living/simple_animal/space_worm/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 - -/mob/living/simple_animal/space_worm/Destroy() //if a chunk a destroyed, make a new worm out of the split halves - if(previous) - previous.Detach() - return ..() - -/mob/living/simple_animal/space_worm/Move() - var/attachementNextPosition = loc - if(..()) - if(previous) - previous.Move(attachementNextPosition) - update_icon() - -/mob/living/simple_animal/space_worm/Bump(atom/obstacle) - if(currentlyEating != obstacle) - currentlyEating = obstacle - eatingDuration = 0 - - if(!AttemptToEat(obstacle)) - eatingDuration++ - else - currentlyEating = null - eatingDuration = 0 - - return - -/mob/living/simple_animal/space_worm/proc/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 - -/mob/living/simple_animal/space_worm/proc/AttemptToEat(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) - new /obj/item/stack/sheet/metal(src, 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 - -/mob/living/simple_animal/space_worm/proc/Attach(mob/living/simple_animal/space_worm/attachement) - if(!attachement) - return - - previous = attachement - attachement.next = src - - return - -/mob/living/simple_animal/space_worm/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.death() - - qdel(src) - -/mob/living/simple_animal/space_worm/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/phoron)) - var/obj/item/stack/oldStack = stomachContent - new /obj/item/stack/sheet/mineral/phoron(src, oldStack.get_amount()) - qdel(oldStack) - 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/phoron(src, oldItem.w_class) - qdel(oldItem) - continue - else - new /obj/item/stack/sheet/mineral/phoron(src, flatPlasmaValue) //just flat amount - qdel(stomachContent) - 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 + + universal_speak =1 + + stop_automated_movement = 1 + animate_movement = SYNC_STEPS + + minbodytemp = 0 + maxbodytemp = 350 + min_oxy = 0 + max_co2 = 0 + max_tox = 0 + + a_intent = "harm" //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 + +/mob/living/simple_animal/space_worm/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 + +/mob/living/simple_animal/space_worm/head/atom_init(mapload, 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 + +/mob/living/simple_animal/space_worm/head/update_icon() + if(stat == CONSCIOUS || stat == UNCONSCIOUS) + icon_state = "spacewormhead[previous?1:0]" + if(previous) + dir = get_dir(previous,src) + else + icon_state = "spacewormheaddead" + +/mob/living/simple_animal/space_worm/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 + +/mob/living/simple_animal/space_worm/Destroy() //if a chunk a destroyed, make a new worm out of the split halves + if(previous) + previous.Detach() + return ..() + +/mob/living/simple_animal/space_worm/Move() + var/attachementNextPosition = loc + if(..()) + if(previous) + previous.Move(attachementNextPosition) + update_icon() + +/mob/living/simple_animal/space_worm/Bump(atom/obstacle) + if(currentlyEating != obstacle) + currentlyEating = obstacle + eatingDuration = 0 + + if(!AttemptToEat(obstacle)) + eatingDuration++ + else + currentlyEating = null + eatingDuration = 0 + + return + +/mob/living/simple_animal/space_worm/proc/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 + +/mob/living/simple_animal/space_worm/proc/AttemptToEat(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) + new /obj/item/stack/sheet/metal(src, 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 + +/mob/living/simple_animal/space_worm/proc/Attach(mob/living/simple_animal/space_worm/attachement) + if(!attachement) + return + + previous = attachement + attachement.next = src + + return + +/mob/living/simple_animal/space_worm/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.death() + + qdel(src) + +/mob/living/simple_animal/space_worm/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/phoron)) + var/obj/item/stack/oldStack = stomachContent + new /obj/item/stack/sheet/mineral/phoron(src, oldStack.get_amount()) + qdel(oldStack) + 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/phoron(src, oldItem.w_class) + qdel(oldItem) + continue + else + new /obj/item/stack/sheet/mineral/phoron(src, flatPlasmaValue) //just flat amount + qdel(stomachContent) + 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 6894ab72b4ea..21f835a6ba20 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -1,77 +1,77 @@ -//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)].") - 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). ") - 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() - - client.images = null //remove the images such as AIs being unable to see runes - client.screen = list() //remove hud items just in case - if(hud_used) - qdel(hud_used) //remove the hud objects - hud_used = new /datum/hud(src) - client.pixel_x = 0 - client.pixel_y = 0 - next_move = 1 - - ..() - - if(loc && !isturf(loc)) - client.eye = loc - client.perspective = EYE_PERSPECTIVE - else - client.eye = src - client.perspective = MOB_PERSPECTIVE - - //Some weird magic to block users who cant see lighting normally - var/obj/screen/blocker = new /obj/screen() - blocker.screen_loc = "WEST,SOUTH to EAST,NORTH" - blocker.icon = 'icons/effects/chaos.dmi' - blocker.icon_state = "8" - blocker.blend_mode = BLEND_MULTIPLY - blocker.color = list(1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,1,0,0,0,1) - blocker.alpha = 255 - blocker.layer = ABOVE_HUD_LAYER - blocker.plane = ABOVE_HUD_PLANE - blocker.mouse_opacity = 0 - - client.screen += blocker - - //Clear ability list and update from mob. - client.verbs -= ability_verbs - - if(abilities) - client.verbs |= abilities - - if(istype(src, /mob/living/silicon/ai)) - client.show_popup_menus = 0 - else - client.show_popup_menus = 1 - - if(istype(src,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - if(H.species && H.species.abilities) - client.verbs |= H.species.abilities +//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)].") + 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). ") + 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() + + client.images = null //remove the images such as AIs being unable to see runes + client.screen = list() //remove hud items just in case + if(hud_used) + qdel(hud_used) //remove the hud objects + hud_used = new /datum/hud(src) + client.pixel_x = 0 + client.pixel_y = 0 + next_move = 1 + + ..() + + if(loc && !isturf(loc)) + client.eye = loc + client.perspective = EYE_PERSPECTIVE + else + client.eye = src + client.perspective = MOB_PERSPECTIVE + + //Some weird magic to block users who cant see lighting normally + var/obj/screen/blocker = new /obj/screen() + blocker.screen_loc = "WEST,SOUTH to EAST,NORTH" + blocker.icon = 'icons/effects/chaos.dmi' + blocker.icon_state = "8" + blocker.blend_mode = BLEND_MULTIPLY + blocker.color = list(1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,1,0,0,0,1) + blocker.alpha = 255 + blocker.layer = ABOVE_HUD_LAYER + blocker.plane = ABOVE_HUD_PLANE + blocker.mouse_opacity = 0 + + client.screen += blocker + + //Clear ability list and update from mob. + client.verbs -= ability_verbs + + if(abilities) + client.verbs |= abilities + + if(istype(src, /mob/living/silicon/ai)) + client.show_popup_menus = 0 + else + client.show_popup_menus = 1 + + if(istype(src,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + if(H.species && H.species.abilities) + client.verbs |= H.species.abilities diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index 0aafbf4e73fc..6ef98d5a49b6 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -1,11 +1,11 @@ -/mob/Logout() - 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)]") - if(admin_datums[src.ckey]) - if(!(src.ckey in stealth_keys)) - if (ticker && ticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing. - message_admins("Admin logout: [key_name(src)]") - ..() - - return 1 +/mob/Logout() + 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)]") + if(admin_datums[src.ckey]) + if(!(src.ckey in stealth_keys)) + if (ticker && ticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing. + message_admins("Admin logout: [key_name(src)]") + ..() + + return 1 diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 96cb90819540..157a39283806 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1,1133 +1,1133 @@ -/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game. - mob_list -= src - dead_mob_list -= src - alive_mob_list -= src - ghostize(bancheck = TRUE) - return ..() - -/mob/atom_init() - spawn() - if(client) animate(client, color = null, time = 0) - mob_list += src - if(stat == DEAD) - dead_mob_list += src - else - alive_mob_list += src - . = ..() - -/mob/proc/Cell() - set category = "Admin" - set hidden = TRUE - - if(!isturf(loc)) - return 0 - - var/turf/T = loc - - var/datum/gas_mixture/env = T.return_air() - - var/t = "Coordinates: [T.x],[T.y],[T.z]\n" - t += "Temperature: [env.temperature]\n" - t += "Pressure: [env.return_pressure()]kPa\n" - for(var/g in env.gas) - t += "[g]: [env.gas[g]] / [env.gas[g] * R_IDEAL_GAS_EQUATION * env.temperature / env.volume]kPa\n" - - usr.show_message(t, 1) - -/mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) - - if(!client) - return FALSE - - if(type) - if((type & 1) && ((sdisabilities & BLIND) || blinded || paralysis) )//Vision related - if(!alt) - return FALSE - else - msg = alt - type = alt_type - if((type & 2) && ((sdisabilities & DEAF) || ear_deaf))//Hearing related - if (!alt) - return FALSE - else - msg = alt - type = alt_type - if (((type & 1) && (sdisabilities & BLIND))) - return FALSE - // Added voice muffling for Issue 41. - if(stat == UNCONSCIOUS || sleeping > 0) - msg = "... You can almost hear someone talking ..." - to_chat(src, msg) - return msg - -/mob/living/carbon/show_message(msg, type, alt, alt_type) - . = ..() - if(. && length(parasites)) - for(var/M in parasites) - to_chat(M, .) -// Show a message to all mobs in sight of this one -// This would be for visible actions by the src mob -// message is the message output to anyone who can see e.g. "[src] does something!" -// self_message (optional) is what the src mob sees e.g. "You do something!" -// blind_message (optional) is what blind people will hear e.g. "You hear something!" - -/mob/visible_message(message, self_message, blind_message) - for(var/mob/M in viewers(src)) - var/msg = message - if(self_message && M == src) - msg = self_message - M.show_message(msg, 1, blind_message, 2) - -// Show a message to all mobs in sight of this atom -// Use for objects performing visible actions -// message is output to anyone who can see, e.g. "The [src] does something!" -// blind_message (optional) is what blind people will hear e.g. "You hear something!" -/atom/proc/visible_message(message, blind_message) - for(var/mob/M in viewers(src)) - M.show_message(message, 1, blind_message, 2) - -// Show a message to all mobs in earshot of this one -// This would be for audible actions by the src mob -// message is the message output to anyone who can hear. -// self_message (optional) is what the src mob hears. -// deaf_message (optional) is what deaf people will see. -// hearing_distance (optional) is the range, how many tiles away the message can be heard. - -/mob/audible_message(message, deaf_message, hearing_distance, self_message) - var/range = world.view - if(hearing_distance) - range = hearing_distance - for(var/mob/M in get_hearers_in_view(range, src)) - var/msg = message - if(self_message && M == src) - msg = self_message - M.show_message(msg, 2, deaf_message, 1) - -// Show a message to all mobs in earshot of this atom -// Use for objects performing audible actions -// message is the message output to anyone who can hear. -// deaf_message (optional) is what deaf people will see. -// hearing_distance (optional) is the range, how many tiles away the message can be heard. - -/atom/proc/audible_message(message, deaf_message, hearing_distance) - var/range = world.view - if(hearing_distance) - range = hearing_distance - for(var/mob/M in get_hearers_in_view(range, src)) - M.show_message(message, 2, deaf_message, 1) - -/mob/proc/findname(msg) - for(var/mob/M in mob_list) - if(M.real_name == text("[]", msg)) - return M - return 0 - -/mob/proc/movement_delay() - return 0 - -/mob/proc/Life() - set waitfor = 0 - return - -/mob/proc/incapacitated(restrained_type = ARMS) - return - -/mob/proc/restrained() - return - -/mob/proc/reset_view(atom/A) - if(client) - if(istype(A, /atom/movable)) - client.perspective = EYE_PERSPECTIVE - client.eye = A - else - if(isturf(loc)) - client.eye = client.mob - client.perspective = MOB_PERSPECTIVE - else - client.perspective = EYE_PERSPECTIVE - client.eye = loc - return - - -/mob/proc/show_inv(mob/user) - user.set_machine(src) - var/dat = {" -


                    [name] -

                    -
                    Head(Mask): [(wear_mask ? wear_mask : "Nothing")] -
                    Left Hand: [(l_hand&&!(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"] -
                    Right Hand: [(r_hand&&!(r_hand.flags&ABSTRACT)) ? 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) : "")] -
                    [(internal ? text("Remove Internal") : "")] -
                    Empty Pockets -
                    Refresh -
                    Close -
                    "} - user << browse(entity_ja(dat), text("window=mob[];size=325x500", name)) - onclose(user, "mob[name]") - return - -/mob/proc/ret_grab(obj/effect/list_container/mobl/L, flag) - if(!(istype(l_hand, /obj/item/weapon/grab) || istype(r_hand, /obj/item/weapon/grab))) - if(!L) - return null - else - return L.container - else - if(!L) - L = new /obj/effect/list_container/mobl(null) - L.container += src - L.master = src - if(istype(l_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = l_hand - if(!L.container.Find(G.affecting)) - L.container += G.affecting - if (G.affecting) - G.affecting.ret_grab(L, 1) - if(istype(r_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = r_hand - if(!L.container.Find(G.affecting)) - L.container += G.affecting - if(G.affecting) - G.affecting.ret_grab(L, 1) - if(!flag) - if(L.master == src) - var/list/temp = list( ) - temp += L.container - //L = null - qdel(L) - return temp - else - return L.container - return - -/mob/verb/mode() - set name = "Activate Held Object" - set category = "Object" - set src = usr - - if(istype(loc,/obj/mecha)) - return - - if(hand) - var/obj/item/W = l_hand - if(W) - W.attack_self(src) - update_inv_l_hand() - else - var/obj/item/W = r_hand - if(W) - W.attack_self(src) - update_inv_r_hand() - if(next_move < world.time) - next_move = world.time + 2 - return - -/* -/mob/verb/dump_source() - - var/master = "
                    "
                    -	for(var/t in typesof(/area))
                    -		master += text("[]\n", t)
                    -		//Foreach goto(26)
                    -	src << browse(master)
                    -	return
                    -*/
                    -
                    -/mob/verb/memory()
                    -	set name = "Notes"
                    -	set category = "IC"
                    -	if(mind)
                    -		mind.show_memory(src)
                    -	else
                    -		to_chat(src, "The game appears to have misplaced your mind datum, so we can't show you your notes.")
                    -
                    -/mob/verb/add_memory(msg as message)
                    -	set name = "Add Note"
                    -	set category = "IC"
                    -
                    -	msg = sanitize(msg)
                    -
                    -	if(msg && mind)
                    -		mind.store_memory(msg)
                    -	else
                    -		to_chat(src, "The game appears to have misplaced your mind datum, so we can't show you your notes.")
                    -
                    -/mob/proc/store_memory(msg, popup)
                    -	msg = sanitize(msg)
                    -
                    -	if(length(memory) == 0)
                    -		memory += msg
                    -	else
                    -		memory += "
                    [msg]" - - if(popup) - memory() - -/mob/proc/update_flavor_text() - set src in usr - if(usr != src) - to_chat(usr, "No.") - var/msg = sanitize(input(usr,"Set the flavor text in your 'examine' verb. Can also be used for OOC notes about your character.","Flavor Text",input_default(flavor_text)) as message|null) - - if(msg) - flavor_text = msg - -/mob/proc/warn_flavor_changed() - if(flavor_text && flavor_text != "") // don't spam people that don't use it! - to_chat(src, "

                    OOC Warning:

                    ") - to_chat(src, "Your flavor text is likely out of date! Change") - -/mob/proc/print_flavor_text() - if(flavor_text && flavor_text != "") - var/msg = flavor_text - if(lentext(msg) <= 40) - return "\blue [msg]" - else - return "\blue [copytext(msg, 1, 37)]... More..." - -//mob verbs are faster than object verbs. See http://www.byond.com/forum/?post=1326139&page=2#comment8198716 for why this isn't atom/verb/examine() -/mob/verb/examinate(atom/A as mob|obj|turf in view()) - set name = "Examine" - set category = "IC" - - if(sdisabilities & BLIND || blinded || stat == UNCONSCIOUS) - to_chat(usr, "Something is there but you can't see it.") - return - - face_atom(A) - A.examine(src) - -/mob/verb/pointed(atom/A as mob|obj|turf in oview()) - set name = "Point To" - set category = "Object" - - if(!usr || !isturf(usr.loc)) - return - if(usr.stat || usr.restrained()) - return - if(usr.status_flags & FAKEDEATH) - return - if(!(A in oview(usr.loc))) - return - if(istype(A, /obj/effect/decal/point)) - return - - var/tile = get_turf(A) - if(!tile) - return - - var/obj/P = new /obj/effect/decal/point(tile) - P.pixel_x = A.pixel_x - P.pixel_y = A.pixel_y - P.plane = GAME_PLANE - - QDEL_IN(P, 20) - - usr.visible_message("[usr] points to [A].") - - if(isliving(A)) - for(var/mob/living/carbon/slime/S in oview()) - if(usr in S.Friends) - S.last_pointed = A - -/mob/verb/abandon_mob() - set name = "Respawn" - set category = "OOC" - - if(!abandon_allowed) - to_chat(usr, "\blue Respawn is disabled.") - return - if(stat != DEAD || !ticker) - to_chat(usr, "\blue You must be dead to use this!") - return - if(ticker && istype(ticker.mode, /datum/game_mode/meteor)) - to_chat(usr, "\blue Respawn is disabled for this roundtype.") - return - else - var/deathtime = world.time - src.timeofdeath - if(istype(src,/mob/dead/observer)) - var/mob/dead/observer/G = src - if(G.has_enabled_antagHUD == 1 && config.antag_hud_restricted) - to_chat(usr, "\blue Upon using the antagHUD you forfeighted the ability to join the round.") - return - var/deathtimeminutes = round(deathtime / 600) - var/pluralcheck = "minute" - if(deathtimeminutes == 0) - pluralcheck = "" - else if(deathtimeminutes == 1) - pluralcheck = " [deathtimeminutes] minute and" - else if(deathtimeminutes > 1) - pluralcheck = " [deathtimeminutes] minutes and" - var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10, 1) - - if(deathtime < config.deathtime_required && !(client.holder && (client.holder.rights & R_ADMIN))) //Holders with R_ADMIN can give themselvs respawn, so it doesn't matter - to_chat(usr, "You have been dead for[pluralcheck] [deathtimeseconds] seconds.") - to_chat(usr, "You must wait 30 minutes to respawn!") - return - else - to_chat(usr, "You can respawn now, enjoy your new life!") - - log_game("[usr.name]/[usr.key] used abandon mob.") - - to_chat(usr, "\blue Make sure to play a different character, and please roleplay correctly!") - - if(!client) - log_game("[usr.key] AM failed due to disconnect.") - return - client.screen.Cut() - client.screen += client.void - if(!client) - log_game("[usr.key] AM failed due to disconnect.") - return - - var/mob/dead/new_player/M = new /mob/dead/new_player() - if(!client) - log_game("[usr.key] AM failed due to disconnect.") - qdel(M) - return - - M.key = key -// M.Login() //wat - return - -/mob/verb/observe() - set name = "Observe" - set category = "OOC" - var/is_admin = FALSE - - if(client.holder && (client.holder.rights & R_ADMIN)) - is_admin = TRUE - else if(stat != DEAD || isnewplayer(src) || jobban_isbanned(src, "Observer")) - to_chat(usr, "\blue You must be observing to use this!") - return - - if(is_admin && stat == DEAD) - is_admin = FALSE - - var/list/creatures = getpois() - - client.perspective = EYE_PERSPECTIVE - - var/eye_name = null - - var/ok = "[is_admin ? "Admin Observe" : "Observe"]" - eye_name = input("Please, select a player!", ok, null, null) as null|anything in creatures - - if(!eye_name) - return - - var/mob/mob_eye = creatures[eye_name] - - if(client && mob_eye) - client.eye = mob_eye - if(is_admin) - client.adminobs = 1 - if(mob_eye == client.mob || client.eye == client.mob) - client.adminobs = 0 - -/mob/verb/cancel_camera() - set name = "Cancel Camera View" - set category = "OOC" - reset_view(null) - unset_machine() - if(istype(src, /mob/living)) - var/mob/living/M = src - if(M.cameraFollow) - M.cameraFollow = null - -//suppress the .click/dblclick macros so people can't use them to identify the location of items or aimbot -/mob/verb/DisClick(argu = null as anything, sec = "" as text, number1 = 0 as num, number2 = 0 as num) - set name = ".click" - set hidden = TRUE - set category = null - return - -/mob/verb/DisDblClick(argu = null as anything, sec = "" as text, number1 = 0 as num, number2 = 0 as num) - set name = ".dblclick" - set hidden = TRUE - set category = null - return - -/mob/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["flavor_more"]) - usr << browse(text("[][]", name, entity_ja(flavor_text)), text("window=[];size=500x200", name)) - - onclose(usr, "[name]") - if(href_list["flavor_change"]) - update_flavor_text() -// ..() - return - - -/mob/proc/pull_damage() - if(ishuman(src)) - var/mob/living/carbon/human/H = src - if((H.health - H.halloss) <= config.health_threshold_softcrit) - for(var/bodypart_name in H.bodyparts_by_name) - var/obj/item/organ/external/BP = H.bodyparts_by_name[bodypart_name] - if(H.lying) - if((((BP.status & ORGAN_BROKEN) && !(BP.status & ORGAN_SPLINTED)) || (BP.status & ORGAN_BLEEDING)) && ((H.getBruteLoss() + H.getFireLoss()) >= 100)) - return 1 - return 0 - -/mob/MouseDrop(mob/M as mob) - ..() - if(M != usr) - return - if(usr == src) - return - if(!Adjacent(usr)) - return - if(isAI(M)) - return - show_inv(usr) - -//this and stop_pulling really ought to be /mob/living procs -/mob/proc/start_pulling(atom/movable/AM) - if(!AM || !src || src == AM || !isturf(AM.loc)) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort! - return - if(!AM.anchored) - AM.add_fingerprint(src) - - // If we're pulling something then drop what we're currently pulling and pull this instead. - if(pulling) - // Are we trying to pull something we are already pulling? Then just stop here, no need to continue. - if(AM == pulling) - return - stop_pulling() - - src.pulling = AM - AM.pulledby = src - if(pullin) - pullin.update_icon(src) - if(ismob(AM)) - var/mob/M = AM - if(!iscarbon(src)) - M.LAssailant = null - else - M.LAssailant = usr - - src.pulling = AM - AM.pulledby = src - - if(ishuman(AM)) - var/mob/living/carbon/human/H = AM - if(H.pull_damage()) - to_chat(src, "Pulling \the [H] in their current condition would probably be a bad idea.") - - count_pull_debuff() - -/mob/verb/stop_pulling() - set name = "Stop Pulling" - set category = "IC" - - if(pulling) - pulling.pulledby = null - pulling = null - if(pullin) - pullin.update_icon(src) - count_pull_debuff() - -/mob/proc/count_pull_debuff() - return - -/mob/proc/can_use_hands() - return - -/mob/proc/is_active() - return (usr.stat <= 0) - -/mob/proc/is_dead() - return stat == DEAD - -/mob/proc/is_mechanical() - if(mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI")) - return 1 - return istype(src, /mob/living/silicon) || get_species() == IPC - -/mob/proc/is_ready() - return client && !!mind - -/mob/proc/get_gender() - return gender - -/mob/proc/see(message) - if(!is_active()) - return 0 - to_chat(src, message) - return 1 - -/mob/proc/show_viewers(message) - for(var/mob/M in viewers()) - M.see(message) - -/* -adds a dizziness amount to a mob -use this rather than directly changing var/dizziness -since this ensures that the dizzy_process proc is started -currently only humans get dizzy - -value of dizziness ranges from 0 to 1000 -below 100 is not dizzy -*/ -/mob/proc/make_dizzy(amount) - if(!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy - return - - dizziness = min(1000, dizziness + amount) // store what will be new value - // clamped to max 1000 - if(dizziness > 100 && !is_dizzy) - spawn(0) - dizzy_process() - - -/* -dizzy process - wiggles the client's pixel offset over time -spawned from make_dizzy(), will terminate automatically when dizziness gets <100 -note dizziness decrements automatically in the mob's Life() proc. -*/ -/mob/proc/dizzy_process() - is_dizzy = TRUE - while(dizziness > 100) - if(client) - var/amplitude = dizziness*(sin(dizziness * 0.044 * world.time) + 1) / 70 - client.pixel_x = amplitude * sin(0.008 * dizziness * world.time) - client.pixel_y = amplitude * cos(0.008 * dizziness * world.time) - - sleep(1) - //endwhile - reset the pixel offsets to zero - is_dizzy = FALSE - if(client) - client.pixel_x = 0 - client.pixel_y = 0 - -// jitteriness - copy+paste of dizziness - -/mob/proc/make_jittery(amount) - if(!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy - return - - jitteriness = min(1000, jitteriness + amount) // store what will be new value - // clamped to max 1000 - if(jitteriness > 100 && !is_jittery) - spawn(0) - jittery_process() - - -// Typo from the oriignal coder here, below lies the jitteriness process. So make of his code what you will, the previous comment here was just a copypaste of the above. -/mob/proc/jittery_process() - is_jittery = TRUE - while(jitteriness > 100) -// var/amplitude = jitteriness*(sin(jitteriness * 0.044 * world.time) + 1) / 70 -// pixel_x = amplitude * sin(0.008 * jitteriness * world.time) -// pixel_y = amplitude * cos(0.008 * jitteriness * world.time) - - var/amplitude = min(4, jitteriness / 100) - pixel_x = rand(-amplitude, amplitude) - pixel_y = rand(-amplitude/3, amplitude/3) - - sleep(1) - //endwhile - reset the pixel offsets to zero - is_jittery = FALSE - pixel_x = initial(pixel_x) - pixel_y = initial(pixel_y) - -/mob/Stat() - ..() - - if(statpanel("Status")) - stat(null, "Server Time: [time2text(world.realtime, "YYYY-MM-DD hh:mm")]") - if(client) - stat(null, "Your in-game age: [client.player_ingame_age]") - if(client.holder) - if(ticker.mode && ticker.mode.config_tag == "malfunction") - var/datum/game_mode/malfunction/GM = ticker.mode - if(GM.malf_mode_declared) - stat(null, "Time left: [max(GM.AI_win_timeleft / (GM.apcs / APC_MIN_TO_MALF_DECLARE), 0)]") - if(SSshuttle.online && SSshuttle.location < 2) - stat(null, "ETA-[shuttleeta2text()]") - - if(client && client.holder) - if((client.holder.rights & R_ADMIN)) - if(statpanel("MC")) - stat("CPU:", "[world.cpu]") - if(client.holder.rights & R_DEBUG) - stat("Location:", "([x], [y], [z])") - stat("Instances:", "[world.contents.len]") - config.stat_entry() - stat(null) - if(Master) - Master.stat_entry() - else - stat("Master Controller:", "ERROR") - if(Failsafe) - Failsafe.stat_entry() - else - stat("Failsafe Controller:", "ERROR") - if(Master) - stat(null) - for(var/datum/subsystem/SS in Master.subsystems) - SS.stat_entry() - cameranet.stat_entry() - - if(listed_turf && client) - if(!TurfAdjacent(listed_turf)) - listed_turf = null - else - statpanel(listed_turf.name, null, listed_turf) - for(var/atom/A in listed_turf) - if(!A.mouse_opacity) - continue - if(A.invisibility > see_invisible) - continue - if(is_type_in_list(A, shouldnt_see)) - continue - statpanel(listed_turf.name, null, A) - - if(spell_list.len) - for(var/obj/effect/proc_holder/spell/S in spell_list) - switch(S.charge_type) - if("recharge") - statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S) - if("charges") - statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S) - if("holdervar") - statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S) - -// facing verbs -/mob/proc/canface() - if(!canmove) return 0 - if(client.moving) return 0 - if(world.time < client.move_delay) return 0 - if(stat==2) return 0 - if(anchored) return 0 - if(monkeyizing) return 0 - if(restrained()) return 0 - return 1 - -// Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it. -// We need speed out of this proc, thats why using incapacitated() helper here is a bad idea. -/mob/proc/update_canmove(no_transform = FALSE) - - var/ko = weakened || paralysis || stat || (status_flags & FAKEDEATH) - - lying = (ko || crawling || resting) && !captured && !buckled && !pinned.len - canmove = !(ko || resting || stunned || captured || pinned.len) - anchored = captured || pinned.len - - if(buckled) - if(buckled.buckle_lying != -1) - lying = buckled.buckle_lying - canmove = canmove && buckled.buckle_movable - anchored = anchored || buckled.buckle_movable - - if(istype(buckled, /obj/vehicle)) - var/obj/vehicle/V = buckled - if(!canmove) - V.unload(src) - else - pixel_y = V.mob_offset_y - else - if(istype(buckled, /obj/structure/stool/bed/chair)) - var/obj/structure/stool/bed/chair/C = buckled - if(C.flipped) - lying = 1 - - density = !lying - - if(lying && ((l_hand && l_hand.canremove) || (r_hand && r_hand.canremove)) && !isalien(src)) - drop_l_hand() - drop_r_hand() - - for(var/obj/item/weapon/grab/G in grabbed_by) - if(G.state >= GRAB_AGGRESSIVE) - canmove = FALSE - if(G.state == GRAB_NECK && G.assailant.zone_sel.selecting == BP_CHEST) - lying = FALSE - density = TRUE - break - - //Temporarily moved here from the various life() procs - //I'm fixing stuff incrementally so this will likely find a better home. - //It just makes sense for now. ~Carn - - if(!no_transform && lying != lying_prev) - update_transform() - if(update_icon) //forces a full overlay update - update_icon = FALSE - regenerate_icons() - return canmove - - -/mob/proc/facedir(ndir) - if(!canface()) - return 0 - dir = ndir - if(buckled && buckled.buckle_movable) - buckled.dir = ndir - buckled.handle_rotation() - client.move_delay += movement_delay() - return 1 - - -/mob/verb/eastface() - set hidden = 1 - return facedir(EAST) - - -/mob/verb/westface() - set hidden = 1 - return facedir(WEST) - - -/mob/verb/northface() - set hidden = 1 - return facedir(NORTH) - - -/mob/verb/southface() - set hidden = 1 - return facedir(SOUTH) - - -/mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check - return 0 - -// ========== STUN ========== -/mob/proc/Stun(amount, updating = 1, ignore_canstun = 0, lock = null) - if(!isnull(lock)) - if(lock) - status_flags |= LOCKSTUN - else - status_flags &= ~LOCKSTUN - else if(status_flags & LOCKSTUN) - return - - if(status_flags & CANSTUN || ignore_canstun) - stunned = max(max(stunned, amount), 0) //can't go below 0, getting a low amount of stun doesn't lower your current stun - if(updating) - update_canmove() - else - stunned = 0 - -/mob/proc/SetStunned(amount, updating = 1, ignore_canstun = 0, lock = null) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned" - if(!isnull(lock)) - if(lock) - status_flags |= LOCKSTUN - else - status_flags &= ~LOCKSTUN - else if(status_flags & LOCKSTUN) - return - - if(status_flags & CANSTUN || ignore_canstun) - stunned = max(amount, 0) - if(updating) - update_canmove() - else - stunned = 0 - -/mob/proc/AdjustStunned(amount, updating = 1, ignore_canstun = 0, lock = null) - if(!isnull(lock)) - if(lock) - status_flags |= LOCKSTUN - else - status_flags &= ~LOCKSTUN - else if(status_flags & LOCKSTUN) - return - - if(status_flags & CANSTUN || ignore_canstun) - stunned = max(stunned + amount, 0) - if(updating) - update_canmove() - else - stunned = 0 - -// ========== WEAKEN ========== -/mob/proc/Weaken(amount) - if(status_flags & CANWEAKEN) - weakened = max(max(weakened, amount), 0) - update_canmove() // updates lying, canmove and icons - else - weakened = 0 - -/mob/proc/SetWeakened(amount) - if(status_flags & CANWEAKEN) - weakened = max(amount, 0) - update_canmove() - else - weakened = 0 - -/mob/proc/AdjustWeakened(amount) - if(status_flags & CANWEAKEN) - weakened = max(weakened + amount, 0) - update_canmove() - else - weakened = 0 - -// ========== PARALYSE ========== -/mob/proc/Paralyse(amount) - if(status_flags & CANPARALYSE) - paralysis = max(max(paralysis, amount), 0) - else - paralysis = 0 - -/mob/proc/SetParalysis(amount) - if(status_flags & CANPARALYSE) - paralysis = max(amount, 0) - else - paralysis = 0 - -/mob/proc/AdjustParalysis(amount) - if(status_flags & CANPARALYSE) - paralysis = max(paralysis + amount, 0) - else - paralysis = 0 - -// ========== SLEEPING ========== -/mob/proc/Sleeping(amount) - if(status_flags & CANPARALYSE) // because sleeping and paralysis are very similar statuses and i see no point in separate flags at this time (anyway, golems mostly). - sleeping = max(max(sleeping, amount), 0) - else - sleeping = 0 - -/mob/proc/SetSleeping(amount) - if(status_flags & CANPARALYSE) - sleeping = max(amount, 0) - else - sleeping = 0 - -/mob/proc/AdjustSleeping(amount) - if(status_flags & CANPARALYSE) - sleeping = max(sleeping + amount, 0) - else - sleeping = 0 - -// ========== RESTING ========== -/mob/proc/Resting(amount) - resting = max(max(resting, amount), 0) - return - -/mob/proc/SetResting(amount) - resting = max(amount, 0) - return - -/mob/proc/AdjustResting(amount) - resting = max(resting + amount, 0) - return - -// ============================= - -/mob/proc/get_species() - return "" - -/mob/proc/flash_weak_pain() - flick("weak_pain",pain) - -/mob/proc/get_visible_implants(class = 0) - var/list/visible_implants = list() - for(var/obj/item/O in embedded) - if(O.w_class > class) - visible_implants += O - return visible_implants - -mob/proc/yank_out_object() - set category = "Object" - set name = "Yank out object" - set desc = "Remove an embedded item at the cost of bleeding and pain." - set src in view(1) - - if(!isliving(usr) || usr.next_move > world.time) - return - usr.next_move = world.time + 20 - - if(usr.stat == UNCONSCIOUS) - to_chat(usr, "You are unconcious and cannot do that!") - return - - if(usr.restrained()) - to_chat(usr, "You are restrained and cannot do that!") - return - - var/mob/S = src - var/mob/U = usr - var/list/valid_objects = list() - var/self = FALSE - - if(S == U) - self = TRUE // Removing object from yourself. - - valid_objects = get_visible_implants(1) - if(!valid_objects.len) - if(self) - to_chat(src, "You have nothing stuck in your body that is large enough to remove.") - else - to_chat(U, "[src] has nothing stuck in their wounds that is large enough to remove.") - return - - var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects - - if(self) - to_chat(src, "You attempt to get a good grip on the [selection] in your body.") - else - to_chat(U, "You attempt to get a good grip on the [selection] in [S]'s body.") - - if(!do_after(U, 80, target = S)) - return - if(!selection || !S || !U) - return - - if(self) - visible_message("[src] rips [selection] out of their body.","You rip [selection] out of your body.") - else - visible_message("[usr] rips [selection] out of [src]'s body.","[usr] rips [selection] out of your body.") - valid_objects = get_visible_implants(0) - if(valid_objects.len == 1) //Yanking out last object - removing verb. - src.verbs -= /mob/proc/yank_out_object - clear_alert("embeddedobject") - - if(istype(src, /mob/living/carbon/human)) - - var/mob/living/carbon/human/H = src - var/obj/item/organ/external/BP - - for(var/obj/item/organ/external/limb in H.bodyparts) //Grab the organ holding the implant. - for(var/obj/item/weapon/O in limb.implants) - if(O == selection) - BP = limb - - BP.implants -= selection - for(var/datum/wound/wound in BP.wounds) - wound.embedded_objects -= selection - - H.shock_stage += 20 - BP.take_damage((selection.w_class * 3), null, DAM_EDGE, "Embedded object extraction") - - if(prob(selection.w_class * 5) && BP.sever_artery()) // I'M SO ANEMIC I COULD JUST -DIE-. - H.custom_pain("Something tears wetly in your [BP.name] as [selection] is pulled free!", 1) - - if(ishuman(U)) - var/mob/living/carbon/human/human_user = U - human_user.bloody_hands(H) - - selection.loc = get_turf(src) - - for(var/obj/item/weapon/O in pinned) - if(O == selection) - pinned -= O - if(!pinned.len) - anchored = 0 - return 1 - -/mob/proc/get_ghost(even_if_they_cant_reenter = 0) - if(mind) - for(var/mob/dead/observer/G in observer_list) - if(G.mind == mind) - if(G.can_reenter_corpse || even_if_they_cant_reenter) - return G - break - -/mob/proc/AddSpell(obj/effect/proc_holder/spell/spell) - spell_list += spell - mind.spell_list += spell //Connect spell to the mind for transfering action buttons between mobs - if(!spell.action) - spell.action = new/datum/action/spell_action - spell.action.target = spell - spell.action.name = spell.name - spell.action.button_icon = spell.action_icon - spell.action.button_icon_state = spell.action_icon_state - spell.action.background_icon_state = spell.action_background_icon_state - if(isliving(src)) - spell.action.Grant(src) - return - -/mob/proc/set_EyesVision(preset = null, transition_time = 5) - if(!client) return - if(ishuman(src) && druggy) - var/datum/ColorMatrix/DruggyMatrix = new(pick("bgr_d","brg_d","gbr_d","grb_d","rbg_d","rgb_d")) - var/multiplied - if(preset) - var/datum/ColorMatrix/CM = new(preset) - multiplied = matrixMultiply(DruggyMatrix.matrix, CM.matrix) - animate(client, color = multiplied ? multiplied : DruggyMatrix.matrix, time = 40) - else if(preset) - var/datum/ColorMatrix/CM = new(preset) - animate(client, color = CM.matrix, time = transition_time) - else - animate(client, color = null, time = transition_time) - -/mob/proc/instant_vision_update(state=null, atom/A) - if(!client || isnull(state)) - return - - switch(state) - if(0) - if(!blinded) - clear_fullscreen("blind", 0) - client.eye = client.mob - client.perspective = MOB_PERSPECTIVE - if(1) - overlay_fullscreen("blind", /obj/screen/fullscreen/blind) - if(A) - client.perspective = EYE_PERSPECTIVE - client.eye = A - -//You can buckle on mobs if you're next to them since most are dense -/mob/buckle_mob(mob/living/M) - if(M.buckled) - return 0 - var/turf/T = get_turf(src) - if(M.loc != T) - var/old_density = density - density = 0 - var/can_step = step_towards(M, T) - density = old_density - if(!can_step) - return 0 - return ..() - -//Default buckling shift visual for mobs -/mob/post_buckle_mob(mob/living/M) - if(M == buckled_mob) //post buckling - M.pixel_y = initial(M.pixel_y) + 9 - if(M.layer < layer) - M.layer = layer + 0.1 - else //post unbuckling - M.layer = initial(M.layer) - M.plane = initial(M.plane) - M.pixel_y = initial(M.pixel_y) - -/mob/proc/can_unbuckle(mob/user) - return 1 - -/* -/mob/living/on_varedit(modified_var) - switch(modified_var) - if("weakened") - SetWeakened(weakened) - if("stunned") - SetStunned(stunned) - if("paralysis") - SetParalysis(paralysis) - if("sleeping") - SetSleeping(sleeping) - if("eye_blind") - set_blindness(eye_blind) - if("eye_damage") - set_eye_damage(eye_damage) - if("eye_blurry") - set_blurriness(eye_blurry) - if("ear_deaf") - setEarDamage(-1, ear_deaf) - if("ear_damage") - setEarDamage(ear_damage, -1) - if("maxHealth") - updatehealth() - if("resize") - update_transform()*/ +/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game. + mob_list -= src + dead_mob_list -= src + alive_mob_list -= src + ghostize(bancheck = TRUE) + return ..() + +/mob/atom_init() + spawn() + if(client) animate(client, color = null, time = 0) + mob_list += src + if(stat == DEAD) + dead_mob_list += src + else + alive_mob_list += src + . = ..() + +/mob/proc/Cell() + set category = "Admin" + set hidden = TRUE + + if(!isturf(loc)) + return 0 + + var/turf/T = loc + + var/datum/gas_mixture/env = T.return_air() + + var/t = "Coordinates: [T.x],[T.y],[T.z]\n" + t += "Temperature: [env.temperature]\n" + t += "Pressure: [env.return_pressure()]kPa\n" + for(var/g in env.gas) + t += "[g]: [env.gas[g]] / [env.gas[g] * R_IDEAL_GAS_EQUATION * env.temperature / env.volume]kPa\n" + + usr.show_message(t, 1) + +/mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) + + if(!client) + return FALSE + + if(type) + if((type & 1) && ((sdisabilities & BLIND) || blinded || paralysis) )//Vision related + if(!alt) + return FALSE + else + msg = alt + type = alt_type + if((type & 2) && ((sdisabilities & DEAF) || ear_deaf))//Hearing related + if (!alt) + return FALSE + else + msg = alt + type = alt_type + if (((type & 1) && (sdisabilities & BLIND))) + return FALSE + // Added voice muffling for Issue 41. + if(stat == UNCONSCIOUS || sleeping > 0) + msg = "... You can almost hear someone talking ..." + to_chat(src, msg) + return msg + +/mob/living/carbon/show_message(msg, type, alt, alt_type) + . = ..() + if(. && length(parasites)) + for(var/M in parasites) + to_chat(M, .) +// Show a message to all mobs in sight of this one +// This would be for visible actions by the src mob +// message is the message output to anyone who can see e.g. "[src] does something!" +// self_message (optional) is what the src mob sees e.g. "You do something!" +// blind_message (optional) is what blind people will hear e.g. "You hear something!" + +/mob/visible_message(message, self_message, blind_message) + for(var/mob/M in viewers(src)) + var/msg = message + if(self_message && M == src) + msg = self_message + M.show_message(msg, 1, blind_message, 2) + +// Show a message to all mobs in sight of this atom +// Use for objects performing visible actions +// message is output to anyone who can see, e.g. "The [src] does something!" +// blind_message (optional) is what blind people will hear e.g. "You hear something!" +/atom/proc/visible_message(message, blind_message) + for(var/mob/M in viewers(src)) + M.show_message(message, 1, blind_message, 2) + +// Show a message to all mobs in earshot of this one +// This would be for audible actions by the src mob +// message is the message output to anyone who can hear. +// self_message (optional) is what the src mob hears. +// deaf_message (optional) is what deaf people will see. +// hearing_distance (optional) is the range, how many tiles away the message can be heard. + +/mob/audible_message(message, deaf_message, hearing_distance, self_message) + var/range = world.view + if(hearing_distance) + range = hearing_distance + for(var/mob/M in get_hearers_in_view(range, src)) + var/msg = message + if(self_message && M == src) + msg = self_message + M.show_message(msg, 2, deaf_message, 1) + +// Show a message to all mobs in earshot of this atom +// Use for objects performing audible actions +// message is the message output to anyone who can hear. +// deaf_message (optional) is what deaf people will see. +// hearing_distance (optional) is the range, how many tiles away the message can be heard. + +/atom/proc/audible_message(message, deaf_message, hearing_distance) + var/range = world.view + if(hearing_distance) + range = hearing_distance + for(var/mob/M in get_hearers_in_view(range, src)) + M.show_message(message, 2, deaf_message, 1) + +/mob/proc/findname(msg) + for(var/mob/M in mob_list) + if(M.real_name == text("[]", msg)) + return M + return 0 + +/mob/proc/movement_delay() + return 0 + +/mob/proc/Life() + set waitfor = 0 + return + +/mob/proc/incapacitated(restrained_type = ARMS) + return + +/mob/proc/restrained() + return + +/mob/proc/reset_view(atom/A) + if(client) + if(istype(A, /atom/movable)) + client.perspective = EYE_PERSPECTIVE + client.eye = A + else + if(isturf(loc)) + client.eye = client.mob + client.perspective = MOB_PERSPECTIVE + else + client.perspective = EYE_PERSPECTIVE + client.eye = loc + return + + +/mob/proc/show_inv(mob/user) + user.set_machine(src) + var/dat = {" +
                    [name]
                    +

                    +
                    Head(Mask): [(wear_mask ? wear_mask : "Nothing")] +
                    Left Hand: [(l_hand&&!(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"] +
                    Right Hand: [(r_hand&&!(r_hand.flags&ABSTRACT)) ? 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) : "")] +
                    [(internal ? text("Remove Internal") : "")] +
                    Empty Pockets +
                    Refresh +
                    Close +
                    "} + user << browse(entity_ja(dat), text("window=mob[];size=325x500", name)) + onclose(user, "mob[name]") + return + +/mob/proc/ret_grab(obj/effect/list_container/mobl/L, flag) + if(!(istype(l_hand, /obj/item/weapon/grab) || istype(r_hand, /obj/item/weapon/grab))) + if(!L) + return null + else + return L.container + else + if(!L) + L = new /obj/effect/list_container/mobl(null) + L.container += src + L.master = src + if(istype(l_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = l_hand + if(!L.container.Find(G.affecting)) + L.container += G.affecting + if (G.affecting) + G.affecting.ret_grab(L, 1) + if(istype(r_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = r_hand + if(!L.container.Find(G.affecting)) + L.container += G.affecting + if(G.affecting) + G.affecting.ret_grab(L, 1) + if(!flag) + if(L.master == src) + var/list/temp = list( ) + temp += L.container + //L = null + qdel(L) + return temp + else + return L.container + return + +/mob/verb/mode() + set name = "Activate Held Object" + set category = "Object" + set src = usr + + if(istype(loc,/obj/mecha)) + return + + if(hand) + var/obj/item/W = l_hand + if(W) + W.attack_self(src) + update_inv_l_hand() + else + var/obj/item/W = r_hand + if(W) + W.attack_self(src) + update_inv_r_hand() + if(next_move < world.time) + next_move = world.time + 2 + return + +/* +/mob/verb/dump_source() + + var/master = "
                    "
                    +	for(var/t in typesof(/area))
                    +		master += text("[]\n", t)
                    +		//Foreach goto(26)
                    +	src << browse(master)
                    +	return
                    +*/
                    +
                    +/mob/verb/memory()
                    +	set name = "Notes"
                    +	set category = "IC"
                    +	if(mind)
                    +		mind.show_memory(src)
                    +	else
                    +		to_chat(src, "The game appears to have misplaced your mind datum, so we can't show you your notes.")
                    +
                    +/mob/verb/add_memory(msg as message)
                    +	set name = "Add Note"
                    +	set category = "IC"
                    +
                    +	msg = sanitize(msg)
                    +
                    +	if(msg && mind)
                    +		mind.store_memory(msg)
                    +	else
                    +		to_chat(src, "The game appears to have misplaced your mind datum, so we can't show you your notes.")
                    +
                    +/mob/proc/store_memory(msg, popup)
                    +	msg = sanitize(msg)
                    +
                    +	if(length(memory) == 0)
                    +		memory += msg
                    +	else
                    +		memory += "
                    [msg]" + + if(popup) + memory() + +/mob/proc/update_flavor_text() + set src in usr + if(usr != src) + to_chat(usr, "No.") + var/msg = sanitize(input(usr,"Set the flavor text in your 'examine' verb. Can also be used for OOC notes about your character.","Flavor Text",input_default(flavor_text)) as message|null) + + if(msg) + flavor_text = msg + +/mob/proc/warn_flavor_changed() + if(flavor_text && flavor_text != "") // don't spam people that don't use it! + to_chat(src, "

                    OOC Warning:

                    ") + to_chat(src, "Your flavor text is likely out of date! Change") + +/mob/proc/print_flavor_text() + if(flavor_text && flavor_text != "") + var/msg = flavor_text + if(lentext(msg) <= 40) + return "\blue [msg]" + else + return "\blue [copytext(msg, 1, 37)]... More..." + +//mob verbs are faster than object verbs. See http://www.byond.com/forum/?post=1326139&page=2#comment8198716 for why this isn't atom/verb/examine() +/mob/verb/examinate(atom/A as mob|obj|turf in view()) + set name = "Examine" + set category = "IC" + + if(sdisabilities & BLIND || blinded || stat == UNCONSCIOUS) + to_chat(usr, "Something is there but you can't see it.") + return + + face_atom(A) + A.examine(src) + +/mob/verb/pointed(atom/A as mob|obj|turf in oview()) + set name = "Point To" + set category = "Object" + + if(!usr || !isturf(usr.loc)) + return + if(usr.stat || usr.restrained()) + return + if(usr.status_flags & FAKEDEATH) + return + if(!(A in oview(usr.loc))) + return + if(istype(A, /obj/effect/decal/point)) + return + + var/tile = get_turf(A) + if(!tile) + return + + var/obj/P = new /obj/effect/decal/point(tile) + P.pixel_x = A.pixel_x + P.pixel_y = A.pixel_y + P.plane = GAME_PLANE + + QDEL_IN(P, 20) + + usr.visible_message("[usr] points to [A].") + + if(isliving(A)) + for(var/mob/living/carbon/slime/S in oview()) + if(usr in S.Friends) + S.last_pointed = A + +/mob/verb/abandon_mob() + set name = "Respawn" + set category = "OOC" + + if(!abandon_allowed) + to_chat(usr, "\blue Respawn is disabled.") + return + if(stat != DEAD || !ticker) + to_chat(usr, "\blue You must be dead to use this!") + return + if(ticker && istype(ticker.mode, /datum/game_mode/meteor)) + to_chat(usr, "\blue Respawn is disabled for this roundtype.") + return + else + var/deathtime = world.time - src.timeofdeath + if(istype(src,/mob/dead/observer)) + var/mob/dead/observer/G = src + if(G.has_enabled_antagHUD == 1 && config.antag_hud_restricted) + to_chat(usr, "\blue Upon using the antagHUD you forfeighted the ability to join the round.") + return + var/deathtimeminutes = round(deathtime / 600) + var/pluralcheck = "minute" + if(deathtimeminutes == 0) + pluralcheck = "" + else if(deathtimeminutes == 1) + pluralcheck = " [deathtimeminutes] minute and" + else if(deathtimeminutes > 1) + pluralcheck = " [deathtimeminutes] minutes and" + var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10, 1) + + if(deathtime < config.deathtime_required && !(client.holder && (client.holder.rights & R_ADMIN))) //Holders with R_ADMIN can give themselvs respawn, so it doesn't matter + to_chat(usr, "You have been dead for[pluralcheck] [deathtimeseconds] seconds.") + to_chat(usr, "You must wait 30 minutes to respawn!") + return + else + to_chat(usr, "You can respawn now, enjoy your new life!") + + log_game("[usr.name]/[usr.key] used abandon mob.") + + to_chat(usr, "\blue Make sure to play a different character, and please roleplay correctly!") + + if(!client) + log_game("[usr.key] AM failed due to disconnect.") + return + client.screen.Cut() + client.screen += client.void + if(!client) + log_game("[usr.key] AM failed due to disconnect.") + return + + var/mob/dead/new_player/M = new /mob/dead/new_player() + if(!client) + log_game("[usr.key] AM failed due to disconnect.") + qdel(M) + return + + M.key = key +// M.Login() //wat + return + +/mob/verb/observe() + set name = "Observe" + set category = "OOC" + var/is_admin = FALSE + + if(client.holder && (client.holder.rights & R_ADMIN)) + is_admin = TRUE + else if(stat != DEAD || isnewplayer(src) || jobban_isbanned(src, "Observer")) + to_chat(usr, "\blue You must be observing to use this!") + return + + if(is_admin && stat == DEAD) + is_admin = FALSE + + var/list/creatures = getpois() + + client.perspective = EYE_PERSPECTIVE + + var/eye_name = null + + var/ok = "[is_admin ? "Admin Observe" : "Observe"]" + eye_name = input("Please, select a player!", ok, null, null) as null|anything in creatures + + if(!eye_name) + return + + var/mob/mob_eye = creatures[eye_name] + + if(client && mob_eye) + client.eye = mob_eye + if(is_admin) + client.adminobs = 1 + if(mob_eye == client.mob || client.eye == client.mob) + client.adminobs = 0 + +/mob/verb/cancel_camera() + set name = "Cancel Camera View" + set category = "OOC" + reset_view(null) + unset_machine() + if(istype(src, /mob/living)) + var/mob/living/M = src + if(M.cameraFollow) + M.cameraFollow = null + +//suppress the .click/dblclick macros so people can't use them to identify the location of items or aimbot +/mob/verb/DisClick(argu = null as anything, sec = "" as text, number1 = 0 as num, number2 = 0 as num) + set name = ".click" + set hidden = TRUE + set category = null + return + +/mob/verb/DisDblClick(argu = null as anything, sec = "" as text, number1 = 0 as num, number2 = 0 as num) + set name = ".dblclick" + set hidden = TRUE + set category = null + return + +/mob/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["flavor_more"]) + usr << browse(text("[][]", name, entity_ja(flavor_text)), text("window=[];size=500x200", name)) + + onclose(usr, "[name]") + if(href_list["flavor_change"]) + update_flavor_text() +// ..() + return + + +/mob/proc/pull_damage() + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if((H.health - H.halloss) <= config.health_threshold_softcrit) + for(var/bodypart_name in H.bodyparts_by_name) + var/obj/item/organ/external/BP = H.bodyparts_by_name[bodypart_name] + if(H.lying) + if((((BP.status & ORGAN_BROKEN) && !(BP.status & ORGAN_SPLINTED)) || (BP.status & ORGAN_BLEEDING)) && ((H.getBruteLoss() + H.getFireLoss()) >= 100)) + return 1 + return 0 + +/mob/MouseDrop(mob/M as mob) + ..() + if(M != usr) + return + if(usr == src) + return + if(!Adjacent(usr)) + return + if(isAI(M)) + return + show_inv(usr) + +//this and stop_pulling really ought to be /mob/living procs +/mob/proc/start_pulling(atom/movable/AM) + if(!AM || !src || src == AM || !isturf(AM.loc)) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort! + return + if(!AM.anchored) + AM.add_fingerprint(src) + + // If we're pulling something then drop what we're currently pulling and pull this instead. + if(pulling) + // Are we trying to pull something we are already pulling? Then just stop here, no need to continue. + if(AM == pulling) + return + stop_pulling() + + src.pulling = AM + AM.pulledby = src + if(pullin) + pullin.update_icon(src) + if(ismob(AM)) + var/mob/M = AM + if(!iscarbon(src)) + M.LAssailant = null + else + M.LAssailant = usr + + src.pulling = AM + AM.pulledby = src + + if(ishuman(AM)) + var/mob/living/carbon/human/H = AM + if(H.pull_damage()) + to_chat(src, "Pulling \the [H] in their current condition would probably be a bad idea.") + + count_pull_debuff() + +/mob/verb/stop_pulling() + set name = "Stop Pulling" + set category = "IC" + + if(pulling) + pulling.pulledby = null + pulling = null + if(pullin) + pullin.update_icon(src) + count_pull_debuff() + +/mob/proc/count_pull_debuff() + return + +/mob/proc/can_use_hands() + return + +/mob/proc/is_active() + return (usr.stat <= 0) + +/mob/proc/is_dead() + return stat == DEAD + +/mob/proc/is_mechanical() + if(mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI")) + return 1 + return istype(src, /mob/living/silicon) || get_species() == IPC + +/mob/proc/is_ready() + return client && !!mind + +/mob/proc/get_gender() + return gender + +/mob/proc/see(message) + if(!is_active()) + return 0 + to_chat(src, message) + return 1 + +/mob/proc/show_viewers(message) + for(var/mob/M in viewers()) + M.see(message) + +/* +adds a dizziness amount to a mob +use this rather than directly changing var/dizziness +since this ensures that the dizzy_process proc is started +currently only humans get dizzy + +value of dizziness ranges from 0 to 1000 +below 100 is not dizzy +*/ +/mob/proc/make_dizzy(amount) + if(!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy + return + + dizziness = min(1000, dizziness + amount) // store what will be new value + // clamped to max 1000 + if(dizziness > 100 && !is_dizzy) + spawn(0) + dizzy_process() + + +/* +dizzy process - wiggles the client's pixel offset over time +spawned from make_dizzy(), will terminate automatically when dizziness gets <100 +note dizziness decrements automatically in the mob's Life() proc. +*/ +/mob/proc/dizzy_process() + is_dizzy = TRUE + while(dizziness > 100) + if(client) + var/amplitude = dizziness*(sin(dizziness * 0.044 * world.time) + 1) / 70 + client.pixel_x = amplitude * sin(0.008 * dizziness * world.time) + client.pixel_y = amplitude * cos(0.008 * dizziness * world.time) + + sleep(1) + //endwhile - reset the pixel offsets to zero + is_dizzy = FALSE + if(client) + client.pixel_x = 0 + client.pixel_y = 0 + +// jitteriness - copy+paste of dizziness + +/mob/proc/make_jittery(amount) + if(!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy + return + + jitteriness = min(1000, jitteriness + amount) // store what will be new value + // clamped to max 1000 + if(jitteriness > 100 && !is_jittery) + spawn(0) + jittery_process() + + +// Typo from the oriignal coder here, below lies the jitteriness process. So make of his code what you will, the previous comment here was just a copypaste of the above. +/mob/proc/jittery_process() + is_jittery = TRUE + while(jitteriness > 100) +// var/amplitude = jitteriness*(sin(jitteriness * 0.044 * world.time) + 1) / 70 +// pixel_x = amplitude * sin(0.008 * jitteriness * world.time) +// pixel_y = amplitude * cos(0.008 * jitteriness * world.time) + + var/amplitude = min(4, jitteriness / 100) + pixel_x = rand(-amplitude, amplitude) + pixel_y = rand(-amplitude/3, amplitude/3) + + sleep(1) + //endwhile - reset the pixel offsets to zero + is_jittery = FALSE + pixel_x = initial(pixel_x) + pixel_y = initial(pixel_y) + +/mob/Stat() + ..() + + if(statpanel("Status")) + stat(null, "Server Time: [time2text(world.realtime, "YYYY-MM-DD hh:mm")]") + if(client) + stat(null, "Your in-game age: [client.player_ingame_age]") + if(client.holder) + if(ticker.mode && ticker.mode.config_tag == "malfunction") + var/datum/game_mode/malfunction/GM = ticker.mode + if(GM.malf_mode_declared) + stat(null, "Time left: [max(GM.AI_win_timeleft / (GM.apcs / APC_MIN_TO_MALF_DECLARE), 0)]") + if(SSshuttle.online && SSshuttle.location < 2) + stat(null, "ETA-[shuttleeta2text()]") + + if(client && client.holder) + if((client.holder.rights & R_ADMIN)) + if(statpanel("MC")) + stat("CPU:", "[world.cpu]") + if(client.holder.rights & R_DEBUG) + stat("Location:", "([x], [y], [z])") + stat("Instances:", "[world.contents.len]") + config.stat_entry() + stat(null) + if(Master) + Master.stat_entry() + else + stat("Master Controller:", "ERROR") + if(Failsafe) + Failsafe.stat_entry() + else + stat("Failsafe Controller:", "ERROR") + if(Master) + stat(null) + for(var/datum/subsystem/SS in Master.subsystems) + SS.stat_entry() + cameranet.stat_entry() + + if(listed_turf && client) + if(!TurfAdjacent(listed_turf)) + listed_turf = null + else + statpanel(listed_turf.name, null, listed_turf) + for(var/atom/A in listed_turf) + if(!A.mouse_opacity) + continue + if(A.invisibility > see_invisible) + continue + if(is_type_in_list(A, shouldnt_see)) + continue + statpanel(listed_turf.name, null, A) + + if(spell_list.len) + for(var/obj/effect/proc_holder/spell/S in spell_list) + switch(S.charge_type) + if("recharge") + statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S) + if("charges") + statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S) + if("holdervar") + statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S) + +// facing verbs +/mob/proc/canface() + if(!canmove) return 0 + if(client.moving) return 0 + if(world.time < client.move_delay) return 0 + if(stat==2) return 0 + if(anchored) return 0 + if(monkeyizing) return 0 + if(restrained()) return 0 + return 1 + +// Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it. +// We need speed out of this proc, thats why using incapacitated() helper here is a bad idea. +/mob/proc/update_canmove(no_transform = FALSE) + + var/ko = weakened || paralysis || stat || (status_flags & FAKEDEATH) + + lying = (ko || crawling || resting) && !captured && !buckled && !pinned.len + canmove = !(ko || resting || stunned || captured || pinned.len) + anchored = captured || pinned.len + + if(buckled) + if(buckled.buckle_lying != -1) + lying = buckled.buckle_lying + canmove = canmove && buckled.buckle_movable + anchored = anchored || buckled.buckle_movable + + if(istype(buckled, /obj/vehicle)) + var/obj/vehicle/V = buckled + if(!canmove) + V.unload(src) + else + pixel_y = V.mob_offset_y + else + if(istype(buckled, /obj/structure/stool/bed/chair)) + var/obj/structure/stool/bed/chair/C = buckled + if(C.flipped) + lying = 1 + + density = !lying + + if(lying && ((l_hand && l_hand.canremove) || (r_hand && r_hand.canremove)) && !isalien(src)) + drop_l_hand() + drop_r_hand() + + for(var/obj/item/weapon/grab/G in grabbed_by) + if(G.state >= GRAB_AGGRESSIVE) + canmove = FALSE + if(G.state == GRAB_NECK && G.assailant.zone_sel.selecting == BP_CHEST) + lying = FALSE + density = TRUE + break + + //Temporarily moved here from the various life() procs + //I'm fixing stuff incrementally so this will likely find a better home. + //It just makes sense for now. ~Carn + + if(!no_transform && lying != lying_prev) + update_transform() + if(update_icon) //forces a full overlay update + update_icon = FALSE + regenerate_icons() + return canmove + + +/mob/proc/facedir(ndir) + if(!canface()) + return 0 + dir = ndir + if(buckled && buckled.buckle_movable) + buckled.dir = ndir + buckled.handle_rotation() + client.move_delay += movement_delay() + return 1 + + +/mob/verb/eastface() + set hidden = 1 + return facedir(EAST) + + +/mob/verb/westface() + set hidden = 1 + return facedir(WEST) + + +/mob/verb/northface() + set hidden = 1 + return facedir(NORTH) + + +/mob/verb/southface() + set hidden = 1 + return facedir(SOUTH) + + +/mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check + return 0 + +// ========== STUN ========== +/mob/proc/Stun(amount, updating = 1, ignore_canstun = 0, lock = null) + if(!isnull(lock)) + if(lock) + status_flags |= LOCKSTUN + else + status_flags &= ~LOCKSTUN + else if(status_flags & LOCKSTUN) + return + + if(status_flags & CANSTUN || ignore_canstun) + stunned = max(max(stunned, amount), 0) //can't go below 0, getting a low amount of stun doesn't lower your current stun + if(updating) + update_canmove() + else + stunned = 0 + +/mob/proc/SetStunned(amount, updating = 1, ignore_canstun = 0, lock = null) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned" + if(!isnull(lock)) + if(lock) + status_flags |= LOCKSTUN + else + status_flags &= ~LOCKSTUN + else if(status_flags & LOCKSTUN) + return + + if(status_flags & CANSTUN || ignore_canstun) + stunned = max(amount, 0) + if(updating) + update_canmove() + else + stunned = 0 + +/mob/proc/AdjustStunned(amount, updating = 1, ignore_canstun = 0, lock = null) + if(!isnull(lock)) + if(lock) + status_flags |= LOCKSTUN + else + status_flags &= ~LOCKSTUN + else if(status_flags & LOCKSTUN) + return + + if(status_flags & CANSTUN || ignore_canstun) + stunned = max(stunned + amount, 0) + if(updating) + update_canmove() + else + stunned = 0 + +// ========== WEAKEN ========== +/mob/proc/Weaken(amount) + if(status_flags & CANWEAKEN) + weakened = max(max(weakened, amount), 0) + update_canmove() // updates lying, canmove and icons + else + weakened = 0 + +/mob/proc/SetWeakened(amount) + if(status_flags & CANWEAKEN) + weakened = max(amount, 0) + update_canmove() + else + weakened = 0 + +/mob/proc/AdjustWeakened(amount) + if(status_flags & CANWEAKEN) + weakened = max(weakened + amount, 0) + update_canmove() + else + weakened = 0 + +// ========== PARALYSE ========== +/mob/proc/Paralyse(amount) + if(status_flags & CANPARALYSE) + paralysis = max(max(paralysis, amount), 0) + else + paralysis = 0 + +/mob/proc/SetParalysis(amount) + if(status_flags & CANPARALYSE) + paralysis = max(amount, 0) + else + paralysis = 0 + +/mob/proc/AdjustParalysis(amount) + if(status_flags & CANPARALYSE) + paralysis = max(paralysis + amount, 0) + else + paralysis = 0 + +// ========== SLEEPING ========== +/mob/proc/Sleeping(amount) + if(status_flags & CANPARALYSE) // because sleeping and paralysis are very similar statuses and i see no point in separate flags at this time (anyway, golems mostly). + sleeping = max(max(sleeping, amount), 0) + else + sleeping = 0 + +/mob/proc/SetSleeping(amount) + if(status_flags & CANPARALYSE) + sleeping = max(amount, 0) + else + sleeping = 0 + +/mob/proc/AdjustSleeping(amount) + if(status_flags & CANPARALYSE) + sleeping = max(sleeping + amount, 0) + else + sleeping = 0 + +// ========== RESTING ========== +/mob/proc/Resting(amount) + resting = max(max(resting, amount), 0) + return + +/mob/proc/SetResting(amount) + resting = max(amount, 0) + return + +/mob/proc/AdjustResting(amount) + resting = max(resting + amount, 0) + return + +// ============================= + +/mob/proc/get_species() + return "" + +/mob/proc/flash_weak_pain() + flick("weak_pain",pain) + +/mob/proc/get_visible_implants(class = 0) + var/list/visible_implants = list() + for(var/obj/item/O in embedded) + if(O.w_class > class) + visible_implants += O + return visible_implants + +mob/proc/yank_out_object() + set category = "Object" + set name = "Yank out object" + set desc = "Remove an embedded item at the cost of bleeding and pain." + set src in view(1) + + if(!isliving(usr) || usr.next_move > world.time) + return + usr.next_move = world.time + 20 + + if(usr.stat == UNCONSCIOUS) + to_chat(usr, "You are unconcious and cannot do that!") + return + + if(usr.restrained()) + to_chat(usr, "You are restrained and cannot do that!") + return + + var/mob/S = src + var/mob/U = usr + var/list/valid_objects = list() + var/self = FALSE + + if(S == U) + self = TRUE // Removing object from yourself. + + valid_objects = get_visible_implants(1) + if(!valid_objects.len) + if(self) + to_chat(src, "You have nothing stuck in your body that is large enough to remove.") + else + to_chat(U, "[src] has nothing stuck in their wounds that is large enough to remove.") + return + + var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects + + if(self) + to_chat(src, "You attempt to get a good grip on the [selection] in your body.") + else + to_chat(U, "You attempt to get a good grip on the [selection] in [S]'s body.") + + if(!do_after(U, 80, target = S)) + return + if(!selection || !S || !U) + return + + if(self) + visible_message("[src] rips [selection] out of their body.","You rip [selection] out of your body.") + else + visible_message("[usr] rips [selection] out of [src]'s body.","[usr] rips [selection] out of your body.") + valid_objects = get_visible_implants(0) + if(valid_objects.len == 1) //Yanking out last object - removing verb. + src.verbs -= /mob/proc/yank_out_object + clear_alert("embeddedobject") + + if(istype(src, /mob/living/carbon/human)) + + var/mob/living/carbon/human/H = src + var/obj/item/organ/external/BP + + for(var/obj/item/organ/external/limb in H.bodyparts) //Grab the organ holding the implant. + for(var/obj/item/weapon/O in limb.implants) + if(O == selection) + BP = limb + + BP.implants -= selection + for(var/datum/wound/wound in BP.wounds) + wound.embedded_objects -= selection + + H.shock_stage += 20 + BP.take_damage((selection.w_class * 3), null, DAM_EDGE, "Embedded object extraction") + + if(prob(selection.w_class * 5) && BP.sever_artery()) // I'M SO ANEMIC I COULD JUST -DIE-. + H.custom_pain("Something tears wetly in your [BP.name] as [selection] is pulled free!", 1) + + if(ishuman(U)) + var/mob/living/carbon/human/human_user = U + human_user.bloody_hands(H) + + selection.loc = get_turf(src) + + for(var/obj/item/weapon/O in pinned) + if(O == selection) + pinned -= O + if(!pinned.len) + anchored = 0 + return 1 + +/mob/proc/get_ghost(even_if_they_cant_reenter = 0) + if(mind) + for(var/mob/dead/observer/G in observer_list) + if(G.mind == mind) + if(G.can_reenter_corpse || even_if_they_cant_reenter) + return G + break + +/mob/proc/AddSpell(obj/effect/proc_holder/spell/spell) + spell_list += spell + mind.spell_list += spell //Connect spell to the mind for transfering action buttons between mobs + if(!spell.action) + spell.action = new/datum/action/spell_action + spell.action.target = spell + spell.action.name = spell.name + spell.action.button_icon = spell.action_icon + spell.action.button_icon_state = spell.action_icon_state + spell.action.background_icon_state = spell.action_background_icon_state + if(isliving(src)) + spell.action.Grant(src) + return + +/mob/proc/set_EyesVision(preset = null, transition_time = 5) + if(!client) return + if(ishuman(src) && druggy) + var/datum/ColorMatrix/DruggyMatrix = new(pick("bgr_d","brg_d","gbr_d","grb_d","rbg_d","rgb_d")) + var/multiplied + if(preset) + var/datum/ColorMatrix/CM = new(preset) + multiplied = matrixMultiply(DruggyMatrix.matrix, CM.matrix) + animate(client, color = multiplied ? multiplied : DruggyMatrix.matrix, time = 40) + else if(preset) + var/datum/ColorMatrix/CM = new(preset) + animate(client, color = CM.matrix, time = transition_time) + else + animate(client, color = null, time = transition_time) + +/mob/proc/instant_vision_update(state=null, atom/A) + if(!client || isnull(state)) + return + + switch(state) + if(0) + if(!blinded) + clear_fullscreen("blind", 0) + client.eye = client.mob + client.perspective = MOB_PERSPECTIVE + if(1) + overlay_fullscreen("blind", /obj/screen/fullscreen/blind) + if(A) + client.perspective = EYE_PERSPECTIVE + client.eye = A + +//You can buckle on mobs if you're next to them since most are dense +/mob/buckle_mob(mob/living/M) + if(M.buckled) + return 0 + var/turf/T = get_turf(src) + if(M.loc != T) + var/old_density = density + density = 0 + var/can_step = step_towards(M, T) + density = old_density + if(!can_step) + return 0 + return ..() + +//Default buckling shift visual for mobs +/mob/post_buckle_mob(mob/living/M) + if(M == buckled_mob) //post buckling + M.pixel_y = initial(M.pixel_y) + 9 + if(M.layer < layer) + M.layer = layer + 0.1 + else //post unbuckling + M.layer = initial(M.layer) + M.plane = initial(M.plane) + M.pixel_y = initial(M.pixel_y) + +/mob/proc/can_unbuckle(mob/user) + return 1 + +/* +/mob/living/on_varedit(modified_var) + switch(modified_var) + if("weakened") + SetWeakened(weakened) + if("stunned") + SetStunned(stunned) + if("paralysis") + SetParalysis(paralysis) + if("sleeping") + SetSleeping(sleeping) + if("eye_blind") + set_blindness(eye_blind) + if("eye_damage") + set_eye_damage(eye_damage) + if("eye_blurry") + set_blurriness(eye_blurry) + if("ear_deaf") + setEarDamage(-1, ear_deaf) + if("ear_damage") + setEarDamage(ear_damage, -1) + if("maxHealth") + updatehealth() + if("resize") + update_transform()*/ diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index a5c622e0945d..eb1d7b11726c 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -1,495 +1,495 @@ -/obj/item/weapon/grab - name = "grab" - icon = 'icons/mob/screen1.dmi' - icon_state = "reinforce" - flags = DROPDEL - var/obj/screen/grab/hud = null - var/mob/living/affecting = null - var/mob/living/carbon/human/assailant = null - var/state = GRAB_PASSIVE - - var/allow_upgrade = 1 - var/last_action = 0 - var/last_hit_zone = 0 - var/force_down //determines if the affecting mob will be pinned to the ground - var/dancing //determines if assailant and affecting keep looking at each other. Basically a wrestling position - - layer = 21 - abstract = 1 - item_state = "nothing" - w_class = 5.0 - - -/obj/item/weapon/grab/atom_init(mapload, mob/victim) - . = ..() - assailant = loc - affecting = victim - - if(affecting.anchored) - return INITIALIZE_HINT_QDEL - last_action = world.time - 10 - - hud = new /obj/screen/grab(src) - hud.icon_state = "reinforce" - icon_state = "grabbed" - hud.name = "reinforce grab" - hud.master = src - - //check if assailant is grabbed by victim as well - if(assailant.grabbed_by) - for (var/obj/item/weapon/grab/G in assailant.grabbed_by) - if(G.assailant == affecting && G.affecting == assailant) - G.dancing = 1 - G.adjust_position() - dancing = 1 - adjust_position() - -//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/throw_held() - if(affecting) - if(affecting.buckled) - return null - if(state >= GRAB_AGGRESSIVE) - animate(affecting, pixel_x = 0, pixel_y = 0, 4, 1) - 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 if(assailant.l_hand == src) - hud.screen_loc = ui_lhand - else - qdel(src) - - -/obj/item/weapon/grab/process() - confirm() - - if(!assailant) - qdel(src) // Same here, except we're trying to delete ourselves. - return PROCESS_KILL - - if(!affecting) - qdel(src) - return PROCESS_KILL - - if(affecting.buckled) - qdel(src) - return PROCESS_KILL - - 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 - //disallow upgrading if we're grabbing more than one person - 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 - - //disallow upgrading past aggressive if we're being grabbed aggressively - 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) - if(state < GRAB_AGGRESSIVE) - hud.icon_state = "reinforce" - else - hud.icon_state = "reinforce1" - else - hud.icon_state = "!reinforce" - - if(state >= GRAB_AGGRESSIVE) - affecting.drop_l_hand() - affecting.drop_r_hand() - - var/hit_zone = assailant.zone_sel.selecting - var/announce = 0 - if(hit_zone != last_hit_zone) - announce = 1 - last_hit_zone = hit_zone - if(ishuman(affecting)) - var/mob/living/carbon/human/AH = affecting - if(!AH.is_in_space_suit(only_helmet = TRUE)) - switch(hit_zone) - if(O_MOUTH) - if(announce) - assailant.visible_message("[assailant] covers [AH]'s mouth!") - if(AH.silent < 3) - AH.silent = 3 - if(O_EYES) - if(announce) - assailant.visible_message("[assailant] covers [AH]'s eyes!") - if(AH.eye_blind < 3) - AH.eye_blind = 3 - if(force_down) - if(affecting.loc != assailant.loc) - force_down = 0 - else - affecting.Weaken(2) - - if(state >= GRAB_NECK) - affecting.Stun(1) - if(isliving(affecting)) - var/mob/living/L = affecting - L.adjustOxyLoss(1) - - if(state >= GRAB_KILL) - //affecting.apply_effect(STUTTER, 5) //would do this, but affecting isn't declared as mob/living for some stupid reason. - affecting.stuttering = max(affecting.stuttering, 5) //It will hamper your voice, being choked and all. - affecting.Weaken(5) //Should keep you down unless you get help. - affecting.losebreath = max(affecting.losebreath + 2, 3) - - adjust_position() - - -/obj/item/weapon/grab/attack_self() - return s_click(hud) - - -//Updating pixelshift, position and direction -//Gets called on process, when the grab gets upgraded or the assailant moves -/obj/item/weapon/grab/proc/adjust_position() - if(!affecting) - return - if(affecting.buckled) - animate(affecting, pixel_x = 0, pixel_y = 0, 4, 1, LINEAR_EASING) - return - if(affecting.lying && state != GRAB_KILL) -// animate(affecting, pixel_x = 0, pixel_y = 0, 5, 1, LINEAR_EASING) - if(force_down) - affecting.set_dir(SOUTH) //face up - return - var/shift = 0 - var/adir = get_dir(assailant, affecting) - affecting.layer = 4 - switch(state) - if(GRAB_PASSIVE) - shift = 8 - if(dancing) //look at partner - shift = 10 - assailant.set_dir(get_dir(assailant, affecting)) - if(GRAB_AGGRESSIVE) - shift = 12 - if(GRAB_NECK, GRAB_UPGRADING) - shift = -10 - adir = assailant.dir - affecting.set_dir(assailant.dir) - affecting.loc = assailant.loc - if(GRAB_KILL) - shift = 0 - adir = 1 - affecting.set_dir(SOUTH) //face up - affecting.loc = assailant.loc - - switch(adir) - if(NORTH) - animate(affecting, pixel_x = 0, pixel_y =-shift, 5, 1, LINEAR_EASING) - affecting.layer = 3.9 - if(SOUTH) - animate(affecting, pixel_x = 0, pixel_y = shift, 5, 1, LINEAR_EASING) - if(WEST) - animate(affecting, pixel_x = shift, pixel_y = 0, 5, 1, LINEAR_EASING) - if(EAST) - animate(affecting, pixel_x =-shift, pixel_y = 0, 5, 1, LINEAR_EASING) - -/obj/item/weapon/grab/proc/s_click(obj/screen/S) - if(!affecting) - return - if(!assailant) - return - if(state == GRAB_UPGRADING) - return - if(assailant.next_move > world.time) - return - if(world.time < (last_action + UPGRADE_COOLDOWN)) - return - if(!assailant.canmove || assailant.lying) - qdel(src) - return - - last_action = world.time - - if(state < GRAB_AGGRESSIVE) - if(!allow_upgrade) - return - if(!affecting.lying) - assailant.visible_message("[assailant] has grabbed [affecting] aggressively (now hands)!") - else - assailant.visible_message("[assailant] pins [affecting] down to the ground (now hands)!") - force_down = 1 - affecting.Weaken(3) - step_to(assailant, affecting) - assailant.set_dir(EAST) //face the victim - affecting.set_dir(SOUTH) //face up - state = GRAB_AGGRESSIVE - icon_state = "grabbed1" - hud.icon_state = "reinforce1" - - 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)!") - state = GRAB_NECK - icon_state = "grabbed+1" - assailant.set_dir(get_dir(assailant, affecting)) - 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])" - msg_admin_attack("[key_name(assailant)] grabbed the neck of [key_name(affecting)] (JMP)") - hud.icon_state = "kill" - hud.name = "kill" - affecting.Stun(10) //10 ticks of ensured grab - - else if(state < GRAB_UPGRADING) - if(ishuman(affecting)) - var/mob/living/carbon/human/AH = affecting - if(AH.is_in_space_suit()) - to_chat(assailant, "You can't strangle him, because space helmet covers [affecting]'s neck.") - return - assailant.visible_message("[assailant] starts to tighten \his grip on [affecting]'s neck!") - hud.icon_state = "kill1" - - state = GRAB_KILL - assailant.visible_message("[assailant] has tightened \his grip on [affecting]'s neck!") - 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])" - msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]") - - assailant.next_move = world.time + 10 - affecting.losebreath += 1 - affecting.set_dir(WEST) - adjust_position() - - -//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) - qdel(src) - return 0 - - if(affecting) - if(!isturf(assailant.loc) || ( !isturf(affecting.loc) || assailant.loc != affecting.loc && get_dist(assailant, affecting) > 1) ) - qdel(src) - return 0 - - return 1 - - -/obj/item/weapon/grab/attack(mob/M, mob/living/user) - if(QDELETED(src)) - return - - if(!affecting) - return - - if(world.time < (last_action + 20)) - return - - if(!M.Adjacent(user)) - qdel(src) - return - - last_action = world.time - - if(M == affecting) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/hit_zone = assailant.zone_sel.selecting - flick(hud.icon_state, hud) - switch(assailant.a_intent) - if("help") - if(force_down) - to_chat(assailant, "You are no longer pinning [affecting] to the ground.") - force_down = 0 - return - if(state >= GRAB_AGGRESSIVE) - H.apply_pressure(assailant, hit_zone) - else - inspect_organ(affecting, assailant, hit_zone) - if("grab") - if(state < GRAB_AGGRESSIVE) - to_chat(assailant, "You require a better grab to do this.") - return - var/obj/item/organ/external/BP = H.bodyparts_by_name[check_zone(hit_zone)] - if(!BP) - return - assailant.visible_message("[assailant] [pick("bent", "twisted")] [H]'s [BP.name] into a jointlock!") - var/armor = H.run_armor_check(H, "melee") - if(armor < 2) - to_chat(H, "You feel extreme pain!") - H.adjustHalLoss(Clamp(0, 40 - H.halloss, 40)) //up to 40 halloss - return - if("hurt") - - if(hit_zone == O_EYES) - if(state < GRAB_NECK) - to_chat(assailant, "You require a better grab to do this.") - return - if((affecting:head && affecting:head.flags & HEADCOVERSEYES) || \ - (affecting:wear_mask && affecting:wear_mask.flags & MASKCOVERSEYES) || \ - (affecting:glasses && affecting:glasses.flags & GLASSESCOVERSEYES)) - to_chat(assailant, "You're going to need to remove the eye covering first.") - return - if(!affecting.has_eyes()) - to_chat(assailant, "You cannot locate any eyes on [affecting]!") - return - assailant.visible_message("[assailant] pressed \his fingers into [affecting]'s eyes!") - to_chat(affecting, "You experience immense pain as you feel digits being pressed into your eyes!") - assailant.attack_log += text("\[[time_stamp()]\] Pressed fingers into the eyes of [affecting.name] ([affecting.ckey])") - affecting.attack_log += text("\[[time_stamp()]\] Had fingers pressed into their eyes by [assailant.name] ([assailant.ckey])") - msg_admin_attack("[key_name(assailant)] has pressed his fingers into [key_name(affecting)]'s eyes.") - var/obj/item/organ/internal/eyes/IO = affecting:organs_by_name[O_EYES] - IO.damage += rand(3,4) - if (IO.damage >= IO.min_broken_damage) - if(affecting.stat != DEAD) - to_chat(affecting, "\red You go blind!") -// else if(hit_zone != BP_HEAD) -// if(state < GRAB_NECK) -// assailant << "You require a better grab to do this." -// return -// if(affecting:grab_joint(assailant)) -// playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) -// return - else - if(affecting.lying) - return - assailant.visible_message("[assailant] thrusts \his head into [affecting]'s skull!") - var/damage = 20 - var/obj/item/clothing/hat = assailant.head - if(istype(hat)) - damage += hat.force * 10 - var/armor = affecting:run_armor_check(affecting, "melee") - affecting.apply_damage(damage*rand(90, 110)/100, BRUTE, BP_HEAD, armor) - assailant.apply_damage(10*rand(90, 110)/100, BRUTE, BP_HEAD, assailant:run_armor_check(BP_HEAD, "melee")) - if(!armor && prob(damage)) - affecting.apply_effect(20, PARALYZE) - affecting.visible_message("[affecting] has been knocked unconscious!") - playsound(assailant.loc, "swing_hit", 25, 1, -1) - assailant.attack_log += text("\[[time_stamp()]\] Headbutted [affecting.name] ([affecting.ckey])") - affecting.attack_log += text("\[[time_stamp()]\] Headbutted by [assailant.name] ([assailant.ckey])") - msg_admin_attack("[key_name(assailant)] has headbutted [key_name(affecting)]") - assailant.drop_from_inventory(src) - src.loc = null - qdel(src) - return - if("disarm") - if(state < GRAB_AGGRESSIVE) - to_chat(assailant, "You require a better grab to do this.") - return - to_chat(assailant, "You start forcing [affecting] to the ground.") - if(!force_down) - sleep(20) - assailant.visible_message("[assailant] is forcing [affecting] to the ground!") - force_down = 1 - affecting.Weaken(3) - affecting.lying = 1 - step_to(assailant, affecting) - assailant.set_dir(EAST) //face the victim - affecting.set_dir(SOUTH) //face up - affecting.layer = 3.9 - return - else - to_chat(assailant, "You are already pinning [affecting] to the ground.") - return - - if(M == assailant && state >= GRAB_AGGRESSIVE) - if( (ishuman(user) && (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]!") - if(istype(user, /mob/living/carbon/alien/humanoid/hunter)) - if(!do_mob(user, affecting)||!do_after(user, 30, target = affecting)) return - else - if(!do_mob(user, affecting)||!do_after(user, 100, target = affecting)) return - user.visible_message("[user] devours [affecting]!") - if(isalien(user)) - if(affecting.stat == DEAD) - affecting.gib() - if(attacker.health >= attacker.maxHealth - attacker.getCloneLoss()) - attacker.adjustToxLoss(100) - to_chat(attacker, "You gain some plasma.") - else - attacker.adjustBruteLoss(-100) - attacker.adjustFireLoss(-100) - attacker.adjustOxyLoss(-100) - attacker.adjustCloneLoss(-100) - to_chat(attacker, "You feel better.") - else - affecting.loc = user - attacker.stomach_contents.Add(affecting) - else - affecting.loc = user - attacker.stomach_contents.Add(affecting) - qdel(src) - -/obj/item/weapon/grab/Destroy() - if(affecting) - animate(affecting, pixel_x = 0, pixel_y = 0, 4, 1, LINEAR_EASING) - affecting.layer = 4 - if(affecting) - affecting.grabbed_by -= src - affecting = null - if(assailant) - if(assailant.client) - assailant.client.screen -= hud - assailant = null - QDEL_NULL(hud) - return ..() - -/obj/item/weapon/grab/proc/inspect_organ(mob/living/carbon/human/H, mob/user, target_zone) - - var/obj/item/organ/external/BP = H.get_bodypart(target_zone) - - if(!BP || (BP.status & ORGAN_DESTROYED)) - to_chat(user, "[H] is missing that bodypart.") - return - - user.visible_message("[user] starts inspecting [affecting]'s [BP.name] carefully.") - if(!do_mob(user,H, 30)) - to_chat(user, "You must stand still to inspect [BP] for wounds.") - else if(BP.wounds.len) - to_chat(user, "You find [BP.get_wounds_desc()]") - else - to_chat(user, "You find no visible wounds.") - - to_chat(user, "Checking bones now...") - if(!do_mob(user, H, 60)) - to_chat(user, "You must stand still to feel [BP] for fractures.") - else if(BP.status & ORGAN_BROKEN) - to_chat(user, "The bone in the [BP.name] moves slightly when you poke it!") - H.custom_pain("Your [BP.name] hurts where it's poked.") - else - to_chat(user, "The bones in the [BP.name] seem to be fine.") - - to_chat(user, "Checking skin now...") - if(!do_mob(user, H, 30)) - to_chat(user, "You must stand still to check [H]'s skin for abnormalities.") - else - var/bad = 0 - if(H.getToxLoss() >= 40) - to_chat(user, "[H] has an unhealthy skin discoloration.") - bad = 1 - if(H.getOxyLoss() >= 20) - to_chat(user, "[H]'s skin is unusaly pale.") - bad = 1 - if(BP.status & ORGAN_DEAD) - to_chat(user, "[BP] is decaying!") - bad = 1 - if(!bad) - to_chat(user, "[H]'s skin is normal.") +/obj/item/weapon/grab + name = "grab" + icon = 'icons/mob/screen1.dmi' + icon_state = "reinforce" + flags = DROPDEL + var/obj/screen/grab/hud = null + var/mob/living/affecting = null + var/mob/living/carbon/human/assailant = null + var/state = GRAB_PASSIVE + + var/allow_upgrade = 1 + var/last_action = 0 + var/last_hit_zone = 0 + var/force_down //determines if the affecting mob will be pinned to the ground + var/dancing //determines if assailant and affecting keep looking at each other. Basically a wrestling position + + layer = 21 + abstract = 1 + item_state = "nothing" + w_class = 5.0 + + +/obj/item/weapon/grab/atom_init(mapload, mob/victim) + . = ..() + assailant = loc + affecting = victim + + if(affecting.anchored) + return INITIALIZE_HINT_QDEL + last_action = world.time - 10 + + hud = new /obj/screen/grab(src) + hud.icon_state = "reinforce" + icon_state = "grabbed" + hud.name = "reinforce grab" + hud.master = src + + //check if assailant is grabbed by victim as well + if(assailant.grabbed_by) + for (var/obj/item/weapon/grab/G in assailant.grabbed_by) + if(G.assailant == affecting && G.affecting == assailant) + G.dancing = 1 + G.adjust_position() + dancing = 1 + adjust_position() + +//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/throw_held() + if(affecting) + if(affecting.buckled) + return null + if(state >= GRAB_AGGRESSIVE) + animate(affecting, pixel_x = 0, pixel_y = 0, 4, 1) + 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 if(assailant.l_hand == src) + hud.screen_loc = ui_lhand + else + qdel(src) + + +/obj/item/weapon/grab/process() + confirm() + + if(!assailant) + qdel(src) // Same here, except we're trying to delete ourselves. + return PROCESS_KILL + + if(!affecting) + qdel(src) + return PROCESS_KILL + + if(affecting.buckled) + qdel(src) + return PROCESS_KILL + + 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 + //disallow upgrading if we're grabbing more than one person + 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 + + //disallow upgrading past aggressive if we're being grabbed aggressively + 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) + if(state < GRAB_AGGRESSIVE) + hud.icon_state = "reinforce" + else + hud.icon_state = "reinforce1" + else + hud.icon_state = "!reinforce" + + if(state >= GRAB_AGGRESSIVE) + affecting.drop_l_hand() + affecting.drop_r_hand() + + var/hit_zone = assailant.zone_sel.selecting + var/announce = 0 + if(hit_zone != last_hit_zone) + announce = 1 + last_hit_zone = hit_zone + if(ishuman(affecting)) + var/mob/living/carbon/human/AH = affecting + if(!AH.is_in_space_suit(only_helmet = TRUE)) + switch(hit_zone) + if(O_MOUTH) + if(announce) + assailant.visible_message("[assailant] covers [AH]'s mouth!") + if(AH.silent < 3) + AH.silent = 3 + if(O_EYES) + if(announce) + assailant.visible_message("[assailant] covers [AH]'s eyes!") + if(AH.eye_blind < 3) + AH.eye_blind = 3 + if(force_down) + if(affecting.loc != assailant.loc) + force_down = 0 + else + affecting.Weaken(2) + + if(state >= GRAB_NECK) + affecting.Stun(1) + if(isliving(affecting)) + var/mob/living/L = affecting + L.adjustOxyLoss(1) + + if(state >= GRAB_KILL) + //affecting.apply_effect(STUTTER, 5) //would do this, but affecting isn't declared as mob/living for some stupid reason. + affecting.stuttering = max(affecting.stuttering, 5) //It will hamper your voice, being choked and all. + affecting.Weaken(5) //Should keep you down unless you get help. + affecting.losebreath = max(affecting.losebreath + 2, 3) + + adjust_position() + + +/obj/item/weapon/grab/attack_self() + return s_click(hud) + + +//Updating pixelshift, position and direction +//Gets called on process, when the grab gets upgraded or the assailant moves +/obj/item/weapon/grab/proc/adjust_position() + if(!affecting) + return + if(affecting.buckled) + animate(affecting, pixel_x = 0, pixel_y = 0, 4, 1, LINEAR_EASING) + return + if(affecting.lying && state != GRAB_KILL) +// animate(affecting, pixel_x = 0, pixel_y = 0, 5, 1, LINEAR_EASING) + if(force_down) + affecting.set_dir(SOUTH) //face up + return + var/shift = 0 + var/adir = get_dir(assailant, affecting) + affecting.layer = 4 + switch(state) + if(GRAB_PASSIVE) + shift = 8 + if(dancing) //look at partner + shift = 10 + assailant.set_dir(get_dir(assailant, affecting)) + if(GRAB_AGGRESSIVE) + shift = 12 + if(GRAB_NECK, GRAB_UPGRADING) + shift = -10 + adir = assailant.dir + affecting.set_dir(assailant.dir) + affecting.loc = assailant.loc + if(GRAB_KILL) + shift = 0 + adir = 1 + affecting.set_dir(SOUTH) //face up + affecting.loc = assailant.loc + + switch(adir) + if(NORTH) + animate(affecting, pixel_x = 0, pixel_y =-shift, 5, 1, LINEAR_EASING) + affecting.layer = 3.9 + if(SOUTH) + animate(affecting, pixel_x = 0, pixel_y = shift, 5, 1, LINEAR_EASING) + if(WEST) + animate(affecting, pixel_x = shift, pixel_y = 0, 5, 1, LINEAR_EASING) + if(EAST) + animate(affecting, pixel_x =-shift, pixel_y = 0, 5, 1, LINEAR_EASING) + +/obj/item/weapon/grab/proc/s_click(obj/screen/S) + if(!affecting) + return + if(!assailant) + return + if(state == GRAB_UPGRADING) + return + if(assailant.next_move > world.time) + return + if(world.time < (last_action + UPGRADE_COOLDOWN)) + return + if(!assailant.canmove || assailant.lying) + qdel(src) + return + + last_action = world.time + + if(state < GRAB_AGGRESSIVE) + if(!allow_upgrade) + return + if(!affecting.lying) + assailant.visible_message("[assailant] has grabbed [affecting] aggressively (now hands)!") + else + assailant.visible_message("[assailant] pins [affecting] down to the ground (now hands)!") + force_down = 1 + affecting.Weaken(3) + step_to(assailant, affecting) + assailant.set_dir(EAST) //face the victim + affecting.set_dir(SOUTH) //face up + state = GRAB_AGGRESSIVE + icon_state = "grabbed1" + hud.icon_state = "reinforce1" + + 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)!") + state = GRAB_NECK + icon_state = "grabbed+1" + assailant.set_dir(get_dir(assailant, affecting)) + 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])" + msg_admin_attack("[key_name(assailant)] grabbed the neck of [key_name(affecting)] (JMP)") + hud.icon_state = "kill" + hud.name = "kill" + affecting.Stun(10) //10 ticks of ensured grab + + else if(state < GRAB_UPGRADING) + if(ishuman(affecting)) + var/mob/living/carbon/human/AH = affecting + if(AH.is_in_space_suit()) + to_chat(assailant, "You can't strangle him, because space helmet covers [affecting]'s neck.") + return + assailant.visible_message("[assailant] starts to tighten \his grip on [affecting]'s neck!") + hud.icon_state = "kill1" + + state = GRAB_KILL + assailant.visible_message("[assailant] has tightened \his grip on [affecting]'s neck!") + 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])" + msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]") + + assailant.next_move = world.time + 10 + affecting.losebreath += 1 + affecting.set_dir(WEST) + adjust_position() + + +//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) + qdel(src) + return 0 + + if(affecting) + if(!isturf(assailant.loc) || ( !isturf(affecting.loc) || assailant.loc != affecting.loc && get_dist(assailant, affecting) > 1) ) + qdel(src) + return 0 + + return 1 + + +/obj/item/weapon/grab/attack(mob/M, mob/living/user) + if(QDELETED(src)) + return + + if(!affecting) + return + + if(world.time < (last_action + 20)) + return + + if(!M.Adjacent(user)) + qdel(src) + return + + last_action = world.time + + if(M == affecting) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/hit_zone = assailant.zone_sel.selecting + flick(hud.icon_state, hud) + switch(assailant.a_intent) + if("help") + if(force_down) + to_chat(assailant, "You are no longer pinning [affecting] to the ground.") + force_down = 0 + return + if(state >= GRAB_AGGRESSIVE) + H.apply_pressure(assailant, hit_zone) + else + inspect_organ(affecting, assailant, hit_zone) + if("grab") + if(state < GRAB_AGGRESSIVE) + to_chat(assailant, "You require a better grab to do this.") + return + var/obj/item/organ/external/BP = H.bodyparts_by_name[check_zone(hit_zone)] + if(!BP) + return + assailant.visible_message("[assailant] [pick("bent", "twisted")] [H]'s [BP.name] into a jointlock!") + var/armor = H.run_armor_check(H, "melee") + if(armor < 2) + to_chat(H, "You feel extreme pain!") + H.adjustHalLoss(Clamp(0, 40 - H.halloss, 40)) //up to 40 halloss + return + if("hurt") + + if(hit_zone == O_EYES) + if(state < GRAB_NECK) + to_chat(assailant, "You require a better grab to do this.") + return + if((affecting:head && affecting:head.flags & HEADCOVERSEYES) || \ + (affecting:wear_mask && affecting:wear_mask.flags & MASKCOVERSEYES) || \ + (affecting:glasses && affecting:glasses.flags & GLASSESCOVERSEYES)) + to_chat(assailant, "You're going to need to remove the eye covering first.") + return + if(!affecting.has_eyes()) + to_chat(assailant, "You cannot locate any eyes on [affecting]!") + return + assailant.visible_message("[assailant] pressed \his fingers into [affecting]'s eyes!") + to_chat(affecting, "You experience immense pain as you feel digits being pressed into your eyes!") + assailant.attack_log += text("\[[time_stamp()]\] Pressed fingers into the eyes of [affecting.name] ([affecting.ckey])") + affecting.attack_log += text("\[[time_stamp()]\] Had fingers pressed into their eyes by [assailant.name] ([assailant.ckey])") + msg_admin_attack("[key_name(assailant)] has pressed his fingers into [key_name(affecting)]'s eyes.") + var/obj/item/organ/internal/eyes/IO = affecting:organs_by_name[O_EYES] + IO.damage += rand(3,4) + if (IO.damage >= IO.min_broken_damage) + if(affecting.stat != DEAD) + to_chat(affecting, "\red You go blind!") +// else if(hit_zone != BP_HEAD) +// if(state < GRAB_NECK) +// assailant << "You require a better grab to do this." +// return +// if(affecting:grab_joint(assailant)) +// playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) +// return + else + if(affecting.lying) + return + assailant.visible_message("[assailant] thrusts \his head into [affecting]'s skull!") + var/damage = 20 + var/obj/item/clothing/hat = assailant.head + if(istype(hat)) + damage += hat.force * 10 + var/armor = affecting:run_armor_check(affecting, "melee") + affecting.apply_damage(damage*rand(90, 110)/100, BRUTE, BP_HEAD, armor) + assailant.apply_damage(10*rand(90, 110)/100, BRUTE, BP_HEAD, assailant:run_armor_check(BP_HEAD, "melee")) + if(!armor && prob(damage)) + affecting.apply_effect(20, PARALYZE) + affecting.visible_message("[affecting] has been knocked unconscious!") + playsound(assailant.loc, "swing_hit", 25, 1, -1) + assailant.attack_log += text("\[[time_stamp()]\] Headbutted [affecting.name] ([affecting.ckey])") + affecting.attack_log += text("\[[time_stamp()]\] Headbutted by [assailant.name] ([assailant.ckey])") + msg_admin_attack("[key_name(assailant)] has headbutted [key_name(affecting)]") + assailant.drop_from_inventory(src) + src.loc = null + qdel(src) + return + if("disarm") + if(state < GRAB_AGGRESSIVE) + to_chat(assailant, "You require a better grab to do this.") + return + to_chat(assailant, "You start forcing [affecting] to the ground.") + if(!force_down) + sleep(20) + assailant.visible_message("[assailant] is forcing [affecting] to the ground!") + force_down = 1 + affecting.Weaken(3) + affecting.lying = 1 + step_to(assailant, affecting) + assailant.set_dir(EAST) //face the victim + affecting.set_dir(SOUTH) //face up + affecting.layer = 3.9 + return + else + to_chat(assailant, "You are already pinning [affecting] to the ground.") + return + + if(M == assailant && state >= GRAB_AGGRESSIVE) + if( (ishuman(user) && (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]!") + if(istype(user, /mob/living/carbon/alien/humanoid/hunter)) + if(!do_mob(user, affecting)||!do_after(user, 30, target = affecting)) return + else + if(!do_mob(user, affecting)||!do_after(user, 100, target = affecting)) return + user.visible_message("[user] devours [affecting]!") + if(isalien(user)) + if(affecting.stat == DEAD) + affecting.gib() + if(attacker.health >= attacker.maxHealth - attacker.getCloneLoss()) + attacker.adjustToxLoss(100) + to_chat(attacker, "You gain some plasma.") + else + attacker.adjustBruteLoss(-100) + attacker.adjustFireLoss(-100) + attacker.adjustOxyLoss(-100) + attacker.adjustCloneLoss(-100) + to_chat(attacker, "You feel better.") + else + affecting.loc = user + attacker.stomach_contents.Add(affecting) + else + affecting.loc = user + attacker.stomach_contents.Add(affecting) + qdel(src) + +/obj/item/weapon/grab/Destroy() + if(affecting) + animate(affecting, pixel_x = 0, pixel_y = 0, 4, 1, LINEAR_EASING) + affecting.layer = 4 + if(affecting) + affecting.grabbed_by -= src + affecting = null + if(assailant) + if(assailant.client) + assailant.client.screen -= hud + assailant = null + QDEL_NULL(hud) + return ..() + +/obj/item/weapon/grab/proc/inspect_organ(mob/living/carbon/human/H, mob/user, target_zone) + + var/obj/item/organ/external/BP = H.get_bodypart(target_zone) + + if(!BP || (BP.status & ORGAN_DESTROYED)) + to_chat(user, "[H] is missing that bodypart.") + return + + user.visible_message("[user] starts inspecting [affecting]'s [BP.name] carefully.") + if(!do_mob(user,H, 30)) + to_chat(user, "You must stand still to inspect [BP] for wounds.") + else if(BP.wounds.len) + to_chat(user, "You find [BP.get_wounds_desc()]") + else + to_chat(user, "You find no visible wounds.") + + to_chat(user, "Checking bones now...") + if(!do_mob(user, H, 60)) + to_chat(user, "You must stand still to feel [BP] for fractures.") + else if(BP.status & ORGAN_BROKEN) + to_chat(user, "The bone in the [BP.name] moves slightly when you poke it!") + H.custom_pain("Your [BP.name] hurts where it's poked.") + else + to_chat(user, "The bones in the [BP.name] seem to be fine.") + + to_chat(user, "Checking skin now...") + if(!do_mob(user, H, 30)) + to_chat(user, "You must stand still to check [H]'s skin for abnormalities.") + else + var/bad = 0 + if(H.getToxLoss() >= 40) + to_chat(user, "[H] has an unhealthy skin discoloration.") + bad = 1 + if(H.getOxyLoss() >= 20) + to_chat(user, "[H]'s skin is unusaly pale.") + bad = 1 + if(BP.status & ORGAN_DEAD) + to_chat(user, "[BP] is decaying!") + bad = 1 + if(!bad) + to_chat(user, "[H]'s skin is normal.") diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index bd9bfb30dc47..2064a2081f32 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -1,485 +1,485 @@ -#define CHANGELING_STATPANEL_STATS(BYOND) \ - if(mind && mind.changeling) \ - { \ - stat("Chemical Storage", "[mind.changeling.chem_charges]/[mind.changeling.chem_storage]"); \ - stat("Genetic Damage Time", mind.changeling.geneticdamage); \ - stat("Absorbed DNA", mind.changeling.absorbedcount); \ - } - - -#define CHANGELING_STATPANEL_POWERS(BYOND) \ - if(mind && mind.changeling && mind.changeling.purchasedpowers.len) \ - { \ - for(var/P in mind.changeling.purchasedpowers) \ - { \ - var/obj/effect/proc_holder/changeling/S = P; \ - if(S.chemical_cost >=0 && S.can_be_used_by(src)) \ - { \ - statpanel("[S.panel]", ((S.chemical_cost > 0) ? "[S.chemical_cost]" : ""), S); \ - } \ - } \ - } - -// see _DEFINES/is_helpers.dm for mob type checks -#define SAFE_PERP -50 - -/mob/living/proc/isSynthetic() - return FALSE - -/mob/living/carbon/human/isSynthetic(target_zone) - if(isnull(full_prosthetic)) - robolimb_count = 0 - for(var/obj/item/organ/external/BP in bodyparts) - if(BP.status & ORGAN_ROBOT) - robolimb_count++ - full_prosthetic = (robolimb_count == bodyparts.len) - - if(!full_prosthetic && target_zone) - var/obj/item/organ/external/BP = get_bodypart(target_zone) - if(BP) - return BP.status & ORGAN_ROBOT - - return full_prosthetic - -/mob/living/silicon/isSynthetic() - return TRUE - -/proc/hsl2rgb(h, s, l) - return - -/proc/ismindshielded(A, only_mindshield = FALSE) //Checks to see if the person contains a mindshield implant, then checks that the implant is actually inside of them - - for(var/obj/item/weapon/implant/mindshield/L in A) - if(only_mindshield && L.type != /obj/item/weapon/implant/mindshield) - continue - if(L.implanted) - return TRUE - return FALSE - -/proc/isloyal(A) - for(var/obj/item/weapon/implant/mindshield/loyalty/L in A) - if(L.implanted) - return TRUE - return FALSE - -/proc/check_zone(zone) - if(!zone) - return BP_CHEST - - switch(zone) - if(O_EYES) - zone = BP_HEAD - if(O_MOUTH) - zone = BP_HEAD - - return zone - -// Returns zone with a certain probability. -// If the probability misses, returns "chest" instead. -// If "chest" was passed in as zone, then on a "miss" will return "head", "l_arm", or "r_arm" -// Do not use this if someone is intentionally trying to hit a specific body part. -// Use get_zone_with_miss_chance() for that. -/proc/ran_zone(zone, probability = 90) - zone = check_zone(zone) - if(probability == 100) - return zone - - if(zone == BP_CHEST) - if(prob(probability)) - return BP_CHEST - - var/t = rand(1, 9) - switch(t) - if(1 to 3) return BP_HEAD - if(4 to 6) return BP_L_ARM - if(7 to 9) return BP_R_ARM - - if(prob(probability * 0.75)) - return zone - - return BP_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, mob/target, miss_chance_mod = 0) - zone = check_zone(zone) - - // you can only miss if your target is standing and not restrained - if(!target.buckled && !target.lying) - var/miss_chance = 10 - switch(zone) - if(BP_HEAD) - miss_chance = 50 - if(BP_GROIN) - miss_chance = 50 - if(BP_L_ARM) - miss_chance = 60 - if(BP_R_ARM) - miss_chance = 60 - if(BP_L_LEG) - miss_chance = 60 - if(BP_R_LEG) - miss_chance = 60 - if(prob(max(miss_chance + miss_chance_mod, 0))) - if(prob(max(20, (miss_chance/2)))) - return null - else - var/t = rand(1, 100) - switch(t) - if(1 to 65) - return BP_CHEST - if(66 to 75) - return BP_HEAD - if(76 to 80) - return BP_L_ARM - if(81 to 85) - return BP_R_ARM - if(86 to 90) - return BP_R_LEG - if(91 to 95) - return BP_L_LEG - if(96 to 100) - return BP_GROIN - - return zone - -/proc/get_zone_with_probabilty(zone, probability = 80) - - zone = check_zone(zone) - - if(prob(probability)) - return zone - - var/t = rand(1, 18) // randomly pick a different zone, or maybe the same one - switch(t) - if(1) return BP_HEAD - if(2) return BP_CHEST - if(3 to 6) return BP_L_ARM - if(7 to 10) return BP_R_ARM - if(11 to 14) return BP_L_LEG - if(15 to 18) return BP_R_LEG - - return zone - -/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=lentext(phrase) - var/counter=lentext(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" - if(lowertext_(newletter)=="ч") newletter="щ" //247 -> 249 - if(lowertext_(newletter)=="е") newletter="и" //229 -> 232 - if(lowertext_(newletter)=="з") newletter="с" //231 -> 241 - switch(rand(1,15)) - if(1,3,5,8) newletter="[lowertext_(newletter)]" - if(2,4,6,15) newletter="[uppertext_(newletter)]" - if(7) 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/alphabet[0] - //latin - //"b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z" - alphabet.Add(98,99,100,102,103,104,105,106,107,108,109,110,112,113,114,115,116,118,119,120,121,122) - //cyrillic - //"б","в","г","д","ж","з","й","к","л","м","н","п","р","с","т","ф","х","ц","ч","ш","щ" - alphabet.Add(225,226,227,228,230,231,233,234,235,236,237,239,240,241,242,244,245,246,247,248,249) - - 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) && (text2ascii(lowertext_(n_letter)) in alphabet)) - 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 sanitize(t) - - -/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/GibberishAll(t) // Same as above, except there is no probability and chance always 100. - /* Turn text into complete gibberish! */ - var/returntext = "" - for(var/i = 1 to length(t)) - - var/letter = "" - - for(var/j = rand(0, 2) to 0 step -1) - letter += pick("#","@","*","&","%","$","/", "<", ">", ";","*","*","*","*","*","*","*") - - returntext += letter - - return returntext - - -/proc/ninjaspeak(n) -/* -The difference with stutter is that this proc can stutter more than 1 letter -The issue here is that anything that does not have a space is treated as one word (in many instances). For instance, "LOOKING," is a word, including the comma. -It's fairly easy to fix if dealing with single letters but not so much with compounds of letters./N -*/ - var/te = html_decode(n) - var/t = "" - n = length(n) - var/p = 1 - while(p <= n) - var/n_letter - var/n_mod = rand(1,4) - if(p+n_mod>n+1) - n_letter = copytext(te, p, n+1) - else - n_letter = copytext(te, p, p+n_mod) - if (prob(50)) - if (prob(30)) - n_letter = text("[n_letter]-[n_letter]-[n_letter]") - else - n_letter = text("[n_letter]-[n_letter]") - else - n_letter = text("[n_letter]") - t = text("[t][n_letter]") - p=p+n_mod - return sanitize(t) - -/proc/shake_camera(mob/M, duration, strength=1) - if(!M || !M.client || !strength) return - spawn() - strength *= 32 - for(var/i=0; i